Compare commits

...

44 Commits

Author SHA1 Message Date
Jesse Suen
21b64886ce Bump version to v0.5.4 2018-06-27 15:56:38 -07:00
Jesse Suen
eeb1036dcf Refresh flag to sync should be optional, not required 2018-06-27 15:54:35 -07:00
Jesse Suen
fa990ab0c9 Support cluster management using the internal k8s API address https://kubernetes.default.svc (#307) 2018-06-20 16:51:31 -07:00
Jesse Suen
933f3da538 Support diffing a local ksonnet app to the live application state (resolves #239) (#298) 2018-06-20 13:57:55 -07:00
Jesse Suen
a7fa2fd256 Add ability to show last operation result in app get. Show path in app list -o wide (#297) 2018-06-19 02:04:45 -07:00
Jesse Suen
0de1a3b20a Update dependencies: ksonnet v0.11, golang v1.10, debian v9.4 (#296) 2018-06-18 14:34:10 -07:00
Jesse Suen
bcc114ec60 Add ability to force a refresh of an app during get (resolves #269) (#293) 2018-06-18 10:22:58 -07:00
Jesse Suen
1148fae419 Add clean-debug make target to prevent packr from boxing debug artifacts into binaries 2018-06-15 14:31:26 -07:00
Jesse Suen
d7188c29f8 Remove redundant 'argocd' namespace from manifests 2018-06-15 14:20:28 -07:00
Jesse Suen
4b97732659 Automatically restart API server upon certificate changes (#292) 2018-06-15 14:16:50 -07:00
Jesse Suen
8ff98cc6e1 Add RBAC unit test for wildcards with sub-resources 2018-06-14 12:50:16 -07:00
Jesse Suen
cf0c324a74 Add unit test for using resource & action wildcards in a RBAC policy. Bump version to v0.5.2 2018-06-14 12:41:26 -07:00
Jesse Suen
69119a21cd Update getting_started.md to point to v0.5.1 2018-06-14 11:13:05 -07:00
Alexander Matyushentsev
16fa41d25b Issue #275 - Application controller fails to get app state if app has resource without name (#285) 2018-06-14 09:08:22 -07:00
Alexander Matyushentsev
4e170c2033 Update version to v0.5.1 2018-06-13 14:30:35 -07:00
Alexander Matyushentsev
3fbbe940a1 Issue #283 - API server incorrectly compose application fully qualified name for RBAC check (#284) 2018-06-13 13:05:39 -07:00
Alexander Matyushentsev
271b57e5c5 Issue #260 - Rate limiter is preventing force refreshes (e.g. webhook) from functioning (#282) 2018-06-13 11:34:33 -07:00
Andrew Merenbach
df0e2e4015 Fail app sync if prune flag is required (#276)
* Add status field to resource details

* Update generated code

* Set up const message responses

* Check number of resources requiring pruning

* Fix imports

* Use string, thanks @alexmt

* Update generated code
2018-06-12 10:54:11 -07:00
Alexander Matyushentsev
9fa622d63b Issue #280 - It is impossible to restrict application access by repository URL (#281)
* Issue #280 - It is impossible to restrict application access by repository URL

* Apply reviewer note
2018-06-12 10:43:16 -07:00
Alexander Matyushentsev
fed2149174 Add progressing deadline to test app to fix e2e tets slowness 2018-06-12 08:54:47 -07:00
Alexander Matyushentsev
aa4291183b Take into account number of unavailable replicas to decided if deployment is healthy or not (#270)
* Take into account number of unavailable replicas to decided if deployment is healthy or not

* Run one controller for all e2e tests to reduce tests duration

* Apply reviewer notes: use logic from kubectl/rollout_status.go to check deployment health
2018-06-07 11:05:46 -07:00
Alexander Matyushentsev
0d3fc9648f Issue #271 - perform three way diff only if resource has expected state and live state with last-applied-configuration annotation (#274) 2018-06-07 10:29:36 -07:00
Jesse Suen
339138b576 Remove hard requirement of initializing OIDC app during server startup (resolves #272) 2018-06-07 02:07:53 -07:00
Jesse Suen
666769f9d9 Fix issue preventing proper parsing of claims subject in RBAC enforcement 2018-06-07 00:17:00 -07:00
Jesse Suen
8fc594bd2b Add missing list, patch, update verbs to application-controller-role 2018-06-06 17:51:18 -07:00
Andrew Merenbach
8cf8ad7e24 Tweak flags for import/export, thanks @jessesuen (#268) 2018-06-06 16:32:30 -07:00
Andrew Merenbach
0818f698e6 Support resource import/export (#255)
* Add initial prototype for export

* Add client opts to argocd-util

* Make flags local

* Support output to file without piping

* Add comment to NewExportCommand

* Vastly clean up output, thanks @alexmt @jessesuen

* Nullify operation, thanks @alexmt

* Add additional error check

* Rm extraneous fmt.Sprint

* Clone export command to import

* Flesh out import feature

* Use const string for YAML separator

* Don't export enclosing lists

* Almost finished prototyping import

* Create settings now, too

* Create all resources now

* Nullify certificate before export

* Add JSON annotations, update comment

* Warn, don't fail, if cluster/repo already exist, thanks @alexmt

* Use minus instead of stdin/stdout, thanks @jessesuen
2018-06-06 14:53:14 -07:00
Jesse Suen
44a33b0a5f Repo names containing underscores were not being accepted (resolves #258) 2018-06-06 14:26:43 -07:00
wanghong230
85078bdb66 fix #120 refactor the rbac code to support customizable claims enforcement function (#265) 2018-06-06 14:20:34 -07:00
Jesse Suen
30a3dba7ad argocd-server needs to be built using packr to bundle RBAC policy files. Update packr (resolves #266) 2018-06-06 12:35:25 -07:00
Jesse Suen
0afc671723 Retry argocd app wait connection errors from EOF watch. Show detailed state changes 2018-06-06 11:24:49 -07:00
Jesse Suen
12e7447e9f Implement RBAC support (issue #120) (#263)
* introduce rbac library around casbin
* supports claims enforcement by iteration through user's groups
* supports filtering of resources by level of access
* policy loader and automatic updates from configmap
* support for builtin and userdefined policies
2018-06-05 21:44:13 -07:00
Alexander Matyushentsev
b675e79b89 Add path to API /application/{repo}/ksonnet response (#264)
* Add path to API /application/{repo}/ksonnet response

* Fix indentation
2018-06-05 14:37:26 -07:00
Jesse Suen
febdccfb58 Introduce argocd app manifests for printing the application manifests from git or live (#261) 2018-06-05 12:59:29 -07:00
Alexander Matyushentsev
54835a0d93 Implement workaround for https://github.com/golang/go/issues/21955 (#256) 2018-06-04 13:52:07 -07:00
Jesse Suen
423fe3487c REST payload of create/update for repos and cluster should be actual object 2018-05-31 18:15:33 -07:00
Jesse Suen
98cb3f7950 Bump version to v0.5.0 2018-05-31 17:56:23 -07:00
Jesse Suen
371492bf5c Handle case where upsert could be nil. Use proper error codes. More RESTful endpoints 2018-05-31 17:54:27 -07:00
Jesse Suen
7df831e96d Clean up .proto definitions for consistency and reduction of pointer usage (#253) 2018-05-31 17:21:09 -07:00
Alexander Matyushentsev
f0be1bd251 Fix bug secret controller which is causing update loop in secret controller (#251) 2018-05-31 16:06:41 -07:00
Alexander Matyushentsev
948341a885 ListDir should not fail if Redis is down (#252) 2018-05-31 16:06:30 -07:00
Alexander Matyushentsev
1b2bf8ce0e GET /cluster/<clustername> API should not panic if invalid cluster url is provided (#250) 2018-05-31 15:13:07 -07:00
Andrew Merenbach
4f68a0f634 Wrap method signatures (#249)
* Update application create to use upsert attribute

* Update CLI interface

* Use pointer to upsert

* Rename DeleteApplicationRequest for parity

* Add new ApplicationUpdateRequest wrapper

* Rename RepoUpdateRequest => RepoRESTUpdateRequest

* Add new RepositoryUpdateRequest

* Rename ClusterUpdateRequest -> ClusterRESTUpdateRequest

* Fix var names

* Update var use

* Use intermediate vars for clarity

* Update generated code

* Update mocks

* Update e2e cluster creation
2018-05-31 14:21:08 -07:00
Alexander Matyushentsev
e785abeb8f Issue #244 - Cluster/Repository connection status (#248) 2018-05-31 13:44:19 -07:00
80 changed files with 4323 additions and 1594 deletions

View File

@@ -1,4 +1,4 @@
FROM debian:9.3 as builder
FROM debian:9.4 as builder
RUN apt-get update && apt-get install -y \
git \
@@ -10,7 +10,7 @@ RUN apt-get update && apt-get install -y \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Install go
ENV GO_VERSION 1.9.3
ENV GO_VERSION 1.10.3
ENV GO_ARCH amd64
ENV GOPATH /root/go
ENV PATH ${GOPATH}/bin:/usr/local/go/bin:${PATH}
@@ -25,7 +25,7 @@ RUN cd /usr/local && \
unzip protoc-*.zip && \
wget https://github.com/golang/dep/releases/download/v0.4.1/dep-linux-amd64 -O /usr/local/bin/dep && \
chmod +x /usr/local/bin/dep && \
wget https://github.com/gobuffalo/packr/releases/download/v1.10.4/packr_1.10.4_linux_amd64.tar.gz && \
wget https://github.com/gobuffalo/packr/releases/download/v1.11.0/packr_1.11.0_linux_amd64.tar.gz && \
tar -vxf packr*.tar.gz -C /tmp/ && \
mv /tmp/packr /usr/local/bin/packr
@@ -58,7 +58,7 @@ FROM golang:1.10 as cli-tooling
#RUN go get -v -u github.com/ksonnet/ksonnet && mv ${GOPATH}/bin/ksonnet /ks
# Option 2: use official tagged ksonnet release
env KSONNET_VERSION=0.10.2
env KSONNET_VERSION=0.11.0
RUN wget https://github.com/ksonnet/ksonnet/releases/download/v${KSONNET_VERSION}/ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
tar -C /tmp/ -xf ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
mv /tmp/ks_${KSONNET_VERSION}_linux_amd64/ks /ks

View File

@@ -1,4 +1,4 @@
FROM golang:1.9.2
FROM golang:1.10.3
WORKDIR /tmp
@@ -15,7 +15,7 @@ RUN curl -o /kubectl -LO https://storage.googleapis.com/kubernetes-release/relea
chmod +x /kubectl && mv /kubectl /usr/local/bin/kubectl
# Install ksonnet
env KSONNET_VERSION=0.10.2
env KSONNET_VERSION=0.11.0
RUN wget https://github.com/ksonnet/ksonnet/releases/download/v${KSONNET_VERSION}/ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
tar -C /tmp/ -xf ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
mv /tmp/ks_${KSONNET_VERSION}_linux_amd64/ks /usr/local/bin/ks && \

191
Gopkg.lock generated
View File

@@ -15,6 +15,12 @@
]
revision = "c02ca9a983da5807ddf7d796784928f5be4afd09"
[[projects]]
name = "github.com/Knetic/govaluate"
packages = ["."]
revision = "d216395917cc49052c7c7094cf57f09657ca08a8"
version = "v3.0.0"
[[projects]]
name = "github.com/PuerkitoBio/purell"
packages = ["."]
@@ -32,6 +38,22 @@
revision = "2ee87856327ba09384cabd113bc6b5d174e9ec0f"
version = "v3.5.1"
[[projects]]
name = "github.com/casbin/casbin"
packages = [
".",
"config",
"effect",
"model",
"persist",
"persist/file-adapter",
"rbac",
"rbac/default-role-manager",
"util"
]
revision = "d71629e497929858300c38cd442098c178121c30"
version = "v1.5.0"
[[projects]]
name = "github.com/coreos/dex"
packages = ["api"]
@@ -62,20 +84,10 @@
revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
version = "v3.2.0"
[[projects]]
name = "github.com/emicklei/go-restful"
packages = [
".",
"log"
]
revision = "26b41036311f2da8242db402557a0dbd09dc83da"
version = "v2.6.0"
[[projects]]
name = "github.com/ghodss/yaml"
packages = ["."]
revision = "0ca9ea5df5451ffdf184b4428c902747c2c11cd7"
version = "v1.0.0"
[[projects]]
branch = "master"
@@ -129,8 +141,8 @@
[[projects]]
name = "github.com/gobuffalo/packr"
packages = ["."]
revision = "6434a292ac52e6964adebfdce3f9ce6d9f16be01"
version = "v1.10.4"
revision = "7f4074995d431987caaa35088199f13c44b24440"
version = "v1.11.0"
[[projects]]
name = "github.com/gogo/protobuf"
@@ -188,12 +200,6 @@
]
revision = "e09c5db296004fbe3f74490e84dcd62c3c5ddb1b"
[[projects]]
branch = "master"
name = "github.com/google/btree"
packages = ["."]
revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
[[projects]]
name = "github.com/google/go-jsonnet"
packages = [
@@ -219,15 +225,6 @@
revision = "ee43cbb60db7bd22502942cccbc39059117352ab"
version = "v0.1.0"
[[projects]]
branch = "master"
name = "github.com/gregjones/httpcache"
packages = [
".",
"diskcache"
]
revision = "2bcd89a1743fd4b373f7370ce8ddc14dfbd18229"
[[projects]]
branch = "master"
name = "github.com/grpc-ecosystem/go-grpc-middleware"
@@ -286,12 +283,6 @@
revision = "e7c7f3b33712573affdcc7a107218e7926b9a05b"
version = "1.0.6"
[[projects]]
name = "github.com/juju/ratelimit"
packages = ["."]
revision = "59fac5042749a5afb9af70e813da1dd5474f0167"
version = "1.0.1"
[[projects]]
branch = "master"
name = "github.com/kardianos/osext"
@@ -306,6 +297,7 @@
"pkg/component",
"pkg/docparser",
"pkg/lib",
"pkg/log",
"pkg/node",
"pkg/params",
"pkg/prototype",
@@ -314,8 +306,8 @@
"pkg/util/kslib",
"pkg/util/strings"
]
revision = "8c44a5b1545d3d03135f610170ef0167129294bc"
version = "v0.10.1"
revision = "e943ae55d4fe256c8330a047ce8426ad9dac110c"
version = "v0.11.0"
[[projects]]
name = "github.com/ksonnet/ksonnet-lib"
@@ -328,8 +320,8 @@
"ksonnet-gen/nodemaker",
"ksonnet-gen/printer"
]
revision = "d15220fdcdd07fd377894abff6276d86cb2d776d"
version = "v0.1.3"
revision = "dfcaa3d01d0c4948cb596403c35e966c774f2678"
version = "v0.1.8"
[[projects]]
branch = "master"
@@ -347,18 +339,6 @@
revision = "a3647f8e31d79543b2d0f0ae2fe5c379d72cedc0"
version = "v2.1.0"
[[projects]]
branch = "master"
name = "github.com/petar/GoLLRB"
packages = ["llrb"]
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
[[projects]]
name = "github.com/peterbourgon/diskv"
packages = ["."]
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
version = "v2.0.1"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
@@ -380,6 +360,12 @@
]
revision = "525d0eb5f91d30e3b1548de401b7ef9ea6898520"
[[projects]]
branch = "master"
name = "github.com/qiangmzsx/string-adapter"
packages = ["."]
revision = "38f25303bb0cd40e674a6fac01e0171ab905f5a1"
[[projects]]
name = "github.com/sergi/go-diff"
packages = ["diffmatchpatch"]
@@ -389,8 +375,7 @@
[[projects]]
name = "github.com/sirupsen/logrus"
packages = ["."]
revision = "c155da19408a8799da419ed3eeb0cb5db0ad5dbc"
version = "v1.0.5"
revision = "ea8897e79973357ba785ac2533559a6297e83c44"
[[projects]]
branch = "master"
@@ -538,6 +523,12 @@
]
revision = "4e4a3210bb54bb31f6ab2cdca2edcc0b50c420c1"
[[projects]]
branch = "master"
name = "golang.org/x/time"
packages = ["rate"]
revision = "fbb02b2291d28baffd63558aa44b4b56f178d650"
[[projects]]
branch = "master"
name = "golang.org/x/tools"
@@ -639,7 +630,7 @@
revision = "eb3733d160e74a9c7e442f435eb3bea458e1d19f"
[[projects]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/api"
packages = [
"admission/v1beta1",
@@ -673,10 +664,10 @@
"storage/v1alpha1",
"storage/v1beta1"
]
revision = "acf347b865f29325eb61f4cd2df11e86e073a5ee"
revision = "8b7507fac302640dd5f1efbf9643199952cc58db"
[[projects]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/apiextensions-apiserver"
packages = [
"pkg/apis/apiextensions",
@@ -685,10 +676,10 @@
"pkg/client/clientset/clientset/scheme",
"pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
]
revision = "b89f5ce12ce6e022fc3e9d7586d61346e694d56e"
revision = "b13a681559816a9c14f93086bbeeed1c7baf2bcb"
[[projects]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/apimachinery"
packages = [
"pkg/api/equality",
@@ -701,7 +692,7 @@
"pkg/apis/meta/internalversion",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
"pkg/apis/meta/v1alpha1",
"pkg/apis/meta/v1beta1",
"pkg/conversion",
"pkg/conversion/queryparams",
"pkg/fields",
@@ -737,16 +728,56 @@
"third_party/forked/golang/json",
"third_party/forked/golang/reflect"
]
revision = "19e3f5aa3adca672c153d324e6b7d82ff8935f03"
revision = "f6313580a4d36c7c74a3d845dda6e116642c4f90"
[[projects]]
branch = "release-6.0"
branch = "release-7.0"
name = "k8s.io/client-go"
packages = [
"discovery",
"discovery/fake",
"dynamic",
"dynamic/fake",
"informers",
"informers/admissionregistration",
"informers/admissionregistration/v1alpha1",
"informers/admissionregistration/v1beta1",
"informers/apps",
"informers/apps/v1",
"informers/apps/v1beta1",
"informers/apps/v1beta2",
"informers/autoscaling",
"informers/autoscaling/v1",
"informers/autoscaling/v2beta1",
"informers/batch",
"informers/batch/v1",
"informers/batch/v1beta1",
"informers/batch/v2alpha1",
"informers/certificates",
"informers/certificates/v1beta1",
"informers/core",
"informers/core/v1",
"informers/events",
"informers/events/v1beta1",
"informers/extensions",
"informers/extensions/v1beta1",
"informers/internalinterfaces",
"informers/networking",
"informers/networking/v1",
"informers/policy",
"informers/policy/v1beta1",
"informers/rbac",
"informers/rbac/v1",
"informers/rbac/v1alpha1",
"informers/rbac/v1beta1",
"informers/scheduling",
"informers/scheduling/v1alpha1",
"informers/settings",
"informers/settings/v1alpha1",
"informers/storage",
"informers/storage/v1",
"informers/storage/v1alpha1",
"informers/storage/v1beta1",
"kubernetes",
"kubernetes/fake",
"kubernetes/scheme",
@@ -806,7 +837,34 @@
"kubernetes/typed/storage/v1alpha1/fake",
"kubernetes/typed/storage/v1beta1",
"kubernetes/typed/storage/v1beta1/fake",
"listers/admissionregistration/v1alpha1",
"listers/admissionregistration/v1beta1",
"listers/apps/v1",
"listers/apps/v1beta1",
"listers/apps/v1beta2",
"listers/autoscaling/v1",
"listers/autoscaling/v2beta1",
"listers/batch/v1",
"listers/batch/v1beta1",
"listers/batch/v2alpha1",
"listers/certificates/v1beta1",
"listers/core/v1",
"listers/events/v1beta1",
"listers/extensions/v1beta1",
"listers/networking/v1",
"listers/policy/v1beta1",
"listers/rbac/v1",
"listers/rbac/v1alpha1",
"listers/rbac/v1beta1",
"listers/scheduling/v1alpha1",
"listers/settings/v1alpha1",
"listers/storage/v1",
"listers/storage/v1alpha1",
"listers/storage/v1beta1",
"pkg/apis/clientauthentication",
"pkg/apis/clientauthentication/v1alpha1",
"pkg/version",
"plugin/pkg/client/auth/exec",
"plugin/pkg/client/auth/gcp",
"plugin/pkg/client/auth/oidc",
"rest",
@@ -829,19 +887,21 @@
"util/homedir",
"util/integer",
"util/jsonpath",
"util/retry",
"util/workqueue"
]
revision = "9389c055a838d4f208b699b3c7c51b70f2368861"
revision = "26a26f55b28aa1b338fbaf6fbbe0bcd76aed05e0"
[[projects]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/code-generator"
packages = [
"cmd/go-to-protobuf",
"cmd/go-to-protobuf/protobuf",
"pkg/util",
"third_party/forked/golang/reflect"
]
revision = "91d3f6a57905178524105a085085901bb73bd3dc"
revision = "9de8e796a74d16d2a285165727d04c185ebca6dc"
[[projects]]
branch = "master"
@@ -858,10 +918,7 @@
[[projects]]
branch = "master"
name = "k8s.io/kube-openapi"
packages = [
"pkg/common",
"pkg/util/proto"
]
packages = ["pkg/util/proto"]
revision = "50ae88d24ede7b8bad68e23c805b5d3da5c8abaf"
[[projects]]
@@ -876,6 +933,6 @@
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "736e8116bcf49bf0889c2caf8e832a78a43fd5af65c5d10c86a443993de63d3c"
inputs-digest = "f2d179e0bbae6ede81f78cf6b0b16cb09fbeb5e97add78bdd97e3051238b86da"
solver-name = "gps-cdcl"
solver-version = 1

View File

@@ -13,25 +13,20 @@ required = [
name = "github.com/grpc-ecosystem/grpc-gateway"
version = "v1.3.1"
# override ksonnet's release-1.8 dependency
[[override]]
branch = "release-1.9"
name = "k8s.io/apimachinery"
[[constraint]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/api"
[[constraint]]
name = "k8s.io/apiextensions-apiserver"
branch = "release-1.9"
branch = "release-1.10"
[[constraint]]
branch = "release-1.9"
branch = "release-1.10"
name = "k8s.io/code-generator"
[[constraint]]
branch = "release-6.0"
branch = "release-7.0"
name = "k8s.io/client-go"
[[constraint]]
@@ -40,9 +35,13 @@ required = [
[[constraint]]
name = "github.com/ksonnet/ksonnet"
version = "v0.10.1"
version = "v0.11.0"
[[constraint]]
name = "github.com/gobuffalo/packr"
version = "v1.11.0"
# override ksonnet's logrus dependency
[[override]]
name = "github.com/sirupsen/logrus"
version = "v1.0.3"
revision = "ea8897e79973357ba785ac2533559a6297e83c44"

View File

@@ -57,30 +57,30 @@ codegen: protogen clientgen
# NOTE: we use packr to do the build instead of go, since we embed .yaml files into the go binary.
# This enables ease of maintenance of the yaml files.
.PHONY: cli
cli:
cli: clean-debug
CGO_ENABLED=0 ${PACKR_CMD} build -v -i -ldflags '${LDFLAGS} -extldflags "-static"' -o ${DIST_DIR}/${CLI_NAME} ./cmd/argocd
.PHONY: cli-linux
cli-linux:
cli-linux: clean-debug
docker build --iidfile /tmp/argocd-linux-id --target builder --build-arg MAKE_TARGET="cli IMAGE_TAG=$(IMAGE_TAG) IMAGE_NAMESPACE=$(IMAGE_NAMESPACE) CLI_NAME=argocd-linux-amd64" -f Dockerfile-argocd .
docker create --name tmp-argocd-linux `cat /tmp/argocd-linux-id`
docker cp tmp-argocd-linux:/root/go/src/github.com/argoproj/argo-cd/dist/argocd-linux-amd64 dist/
docker rm tmp-argocd-linux
.PHONY: cli-darwin
cli-darwin:
cli-darwin: clean-debug
docker build --iidfile /tmp/argocd-darwin-id --target builder --build-arg MAKE_TARGET="cli GOOS=darwin IMAGE_TAG=$(IMAGE_TAG) IMAGE_NAMESPACE=$(IMAGE_NAMESPACE) CLI_NAME=argocd-darwin-amd64" -f Dockerfile-argocd .
docker create --name tmp-argocd-darwin `cat /tmp/argocd-darwin-id`
docker cp tmp-argocd-darwin:/root/go/src/github.com/argoproj/argo-cd/dist/argocd-darwin-amd64 dist/
docker rm tmp-argocd-darwin
.PHONY: argocd-util
argocd-util:
argocd-util: clean-debug
CGO_ENABLED=0 go build -v -i -ldflags '${LDFLAGS} -extldflags "-static"' -o ${DIST_DIR}/argocd-util ./cmd/argocd-util
.PHONY: server
server:
CGO_ENABLED=0 go build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-server ./cmd/argocd-server
server: clean-debug
CGO_ENABLED=0 ${PACKR_CMD} build -v -i -ldflags '${LDFLAGS}' -o ${DIST_DIR}/argocd-server ./cmd/argocd-server
.PHONY: server-image
server-image:
@@ -126,8 +126,13 @@ test:
test-e2e:
go test ./test/e2e
# Cleans VSCode debug.test files from sub-dirs to prevent them from being included in packr boxes
.PHONY: clean-debug
clean-debug:
-find ${CURRENT_DIR} -name debug.test | xargs rm -f
.PHONY: clean
clean:
clean: clean-debug
-rm -rf ${CURRENT_DIR}/dist
.PHONY: precheckin

View File

@@ -1,5 +1,5 @@
controller: go run ./cmd/argocd-application-controller/main.go --app-resync 10
controller: go run ./cmd/argocd-application-controller/main.go --app-resync 60
api-server: go run ./cmd/argocd-server/main.go --insecure --disable-auth
repo-server: go run ./cmd/argocd-repo-server/main.go --loglevel debug
dex: sh -c "go run ./cmd/argocd-util/main.go gendexcfg -o `pwd`/dist/dex.yaml && docker run --rm -p 5556:5556 -p 5557:5557 -v `pwd`/dist/dex.yaml:/dex.yaml quay.io/coreos/dex:v2.10.0 serve /dex.yaml"
redis: docker run --rm -p 6379:6379 redis:3.2.11
redis: docker run --rm -p 6379:6379 redis:3.2.11

View File

@@ -1 +1 @@
0.4.5
0.5.4

View File

@@ -22,6 +22,7 @@ import (
// load the gcp plugin (required to authenticate against GKE clusters).
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
// load the oidc plugin (required to authenticate with OpenID Connect).
"github.com/argoproj/argo-cd/reposerver"
_ "k8s.io/client-go/plugin/pkg/client/auth/oidc"
)
@@ -72,7 +73,8 @@ func newCommand() *cobra.Command {
}
db := db.NewDB(namespace, kubeClient)
resyncDuration := time.Duration(appResyncPeriod) * time.Second
appStateManager := controller.NewAppStateManager(db, appClient, reposerver.NewRepositoryServerClientset(repoServerAddress), namespace)
repoClientset := reposerver.NewRepositoryServerClientset(repoServerAddress)
appStateManager := controller.NewAppStateManager(db, appClient, repoClientset, namespace)
appHealthManager := controller.NewAppHealthManager(db, namespace)
appController := controller.NewApplicationController(
@@ -84,11 +86,14 @@ func newCommand() *cobra.Command {
appHealthManager,
resyncDuration,
&controllerConfig)
secretController := controller.NewSecretController(kubeClient, repoClientset, resyncDuration, namespace)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
log.Infof("Application Controller (version: %s) starting (namespace: %s)", argocd.GetVersion(), namespace)
go secretController.Run(ctx)
go appController.Run(ctx, statusProcessors, operationProcessors)
// Wait forever
select {}

View File

@@ -2,6 +2,8 @@ package commands
import (
"context"
"flag"
"strconv"
"github.com/argoproj/argo-cd/errors"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
@@ -19,6 +21,7 @@ func NewCommand() *cobra.Command {
var (
insecure bool
logLevel string
glogLevel int
clientConfig clientcmd.ClientConfig
staticAssetsDir string
repoServerAddress string
@@ -33,6 +36,11 @@ func NewCommand() *cobra.Command {
errors.CheckError(err)
log.SetLevel(level)
// Set the glog level for the k8s go-client
_ = flag.CommandLine.Parse([]string{})
_ = flag.Lookup("logtostderr").Value.Set("true")
_ = flag.Lookup("v").Value.Set(strconv.Itoa(glogLevel))
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
@@ -52,9 +60,9 @@ func NewCommand() *cobra.Command {
RepoClientset: repoclientset,
DisableAuth: disableAuth,
}
argocd := server.NewServer(argoCDOpts)
for {
argocd := server.NewServer(argoCDOpts)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
argocd.Run(ctx, 8080)
@@ -67,6 +75,7 @@ func NewCommand() *cobra.Command {
command.Flags().BoolVar(&insecure, "insecure", false, "Run server without TLS")
command.Flags().StringVar(&staticAssetsDir, "staticassets", "", "Static assets directory path")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level")
command.Flags().StringVar(&repoServerAddress, "repo-server", "localhost:8081", "Repo server address.")
command.Flags().BoolVar(&disableAuth, "disable-auth", false, "Disable client authentication")
command.AddCommand(cli.NewVersionCmd(cliName))

View File

@@ -6,14 +6,20 @@ import (
"io/ioutil"
"os"
"os/exec"
"strings"
"syscall"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/dex"
"github.com/argoproj/argo-cd/util/settings"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
@@ -26,6 +32,9 @@ import (
const (
// CLIName is the name of the CLI
cliName = "argocd-util"
// YamlSeparator separates sections of a YAML file
yamlSeparator = "\n---\n"
)
// NewCommand returns a new instance of an argocd command
@@ -45,6 +54,8 @@ func NewCommand() *cobra.Command {
command.AddCommand(cli.NewVersionCmd(cliName))
command.AddCommand(NewRunDexCommand())
command.AddCommand(NewGenDexConfigCommand())
command.AddCommand(NewImportCommand())
command.AddCommand(NewExportCommand())
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
return command
@@ -154,6 +165,168 @@ func NewGenDexConfigCommand() *cobra.Command {
return &command
}
// NewImportCommand defines a new command for exporting Kubernetes and Argo CD resources.
func NewImportCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
)
var command = cobra.Command{
Use: "import SOURCE",
Short: "Import Argo CD data from stdin (specify `-') or a file",
RunE: func(c *cobra.Command, args []string) error {
if len(args) != 1 {
c.HelpFunc()(c, args)
os.Exit(1)
}
var (
input []byte
err error
newSettings *settings.ArgoCDSettings
newRepos []*v1alpha1.Repository
newClusters []*v1alpha1.Cluster
newApps []*v1alpha1.Application
)
if in := args[0]; in == "-" {
input, err = ioutil.ReadAll(os.Stdin)
errors.CheckError(err)
} else {
input, err = ioutil.ReadFile(in)
errors.CheckError(err)
}
inputStrings := strings.Split(string(input), yamlSeparator)
err = yaml.Unmarshal([]byte(inputStrings[0]), &newSettings)
errors.CheckError(err)
err = yaml.Unmarshal([]byte(inputStrings[1]), &newRepos)
errors.CheckError(err)
err = yaml.Unmarshal([]byte(inputStrings[2]), &newClusters)
errors.CheckError(err)
err = yaml.Unmarshal([]byte(inputStrings[3]), &newApps)
errors.CheckError(err)
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
namespace, _, err := clientConfig.Namespace()
errors.CheckError(err)
kubeClientset := kubernetes.NewForConfigOrDie(config)
settingsMgr := settings.NewSettingsManager(kubeClientset, namespace)
err = settingsMgr.SaveSettings(newSettings)
errors.CheckError(err)
db := db.NewDB(namespace, kubeClientset)
for _, repo := range newRepos {
_, err := db.CreateRepository(context.Background(), repo)
if err != nil {
log.Warn(err)
}
}
for _, cluster := range newClusters {
_, err := db.CreateCluster(context.Background(), cluster)
if err != nil {
log.Warn(err)
}
}
appClientset := appclientset.NewForConfigOrDie(config)
for _, app := range newApps {
out, err := appClientset.ArgoprojV1alpha1().Applications(namespace).Create(app)
errors.CheckError(err)
log.Println(out)
}
return nil
},
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
return &command
}
// NewExportCommand defines a new command for exporting Kubernetes and Argo CD resources.
func NewExportCommand() *cobra.Command {
var (
clientConfig clientcmd.ClientConfig
out string
)
var command = cobra.Command{
Use: "export",
Short: "Export all Argo CD data to stdout (default) or a file",
RunE: func(c *cobra.Command, args []string) error {
config, err := clientConfig.ClientConfig()
errors.CheckError(err)
namespace, _, err := clientConfig.Namespace()
errors.CheckError(err)
kubeClientset := kubernetes.NewForConfigOrDie(config)
settingsMgr := settings.NewSettingsManager(kubeClientset, namespace)
settings, err := settingsMgr.GetSettings()
errors.CheckError(err)
// certificate data is included in secrets that are exported alongside
settings.Certificate = nil
settingsData, err := yaml.Marshal(settings)
errors.CheckError(err)
db := db.NewDB(namespace, kubeClientset)
clusters, err := db.ListClusters(context.Background())
errors.CheckError(err)
clusterData, err := yaml.Marshal(clusters.Items)
errors.CheckError(err)
repos, err := db.ListRepositories(context.Background())
errors.CheckError(err)
repoData, err := yaml.Marshal(repos.Items)
errors.CheckError(err)
appClientset := appclientset.NewForConfigOrDie(config)
apps, err := appClientset.ArgoprojV1alpha1().Applications(namespace).List(metav1.ListOptions{})
errors.CheckError(err)
// remove extraneous cruft from output
for idx, app := range apps.Items {
apps.Items[idx].ObjectMeta = metav1.ObjectMeta{
Name: app.ObjectMeta.Name,
Finalizers: app.ObjectMeta.Finalizers,
}
apps.Items[idx].Status = v1alpha1.ApplicationStatus{
History: app.Status.History,
}
apps.Items[idx].Operation = nil
}
appsData, err := yaml.Marshal(apps.Items)
errors.CheckError(err)
outputStrings := []string{
string(settingsData),
string(repoData),
string(clusterData),
string(appsData),
}
output := strings.Join(outputStrings, yamlSeparator)
if out == "-" {
fmt.Println(output)
} else {
err = ioutil.WriteFile(out, []byte(output), 0644)
errors.CheckError(err)
}
return nil
},
}
clientConfig = cli.AddKubectlFlagsToCmd(&command)
command.Flags().StringVarP(&out, "out", "o", "-", "Output to the specified file instead of stdout")
return &command
}
func main() {
if err := NewCommand().Execute(); err != nil {
fmt.Println(err)

View File

@@ -2,13 +2,28 @@ package commands
import (
"context"
"encoding/json"
"fmt"
"io"
"net/url"
"os"
"strconv"
"strings"
"text/tabwriter"
"time"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/yudai/gojsondiff/formatter"
"golang.org/x/crypto/ssh/terminal"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
argocdclient "github.com/argoproj/argo-cd/pkg/apiclient"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -16,13 +31,8 @@ import (
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/diff"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/yudai/gojsondiff/formatter"
"golang.org/x/crypto/ssh/terminal"
"google.golang.org/grpc/metadata"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/argoproj/argo-cd/util/ksonnet"
kubeutil "github.com/argoproj/argo-cd/util/kube"
)
// NewApplicationCommand returns a new instance of an `argocd app` command
@@ -46,6 +56,7 @@ func NewApplicationCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
command.AddCommand(NewApplicationListCommand(clientOpts))
command.AddCommand(NewApplicationDeleteCommand(clientOpts))
command.AddCommand(NewApplicationWaitCommand(clientOpts))
command.AddCommand(NewApplicationManifestsCommand(clientOpts))
return command
}
@@ -105,8 +116,11 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
setParameterOverrides(&app, appOpts.parameters)
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
ctx := metadata.AppendToOutgoingContext(context.Background(), "upsert", strconv.FormatBool(upsert))
created, err := appIf.Create(ctx, &app)
appCreateRequest := application.ApplicationCreateRequest{
Application: app,
Upsert: &upsert,
}
created, err := appIf.Create(context.Background(), &appCreateRequest)
errors.CheckError(err)
fmt.Printf("application '%s' created\n", created.ObjectMeta.Name)
},
@@ -121,7 +135,10 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
// NewApplicationGetCommand returns a new instance of an `argocd app get` command
func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
showParams bool
output string
showParams bool
showOperation bool
refresh bool
)
var command = &cobra.Command{
Use: "get APPNAME",
@@ -135,41 +152,74 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
conn, appIf := acdClient.NewApplicationClientOrDie()
defer util.Close(conn)
appName := args[0]
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName})
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: refresh})
errors.CheckError(err)
format := "%-15s%s\n"
fmt.Printf(format, "Name:", app.Name)
fmt.Printf(format, "Server:", app.Spec.Destination.Server)
fmt.Printf(format, "Namespace:", app.Spec.Destination.Namespace)
fmt.Printf(format, "URL:", appURL(acdClient, app))
fmt.Printf(format, "Environment:", app.Spec.Source.Environment)
fmt.Printf(format, "Repo:", app.Spec.Source.RepoURL)
fmt.Printf(format, "Path:", app.Spec.Source.Path)
fmt.Printf(format, "Target:", app.Spec.Source.TargetRevision)
if app.Status.ComparisonResult.Error != "" {
fmt.Printf(format, "Error:", app.Status.ComparisonResult.Error)
}
if showParams {
printParams(app)
}
if len(app.Status.ComparisonResult.Resources) > 0 {
fmt.Println()
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "KIND\tNAME\tSTATUS\tHEALTH\n")
for _, res := range app.Status.ComparisonResult.Resources {
obj, err := argoappv1.UnmarshalToUnstructured(res.TargetState)
errors.CheckError(err)
if obj == nil {
obj, err = argoappv1.UnmarshalToUnstructured(res.LiveState)
errors.CheckError(err)
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", obj.GetKind(), obj.GetName(), res.Status, res.Health.Status)
switch output {
case "yaml":
yamlBytes, err := yaml.Marshal(app)
errors.CheckError(err)
fmt.Println(string(yamlBytes))
case "json":
jsonBytes, err := json.MarshalIndent(app, "", " ")
errors.CheckError(err)
fmt.Println(string(jsonBytes))
case "":
format := "%-15s%s\n"
fmt.Printf(format, "Name:", app.Name)
fmt.Printf(format, "Server:", app.Spec.Destination.Server)
fmt.Printf(format, "Namespace:", app.Spec.Destination.Namespace)
fmt.Printf(format, "URL:", appURL(acdClient, app))
fmt.Printf(format, "Environment:", app.Spec.Source.Environment)
fmt.Printf(format, "Repo:", app.Spec.Source.RepoURL)
fmt.Printf(format, "Path:", app.Spec.Source.Path)
fmt.Printf(format, "Target:", app.Spec.Source.TargetRevision)
if app.Status.ComparisonResult.Error != "" {
fmt.Printf(format, "Error:", app.Status.ComparisonResult.Error)
}
_ = w.Flush()
var opState *argoappv1.OperationState
if showOperation && app.Status.OperationState != nil {
opState = app.Status.OperationState
fmt.Println()
var opName string
if opState.SyncResult != nil {
opName = "Sync"
} else if opState.RollbackResult != nil {
opName = "Rollback"
}
fmt.Printf(format, "Operation:", opName)
fmt.Printf(format, " Phase:", opState.Phase)
fmt.Printf(format, " Start:", opState.StartedAt)
fmt.Printf(format, " Finished:", opState.FinishedAt)
var duration time.Duration
if !opState.FinishedAt.IsZero() {
duration = time.Second * time.Duration(opState.FinishedAt.Unix()-opState.StartedAt.Unix())
} else {
duration = time.Second * time.Duration(time.Now().UTC().Unix()-opState.StartedAt.Unix())
}
fmt.Printf(format, " Duration:", duration)
fmt.Printf(format, " Phase:", opState.Phase)
if opState.Message != "" {
fmt.Printf(format, " Message:", opState.Message)
}
}
if showParams {
printParams(app)
}
if len(app.Status.ComparisonResult.Resources) > 0 {
fmt.Println()
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
printAppResources(w, app, opState)
_ = w.Flush()
}
default:
log.Fatalf("Unknown output format: %s", output)
}
},
}
command.Flags().StringVarP(&output, "output", "o", "", "Output format. One of: yaml, json")
command.Flags().BoolVar(&showOperation, "show-operation", false, "Show application operation")
command.Flags().BoolVar(&showParams, "show-params", false, "Show application parameters and overrides")
command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
return command
}
@@ -259,9 +309,9 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
os.Exit(1)
}
setParameterOverrides(app, appOpts.parameters)
_, err = appIf.UpdateSpec(context.Background(), &application.ApplicationSpecRequest{
AppName: &app.Name,
Spec: app.Spec,
_, err = appIf.UpdateSpec(context.Background(), &application.ApplicationUpdateSpecRequest{
Name: &app.Name,
Spec: app.Spec,
})
errors.CheckError(err)
},
@@ -327,9 +377,9 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
if !updated {
return
}
_, err = appIf.UpdateSpec(context.Background(), &application.ApplicationSpecRequest{
AppName: &app.Name,
Spec: app.Spec,
_, err = appIf.UpdateSpec(context.Background(), &application.ApplicationUpdateSpecRequest{
Name: &app.Name,
Spec: app.Spec,
})
errors.CheckError(err)
},
@@ -340,6 +390,11 @@ func NewApplicationUnsetCommand(clientOpts *argocdclient.ClientOptions) *cobra.C
// NewApplicationDiffCommand returns a new instance of an `argocd app diff` command
func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
refresh bool
local string
env string
)
var command = &cobra.Command{
Use: "diff APPNAME",
Short: "Perform a diff against the target and live state",
@@ -351,32 +406,76 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
appName := args[0]
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName})
errors.CheckError(err)
targetObjs, err := app.Status.ComparisonResult.TargetObjects()
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: refresh})
errors.CheckError(err)
liveObjs, err := app.Status.ComparisonResult.LiveObjects()
errors.CheckError(err)
diffResults, err := diff.DiffArray(targetObjs, liveObjs)
var compareObjs []*unstructured.Unstructured
if local != "" {
if env == "" {
log.Fatal("--env required when performing local diff")
}
ksApp, err := ksonnet.NewKsonnetApp(local)
errors.CheckError(err)
compareObjs, err = ksApp.Show(env)
errors.CheckError(err)
if len(app.Spec.Source.ComponentParameterOverrides) > 0 {
log.Warnf("Unable to display parameter overrides")
}
compareObjs, liveObjs = diff.MatchObjectLists(compareObjs, liveObjs)
} else {
if env != "" {
log.Fatal("--env option invalid when performing git diff")
}
compareObjs, err = app.Status.ComparisonResult.TargetObjects()
errors.CheckError(err)
}
// In order for the diff to be clean, need to set our app labels
setAppLabels(appName, compareObjs)
diffResults, err := diff.DiffArray(compareObjs, liveObjs)
errors.CheckError(err)
for i := 0; i < len(targetObjs); i++ {
targetObj := targetObjs[i]
for i := 0; i < len(compareObjs); i++ {
kind, name := getObjKindName(compareObjs[i], liveObjs[i])
diffRes := diffResults.Diffs[i]
fmt.Printf("===== %s %s ======\n", targetObj.GetKind(), targetObj.GetName())
fmt.Printf("===== %s %s ======\n", kind, name)
if diffRes.Modified {
formatOpts := formatter.AsciiFormatterConfig{
Coloring: terminal.IsTerminal(int(os.Stdout.Fd())),
}
out, err := diffResults.Diffs[i].ASCIIFormat(targetObj, formatOpts)
out, err := diffResults.Diffs[i].ASCIIFormat(compareObjs[i], formatOpts)
errors.CheckError(err)
fmt.Println(out)
}
}
if local != "" && len(app.Spec.Source.ComponentParameterOverrides) > 0 {
log.Warnf("Unable to display parameter overrides")
}
},
}
command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
command.Flags().StringVar(&local, "local", "", "Compare live app to a local ksonnet app")
command.Flags().StringVar(&env, "env", "", "Compare live app to a specific environment")
return command
}
func getObjKindName(compare, live *unstructured.Unstructured) (string, string) {
if compare == nil {
return live.GetKind(), live.GetName()
}
return compare.GetKind(), compare.GetName()
}
func setAppLabels(appName string, compareObjs []*unstructured.Unstructured) {
for _, obj := range compareObjs {
if obj == nil {
continue
}
_ = kubeutil.SetLabel(obj, common.LabelApplicationName, appName)
}
}
// NewApplicationDeleteCommand returns a new instance of an `argocd app delete` command
func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
@@ -393,7 +492,7 @@ func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
for _, appName := range args {
appDeleteReq := application.DeleteApplicationRequest{
appDeleteReq := application.ApplicationDeleteRequest{
Name: &appName,
}
if c.Flag("cascade").Changed {
@@ -425,8 +524,8 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
var fmtStr string
headers := []interface{}{"NAME", "CLUSTER", "NAMESPACE", "STATUS", "HEALTH"}
if output == "wide" {
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
headers = append(headers, "ENV", "REPO", "TARGET")
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
headers = append(headers, "ENV", "REPO", "PATH", "TARGET")
} else {
fmtStr = "%s\t%s\t%s\t%s\t%s\n"
}
@@ -440,7 +539,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
app.Status.Health.Status,
}
if output == "wide" {
vals = append(vals, app.Spec.Source.Environment, app.Spec.Source.RepoURL, app.Spec.Source.TargetRevision)
vals = append(vals, app.Spec.Source.Environment, app.Spec.Source.RepoURL, app.Spec.Source.Path, app.Spec.Source.TargetRevision)
}
fmt.Fprintf(w, fmtStr, vals...)
}
@@ -470,51 +569,42 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
if syncOnly && healthOnly {
log.Fatalln("Please specify at most one of --sync-only or --health-only.")
}
appName := args[0]
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
appName := args[0]
wc, err := appIf.Watch(context.Background(), &application.ApplicationQuery{
Name: &appName,
})
errors.CheckError(err)
success := util.Wait(timeout, func(done chan<- bool) {
for {
appEvent, err := wc.Recv()
errors.CheckError(err)
app := appEvent.Application
healthStatus := app.Status.Health.Status
syncStatus := app.Status.ComparisonResult.Status
log.Printf("App %q has sync status %q and health status %q", appName, syncStatus, healthStatus)
synced := (syncStatus == argoappv1.ComparisonStatusSynced)
healthy := (healthStatus == argoappv1.HealthStatusHealthy)
if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) {
done <- true
}
}
})
if success {
log.Printf("App %q matches desired state", appName)
} else {
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName})
errors.CheckError(err)
if len(app.Status.ComparisonResult.Resources) > 0 {
for _, res := range app.Status.ComparisonResult.Resources {
targetObj, err := argoappv1.UnmarshalToUnstructured(res.TargetState)
errors.CheckError(err)
if res.Status != argoappv1.ComparisonStatusSynced || res.Health.Status != argoappv1.HealthStatusHealthy {
log.Warnf("%s %q has sync status %q and health status %q: %s", targetObj.GetKind(), targetObj.GetName(), res.Status, res.Health.Status, res.Health.StatusDetails)
}
}
}
log.Fatalf("Timed out before seeing app %q match desired state", appName)
if timeout != 0 {
time.AfterFunc(time.Duration(timeout)*time.Second, func() {
cancel()
})
}
// print the initial components to format the tabwriter columns
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName})
errors.CheckError(err)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
printAppResources(w, app, nil)
_ = w.Flush()
prevCompRes := &app.Status.ComparisonResult
appEventCh := watchApp(ctx, appIf, appName)
for appEvent := range appEventCh {
app := appEvent.Application
printAppStateChange(w, prevCompRes, &app)
_ = w.Flush()
prevCompRes = &app.Status.ComparisonResult
synced := (app.Status.ComparisonResult.Status == argoappv1.ComparisonStatusSynced)
healthy := (app.Status.Health.Status == argoappv1.HealthStatusHealthy)
if (synced && healthy) || (synced && syncOnly) || (healthy && healthOnly) {
log.Printf("App %q matches desired state", appName)
return
}
}
log.Fatalf("Timed out (%ds) waiting for app %q match desired state", timeout, appName)
},
}
command.Flags().BoolVar(&syncOnly, "sync-only", false, "Wait only for sync")
@@ -523,6 +613,121 @@ func NewApplicationWaitCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
return command
}
func isCanceledContextErr(err error) bool {
if err == context.Canceled {
return true
}
if stat, ok := status.FromError(err); ok {
if stat.Code() == codes.Canceled {
return true
}
}
return false
}
// watchApp returns a channel of watch events for an app, retrying the watch upon errors. Closes
// the returned channel when the context is discovered to be canceled.
func watchApp(ctx context.Context, appIf application.ApplicationServiceClient, appName string) chan *argoappv1.ApplicationWatchEvent {
appEventsCh := make(chan *argoappv1.ApplicationWatchEvent)
go func() {
defer close(appEventsCh)
for {
wc, err := appIf.Watch(ctx, &application.ApplicationQuery{
Name: &appName,
})
if err != nil {
if isCanceledContextErr(err) {
return
}
if err != io.EOF {
log.Warnf("watch err: %v", err)
}
time.Sleep(1 * time.Second)
continue
}
for {
appEvent, err := wc.Recv()
if err != nil {
if isCanceledContextErr(err) {
return
}
if err != io.EOF {
log.Warnf("recv err: %v", err)
}
time.Sleep(1 * time.Second)
break
} else {
appEventsCh <- appEvent
}
}
}
}()
return appEventsCh
}
// printAppResources prints the resources of an application in a tabwriter table
// Optionally prints the message from the operation state
func printAppResources(w io.Writer, app *argoappv1.Application, opState *argoappv1.OperationState) {
messages := make(map[string]string)
if opState != nil && opState.SyncResult != nil {
for _, resDetails := range opState.SyncResult.Resources {
messages[fmt.Sprintf("%s/%s", resDetails.Kind, resDetails.Name)] = resDetails.Message
}
}
if opState != nil {
fmt.Fprintf(w, "KIND\tNAME\tSTATUS\tHEALTH\tOPERATIONMSG\n")
} else {
fmt.Fprintf(w, "KIND\tNAME\tSTATUS\tHEALTH\n")
}
for _, res := range app.Status.ComparisonResult.Resources {
obj, err := argoappv1.UnmarshalToUnstructured(res.TargetState)
errors.CheckError(err)
if obj == nil {
obj, err = argoappv1.UnmarshalToUnstructured(res.LiveState)
errors.CheckError(err)
}
fmt.Fprintf(w, "%s\t%s\t%s\t%s", obj.GetKind(), obj.GetName(), res.Status, res.Health.Status)
if opState != nil {
message := messages[fmt.Sprintf("%s/%s", obj.GetKind(), obj.GetName())]
fmt.Fprintf(w, "\t%s", message)
}
fmt.Fprint(w, "\n")
}
}
// printAppStateChange prints a component state change if it was different from the last time we saw it
func printAppStateChange(w io.Writer, prevComp *argoappv1.ComparisonResult, app *argoappv1.Application) {
getPrevResState := func(kind, name string) (argoappv1.ComparisonStatus, argoappv1.HealthStatusCode) {
for _, res := range prevComp.Resources {
obj, err := argoappv1.UnmarshalToUnstructured(res.TargetState)
errors.CheckError(err)
if obj == nil {
obj, err = argoappv1.UnmarshalToUnstructured(res.LiveState)
errors.CheckError(err)
}
if obj.GetKind() == kind && obj.GetName() == name {
return res.Status, res.Health.Status
}
}
return "", ""
}
if len(app.Status.ComparisonResult.Resources) > 0 {
for _, res := range app.Status.ComparisonResult.Resources {
obj, err := argoappv1.UnmarshalToUnstructured(res.TargetState)
errors.CheckError(err)
if obj == nil {
obj, err = argoappv1.UnmarshalToUnstructured(res.LiveState)
errors.CheckError(err)
}
prevSync, prevHealth := getPrevResState(obj.GetKind(), obj.GetName())
if prevSync != res.Status || prevHealth != res.Health.Status {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", obj.GetKind(), obj.GetName(), res.Status, res.Health.Status)
}
}
}
}
// NewApplicationSyncCommand returns a new instance of an `argocd app sync` command
func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
@@ -551,8 +756,9 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
errors.CheckError(err)
status, err := waitUntilOperationCompleted(appIf, appName)
errors.CheckError(err)
printOperationResult(appName, status)
if !status.Phase.Successful() {
err = printOperationResult(appName, status)
errors.CheckError(err)
if !status.Phase.Successful() && !dryRun {
os.Exit(1)
}
},
@@ -701,7 +907,8 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr
status, err := waitUntilOperationCompleted(appIf, appName)
errors.CheckError(err)
printOperationResult(appName, status)
err = printOperationResult(appName, status)
errors.CheckError(err)
if !status.Phase.Successful() {
os.Exit(1)
}
@@ -713,7 +920,7 @@ func NewApplicationRollbackCommand(clientOpts *argocdclient.ClientOptions) *cobr
const printOpFmtStr = "%-20s%s\n"
func printOperationResult(appName string, opState *argoappv1.OperationState) {
func printOperationResult(appName string, opState *argoappv1.OperationState) error {
fmt.Printf(printOpFmtStr, "Application:", appName)
var syncRes *argoappv1.SyncOperationResult
if opState.SyncResult != nil {
@@ -731,9 +938,79 @@ func printOperationResult(appName string, opState *argoappv1.OperationState) {
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Printf("\n")
fmt.Fprintf(w, "KIND\tNAME\tMESSAGE\n")
pruningRequired := 0
for _, resDetails := range syncRes.Resources {
fmt.Fprintf(w, "%s\t%s\t%s\n", resDetails.Kind, resDetails.Name, resDetails.Message)
if resDetails.Status == argoappv1.ResourceDetailsPruningRequired {
pruningRequired++
}
}
_ = w.Flush()
if pruningRequired > 0 {
return fmt.Errorf("Some resources (%d) require pruning", pruningRequired)
}
}
return nil
}
// NewApplicationManifestsCommand returns a new instance of an `argocd app manifests` command
func NewApplicationManifestsCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
source string
revision string
)
var command = &cobra.Command{
Use: "manifests APPNAME",
Short: "Print manifests of an application",
Run: func(c *cobra.Command, args []string) {
if len(args) != 1 {
c.HelpFunc()(c, args)
os.Exit(1)
}
appName := args[0]
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
ctx := context.Background()
app, err := appIf.Get(ctx, &application.ApplicationQuery{Name: &appName})
errors.CheckError(err)
var unstructureds []*unstructured.Unstructured
switch source {
case "git":
if revision != "" {
q := application.ApplicationManifestQuery{
Name: &appName,
Revision: revision,
}
res, err := appIf.GetManifests(ctx, &q)
errors.CheckError(err)
for _, mfst := range res.Manifests {
obj, err := argoappv1.UnmarshalToUnstructured(mfst)
errors.CheckError(err)
unstructureds = append(unstructureds, obj)
}
} else {
targetObjs, err := app.Status.ComparisonResult.TargetObjects()
errors.CheckError(err)
unstructureds = targetObjs
}
case "live":
liveObjs, err := app.Status.ComparisonResult.LiveObjects()
errors.CheckError(err)
unstructureds = liveObjs
default:
log.Fatalf("Unknown source type '%s'", source)
}
for _, obj := range unstructureds {
fmt.Println("---")
yamlBytes, err := yaml.Marshal(obj)
errors.CheckError(err)
fmt.Printf("%s\n", yamlBytes)
}
},
}
command.Flags().StringVar(&source, "source", "git", "Source of manifests. One of: live|git")
command.Flags().StringVar(&revision, "revision", "", "Show manifests at a specific revision")
return command
}

View File

@@ -42,6 +42,9 @@ func NewClusterCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clientc
// NewClusterAddCommand returns a new instance of an `argocd cluster add` command
func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clientcmd.PathOptions) *cobra.Command {
var (
inCluster bool
)
var command = &cobra.Command{
Use: "add",
Short: fmt.Sprintf("%s cluster add CONTEXT", cliName),
@@ -71,12 +74,17 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
defer util.Close(conn)
clst := NewCluster(args[0], conf, managerBearerToken)
clst, err = clusterIf.Create(context.Background(), clst)
if inCluster {
clst.Server = common.KubernetesInternalAPIServerAddr
}
clstCreateReq := cluster.ClusterCreateRequest{Cluster: clst}
clst, err = clusterIf.Create(context.Background(), &clstCreateReq)
errors.CheckError(err)
fmt.Printf("Cluster '%s' added\n", clst.Name)
},
}
command.PersistentFlags().StringVar(&pathOpts.LoadingRules.ExplicitPath, pathOpts.ExplicitFileFlag, pathOpts.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
command.Flags().BoolVar(&inCluster, "in-cluster", false, "Indicates ArgoCD resides inside this cluster and should connect using the internal k8s hostname (kubernetes.default.svc)")
return command
}
@@ -200,9 +208,9 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
clusters, err := clusterIf.List(context.Background(), &cluster.ClusterQuery{})
errors.CheckError(err)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "SERVER\tNAME\tMESSAGE\n")
fmt.Fprintf(w, "SERVER\tNAME\tSTATUS\tMESSAGE\n")
for _, c := range clusters.Items {
fmt.Fprintf(w, "%s\t%s\t%s\n", c.Server, c.Name, c.Message)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", c.Server, c.Name, c.ConnectionState.Status, c.ConnectionState.Message)
}
_ = w.Flush()
},

View File

@@ -70,7 +70,8 @@ func NewRepoAddCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
errors.CheckError(err)
conn, repoIf := argocdclient.NewClientOrDie(clientOpts).NewRepoClientOrDie()
defer util.Close(conn)
createdRepo, err := repoIf.Create(context.Background(), &repo)
repoCreateReq := repository.RepoCreateRequest{Repo: &repo}
createdRepo, err := repoIf.Create(context.Background(), &repoCreateReq)
errors.CheckError(err)
fmt.Printf("repository '%s' added\n", createdRepo.Repo)
},
@@ -113,9 +114,9 @@ func NewRepoListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
repos, err := repoIf.List(context.Background(), &repository.RepoQuery{})
errors.CheckError(err)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
fmt.Fprintf(w, "REPO\tUSER\tMESSAGE\n")
fmt.Fprintf(w, "REPO\tUSER\tSTATUS\tMESSAGE\n")
for _, r := range repos.Items {
fmt.Fprintf(w, "%s\t%s\t%s\n", r.Repo, r.Username, r.Message)
fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", r.Repo, r.Username, r.ConnectionState.Status, r.ConnectionState.Message)
}
_ = w.Flush()
},

View File

@@ -1,8 +1,9 @@
package common
import (
"github.com/argoproj/argo-cd/pkg/apis/application"
rbacv1 "k8s.io/api/rbac/v1"
"github.com/argoproj/argo-cd/pkg/apis/application"
)
const (
@@ -19,12 +20,16 @@ const (
AuthCookieName = "argocd.token"
// ResourcesFinalizerName is a number of application CRD finalizer
ResourcesFinalizerName = "resources-finalizer." + MetadataPrefix
// KubernetesInternalAPIServerAddr is address of the k8s API server when accessing internal to the cluster
KubernetesInternalAPIServerAddr = "https://kubernetes.default.svc"
)
const (
ArgoCDAdminUsername = "admin"
ArgoCDSecretName = "argocd-secret"
ArgoCDConfigMapName = "argocd-cm"
ArgoCDAdminUsername = "admin"
ArgoCDSecretName = "argocd-secret"
ArgoCDConfigMapName = "argocd-cm"
ArgoCDRBACConfigMapName = "argocd-rbac-cm"
)
const (
@@ -44,6 +49,8 @@ const (
ArgoCDCLIClientAppID = "argo-cd-cli"
// EnvVarSSODebug is an environment variable to enable additional OAuth debugging in the API server
EnvVarSSODebug = "ARGOCD_SSO_DEBUG"
// EnvVarRBACDebug is an environment variable to enable additional RBAC debugging in the API server
EnvVarRBACDebug = "ARGOCD_RBAC_DEBUG"
)
var (
@@ -53,6 +60,13 @@ var (
// LabelKeySecretType contains the type of argocd secret (either 'cluster' or 'repo')
LabelKeySecretType = MetadataPrefix + "/secret-type"
// AnnotationConnectionStatus contains connection state status
AnnotationConnectionStatus = MetadataPrefix + "/connection-status"
// AnnotationConnectionMessage contains additional information about connection status
AnnotationConnectionMessage = MetadataPrefix + "/connection-message"
// AnnotationConnectionModifiedAt contains timestamp when connection state had been modified
AnnotationConnectionModifiedAt = MetadataPrefix + "/connection-modified-at"
// LabelKeyApplicationControllerInstanceID is the label which allows to separate application among multiple running application controllers.
LabelKeyApplicationControllerInstanceID = application.ApplicationFullName + "/controller-instanceid"

View File

@@ -155,7 +155,7 @@ func (ctrl *ApplicationController) watchClusterResources(ctx context.Context, it
}
// watchAppsResources watches for resource changes annotated with application label on all registered clusters and schedule corresponding app refresh.
// WatchAppsResources watches for resource changes annotated with application label on all registered clusters and schedule corresponding app refresh.
func (ctrl *ApplicationController) watchAppsResources() {
watchingClusters := make(map[string]context.CancelFunc)

View File

@@ -60,30 +60,54 @@ func (ctrl *kubeAppHealthManager) getDeploymentHealth(config *rest.Config, names
if err != nil {
return nil, err
}
deploy, err := clientSet.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
deployment, err := clientSet.AppsV1().Deployments(namespace).Get(name, metav1.GetOptions{})
if err != nil {
return nil, err
}
health := appv1.HealthStatus{
Status: appv1.HealthStatusUnknown,
}
for _, condition := range deploy.Status.Conditions {
// deployment is healthy is it successfully progressed
if condition.Type == v1.DeploymentProgressing && condition.Status == "True" {
health.Status = appv1.HealthStatusHealthy
} else if condition.Type == v1.DeploymentReplicaFailure && condition.Status == "True" {
health.Status = appv1.HealthStatusDegraded
} else if condition.Type == v1.DeploymentProgressing && condition.Status == "False" {
health.Status = appv1.HealthStatusDegraded
} else if condition.Type == v1.DeploymentAvailable && condition.Status == "False" {
health.Status = appv1.HealthStatusDegraded
if deployment.Generation <= deployment.Status.ObservedGeneration {
cond := getDeploymentCondition(deployment.Status, v1.DeploymentProgressing)
if cond != nil && cond.Reason == "ProgressDeadlineExceeded" {
return &appv1.HealthStatus{
Status: appv1.HealthStatusDegraded,
StatusDetails: fmt.Sprintf("Deployment %q exceeded its progress deadline", name),
}, nil
} else if deployment.Spec.Replicas != nil && deployment.Status.UpdatedReplicas < *deployment.Spec.Replicas {
return &appv1.HealthStatus{
Status: appv1.HealthStatusProgressing,
StatusDetails: fmt.Sprintf("Waiting for rollout to finish: %d out of %d new replicas have been updated...\n", deployment.Status.UpdatedReplicas, *deployment.Spec.Replicas),
}, nil
} else if deployment.Status.Replicas > deployment.Status.UpdatedReplicas {
return &appv1.HealthStatus{
Status: appv1.HealthStatusProgressing,
StatusDetails: fmt.Sprintf("Waiting for rollout to finish: %d old replicas are pending termination...\n", deployment.Status.Replicas-deployment.Status.UpdatedReplicas),
}, nil
} else if deployment.Status.AvailableReplicas < deployment.Status.UpdatedReplicas {
return &appv1.HealthStatus{
Status: appv1.HealthStatusProgressing,
StatusDetails: fmt.Sprintf("Waiting for rollout to finish: %d of %d updated replicas are available...\n", deployment.Status.AvailableReplicas, deployment.Status.UpdatedReplicas),
}, nil
}
if health.Status != appv1.HealthStatusUnknown {
health.StatusDetails = fmt.Sprintf("%s:%s", condition.Reason, condition.Message)
break
} else {
return &appv1.HealthStatus{
Status: appv1.HealthStatusProgressing,
StatusDetails: "Waiting for rollout to finish: observed deployment generation less then desired generation",
}, nil
}
return &appv1.HealthStatus{
Status: appv1.HealthStatusHealthy,
}, nil
}
func getDeploymentCondition(status v1.DeploymentStatus, condType v1.DeploymentConditionType) *v1.DeploymentCondition {
for i := range status.Conditions {
c := status.Conditions[i]
if c.Type == condType {
return &c
}
}
return &health, nil
return nil
}
func (ctrl *kubeAppHealthManager) GetAppHealth(server string, namespace string, comparisonResult *appv1.ComparisonResult) (*appv1.HealthStatus, error) {

View File

@@ -0,0 +1,205 @@
package controller
import (
"context"
"encoding/json"
"time"
"runtime/debug"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/reposerver"
"github.com/argoproj/argo-cd/reposerver/repository"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/db"
log "github.com/sirupsen/logrus"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/selection"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/informers"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
)
type SecretController struct {
kubeClient kubernetes.Interface
secretQueue workqueue.RateLimitingInterface
secretInformer cache.SharedIndexInformer
repoClientset reposerver.Clientset
namespace string
}
func (ctrl *SecretController) Run(ctx context.Context) {
go ctrl.secretInformer.Run(ctx.Done())
if !cache.WaitForCacheSync(ctx.Done(), ctrl.secretInformer.HasSynced) {
log.Error("Timed out waiting for caches to sync")
return
}
go wait.Until(func() {
for ctrl.processSecret() {
}
}, time.Second, ctx.Done())
}
func (ctrl *SecretController) processSecret() (processNext bool) {
secretKey, shutdown := ctrl.secretQueue.Get()
if shutdown {
processNext = false
return
} else {
processNext = true
}
defer func() {
if r := recover(); r != nil {
log.Errorf("Recovered from panic: %+v\n%s", r, debug.Stack())
}
ctrl.secretQueue.Done(secretKey)
}()
obj, exists, err := ctrl.secretInformer.GetIndexer().GetByKey(secretKey.(string))
if err != nil {
log.Errorf("Failed to get secret '%s' from informer index: %+v", secretKey, err)
return
}
if !exists {
// This happens after secret was deleted, but the work queue still had an entry for it.
return
}
secret, ok := obj.(*corev1.Secret)
if !ok {
log.Warnf("Key '%s' in index is not an secret", secretKey)
return
}
if secret.Labels[common.LabelKeySecretType] == common.SecretTypeCluster {
cluster := db.SecretToCluster(secret)
ctrl.updateState(secret, ctrl.getClusterState(cluster))
} else if secret.Labels[common.LabelKeySecretType] == common.SecretTypeRepository {
repo := db.SecretToRepo(secret)
ctrl.updateState(secret, ctrl.getRepoConnectionState(repo))
}
return
}
func (ctrl *SecretController) getRepoConnectionState(repo *v1alpha1.Repository) v1alpha1.ConnectionState {
state := v1alpha1.ConnectionState{
ModifiedAt: repo.ConnectionState.ModifiedAt,
Status: v1alpha1.ConnectionStatusUnknown,
}
closer, client, err := ctrl.repoClientset.NewRepositoryClient()
if err != nil {
log.Errorf("Unable to create repository client: %v", err)
return state
}
defer util.Close(closer)
_, err = client.ListDir(context.Background(), &repository.ListDirRequest{Repo: repo, Path: ".gitignore"})
if err == nil {
state.Status = v1alpha1.ConnectionStatusSuccessful
} else {
state.Status = v1alpha1.ConnectionStatusFailed
state.Message = err.Error()
}
return state
}
func (ctrl *SecretController) getClusterState(cluster *v1alpha1.Cluster) v1alpha1.ConnectionState {
state := v1alpha1.ConnectionState{
ModifiedAt: cluster.ConnectionState.ModifiedAt,
Status: v1alpha1.ConnectionStatusUnknown,
}
kubeClientset, err := kubernetes.NewForConfig(cluster.RESTConfig())
if err == nil {
_, err = kubeClientset.Discovery().ServerVersion()
}
if err == nil {
state.Status = v1alpha1.ConnectionStatusSuccessful
} else {
state.Status = v1alpha1.ConnectionStatusFailed
state.Message = err.Error()
}
return state
}
func (ctrl *SecretController) updateState(secret *corev1.Secret, state v1alpha1.ConnectionState) {
annotationsPatch := make(map[string]string)
for key, value := range db.AnnotationsFromConnectionState(&state) {
if secret.Annotations[key] != value {
annotationsPatch[key] = value
}
}
if len(annotationsPatch) > 0 {
annotationsPatch[common.AnnotationConnectionModifiedAt] = metav1.Now().Format(time.RFC3339)
patchData, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": annotationsPatch,
},
})
if err != nil {
log.Warnf("Unable to prepare secret state annotation patch: %v", err)
} else {
_, err := ctrl.kubeClient.CoreV1().Secrets(secret.Namespace).Patch(secret.Name, types.MergePatchType, patchData)
if err != nil {
log.Warnf("Unable to patch secret state annotation: %v", err)
}
}
}
}
func newSecretInformer(client kubernetes.Interface, resyncPeriod time.Duration, namespace string, secretQueue workqueue.RateLimitingInterface) cache.SharedIndexInformer {
informerFactory := informers.NewFilteredSharedInformerFactory(
client,
resyncPeriod,
namespace,
func(options *metav1.ListOptions) {
var req *labels.Requirement
req, err := labels.NewRequirement(common.LabelKeySecretType, selection.In, []string{common.SecretTypeCluster, common.SecretTypeRepository})
if err != nil {
panic(err)
}
options.FieldSelector = fields.Everything().String()
labelSelector := labels.NewSelector().Add(*req)
options.LabelSelector = labelSelector.String()
},
)
informer := informerFactory.Core().V1().Secrets().Informer()
informer.AddEventHandler(
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
key, err := cache.MetaNamespaceKeyFunc(obj)
if err == nil {
secretQueue.Add(key)
}
},
UpdateFunc: func(old, new interface{}) {
key, err := cache.MetaNamespaceKeyFunc(new)
if err == nil {
secretQueue.Add(key)
}
},
},
)
return informer
}
func NewSecretController(kubeClient kubernetes.Interface, repoClientset reposerver.Clientset, resyncPeriod time.Duration, namespace string) *SecretController {
secretQueue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
return &SecretController{
kubeClient: kubeClient,
secretQueue: secretQueue,
secretInformer: newSecretInformer(kubeClient, resyncPeriod, namespace, secretQueue),
namespace: namespace,
repoClientset: repoClientset,
}
}

View File

@@ -145,7 +145,7 @@ func (ks *KsonnetAppStateManager) CompareAppState(app *v1alpha1.Application) (*v
for i, targetObj := range targetObjs {
fullName := getResourceFullName(targetObj)
liveObj := liveObjByFullName[fullName]
if liveObj == nil {
if liveObj == nil && targetObj.GetName() != "" {
// If we get here, it indicates we did not find the live resource when querying using
// our app label. However, it is possible that the resource was created/modified outside
// of ArgoCD. In order to determine that it is truly missing, we fall back to perform a
@@ -454,25 +454,31 @@ func syncObject(config *rest.Config, namespace string, targetObj, liveObj *unstr
if prune {
if dryRun {
resDetails.Message = "pruned (dry run)"
resDetails.Status = v1alpha1.ResourceDetailsSyncedAndPruned
} else {
err := kubeutil.DeleteResource(config, liveObj, namespace)
if err != nil {
resDetails.Message = err.Error()
resDetails.Status = v1alpha1.ResourceDetailsSyncFailed
successful = false
} else {
resDetails.Message = "pruned"
resDetails.Status = v1alpha1.ResourceDetailsSyncedAndPruned
}
}
} else {
resDetails.Message = "ignored (requires pruning)"
resDetails.Status = v1alpha1.ResourceDetailsPruningRequired
}
} else {
message, err := kube.ApplyResource(config, targetObj, namespace, dryRun)
if err != nil {
resDetails.Message = err.Error()
resDetails.Status = v1alpha1.ResourceDetailsSyncFailed
successful = false
} else {
resDetails.Message = message
resDetails.Status = v1alpha1.ResourceDetailsSynced
}
}
return resDetails, successful

View File

@@ -11,7 +11,7 @@ An example Ksonnet guestbook application is provided to demonstrates how Argo CD
Download the latest Argo CD version
```
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v0.4.3/argocd-darwin-amd64
curl -sSL -o /usr/local/bin/argocd https://github.com/argoproj/argo-cd/releases/download/v0.5.1/argocd-darwin-amd64
chmod +x /usr/local/bin/argocd
```

View File

@@ -23,7 +23,7 @@ local appDeployment = deployment
params.replicas,
container
.new(params.name, params.image)
.withPorts(containerPort.new(targetPort)),
labels);
.withPorts(containerPort.new(targetPort)) + if params.command != null then { command: [ params.command ] } else {},
labels).withProgressDeadlineSeconds(5);
k.core.v1.list.new([appService, appDeployment])

View File

@@ -12,7 +12,8 @@
name: "guestbook-ui",
replicas: 1,
servicePort: 80,
type: "LoadBalancer",
type: "ClusterIP",
command: null,
},
},
}

View File

@@ -5,14 +5,6 @@ import (
"strings"
"syscall"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/util/diff"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/password"
"github.com/argoproj/argo-cd/util/session"
"github.com/argoproj/argo-cd/util/settings"
tlsutil "github.com/argoproj/argo-cd/util/tls"
"github.com/ghodss/yaml"
"github.com/gobuffalo/packr"
log "github.com/sirupsen/logrus"
@@ -29,6 +21,15 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/util/diff"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/password"
"github.com/argoproj/argo-cd/util/session"
"github.com/argoproj/argo-cd/util/settings"
tlsutil "github.com/argoproj/argo-cd/util/tls"
)
var (
@@ -91,6 +92,7 @@ func (i *Installer) Install() {
i.InstallNamespace()
i.InstallApplicationCRD()
i.InstallSettings()
i.InstallRBACConfigMap()
i.InstallApplicationController()
i.InstallArgoCDServer()
i.InstallArgoCDRepoServer()
@@ -194,6 +196,15 @@ func (i *Installer) InstallSettings() {
errors.CheckError(err)
}
func (i *Installer) InstallRBACConfigMap() {
var rbacCM apiv1.ConfigMap
i.unmarshalManifest("02c_argocd-rbac-cm.yaml", &rbacCM)
_, err := i.InstallResource(kube.MustToUnstructured(&rbacCM))
if err != nil && !apierr.IsAlreadyExists(err) {
errors.CheckError(err)
}
}
func readAndConfirmPassword() string {
for {
fmt.Print("*** Enter an admin password: ")

View File

@@ -3,7 +3,6 @@ apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-cm
namespace: argocd
data:
# url is the externally facing base URL of ArgoCD.
# This field is required when configuring SSO, which ArgoCD uses as part the redirectURI for the

View File

@@ -4,7 +4,6 @@ apiVersion: v1
kind: Secret
metadata:
name: argocd-secret
namespace: argocd
type: Opaque
stringData:
# bcrypt hash of the string "password"

View File

@@ -0,0 +1,26 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-rbac-cm
data:
# policy.csv holds the CSV file policy file which contains additional policy and role definitions.
# ArgoCD defines two built-in roles:
# * role:readonly - readonly access to all objects
# * role:admin - admin access to all objects
# The built-in policy can be seen under util/rbac/builtin-policy.csv
#
# The policy definition format is:
# p, <user/group>, <resource>, <action>, <project>/<object>
# For example, the following rule gives all members of 'my-org:team1' the ability to sync
# applications in the project named: my-project
# p, my-org:team1, applications, sync, my-project/*
#
# The role definition format is:
# g, <user/group>, <group>
# For example, the following rule makes all members of 'my-org:team2' have the role:admin role:
# g, my-org:team2, role:admin
policy.csv: ""
# policy.default holds the default policy which will ArgoCD will fall back to, when authorizing
# a user for API requests.
policy.default: role:readonly

View File

@@ -2,4 +2,3 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: application-controller
namespace: argocd

View File

@@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: application-controller-role
namespace: argocd
rules:
- apiGroups:
- ""
@@ -11,6 +10,9 @@ rules:
verbs:
- get
- watch
- list
- patch
- update
- apiGroups:
- argoproj.io
resources:

View File

@@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: application-controller-role-binding
namespace: argocd
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role

View File

@@ -2,7 +2,6 @@ apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: application-controller
namespace: argocd
spec:
selector:
matchLabels:

View File

@@ -2,4 +2,3 @@ apiVersion: v1
kind: ServiceAccount
metadata:
name: argocd-server
namespace: argocd

View File

@@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: argocd-server-role
namespace: argocd
rules:
- apiGroups:
- ""

View File

@@ -2,7 +2,6 @@ apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argocd-server-role-binding
namespace: argocd
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role

View File

@@ -2,7 +2,6 @@ apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: argocd-server
namespace: argocd
spec:
selector:
matchLabels:

View File

@@ -2,7 +2,6 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-server
namespace: argocd
spec:
ports:
- name: http

View File

@@ -2,7 +2,6 @@ apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: argocd-repo-server
namespace: argocd
spec:
selector:
matchLabels:

View File

@@ -2,7 +2,6 @@ apiVersion: v1
kind: Service
metadata:
name: argocd-repo-server
namespace: argocd
spec:
ports:
- port: 8081

View File

@@ -21,6 +21,7 @@
ClusterList
ComparisonResult
ComponentParameter
ConnectionState
DeploymentInfo
HealthStatus
Operation
@@ -113,57 +114,61 @@ func (m *ComponentParameter) Reset() { *m = ComponentParamete
func (*ComponentParameter) ProtoMessage() {}
func (*ComponentParameter) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{12} }
func (m *ConnectionState) Reset() { *m = ConnectionState{} }
func (*ConnectionState) ProtoMessage() {}
func (*ConnectionState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} }
func (m *DeploymentInfo) Reset() { *m = DeploymentInfo{} }
func (*DeploymentInfo) ProtoMessage() {}
func (*DeploymentInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{13} }
func (*DeploymentInfo) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} }
func (m *HealthStatus) Reset() { *m = HealthStatus{} }
func (*HealthStatus) ProtoMessage() {}
func (*HealthStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{14} }
func (*HealthStatus) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} }
func (m *Operation) Reset() { *m = Operation{} }
func (*Operation) ProtoMessage() {}
func (*Operation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{15} }
func (*Operation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} }
func (m *OperationState) Reset() { *m = OperationState{} }
func (*OperationState) ProtoMessage() {}
func (*OperationState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{16} }
func (*OperationState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} }
func (m *Repository) Reset() { *m = Repository{} }
func (*Repository) ProtoMessage() {}
func (*Repository) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{17} }
func (*Repository) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} }
func (m *RepositoryList) Reset() { *m = RepositoryList{} }
func (*RepositoryList) ProtoMessage() {}
func (*RepositoryList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{18} }
func (*RepositoryList) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} }
func (m *ResourceDetails) Reset() { *m = ResourceDetails{} }
func (*ResourceDetails) ProtoMessage() {}
func (*ResourceDetails) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{19} }
func (*ResourceDetails) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} }
func (m *ResourceNode) Reset() { *m = ResourceNode{} }
func (*ResourceNode) ProtoMessage() {}
func (*ResourceNode) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{20} }
func (*ResourceNode) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} }
func (m *ResourceState) Reset() { *m = ResourceState{} }
func (*ResourceState) ProtoMessage() {}
func (*ResourceState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{21} }
func (*ResourceState) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} }
func (m *RollbackOperation) Reset() { *m = RollbackOperation{} }
func (*RollbackOperation) ProtoMessage() {}
func (*RollbackOperation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{22} }
func (*RollbackOperation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} }
func (m *SyncOperation) Reset() { *m = SyncOperation{} }
func (*SyncOperation) ProtoMessage() {}
func (*SyncOperation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{23} }
func (*SyncOperation) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} }
func (m *SyncOperationResult) Reset() { *m = SyncOperationResult{} }
func (*SyncOperationResult) ProtoMessage() {}
func (*SyncOperationResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{24} }
func (*SyncOperationResult) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} }
func (m *TLSClientConfig) Reset() { *m = TLSClientConfig{} }
func (*TLSClientConfig) ProtoMessage() {}
func (*TLSClientConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{25} }
func (*TLSClientConfig) Descriptor() ([]byte, []int) { return fileDescriptorGenerated, []int{26} }
func init() {
proto.RegisterType((*Application)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application")
@@ -179,6 +184,7 @@ func init() {
proto.RegisterType((*ClusterList)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ClusterList")
proto.RegisterType((*ComparisonResult)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ComparisonResult")
proto.RegisterType((*ComponentParameter)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ComponentParameter")
proto.RegisterType((*ConnectionState)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ConnectionState")
proto.RegisterType((*DeploymentInfo)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.DeploymentInfo")
proto.RegisterType((*HealthStatus)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HealthStatus")
proto.RegisterType((*Operation)(nil), "github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Operation")
@@ -558,8 +564,12 @@ func (m *Cluster) MarshalTo(dAtA []byte) (int, error) {
i += n12
dAtA[i] = 0x22
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message)))
i += copy(dAtA[i:], m.Message)
i = encodeVarintGenerated(dAtA, i, uint64(m.ConnectionState.Size()))
n13, err := m.ConnectionState.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n13
return i, nil
}
@@ -593,11 +603,11 @@ func (m *ClusterConfig) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x22
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.TLSClientConfig.Size()))
n13, err := m.TLSClientConfig.MarshalTo(dAtA[i:])
n14, err := m.TLSClientConfig.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n13
i += n14
return i, nil
}
@@ -619,11 +629,11 @@ func (m *ClusterList) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size()))
n14, err := m.ListMeta.MarshalTo(dAtA[i:])
n15, err := m.ListMeta.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n14
i += n15
if len(m.Items) > 0 {
for _, msg := range m.Items {
dAtA[i] = 0x12
@@ -657,19 +667,19 @@ func (m *ComparisonResult) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ComparedAt.Size()))
n15, err := m.ComparedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n15
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ComparedTo.Size()))
n16, err := m.ComparedTo.MarshalTo(dAtA[i:])
n16, err := m.ComparedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n16
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ComparedTo.Size()))
n17, err := m.ComparedTo.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n17
dAtA[i] = 0x2a
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status)))
@@ -723,6 +733,42 @@ func (m *ComponentParameter) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *ConnectionState) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ConnectionState) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status)))
i += copy(dAtA[i:], m.Status)
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message)))
i += copy(dAtA[i:], m.Message)
if m.ModifiedAt != nil {
dAtA[i] = 0x1a
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ModifiedAt.Size()))
n18, err := m.ModifiedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n18
}
return i, nil
}
func (m *DeploymentInfo) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -769,11 +815,11 @@ func (m *DeploymentInfo) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x22
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.DeployedAt.Size()))
n17, err := m.DeployedAt.MarshalTo(dAtA[i:])
n19, err := m.DeployedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n17
i += n19
dAtA[i] = 0x28
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ID))
@@ -825,21 +871,21 @@ func (m *Operation) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.Sync.Size()))
n18, err := m.Sync.MarshalTo(dAtA[i:])
n20, err := m.Sync.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n18
i += n20
}
if m.Rollback != nil {
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.Rollback.Size()))
n19, err := m.Rollback.MarshalTo(dAtA[i:])
n21, err := m.Rollback.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n19
i += n21
}
return i, nil
}
@@ -862,11 +908,11 @@ func (m *OperationState) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.Operation.Size()))
n20, err := m.Operation.MarshalTo(dAtA[i:])
n22, err := m.Operation.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n20
i += n22
dAtA[i] = 0x12
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Phase)))
@@ -879,40 +925,40 @@ func (m *OperationState) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x22
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.SyncResult.Size()))
n21, err := m.SyncResult.MarshalTo(dAtA[i:])
n23, err := m.SyncResult.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n21
i += n23
}
if m.RollbackResult != nil {
dAtA[i] = 0x2a
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.RollbackResult.Size()))
n22, err := m.RollbackResult.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n22
}
dAtA[i] = 0x32
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size()))
n23, err := m.StartedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n23
if m.FinishedAt != nil {
dAtA[i] = 0x3a
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.FinishedAt.Size()))
n24, err := m.FinishedAt.MarshalTo(dAtA[i:])
n24, err := m.RollbackResult.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n24
}
dAtA[i] = 0x32
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.StartedAt.Size()))
n25, err := m.StartedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n25
if m.FinishedAt != nil {
dAtA[i] = 0x3a
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.FinishedAt.Size()))
n26, err := m.FinishedAt.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n26
}
return i, nil
}
@@ -949,8 +995,12 @@ func (m *Repository) MarshalTo(dAtA []byte) (int, error) {
i += copy(dAtA[i:], m.SSHPrivateKey)
dAtA[i] = 0x2a
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message)))
i += copy(dAtA[i:], m.Message)
i = encodeVarintGenerated(dAtA, i, uint64(m.ConnectionState.Size()))
n27, err := m.ConnectionState.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n27
return i, nil
}
@@ -972,11 +1022,11 @@ func (m *RepositoryList) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0xa
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.ListMeta.Size()))
n25, err := m.ListMeta.MarshalTo(dAtA[i:])
n28, err := m.ListMeta.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n25
i += n28
if len(m.Items) > 0 {
for _, msg := range m.Items {
dAtA[i] = 0x12
@@ -1023,6 +1073,10 @@ func (m *ResourceDetails) MarshalTo(dAtA []byte) (int, error) {
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Message)))
i += copy(dAtA[i:], m.Message)
dAtA[i] = 0x2a
i++
i = encodeVarintGenerated(dAtA, i, uint64(len(m.Status)))
i += copy(dAtA[i:], m.Status)
return i, nil
}
@@ -1102,11 +1156,11 @@ func (m *ResourceState) MarshalTo(dAtA []byte) (int, error) {
dAtA[i] = 0x2a
i++
i = encodeVarintGenerated(dAtA, i, uint64(m.Health.Size()))
n26, err := m.Health.MarshalTo(dAtA[i:])
n29, err := m.Health.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n26
i += n29
return i, nil
}
@@ -1403,7 +1457,7 @@ func (m *Cluster) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
l = m.Config.Size()
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Message)
l = m.ConnectionState.Size()
n += 1 + l + sovGenerated(uint64(l))
return n
}
@@ -1468,6 +1522,20 @@ func (m *ComponentParameter) Size() (n int) {
return n
}
func (m *ConnectionState) Size() (n int) {
var l int
_ = l
l = len(m.Status)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Message)
n += 1 + l + sovGenerated(uint64(l))
if m.ModifiedAt != nil {
l = m.ModifiedAt.Size()
n += 1 + l + sovGenerated(uint64(l))
}
return n
}
func (m *DeploymentInfo) Size() (n int) {
var l int
_ = l
@@ -1552,7 +1620,7 @@ func (m *Repository) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
l = len(m.SSHPrivateKey)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Message)
l = m.ConnectionState.Size()
n += 1 + l + sovGenerated(uint64(l))
return n
}
@@ -1582,6 +1650,8 @@ func (m *ResourceDetails) Size() (n int) {
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Message)
n += 1 + l + sovGenerated(uint64(l))
l = len(m.Status)
n += 1 + l + sovGenerated(uint64(l))
return n
}
@@ -1789,7 +1859,7 @@ func (this *Cluster) String() string {
`Server:` + fmt.Sprintf("%v", this.Server) + `,`,
`Name:` + fmt.Sprintf("%v", this.Name) + `,`,
`Config:` + strings.Replace(strings.Replace(this.Config.String(), "ClusterConfig", "ClusterConfig", 1), `&`, ``, 1) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`ConnectionState:` + strings.Replace(strings.Replace(this.ConnectionState.String(), "ConnectionState", "ConnectionState", 1), `&`, ``, 1) + `,`,
`}`,
}, "")
return s
@@ -1844,6 +1914,18 @@ func (this *ComponentParameter) String() string {
}, "")
return s
}
func (this *ConnectionState) String() string {
if this == nil {
return "nil"
}
s := strings.Join([]string{`&ConnectionState{`,
`Status:` + fmt.Sprintf("%v", this.Status) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`ModifiedAt:` + strings.Replace(fmt.Sprintf("%v", this.ModifiedAt), "Time", "k8s_io_apimachinery_pkg_apis_meta_v1.Time", 1) + `,`,
`}`,
}, "")
return s
}
func (this *DeploymentInfo) String() string {
if this == nil {
return "nil"
@@ -1905,7 +1987,7 @@ func (this *Repository) String() string {
`Username:` + fmt.Sprintf("%v", this.Username) + `,`,
`Password:` + fmt.Sprintf("%v", this.Password) + `,`,
`SSHPrivateKey:` + fmt.Sprintf("%v", this.SSHPrivateKey) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`ConnectionState:` + strings.Replace(strings.Replace(this.ConnectionState.String(), "ConnectionState", "ConnectionState", 1), `&`, ``, 1) + `,`,
`}`,
}, "")
return s
@@ -1930,6 +2012,7 @@ func (this *ResourceDetails) String() string {
`Kind:` + fmt.Sprintf("%v", this.Kind) + `,`,
`Namespace:` + fmt.Sprintf("%v", this.Namespace) + `,`,
`Message:` + fmt.Sprintf("%v", this.Message) + `,`,
`Status:` + fmt.Sprintf("%v", this.Status) + `,`,
`}`,
}, "")
return s
@@ -3286,9 +3369,9 @@ func (m *Cluster) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field ConnectionState", wireType)
}
var stringLen uint64
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
@@ -3298,20 +3381,21 @@ func (m *Cluster) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Message = string(dAtA[iNdEx:postIndex])
if err := m.ConnectionState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
@@ -3948,6 +4032,147 @@ func (m *ComponentParameter) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *ConnectionState) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ConnectionState: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ConnectionState: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Status = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Message = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field ModifiedAt", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.ModifiedAt == nil {
m.ModifiedAt = &k8s_io_apimachinery_pkg_apis_meta_v1.Time{}
}
if err := m.ModifiedAt.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthGenerated
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *DeploymentInfo) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -4776,9 +5001,9 @@ func (m *Repository) Unmarshal(dAtA []byte) error {
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Message", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field ConnectionState", wireType)
}
var stringLen uint64
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
@@ -4788,20 +5013,21 @@ func (m *Repository) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
if msglen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Message = string(dAtA[iNdEx:postIndex])
if err := m.ConnectionState.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
@@ -5080,6 +5306,35 @@ func (m *ResourceDetails) Unmarshal(dAtA []byte) error {
}
m.Message = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Status", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGenerated
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGenerated
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Status = ResourceSyncStatus(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGenerated(dAtA[iNdEx:])
@@ -6020,133 +6275,138 @@ func init() {
}
var fileDescriptorGenerated = []byte{
// 2047 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0xcd, 0x8f, 0x23, 0x47,
0x15, 0x9f, 0x1a, 0x7f, 0x8c, 0xfd, 0xe6, 0x6b, 0xb7, 0x42, 0x82, 0x35, 0x91, 0x3c, 0xa3, 0x5e,
0x01, 0x0b, 0x22, 0x36, 0xbb, 0x10, 0x3e, 0x25, 0xa4, 0xb5, 0x67, 0x93, 0x9d, 0xcc, 0xec, 0xee,
0x50, 0x9e, 0x80, 0x14, 0x10, 0xd0, 0xd3, 0xae, 0xb1, 0x7b, 0xc7, 0xee, 0xee, 0x54, 0x95, 0xbd,
0xb2, 0x04, 0x28, 0x08, 0x21, 0xa1, 0x08, 0x22, 0x3e, 0xfe, 0x01, 0xce, 0x5c, 0x10, 0x88, 0x13,
0x7f, 0x00, 0xda, 0x63, 0x90, 0x38, 0x44, 0x08, 0xad, 0xd8, 0xc9, 0x25, 0x12, 0x17, 0xc4, 0x71,
0x4f, 0xa8, 0xaa, 0xab, 0xab, 0xab, 0xdb, 0x33, 0x99, 0x9d, 0xd8, 0xbb, 0xca, 0xcd, 0xfd, 0xde,
0xeb, 0xf7, 0x7b, 0xfd, 0xaa, 0xde, 0x7b, 0xbf, 0x2a, 0xc3, 0x4e, 0xcf, 0x17, 0xfd, 0xd1, 0x61,
0xc3, 0x0b, 0x87, 0x4d, 0x97, 0xf5, 0xc2, 0x88, 0x85, 0xf7, 0xd4, 0x8f, 0x97, 0xbc, 0x6e, 0x33,
0x3a, 0xee, 0x35, 0xdd, 0xc8, 0xe7, 0x4d, 0x37, 0x8a, 0x06, 0xbe, 0xe7, 0x0a, 0x3f, 0x0c, 0x9a,
0xe3, 0x6b, 0xee, 0x20, 0xea, 0xbb, 0xd7, 0x9a, 0x3d, 0x1a, 0x50, 0xe6, 0x0a, 0xda, 0x6d, 0x44,
0x2c, 0x14, 0x21, 0xfe, 0x5a, 0xea, 0xaa, 0x91, 0xb8, 0x52, 0x3f, 0x7e, 0xe0, 0x75, 0x1b, 0xd1,
0x71, 0xaf, 0x21, 0x5d, 0x35, 0x2c, 0x57, 0x8d, 0xc4, 0xd5, 0xc6, 0x4b, 0x56, 0x14, 0xbd, 0xb0,
0x17, 0x36, 0x95, 0xc7, 0xc3, 0xd1, 0x91, 0x7a, 0x52, 0x0f, 0xea, 0x57, 0x8c, 0xb4, 0xf1, 0xa5,
0xe3, 0xaf, 0xf2, 0x86, 0x1f, 0xca, 0xd8, 0x86, 0xae, 0xd7, 0xf7, 0x03, 0xca, 0x26, 0x69, 0xb0,
0x43, 0x2a, 0xdc, 0xe6, 0x78, 0x2a, 0xbe, 0x8d, 0xe6, 0x59, 0x6f, 0xb1, 0x51, 0x20, 0xfc, 0x21,
0x9d, 0x7a, 0xe1, 0xcb, 0xe7, 0xbd, 0xc0, 0xbd, 0x3e, 0x1d, 0xba, 0x53, 0xef, 0x7d, 0xf1, 0xac,
0xf7, 0x46, 0xc2, 0x1f, 0x34, 0xfd, 0x40, 0x70, 0xc1, 0xf2, 0x2f, 0x39, 0x7f, 0x2b, 0xc0, 0xf2,
0x8d, 0x34, 0x37, 0xf8, 0x87, 0x50, 0x91, 0x1f, 0xd2, 0x75, 0x85, 0x5b, 0x43, 0x5b, 0xe8, 0xea,
0xf2, 0xf5, 0x2f, 0x34, 0x62, 0xbf, 0x0d, 0xdb, 0x6f, 0x9a, 0x58, 0x69, 0xdd, 0x18, 0x5f, 0x6b,
0xdc, 0x3d, 0xbc, 0x47, 0x3d, 0x71, 0x9b, 0x0a, 0xb7, 0x85, 0x1f, 0x3c, 0xdc, 0x5c, 0x38, 0x79,
0xb8, 0x09, 0xa9, 0x8c, 0x18, 0xaf, 0x78, 0x00, 0x45, 0x1e, 0x51, 0xaf, 0xb6, 0xa8, 0xbc, 0xbf,
0xd6, 0xf8, 0xc8, 0xcb, 0xd7, 0xb0, 0xe2, 0xee, 0x44, 0xd4, 0x6b, 0xad, 0x68, 0xdc, 0xa2, 0x7c,
0x22, 0x0a, 0x05, 0x0b, 0x28, 0x73, 0xe1, 0x8a, 0x11, 0xaf, 0x15, 0x14, 0xde, 0xde, 0x9c, 0xf0,
0x94, 0xcf, 0xd6, 0x9a, 0x46, 0x2c, 0xc7, 0xcf, 0x44, 0x63, 0xe1, 0x37, 0xa1, 0x1a, 0x46, 0x32,
0xcf, 0x7e, 0x18, 0xd4, 0x8a, 0x0a, 0x78, 0x7b, 0x06, 0xe0, 0xbb, 0x89, 0xaf, 0xd6, 0xea, 0xc9,
0xc3, 0xcd, 0xaa, 0x79, 0x24, 0x29, 0x8a, 0xe3, 0xc1, 0x27, 0xac, 0xf8, 0xda, 0x61, 0xd0, 0xf5,
0xd5, 0x82, 0x6e, 0x41, 0x51, 0x4c, 0x22, 0xaa, 0x16, 0xb3, 0x9a, 0xa6, 0xe8, 0x60, 0x12, 0x51,
0xa2, 0x34, 0xf8, 0xb3, 0xb0, 0x34, 0xa4, 0x9c, 0xbb, 0x3d, 0xaa, 0xd6, 0xa4, 0xda, 0x5a, 0xd7,
0x46, 0x4b, 0xb7, 0x63, 0x31, 0x49, 0xf4, 0xce, 0x9b, 0xf0, 0x82, 0x05, 0xb2, 0x4d, 0xb9, 0xf0,
0x83, 0x78, 0xdf, 0x7c, 0x1a, 0xca, 0x9c, 0xb2, 0x31, 0x65, 0x1a, 0x28, 0xcd, 0x8c, 0x92, 0x12,
0xad, 0xc5, 0x4d, 0xa8, 0x06, 0xee, 0x90, 0xf2, 0xc8, 0xf5, 0x12, 0xb8, 0xcb, 0xda, 0xb4, 0x7a,
0x27, 0x51, 0x90, 0xd4, 0xc6, 0xf9, 0x17, 0x82, 0x75, 0x0b, 0x73, 0xcf, 0xe7, 0x02, 0x7f, 0x6f,
0x6a, 0x93, 0x36, 0x9e, 0x6c, 0x93, 0xca, 0xb7, 0xd5, 0x16, 0xbd, 0xa4, 0x31, 0x2b, 0x89, 0xc4,
0xda, 0xa0, 0xc7, 0x50, 0xf2, 0x05, 0x1d, 0xf2, 0xda, 0xe2, 0x56, 0xe1, 0xea, 0xf2, 0xf5, 0x57,
0xe6, 0xb3, 0x63, 0x5a, 0xab, 0x1a, 0xb2, 0xb4, 0x23, 0x9d, 0x93, 0x18, 0xc3, 0x79, 0xa7, 0x00,
0x97, 0xed, 0x7d, 0x15, 0x8e, 0x98, 0xa7, 0x96, 0x84, 0xd1, 0x28, 0x7c, 0x9d, 0xec, 0xe9, 0x74,
0x9a, 0x25, 0x21, 0xb1, 0x98, 0x24, 0x7a, 0xb9, 0xbe, 0x91, 0x2b, 0xfa, 0x3a, 0x97, 0x66, 0x7d,
0xf7, 0x5d, 0xd1, 0x27, 0x4a, 0x83, 0x5f, 0x86, 0x65, 0x1a, 0x8c, 0x7d, 0x16, 0x06, 0x43, 0x1a,
0x08, 0x55, 0x07, 0xd5, 0xd6, 0x73, 0xda, 0x70, 0xf9, 0x66, 0xaa, 0x22, 0xb6, 0x1d, 0xfe, 0x26,
0xac, 0x09, 0x97, 0xf5, 0xa8, 0x20, 0x74, 0xec, 0xf3, 0x64, 0x23, 0x57, 0x5b, 0x2f, 0xe8, 0x37,
0xd7, 0x0e, 0x32, 0x5a, 0x92, 0xb3, 0xc6, 0x7f, 0x41, 0xf0, 0xa2, 0x17, 0x0e, 0xa3, 0x30, 0xa0,
0x81, 0xd8, 0x77, 0x99, 0x3b, 0xa4, 0x82, 0xb2, 0xbb, 0x63, 0xca, 0x98, 0xdf, 0xa5, 0xbc, 0x56,
0x52, 0xd9, 0xbd, 0x3d, 0x43, 0x76, 0xdb, 0x53, 0xde, 0x5b, 0x57, 0x74, 0x70, 0x2f, 0xb6, 0xcf,
0x46, 0x26, 0x1f, 0x16, 0x96, 0xf3, 0xdb, 0xc5, 0xcc, 0x7e, 0xeb, 0x24, 0x4d, 0x44, 0x2d, 0x8c,
0xde, 0x6d, 0xf3, 0x6a, 0x22, 0xca, 0xa7, 0x55, 0x2a, 0xea, 0x99, 0x68, 0x2c, 0xfc, 0x0b, 0x04,
0xcb, 0xdd, 0xb4, 0xc4, 0x74, 0xc3, 0xfc, 0xd6, 0x7c, 0xb0, 0xad, 0xda, 0x4d, 0xf7, 0x82, 0x25,
0x24, 0x36, 0xb4, 0xf3, 0xfb, 0x72, 0x76, 0x97, 0xc6, 0x5d, 0xee, 0x37, 0x08, 0x2e, 0xc9, 0x54,
0xba, 0xcc, 0xe7, 0x61, 0x40, 0x28, 0x1f, 0x0d, 0x84, 0xce, 0xd0, 0xee, 0x8c, 0xcb, 0x6a, 0xbb,
0x6c, 0xd5, 0x74, 0x7c, 0x97, 0xf2, 0x1a, 0x32, 0x05, 0x8f, 0x05, 0x2c, 0xf5, 0x7d, 0x2e, 0x42,
0x36, 0xd1, 0xe5, 0xbb, 0x33, 0x43, 0x24, 0xdb, 0x34, 0x1a, 0x84, 0x13, 0x59, 0x0d, 0x3b, 0xc1,
0x51, 0x98, 0x16, 0xe1, 0xad, 0x18, 0x81, 0x24, 0x50, 0xf8, 0xa7, 0x08, 0x20, 0x4a, 0xf6, 0x92,
0x1c, 0x35, 0x4f, 0x61, 0x6b, 0x9b, 0xa9, 0x6a, 0x44, 0x9c, 0x58, 0xa0, 0x38, 0x84, 0x72, 0x9f,
0xba, 0x03, 0xd1, 0xd7, 0x03, 0xe7, 0xd5, 0x19, 0xe0, 0x6f, 0x29, 0x47, 0xf9, 0x21, 0x17, 0x4b,
0x89, 0x86, 0xc1, 0x3f, 0x47, 0xb0, 0x66, 0xe6, 0x8f, 0xb4, 0xa5, 0xb5, 0x92, 0x42, 0xde, 0x99,
0xc7, 0xa8, 0x53, 0x0e, 0x5b, 0x58, 0x36, 0x9a, 0xac, 0x8c, 0xe4, 0x40, 0xf1, 0xcf, 0x10, 0x80,
0x97, 0xcc, 0x3b, 0x5e, 0x2b, 0xab, 0xe4, 0xdf, 0x9d, 0x4f, 0x99, 0x98, 0x39, 0x9a, 0xa6, 0xdf,
0x88, 0x38, 0xb1, 0x60, 0x9d, 0xf7, 0x11, 0x3c, 0x6f, 0xbd, 0xf8, 0x1d, 0x57, 0x78, 0xfd, 0x9b,
0x63, 0xd9, 0x48, 0x77, 0x33, 0x13, 0xf8, 0x2b, 0xf6, 0x04, 0x7e, 0xfc, 0x70, 0xf3, 0x33, 0x67,
0xb1, 0xb6, 0xfb, 0xd2, 0x43, 0x43, 0xb9, 0xb0, 0x86, 0xf5, 0x8f, 0x61, 0xd9, 0x8a, 0x59, 0xf7,
0x84, 0x79, 0x8d, 0x28, 0xd3, 0x08, 0x2c, 0x21, 0xb1, 0xf1, 0x9c, 0xff, 0x22, 0x58, 0x6a, 0x0f,
0x46, 0x5c, 0x50, 0xf6, 0xc4, 0x23, 0x7f, 0x0b, 0x8a, 0x72, 0x9c, 0xe7, 0x27, 0x94, 0x9c, 0xf6,
0x44, 0x69, 0x70, 0x04, 0x65, 0x2f, 0x0c, 0x8e, 0xfc, 0x9e, 0x26, 0x69, 0xb7, 0x66, 0xa9, 0x9c,
0x38, 0xba, 0xb6, 0xf2, 0x97, 0xc6, 0x14, 0x3f, 0x13, 0x8d, 0x63, 0x73, 0x9e, 0xe2, 0x39, 0x9c,
0xe7, 0xcf, 0x8b, 0xb0, 0x9a, 0x71, 0x8a, 0x3f, 0x0f, 0x95, 0x11, 0xa7, 0x4c, 0x7d, 0x54, 0xfc,
0xe9, 0x86, 0x4e, 0xbc, 0xae, 0xe5, 0xc4, 0x58, 0x48, 0xeb, 0xc8, 0xe5, 0xfc, 0x7e, 0xc8, 0xba,
0x3a, 0x05, 0xc6, 0x7a, 0x5f, 0xcb, 0x89, 0xb1, 0x90, 0xc3, 0xfa, 0x90, 0xba, 0x8c, 0xb2, 0x83,
0xf0, 0x98, 0x06, 0xf9, 0x61, 0xdd, 0x4a, 0x55, 0xc4, 0xb6, 0xc3, 0xbf, 0x42, 0xb0, 0x2e, 0x06,
0xbc, 0x3d, 0xf0, 0x69, 0x20, 0xe2, 0x30, 0x75, 0x1b, 0x98, 0x85, 0x60, 0x1f, 0xec, 0x75, 0x6c,
0x8f, 0xad, 0x4f, 0xea, 0x38, 0xd6, 0x73, 0x0a, 0x92, 0xc7, 0x76, 0xfe, 0x81, 0x60, 0x59, 0x27,
0xed, 0x19, 0x30, 0xb6, 0x5e, 0x96, 0xb1, 0xb5, 0x66, 0xdf, 0x3e, 0x67, 0xb0, 0xb5, 0xbf, 0x17,
0x60, 0x6a, 0x08, 0xe1, 0xef, 0xcb, 0xf6, 0x23, 0x65, 0xb4, 0x7b, 0x23, 0x99, 0x7f, 0x9f, 0x7b,
0xb2, 0xaf, 0x3b, 0xf0, 0x87, 0xd4, 0xee, 0x2c, 0x89, 0x17, 0x62, 0x79, 0xc4, 0x6f, 0xa1, 0x14,
0xe0, 0x20, 0xd4, 0x25, 0x3f, 0x5f, 0x0a, 0x32, 0x15, 0xc2, 0x41, 0x48, 0x2c, 0x4c, 0xfc, 0x75,
0x73, 0x8a, 0x2a, 0xa9, 0x0d, 0xe9, 0x64, 0xcf, 0x3d, 0x8f, 0x33, 0xb3, 0x39, 0x77, 0x16, 0x9a,
0x40, 0x95, 0xd1, 0x98, 0xd2, 0x24, 0xcd, 0x79, 0x96, 0xfa, 0x26, 0xda, 0x57, 0x3c, 0x1f, 0xcc,
0xd9, 0x21, 0x11, 0x73, 0x92, 0xa2, 0xe1, 0x2b, 0x50, 0xa2, 0x8c, 0x85, 0xac, 0xb6, 0xa4, 0xa2,
0x36, 0x6b, 0x7a, 0x53, 0x0a, 0x49, 0xac, 0x73, 0x7e, 0x89, 0x00, 0x4f, 0x8f, 0x5b, 0x79, 0x50,
0x31, 0x34, 0x51, 0x57, 0xb9, 0x01, 0x33, 0xe6, 0x24, 0xb5, 0x79, 0x82, 0x36, 0x77, 0x05, 0x4a,
0x63, 0x77, 0x30, 0xa2, 0xba, 0xaa, 0x4d, 0x38, 0xdf, 0x96, 0x42, 0x12, 0xeb, 0x9c, 0x0f, 0x0a,
0xb0, 0x96, 0xe5, 0x1d, 0x78, 0x04, 0x65, 0x35, 0xe7, 0x79, 0x0d, 0x3d, 0x0d, 0x62, 0x61, 0x7a,
0xa4, 0x12, 0x71, 0xa2, 0xc1, 0x64, 0xe3, 0x62, 0x09, 0xf5, 0xcf, 0x35, 0x2e, 0x43, 0xfa, 0x8d,
0xc5, 0xb9, 0x74, 0xbf, 0xf0, 0xb1, 0xa4, 0xfb, 0xb2, 0x78, 0xbb, 0x2a, 0xdb, 0xaa, 0x78, 0x8b,
0x1f, 0xbd, 0x78, 0xb7, 0x8d, 0x17, 0x62, 0x79, 0xc4, 0x1b, 0xb0, 0xe8, 0x77, 0x55, 0xd5, 0x14,
0x5a, 0xa0, 0x6d, 0x17, 0x77, 0xb6, 0xc9, 0xa2, 0xdf, 0x75, 0x38, 0xac, 0xd8, 0x44, 0x4b, 0x0d,
0xd4, 0xb8, 0xca, 0xf2, 0x03, 0x35, 0x5b, 0x51, 0xdf, 0x80, 0xd5, 0xf8, 0xd7, 0x36, 0x15, 0xae,
0x3f, 0xe0, 0x7a, 0x75, 0x9e, 0xd7, 0xe6, 0xab, 0x1d, 0x5b, 0x49, 0xb2, 0xb6, 0xce, 0x7f, 0x10,
0xa4, 0x17, 0x08, 0xf8, 0x08, 0x8a, 0x7c, 0x12, 0x78, 0xba, 0x6b, 0xcd, 0x52, 0x97, 0x9d, 0x49,
0xe0, 0xa5, 0xf7, 0x14, 0x15, 0x75, 0x0d, 0x33, 0x09, 0x3c, 0xa2, 0xfc, 0xe3, 0x31, 0x54, 0x58,
0x38, 0x18, 0x1c, 0xba, 0xde, 0xf1, 0x1c, 0x1a, 0x18, 0xd1, 0xae, 0x52, 0xbc, 0x15, 0xb5, 0x2b,
0xb5, 0x98, 0x18, 0x2c, 0xe7, 0x8f, 0x25, 0xc8, 0xd1, 0x47, 0x3c, 0xb2, 0xef, 0x66, 0xd0, 0x1c,
0xef, 0x66, 0x4c, 0x7b, 0x38, 0xed, 0x7e, 0x06, 0xbf, 0x0c, 0xa5, 0xa8, 0xef, 0xf2, 0xa4, 0x3f,
0x6c, 0x26, 0xc5, 0xbf, 0x2f, 0x85, 0x8f, 0x6d, 0x96, 0xab, 0x24, 0x24, 0xb6, 0xb6, 0x89, 0x4a,
0xe1, 0xc3, 0x89, 0x0a, 0xfe, 0x09, 0x80, 0xcc, 0xb5, 0x3e, 0x87, 0xc5, 0x5b, 0xf9, 0xce, 0xbc,
0x56, 0x54, 0x1f, 0xc5, 0xd6, 0xe4, 0x56, 0xef, 0x18, 0x14, 0x62, 0x21, 0xe2, 0xb7, 0x11, 0xac,
0x25, 0x89, 0xd7, 0x41, 0x94, 0x9e, 0x4a, 0x10, 0xea, 0x50, 0x40, 0x32, 0x48, 0x24, 0x87, 0x8c,
0xbf, 0x0b, 0x55, 0x2e, 0x5c, 0x26, 0x54, 0x59, 0x97, 0x2f, 0x5c, 0xd6, 0x66, 0x2d, 0x3b, 0x89,
0x13, 0x92, 0xfa, 0xc3, 0x6f, 0x00, 0x1c, 0xf9, 0x81, 0xcf, 0xfb, 0xca, 0xfb, 0xd2, 0x85, 0xbd,
0xab, 0x2c, 0xbe, 0x62, 0x3c, 0x10, 0xcb, 0x9b, 0xf3, 0x3f, 0x04, 0x40, 0x68, 0x14, 0x72, 0x5f,
0x9d, 0x2c, 0xb7, 0xa0, 0xc8, 0x68, 0x14, 0xe6, 0xaf, 0xef, 0xa4, 0x05, 0x51, 0x9a, 0x0c, 0x1b,
0x5d, 0xbc, 0x10, 0x1b, 0x2d, 0x9c, 0xcb, 0x46, 0x65, 0xa7, 0xe1, 0xfd, 0x7d, 0xe6, 0x8f, 0x5d,
0x41, 0x77, 0xe9, 0x44, 0x93, 0xe5, 0xb4, 0xd3, 0x74, 0x6e, 0xa5, 0x4a, 0x92, 0xb5, 0xb5, 0xb7,
0x6e, 0xe9, 0x1c, 0x8e, 0xfd, 0x4f, 0x04, 0x6b, 0xe9, 0x47, 0x3f, 0x03, 0xc6, 0x78, 0x2f, 0xcb,
0x18, 0x6f, 0xce, 0x44, 0x48, 0x92, 0xb8, 0xcf, 0x20, 0x8d, 0x7f, 0x42, 0xb0, 0x9e, 0xd0, 0x13,
0xdd, 0x85, 0x0d, 0x59, 0x40, 0x67, 0x92, 0x85, 0x2d, 0x28, 0x1e, 0xfb, 0x41, 0x37, 0x4f, 0x27,
0x76, 0xfd, 0xa0, 0x4b, 0x94, 0x26, 0x7b, 0x95, 0x5a, 0x38, 0xff, 0x2a, 0xf5, 0x22, 0x87, 0x9e,
0x3f, 0x20, 0x58, 0x49, 0x62, 0xbe, 0x13, 0x76, 0x15, 0x77, 0xe1, 0xea, 0x88, 0x8f, 0xb2, 0xdc,
0x25, 0x3e, 0x92, 0xc7, 0x3a, 0x3c, 0x82, 0x8a, 0xd7, 0xf7, 0x07, 0x5d, 0x46, 0x03, 0x9d, 0xd8,
0x57, 0xe7, 0xc0, 0xf4, 0x24, 0x7e, 0xba, 0x98, 0x6d, 0x0d, 0x40, 0x0c, 0x94, 0xf3, 0xd7, 0x02,
0xac, 0x66, 0x68, 0xa1, 0x3c, 0x45, 0xc5, 0xb7, 0x91, 0x1d, 0x2b, 0x66, 0x73, 0x8a, 0x3a, 0x48,
0x55, 0xc4, 0xb6, 0x93, 0x19, 0x1d, 0xf8, 0xe3, 0xd8, 0x47, 0xfe, 0x72, 0x7a, 0x2f, 0x51, 0x90,
0xd4, 0xc6, 0xe2, 0xc5, 0x85, 0x0b, 0xf3, 0xe2, 0xdf, 0x21, 0xc0, 0xea, 0x13, 0xa4, 0x67, 0x43,
0x5f, 0x6b, 0xc5, 0xf9, 0xe6, 0x6d, 0x43, 0x47, 0x84, 0xdb, 0x53, 0x50, 0xe4, 0x14, 0x78, 0xeb,
0x16, 0xa9, 0xf4, 0x4c, 0x6e, 0x91, 0x9c, 0x1f, 0xc1, 0xe5, 0xa9, 0x71, 0xae, 0x59, 0x13, 0x3a,
0x8d, 0x35, 0xc9, 0x9d, 0x18, 0xb1, 0x51, 0x10, 0x2f, 0x50, 0x25, 0xdd, 0x89, 0xfb, 0x52, 0x48,
0x62, 0x9d, 0xa4, 0x52, 0x5d, 0x36, 0x21, 0xa3, 0xf8, 0x04, 0x5d, 0x49, 0xd1, 0xb7, 0x95, 0x94,
0x68, 0xad, 0xf3, 0x36, 0x82, 0xd5, 0xcc, 0x88, 0xc9, 0xb0, 0x5e, 0x74, 0x2e, 0xeb, 0x9d, 0x6b,
0x30, 0xef, 0x20, 0x78, 0xee, 0x94, 0x79, 0x87, 0xef, 0xdb, 0x27, 0xa8, 0xf8, 0x08, 0xf0, 0xda,
0x1c, 0xf6, 0x87, 0xee, 0x45, 0xf1, 0x7f, 0x4a, 0xa7, 0x9d, 0x9f, 0x9c, 0x0f, 0x10, 0xe4, 0x8f,
0xfa, 0x32, 0x3f, 0x7e, 0xc0, 0xa9, 0x37, 0x62, 0x71, 0x5d, 0x55, 0xd2, 0xfc, 0xec, 0x68, 0x39,
0x31, 0x16, 0xf8, 0x3a, 0x40, 0x7c, 0x0b, 0x74, 0x27, 0x1d, 0x4f, 0x86, 0x32, 0x77, 0x8c, 0x86,
0x58, 0x56, 0xf8, 0x2a, 0x54, 0x3c, 0xca, 0xc4, 0xb6, 0xec, 0xfc, 0x32, 0x61, 0x2b, 0x31, 0xbb,
0x6b, 0x6b, 0x19, 0x31, 0x5a, 0xfc, 0x29, 0x58, 0x3a, 0xa6, 0x13, 0x65, 0x58, 0x54, 0x86, 0xcb,
0xb2, 0x99, 0xed, 0xc6, 0x22, 0x92, 0xe8, 0xb0, 0x03, 0x65, 0xcf, 0x55, 0x56, 0x25, 0x65, 0x05,
0xea, 0x42, 0xe8, 0x86, 0x32, 0xd2, 0x9a, 0x56, 0xe3, 0xc1, 0xa3, 0xfa, 0xc2, 0xbb, 0x8f, 0xea,
0x0b, 0xef, 0x3d, 0xaa, 0x2f, 0xbc, 0x75, 0x52, 0x47, 0x0f, 0x4e, 0xea, 0xe8, 0xdd, 0x93, 0x3a,
0x7a, 0xef, 0xa4, 0x8e, 0xfe, 0x7d, 0x52, 0x47, 0xbf, 0x7e, 0xbf, 0xbe, 0xf0, 0x46, 0x25, 0x49,
0xe2, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x41, 0x22, 0xb1, 0xcb, 0xc1, 0x1e, 0x00, 0x00,
// 2117 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x59, 0xcd, 0x8f, 0x1b, 0x49,
0x15, 0x9f, 0xf6, 0xd7, 0xd8, 0xcf, 0xf3, 0x91, 0xd4, 0xb2, 0x8b, 0x35, 0x2b, 0xcd, 0x8c, 0x3a,
0x7c, 0x04, 0xc4, 0xda, 0x24, 0xb0, 0x7c, 0x0b, 0x29, 0xf6, 0x64, 0x37, 0xb3, 0x33, 0x49, 0x86,
0xf2, 0x2c, 0x48, 0xcb, 0x0a, 0xe8, 0xe9, 0xae, 0xb1, 0x3b, 0x63, 0x77, 0xf7, 0x56, 0x95, 0x1d,
0x59, 0x02, 0xb4, 0x08, 0x21, 0xa1, 0x15, 0xac, 0xf8, 0xf8, 0x07, 0x38, 0x73, 0x41, 0x42, 0x9c,
0x38, 0x72, 0x40, 0x39, 0x2e, 0x12, 0x88, 0x15, 0x42, 0x11, 0x99, 0xbd, 0x44, 0xe2, 0xc0, 0x3d,
0x27, 0x54, 0xd5, 0xd5, 0xd5, 0xd5, 0xed, 0x19, 0x66, 0x12, 0x3b, 0x61, 0x6f, 0xee, 0xf7, 0x5e,
0xbf, 0x5f, 0xf5, 0xab, 0x57, 0xef, 0xfd, 0x5e, 0x19, 0xb6, 0x7b, 0x3e, 0xef, 0x8f, 0x0e, 0x9a,
0x6e, 0x38, 0x6c, 0x39, 0xb4, 0x17, 0x46, 0x34, 0xbc, 0x23, 0x7f, 0xbc, 0xe4, 0x7a, 0xad, 0xe8,
0xa8, 0xd7, 0x72, 0x22, 0x9f, 0xb5, 0x9c, 0x28, 0x1a, 0xf8, 0xae, 0xc3, 0xfd, 0x30, 0x68, 0x8d,
0xaf, 0x38, 0x83, 0xa8, 0xef, 0x5c, 0x69, 0xf5, 0x48, 0x40, 0xa8, 0xc3, 0x89, 0xd7, 0x8c, 0x68,
0xc8, 0x43, 0xf4, 0xe5, 0xd4, 0x55, 0x33, 0x71, 0x25, 0x7f, 0x7c, 0xd7, 0xf5, 0x9a, 0xd1, 0x51,
0xaf, 0x29, 0x5c, 0x35, 0x0d, 0x57, 0xcd, 0xc4, 0xd5, 0xda, 0x4b, 0xc6, 0x2a, 0x7a, 0x61, 0x2f,
0x6c, 0x49, 0x8f, 0x07, 0xa3, 0x43, 0xf9, 0x24, 0x1f, 0xe4, 0xaf, 0x18, 0x69, 0xed, 0xf3, 0x47,
0x5f, 0x62, 0x4d, 0x3f, 0x14, 0x6b, 0x1b, 0x3a, 0x6e, 0xdf, 0x0f, 0x08, 0x9d, 0xa4, 0x8b, 0x1d,
0x12, 0xee, 0xb4, 0xc6, 0x53, 0xeb, 0x5b, 0x6b, 0x9d, 0xf6, 0x16, 0x1d, 0x05, 0xdc, 0x1f, 0x92,
0xa9, 0x17, 0xbe, 0x70, 0xd6, 0x0b, 0xcc, 0xed, 0x93, 0xa1, 0x33, 0xf5, 0xde, 0xe7, 0x4e, 0x7b,
0x6f, 0xc4, 0xfd, 0x41, 0xcb, 0x0f, 0x38, 0xe3, 0x34, 0xff, 0x92, 0xfd, 0xe7, 0x22, 0xd4, 0xaf,
0xa5, 0xb1, 0x41, 0xdf, 0x83, 0xaa, 0xf8, 0x10, 0xcf, 0xe1, 0x4e, 0xc3, 0xda, 0xb4, 0x2e, 0xd7,
0xaf, 0x7e, 0xb6, 0x19, 0xfb, 0x6d, 0x9a, 0x7e, 0xd3, 0xc0, 0x0a, 0xeb, 0xe6, 0xf8, 0x4a, 0xf3,
0xf6, 0xc1, 0x1d, 0xe2, 0xf2, 0x9b, 0x84, 0x3b, 0x6d, 0x74, 0xef, 0xfe, 0xc6, 0xc2, 0xf1, 0xfd,
0x0d, 0x48, 0x65, 0x58, 0x7b, 0x45, 0x03, 0x28, 0xb1, 0x88, 0xb8, 0x8d, 0x82, 0xf4, 0xfe, 0x5a,
0xf3, 0x89, 0xb7, 0xaf, 0x69, 0xac, 0xbb, 0x1b, 0x11, 0xb7, 0xbd, 0xa4, 0x70, 0x4b, 0xe2, 0x09,
0x4b, 0x14, 0xc4, 0xa1, 0xc2, 0xb8, 0xc3, 0x47, 0xac, 0x51, 0x94, 0x78, 0xbb, 0x73, 0xc2, 0x93,
0x3e, 0xdb, 0x2b, 0x0a, 0xb1, 0x12, 0x3f, 0x63, 0x85, 0x85, 0xde, 0x82, 0x5a, 0x18, 0x89, 0x38,
0xfb, 0x61, 0xd0, 0x28, 0x49, 0xe0, 0xad, 0x19, 0x80, 0x6f, 0x27, 0xbe, 0xda, 0xcb, 0xc7, 0xf7,
0x37, 0x6a, 0xfa, 0x11, 0xa7, 0x28, 0xb6, 0x0b, 0x1f, 0x31, 0xd6, 0xd7, 0x09, 0x03, 0xcf, 0x97,
0x1b, 0xba, 0x09, 0x25, 0x3e, 0x89, 0x88, 0xdc, 0xcc, 0x5a, 0x1a, 0xa2, 0xfd, 0x49, 0x44, 0xb0,
0xd4, 0xa0, 0x4f, 0xc1, 0xe2, 0x90, 0x30, 0xe6, 0xf4, 0x88, 0xdc, 0x93, 0x5a, 0x7b, 0x55, 0x19,
0x2d, 0xde, 0x8c, 0xc5, 0x38, 0xd1, 0xdb, 0x6f, 0xc1, 0x0b, 0x06, 0xc8, 0x16, 0x61, 0xdc, 0x0f,
0xe2, 0xbc, 0xf9, 0x04, 0x54, 0x18, 0xa1, 0x63, 0x42, 0x15, 0x50, 0x1a, 0x19, 0x29, 0xc5, 0x4a,
0x8b, 0x5a, 0x50, 0x0b, 0x9c, 0x21, 0x61, 0x91, 0xe3, 0x26, 0x70, 0x17, 0x95, 0x69, 0xed, 0x56,
0xa2, 0xc0, 0xa9, 0x8d, 0xfd, 0x4f, 0x0b, 0x56, 0x0d, 0xcc, 0x5d, 0x9f, 0x71, 0xf4, 0xe6, 0x54,
0x92, 0x36, 0xcf, 0x97, 0xa4, 0xe2, 0x6d, 0x99, 0xa2, 0x17, 0x14, 0x66, 0x35, 0x91, 0x18, 0x09,
0x7a, 0x04, 0x65, 0x9f, 0x93, 0x21, 0x6b, 0x14, 0x36, 0x8b, 0x97, 0xeb, 0x57, 0x5f, 0x99, 0x4f,
0xc6, 0xb4, 0x97, 0x15, 0x64, 0x79, 0x5b, 0x38, 0xc7, 0x31, 0x86, 0xfd, 0x6e, 0x11, 0x2e, 0x9a,
0x79, 0x15, 0x8e, 0xa8, 0x2b, 0xb7, 0x84, 0x92, 0x28, 0x7c, 0x1d, 0xef, 0xaa, 0x70, 0xea, 0x2d,
0xc1, 0xb1, 0x18, 0x27, 0x7a, 0xb1, 0xbf, 0x91, 0xc3, 0xfb, 0x2a, 0x96, 0x7a, 0x7f, 0xf7, 0x1c,
0xde, 0xc7, 0x52, 0x83, 0x5e, 0x86, 0x3a, 0x09, 0xc6, 0x3e, 0x0d, 0x83, 0x21, 0x09, 0xb8, 0x3c,
0x07, 0xb5, 0xf6, 0x73, 0xca, 0xb0, 0x7e, 0x3d, 0x55, 0x61, 0xd3, 0x0e, 0x7d, 0x1d, 0x56, 0xb8,
0x43, 0x7b, 0x84, 0x63, 0x32, 0xf6, 0x59, 0x92, 0xc8, 0xb5, 0xf6, 0x0b, 0xea, 0xcd, 0x95, 0xfd,
0x8c, 0x16, 0xe7, 0xac, 0xd1, 0x1f, 0x2c, 0x78, 0xd1, 0x0d, 0x87, 0x51, 0x18, 0x90, 0x80, 0xef,
0x39, 0xd4, 0x19, 0x12, 0x4e, 0xe8, 0xed, 0x31, 0xa1, 0xd4, 0xf7, 0x08, 0x6b, 0x94, 0x65, 0x74,
0x6f, 0xce, 0x10, 0xdd, 0xce, 0x94, 0xf7, 0xf6, 0x25, 0xb5, 0xb8, 0x17, 0x3b, 0xa7, 0x23, 0xe3,
0xff, 0xb5, 0x2c, 0xfb, 0x57, 0x85, 0x4c, 0xbe, 0x75, 0x93, 0x22, 0x22, 0x37, 0x46, 0x65, 0xdb,
0xbc, 0x8a, 0x88, 0xf4, 0x69, 0x1c, 0x15, 0xf9, 0x8c, 0x15, 0x16, 0xfa, 0xa9, 0x05, 0x75, 0x2f,
0x3d, 0x62, 0xaa, 0x60, 0x7e, 0x63, 0x3e, 0xd8, 0xc6, 0xd9, 0x4d, 0x73, 0xc1, 0x10, 0x62, 0x13,
0xda, 0xfe, 0x4d, 0x25, 0x9b, 0xa5, 0x71, 0x95, 0xfb, 0xa5, 0x05, 0x17, 0x44, 0x28, 0x1d, 0xea,
0xb3, 0x30, 0xc0, 0x84, 0x8d, 0x06, 0x5c, 0x45, 0x68, 0x67, 0xc6, 0x6d, 0x35, 0x5d, 0xb6, 0x1b,
0x6a, 0x7d, 0x17, 0xf2, 0x1a, 0x3c, 0x05, 0x8f, 0x38, 0x2c, 0xf6, 0x7d, 0xc6, 0x43, 0x3a, 0x51,
0xc7, 0x77, 0x7b, 0x86, 0x95, 0x6c, 0x91, 0x68, 0x10, 0x4e, 0xc4, 0x69, 0xd8, 0x0e, 0x0e, 0xc3,
0xf4, 0x10, 0xde, 0x88, 0x11, 0x70, 0x02, 0x85, 0x7e, 0x64, 0x01, 0x44, 0x49, 0x2e, 0x89, 0x56,
0xf3, 0x14, 0x52, 0x5b, 0x77, 0x55, 0x2d, 0x62, 0xd8, 0x00, 0x45, 0x21, 0x54, 0xfa, 0xc4, 0x19,
0xf0, 0xbe, 0x6a, 0x38, 0xaf, 0xce, 0x00, 0x7f, 0x43, 0x3a, 0xca, 0x37, 0xb9, 0x58, 0x8a, 0x15,
0x0c, 0xfa, 0x89, 0x05, 0x2b, 0xba, 0xff, 0x08, 0x5b, 0xd2, 0x28, 0x4b, 0xe4, 0xed, 0x79, 0xb4,
0x3a, 0xe9, 0xb0, 0x8d, 0x44, 0xa1, 0xc9, 0xca, 0x70, 0x0e, 0x14, 0xfd, 0xd8, 0x02, 0x70, 0x93,
0x7e, 0xc7, 0x1a, 0x15, 0x19, 0xfc, 0xdb, 0xf3, 0x39, 0x26, 0xba, 0x8f, 0xa6, 0xe1, 0xd7, 0x22,
0x86, 0x0d, 0x58, 0xfb, 0x03, 0x0b, 0x9e, 0x37, 0x5e, 0xfc, 0x96, 0xc3, 0xdd, 0xfe, 0xf5, 0xb1,
0x28, 0xa4, 0x3b, 0x99, 0x0e, 0xfc, 0x45, 0xb3, 0x03, 0x3f, 0xba, 0xbf, 0xf1, 0xc9, 0xd3, 0x58,
0xdb, 0x5d, 0xe1, 0xa1, 0x29, 0x5d, 0x18, 0xcd, 0xfa, 0x07, 0x50, 0x37, 0xd6, 0xac, 0x6a, 0xc2,
0xbc, 0x5a, 0x94, 0x2e, 0x04, 0x86, 0x10, 0x9b, 0x78, 0xf6, 0xdf, 0x0a, 0xb0, 0xd8, 0x19, 0x8c,
0x18, 0x27, 0xf4, 0xdc, 0x2d, 0x7f, 0x13, 0x4a, 0xa2, 0x9d, 0xe7, 0x3b, 0x94, 0xe8, 0xf6, 0x58,
0x6a, 0x50, 0x04, 0x15, 0x37, 0x0c, 0x0e, 0xfd, 0x9e, 0x22, 0x69, 0x37, 0x66, 0x39, 0x39, 0xf1,
0xea, 0x3a, 0xd2, 0x5f, 0xba, 0xa6, 0xf8, 0x19, 0x2b, 0x1c, 0xf4, 0x73, 0x0b, 0x56, 0xdd, 0x30,
0x08, 0x88, 0x9b, 0x26, 0x6f, 0x69, 0x66, 0x42, 0xda, 0xc9, 0x7a, 0x6c, 0x7f, 0x54, 0xa1, 0xaf,
0xe6, 0x14, 0x38, 0x8f, 0x6d, 0xff, 0xbe, 0x00, 0xcb, 0x99, 0x95, 0xa3, 0xcf, 0x40, 0x75, 0xc4,
0x08, 0x95, 0x91, 0x8b, 0xe3, 0xab, 0x39, 0xcb, 0xeb, 0x4a, 0x8e, 0xb5, 0x85, 0xb0, 0x8e, 0x1c,
0xc6, 0xee, 0x86, 0xd4, 0x53, 0x71, 0xd6, 0xd6, 0x7b, 0x4a, 0x8e, 0xb5, 0x85, 0x60, 0x04, 0x07,
0xc4, 0xa1, 0x84, 0xee, 0x87, 0x47, 0x24, 0xc8, 0x33, 0x82, 0x76, 0xaa, 0xc2, 0xa6, 0x9d, 0x0c,
0x1a, 0x1f, 0xb0, 0xce, 0xc0, 0x27, 0x01, 0x8f, 0x97, 0x39, 0x87, 0xa0, 0xed, 0xef, 0x76, 0x4d,
0x8f, 0x69, 0xd0, 0x72, 0x0a, 0x9c, 0xc7, 0xb6, 0xff, 0x6a, 0x41, 0x5d, 0x05, 0xed, 0x19, 0xd0,
0xc2, 0x5e, 0x96, 0x16, 0xb6, 0x67, 0xcf, 0xd1, 0x53, 0x28, 0xe1, 0x5f, 0x8a, 0x30, 0xd5, 0xe9,
0xd0, 0x77, 0x44, 0x8d, 0x13, 0x32, 0xe2, 0x5d, 0x4b, 0x9a, 0xec, 0xa7, 0xcf, 0xf7, 0x75, 0xfb,
0xfe, 0x90, 0x98, 0xe5, 0x2b, 0xf1, 0x82, 0x0d, 0x8f, 0xe8, 0x6d, 0x2b, 0x05, 0xd8, 0x0f, 0x55,
0x5d, 0x99, 0x2f, 0xcf, 0x99, 0x5a, 0xc2, 0x7e, 0x88, 0x0d, 0x4c, 0xf4, 0x15, 0x3d, 0xaa, 0x95,
0x65, 0x42, 0xda, 0xd9, 0xe1, 0xea, 0x51, 0x86, 0x00, 0xe4, 0x06, 0xae, 0x09, 0xd4, 0x28, 0x89,
0x79, 0x53, 0xd2, 0x01, 0x66, 0x29, 0x22, 0x58, 0xf9, 0x8a, 0x8f, 0xb1, 0x1e, 0x50, 0x12, 0x31,
0xc3, 0x29, 0x1a, 0xba, 0x04, 0x65, 0x42, 0x69, 0x48, 0x1b, 0x8b, 0x72, 0xd5, 0x7a, 0x4f, 0xaf,
0x0b, 0x21, 0x8e, 0x75, 0xf6, 0xcf, 0x2c, 0x40, 0xd3, 0x3d, 0x5d, 0x4c, 0x43, 0x9a, 0x8b, 0xaa,
0x53, 0xae, 0xc1, 0xb4, 0x39, 0x4e, 0x6d, 0xce, 0x51, 0x4b, 0x2f, 0x41, 0x79, 0xec, 0x0c, 0x46,
0x44, 0x9d, 0x6a, 0xbd, 0x9c, 0x6f, 0x0a, 0x21, 0x8e, 0x75, 0xf6, 0x9f, 0x2c, 0xc8, 0xd7, 0x24,
0x59, 0xce, 0xe3, 0xf0, 0xe7, 0xcb, 0x79, 0x36, 0xd4, 0xe7, 0x1f, 0x17, 0xd1, 0x9b, 0x50, 0x77,
0x38, 0x27, 0xc3, 0x88, 0xcb, 0xac, 0x2d, 0x3e, 0x76, 0xd6, 0xae, 0x88, 0x74, 0xb9, 0x19, 0x7a,
0xfe, 0xa1, 0x2f, 0x33, 0xd6, 0x74, 0x67, 0x3f, 0x2c, 0xc2, 0x4a, 0x96, 0xa1, 0xa1, 0x11, 0x54,
0x24, 0x23, 0x12, 0xdf, 0xf0, 0x14, 0x28, 0x98, 0x0e, 0x89, 0x14, 0x31, 0xac, 0xc0, 0x44, 0xf5,
0xa5, 0xc9, 0x90, 0x94, 0xab, 0xbe, 0x7a, 0x3c, 0xd2, 0x16, 0x67, 0x0e, 0x46, 0xc5, 0x0f, 0xe5,
0x60, 0x24, 0x2a, 0x90, 0x27, 0xa3, 0x2d, 0xf7, 0xb2, 0xf4, 0xe4, 0x15, 0x68, 0x4b, 0x7b, 0xc1,
0x86, 0x47, 0xb4, 0x06, 0x05, 0xdf, 0x93, 0x47, 0xbf, 0xd8, 0x06, 0x65, 0x5b, 0xd8, 0xde, 0xc2,
0x05, 0xdf, 0xb3, 0x19, 0x2c, 0x99, 0x94, 0xf4, 0xdc, 0xb9, 0xfa, 0x55, 0x58, 0x8e, 0x7f, 0x6d,
0x11, 0xee, 0xf8, 0x03, 0xa6, 0x76, 0xe7, 0x79, 0x65, 0xbe, 0xdc, 0x35, 0x95, 0x38, 0x6b, 0x6b,
0xff, 0xdb, 0x82, 0xf4, 0xaa, 0x05, 0x1d, 0x42, 0x89, 0x4d, 0x02, 0x57, 0x95, 0xde, 0x59, 0x8a,
0x4b, 0x77, 0x12, 0xb8, 0xe9, 0x8d, 0x4e, 0x55, 0x5e, 0x58, 0x4d, 0x02, 0x17, 0x4b, 0xff, 0x68,
0x0c, 0x55, 0x1a, 0x0e, 0x06, 0x07, 0x8e, 0x7b, 0x34, 0x87, 0x2a, 0x8c, 0x95, 0xab, 0x14, 0x6f,
0x49, 0x66, 0xa5, 0x12, 0x63, 0x8d, 0x65, 0xff, 0xae, 0x0c, 0x39, 0xa2, 0x8d, 0x46, 0xe6, 0x2d,
0x96, 0x35, 0xc7, 0x5b, 0x2c, 0x5d, 0xe3, 0x4e, 0xba, 0xc9, 0x42, 0x2f, 0x43, 0x39, 0xea, 0x3b,
0x2c, 0x29, 0x2f, 0x1b, 0x49, 0x05, 0xdb, 0x13, 0xc2, 0x47, 0xe6, 0x3c, 0x20, 0x25, 0x38, 0xb6,
0x36, 0xeb, 0x52, 0xf1, 0x8c, 0xba, 0xf4, 0x43, 0x00, 0x11, 0x6b, 0x35, 0xb1, 0xc6, 0xa9, 0x7c,
0x6b, 0x5e, 0x3b, 0xaa, 0x86, 0x56, 0x59, 0xba, 0xba, 0x1a, 0x05, 0x1b, 0x88, 0xe8, 0x1d, 0x0b,
0x56, 0x92, 0xc0, 0xab, 0x45, 0x94, 0x9f, 0xca, 0x22, 0xe4, 0xf8, 0x84, 0x33, 0x48, 0x38, 0x87,
0x8c, 0xbe, 0x0d, 0x35, 0xc6, 0x1d, 0x1a, 0x97, 0xe8, 0xca, 0x63, 0x1f, 0x6b, 0xbd, 0x97, 0xdd,
0xc4, 0x09, 0x4e, 0xfd, 0xa1, 0x37, 0x00, 0x0e, 0xfd, 0xc0, 0x67, 0x7d, 0xe9, 0x7d, 0xf1, 0xc9,
0x1a, 0xc0, 0x2b, 0xda, 0x03, 0x36, 0xbc, 0xd9, 0x7f, 0x2f, 0x00, 0x60, 0x12, 0x85, 0xcc, 0x97,
0x33, 0xf8, 0x26, 0x94, 0x28, 0x89, 0xc2, 0xfc, 0x45, 0xa7, 0xb0, 0xc0, 0x52, 0x93, 0xa1, 0xd4,
0x85, 0xc7, 0xa2, 0xd4, 0xc5, 0x33, 0x29, 0xb5, 0xa8, 0x34, 0xac, 0xbf, 0x47, 0xfd, 0xb1, 0xc3,
0xc9, 0x0e, 0x99, 0xa8, 0xcb, 0xb2, 0xb4, 0xd2, 0x74, 0x6f, 0xa4, 0x4a, 0x9c, 0xb5, 0x3d, 0x71,
0x1a, 0x29, 0xff, 0x1f, 0xa7, 0x91, 0x7f, 0x58, 0xb0, 0x92, 0x46, 0xf6, 0x19, 0x70, 0xeb, 0x3b,
0x59, 0x6e, 0x7d, 0x7d, 0x26, 0xea, 0x96, 0xac, 0xfb, 0x14, 0x7a, 0xfd, 0x1f, 0x0b, 0x56, 0x13,
0x22, 0xa7, 0x4a, 0xbd, 0xa6, 0x55, 0xd6, 0xa9, 0xb4, 0x6a, 0x13, 0x4a, 0x47, 0x7e, 0xe0, 0xe5,
0x89, 0xd7, 0x8e, 0x1f, 0x78, 0x58, 0x6a, 0xb2, 0x37, 0xdb, 0xc5, 0xb3, 0x6f, 0xb6, 0xcd, 0x82,
0x55, 0x3a, 0xa3, 0x60, 0x7d, 0x2d, 0x47, 0x8d, 0x3f, 0x36, 0x45, 0x8d, 0x91, 0xa6, 0xac, 0x93,
0xc0, 0xcd, 0x76, 0x41, 0xfb, 0xb7, 0x16, 0x2c, 0x25, 0xea, 0x5b, 0xa1, 0x27, 0x39, 0x22, 0x93,
0x49, 0x66, 0x65, 0x39, 0x62, 0x9c, 0x0e, 0xb1, 0x0e, 0x8d, 0xa0, 0xea, 0xf6, 0xfd, 0x81, 0x47,
0x49, 0xa0, 0xb6, 0xe5, 0xd5, 0x39, 0x30, 0x6a, 0x81, 0x9f, 0xa6, 0x42, 0x47, 0x01, 0x60, 0x0d,
0x65, 0xff, 0xb1, 0x08, 0xcb, 0x19, 0xfa, 0x2d, 0xa6, 0xd5, 0xf8, 0x6a, 0xb9, 0x6b, 0xac, 0x59,
0x4f, 0xab, 0xfb, 0xa9, 0x0a, 0x9b, 0x76, 0x62, 0x3f, 0x06, 0xfe, 0x38, 0xf6, 0x91, 0xff, 0xa7,
0x61, 0x37, 0x51, 0xe0, 0xd4, 0xc6, 0x98, 0x3f, 0x8a, 0x8f, 0x3d, 0x7f, 0xfc, 0xda, 0x02, 0x24,
0x3f, 0x41, 0x78, 0xd6, 0x63, 0x42, 0xa3, 0x34, 0xdf, 0xb8, 0xad, 0xa9, 0x15, 0xa1, 0xce, 0x14,
0x14, 0x3e, 0x01, 0xde, 0xb8, 0x12, 0x2c, 0x3f, 0x93, 0x2b, 0x41, 0xfb, 0xfb, 0x70, 0x71, 0x8a,
0x71, 0x28, 0x62, 0x67, 0x9d, 0x44, 0xec, 0x44, 0x26, 0x46, 0x74, 0x14, 0xc4, 0x1b, 0x54, 0x4d,
0x33, 0x71, 0x4f, 0x08, 0x71, 0xac, 0x13, 0x6c, 0xcf, 0xa3, 0x13, 0x3c, 0x8a, 0x6f, 0x2a, 0xaa,
0x29, 0xfa, 0x96, 0x94, 0x62, 0xa5, 0xb5, 0xdf, 0xb1, 0x60, 0x39, 0xd3, 0x05, 0x33, 0xc4, 0xdc,
0x3a, 0x93, 0x98, 0xcf, 0x75, 0x31, 0xef, 0x5a, 0xf0, 0xdc, 0x09, 0x2d, 0x19, 0xdd, 0x35, 0x27,
0xd5, 0x78, 0x4a, 0x79, 0x6d, 0x0e, 0xf9, 0xa1, 0x2a, 0x59, 0xfc, 0x07, 0xe1, 0x49, 0x73, 0xaa,
0xfd, 0xd0, 0x82, 0xfc, 0x95, 0x8a, 0x88, 0x8f, 0x1f, 0x30, 0xe2, 0x8e, 0x68, 0x7c, 0xae, 0xaa,
0x69, 0x7c, 0xb6, 0x95, 0x1c, 0x6b, 0x0b, 0x74, 0x15, 0x20, 0xbe, 0xd2, 0xbb, 0x95, 0x76, 0x50,
0xcd, 0xea, 0xbb, 0x5a, 0x83, 0x0d, 0x2b, 0x74, 0x19, 0xaa, 0x2e, 0xa1, 0x7c, 0x4b, 0xf4, 0x0d,
0x11, 0xb0, 0xa5, 0x98, 0x80, 0x76, 0x94, 0x0c, 0x6b, 0x2d, 0xfa, 0x38, 0x2c, 0x1e, 0x91, 0x89,
0x34, 0x2c, 0x49, 0xc3, 0xba, 0x28, 0x85, 0x3b, 0xb1, 0x08, 0x27, 0x3a, 0x64, 0x43, 0xc5, 0x75,
0xa4, 0x55, 0x59, 0x5a, 0x81, 0xbc, 0xdd, 0xbb, 0x26, 0x8d, 0x94, 0xa6, 0xdd, 0xbc, 0xf7, 0x60,
0x7d, 0xe1, 0xbd, 0x07, 0xeb, 0x0b, 0xef, 0x3f, 0x58, 0x5f, 0x78, 0xfb, 0x78, 0xdd, 0xba, 0x77,
0xbc, 0x6e, 0xbd, 0x77, 0xbc, 0x6e, 0xbd, 0x7f, 0xbc, 0x6e, 0xfd, 0xeb, 0x78, 0xdd, 0xfa, 0xc5,
0x07, 0xeb, 0x0b, 0x6f, 0x54, 0x93, 0x20, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x88, 0x76, 0xce,
0xcf, 0x8e, 0x20, 0x00, 0x00,
}

View File

@@ -119,8 +119,8 @@ message Cluster {
// Config holds cluster information for connecting to a cluster
optional ClusterConfig config = 3;
// Message can hold a status message or error.
optional string message = 4;
// ConnectionState contains information about cluster connection state
optional ConnectionState connectionState = 4;
}
// ClusterConfig is the configuration attributes. This structure is subset of the go-client
@@ -169,6 +169,15 @@ message ComponentParameter {
optional string value = 3;
}
// ConnectionState contains information about remote resource connection state
message ConnectionState {
optional string status = 1;
optional string message = 2;
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time attemptedAt = 3;
}
// DeploymentInfo contains information relevant to an application deployment
message DeploymentInfo {
repeated ComponentParameter params = 1;
@@ -229,7 +238,7 @@ message Repository {
optional string sshPrivateKey = 4;
optional string message = 5;
optional ConnectionState connectionState = 5;
}
// RepositoryList is a collection of Repositories.
@@ -247,6 +256,8 @@ message ResourceDetails {
optional string namespace = 3;
optional string message = 4;
optional string status = 5;
}
// ResourceNode contains information about live resource and its children

View File

@@ -11,7 +11,9 @@ type objectMeta struct {
}
func (a *Application) GetMetadata() *objectMeta {
return &objectMeta{
Name: &a.Name,
var om objectMeta
if a != nil {
om.Name = &a.Name
}
return &om
}

View File

@@ -74,11 +74,21 @@ type SyncOperationResult struct {
Resources []*ResourceDetails `json:"resources" protobuf:"bytes,1,opt,name=resources"`
}
type ResourceSyncStatus string
const (
ResourceDetailsSynced ResourceSyncStatus = "Synced"
ResourceDetailsSyncFailed ResourceSyncStatus = "SyncFailed"
ResourceDetailsSyncedAndPruned ResourceSyncStatus = "SyncedAndPruned"
ResourceDetailsPruningRequired ResourceSyncStatus = "PruningRequired"
)
type ResourceDetails struct {
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
Namespace string `json:"namespace" protobuf:"bytes,3,opt,name=namespace"`
Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
Name string `json:"name" protobuf:"bytes,1,opt,name=name"`
Kind string `json:"kind" protobuf:"bytes,2,opt,name=kind"`
Namespace string `json:"namespace" protobuf:"bytes,3,opt,name=namespace"`
Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
Status ResourceSyncStatus `json:"status,omitempty" protobuf:"bytes,5,opt,name=status"`
}
// DeploymentInfo contains information relevant to an application deployment
@@ -234,6 +244,22 @@ type ResourceState struct {
Health HealthStatus `json:"health,omitempty" protobuf:"bytes,5,opt,name=health"`
}
// ConnectionStatus represents connection status
type ConnectionStatus = string
const (
ConnectionStatusUnknown = "Unknown"
ConnectionStatusSuccessful = "Successful"
ConnectionStatusFailed = "Failed"
)
// ConnectionState contains information about remote resource connection state
type ConnectionState struct {
Status ConnectionStatus `json:"status" protobuf:"bytes,1,opt,name=status"`
Message string `json:"message" protobuf:"bytes,2,opt,name=message"`
ModifiedAt *metav1.Time `json:"attemptedAt" protobuf:"bytes,3,opt,name=attemptedAt"`
}
// Cluster is the definition of a cluster resource
type Cluster struct {
// Server is the API server URL of the Kubernetes cluster
@@ -245,8 +271,8 @@ type Cluster struct {
// Config holds cluster information for connecting to a cluster
Config ClusterConfig `json:"config" protobuf:"bytes,3,opt,name=config"`
// Message can hold a status message or error.
Message string `json:"message,omitempty" protobuf:"bytes,4,opt,name=message"`
// ConnectionState contains information about cluster connection state
ConnectionState ConnectionState `json:"connectionState,omitempty" protobuf:"bytes,4,opt,name=connectionState"`
}
// ClusterList is a collection of Clusters.
@@ -293,11 +319,11 @@ type TLSClientConfig struct {
// Repository is a Git repository holding application configurations
type Repository struct {
Repo string `json:"repo" protobuf:"bytes,1,opt,name=repo"`
Username string `json:"username,omitempty" protobuf:"bytes,2,opt,name=username"`
Password string `json:"password,omitempty" protobuf:"bytes,3,opt,name=password"`
SSHPrivateKey string `json:"sshPrivateKey,omitempty" protobuf:"bytes,4,opt,name=sshPrivateKey"`
Message string `json:"message,omitempty" protobuf:"bytes,5,opt,name=message"`
Repo string `json:"repo" protobuf:"bytes,1,opt,name=repo"`
Username string `json:"username,omitempty" protobuf:"bytes,2,opt,name=username"`
Password string `json:"password,omitempty" protobuf:"bytes,3,opt,name=password"`
SSHPrivateKey string `json:"sshPrivateKey,omitempty" protobuf:"bytes,4,opt,name=sshPrivateKey"`
ConnectionState ConnectionState `json:"connectionState,omitempty" protobuf:"bytes,5,opt,name=connectionState"`
}
// RepositoryList is a collection of Repositories.

View File

@@ -215,6 +215,7 @@ func (in *ApplicationWatchEvent) DeepCopy() *ApplicationWatchEvent {
func (in *Cluster) DeepCopyInto(out *Cluster) {
*out = *in
in.Config.DeepCopyInto(&out.Config)
in.ConnectionState.DeepCopyInto(&out.ConnectionState)
return
}
@@ -310,6 +311,31 @@ func (in *ComponentParameter) DeepCopy() *ComponentParameter {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ConnectionState) DeepCopyInto(out *ConnectionState) {
*out = *in
if in.ModifiedAt != nil {
in, out := &in.ModifiedAt, &out.ModifiedAt
if *in == nil {
*out = nil
} else {
*out = new(v1.Time)
(*in).DeepCopyInto(*out)
}
}
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ConnectionState.
func (in *ConnectionState) DeepCopy() *ConnectionState {
if in == nil {
return nil
}
out := new(ConnectionState)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *DeploymentInfo) DeepCopyInto(out *DeploymentInfo) {
*out = *in
@@ -435,6 +461,7 @@ func (in *OperationState) DeepCopy() *OperationState {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *Repository) DeepCopyInto(out *Repository) {
*out = *in
in.ConnectionState.DeepCopyInto(&out.ConnectionState)
return
}
@@ -455,7 +482,9 @@ func (in *RepositoryList) DeepCopyInto(out *RepositoryList) {
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Repository, len(*in))
copy(*out, *in)
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
return
}

View File

@@ -1,6 +1,7 @@
package repository
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -9,15 +10,14 @@ import (
"strings"
"time"
log "github.com/sirupsen/logrus"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/git"
ksutil "github.com/argoproj/argo-cd/util/ksonnet"
"github.com/argoproj/argo-cd/util/kube"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
const (
@@ -84,7 +84,7 @@ func (s *Service) ListDir(ctx context.Context, q *ListDirRequest) (*FileList, er
Expiration: DefaultRepoCacheExpiration,
})
if err != nil {
return nil, err
log.Warnf("manifest cache set error %s: %v", cacheKey, err)
}
return &res, nil
}
@@ -177,7 +177,7 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani
manifests := make([]string, len(targetObjs))
for i, target := range targetObjs {
if q.AppLabel != "" {
err = setAppLabels(target, q.AppLabel)
err = kube.SetLabel(target, common.LabelApplicationName, q.AppLabel)
if err != nil {
return nil, err
}
@@ -206,28 +206,6 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani
return &res, nil
}
// setAppLabels sets our app labels against an unstructured object
func setAppLabels(target *unstructured.Unstructured, appName string) error {
labels := target.GetLabels()
if labels == nil {
labels = make(map[string]string)
}
labels[common.LabelApplicationName] = appName
target.SetLabels(labels)
// special case for deployment: make sure that derived replicaset and pod has application label
if target.GetKind() == kube.DeploymentKind {
labels, ok := unstructured.NestedMap(target.UnstructuredContent(), "spec", "template", "metadata", "labels")
if ok {
if labels == nil {
labels = make(map[string]interface{})
}
labels[common.LabelApplicationName] = appName
}
unstructured.SetNestedMap(target.UnstructuredContent(), labels, "spec", "template", "metadata", "labels")
}
return nil
}
// tempRepoPath returns a formulated temporary directory location to clone a repository
func tempRepoPath(repo string) string {
return path.Join(os.TempDir(), strings.Replace(repo, "/", "_", -1))

View File

@@ -9,21 +9,11 @@ import (
"strings"
"time"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/controller"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/reposerver"
"github.com/argoproj/argo-cd/reposerver/repository"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/git"
"github.com/ghodss/yaml"
"github.com/ksonnet/ksonnet/pkg/app"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
@@ -32,6 +22,19 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/controller"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/reposerver"
"github.com/argoproj/argo-cd/reposerver/repository"
"github.com/argoproj/argo-cd/util"
argoutil "github.com/argoproj/argo-cd/util/argo"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/git"
"github.com/argoproj/argo-cd/util/grpc"
"github.com/argoproj/argo-cd/util/rbac"
)
// Server provides a Application service
@@ -42,6 +45,7 @@ type Server struct {
repoClientset reposerver.Clientset
db db.ArgoDB
appComparator controller.AppStateManager
enf *rbac.Enforcer
}
// NewServer returns a new instance of the Application service
@@ -51,6 +55,7 @@ func NewServer(
appclientset appclientset.Interface,
repoClientset reposerver.Clientset,
db db.ArgoDB,
enf *rbac.Enforcer,
) ApplicationServiceServer {
return &Server{
@@ -60,43 +65,60 @@ func NewServer(
db: db,
repoClientset: repoClientset,
appComparator: controller.NewAppStateManager(db, appclientset, repoClientset, namespace),
enf: enf,
}
}
// appRBACName formats fully qualified application name for RBAC check
func appRBACName(app appv1.Application) string {
return fmt.Sprintf("%s/%s", git.NormalizeGitURL(app.Spec.Source.RepoURL), app.Name)
}
// List returns list of applications
func (s *Server) List(ctx context.Context, q *ApplicationQuery) (*appv1.ApplicationList, error) {
return s.appclientset.ArgoprojV1alpha1().Applications(s.ns).List(metav1.ListOptions{})
appList, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).List(metav1.ListOptions{})
if err != nil {
return nil, err
}
newItems := make([]appv1.Application, 0)
for _, a := range appList.Items {
if s.enf.EnforceClaims(ctx.Value("claims"), "applications", "get", appRBACName(a)) {
newItems = append(newItems, a)
}
}
appList.Items = newItems
return appList, nil
}
// Create creates an application
func (s *Server) Create(ctx context.Context, a *appv1.Application) (*appv1.Application, error) {
upsert := false
md, ok := metadata.FromIncomingContext(ctx)
if ok {
upsertMd := md["upsert"]
upsert = len(upsertMd) > 0 && upsertMd[0] == "true"
func (s *Server) Create(ctx context.Context, q *ApplicationCreateRequest) (*appv1.Application, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "create", appRBACName(q.Application)) {
return nil, grpc.ErrPermissionDenied
}
a := q.Application
err := s.validateApp(ctx, &a.Spec)
if err != nil {
return nil, err
}
a.SetCascadedDeletion(true)
out, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Create(a)
out, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Create(&a)
if apierr.IsAlreadyExists(err) {
// act idempotent if existing spec matches new spec
existing, getErr := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(a.Name, metav1.GetOptions{})
if getErr != nil {
return nil, fmt.Errorf("unable to check existing application details: %v", err)
return nil, status.Errorf(codes.Internal, "unable to check existing application details: %v", err)
}
if upsert {
if q.Upsert != nil && *q.Upsert {
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "update", appRBACName(a)) {
return nil, grpc.ErrPermissionDenied
}
existing.Spec = a.Spec
out, err = s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Update(existing)
} else {
if reflect.DeepEqual(existing.Spec, a.Spec) {
return existing, nil
} else {
return nil, fmt.Errorf("existing application spec is different, use upsert flag to force update")
return nil, status.Errorf(codes.InvalidArgument, "existing application spec is different, use upsert flag to force update")
}
}
}
@@ -104,37 +126,40 @@ func (s *Server) Create(ctx context.Context, a *appv1.Application) (*appv1.Appli
}
// GetManifests returns application manifests
func (s *Server) GetManifests(ctx context.Context, q *ManifestQuery) (*repository.ManifestResponse, error) {
app, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.AppName, metav1.GetOptions{})
func (s *Server) GetManifests(ctx context.Context, q *ApplicationManifestQuery) (*repository.ManifestResponse, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
repo := s.getRepo(ctx, app.Spec.Source.RepoURL)
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications/manifests", "get", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
repo := s.getRepo(ctx, a.Spec.Source.RepoURL)
conn, repoClient, err := s.repoClientset.NewRepositoryClient()
if err != nil {
return nil, err
}
defer util.Close(conn)
overrides := make([]*appv1.ComponentParameter, len(app.Spec.Source.ComponentParameterOverrides))
if app.Spec.Source.ComponentParameterOverrides != nil {
for i := range app.Spec.Source.ComponentParameterOverrides {
item := app.Spec.Source.ComponentParameterOverrides[i]
overrides := make([]*appv1.ComponentParameter, len(a.Spec.Source.ComponentParameterOverrides))
if a.Spec.Source.ComponentParameterOverrides != nil {
for i := range a.Spec.Source.ComponentParameterOverrides {
item := a.Spec.Source.ComponentParameterOverrides[i]
overrides[i] = &item
}
}
revision := app.Spec.Source.TargetRevision
if q.Revision != nil && *q.Revision != "" {
revision = *q.Revision
revision := a.Spec.Source.TargetRevision
if q.Revision != "" {
revision = q.Revision
}
manifestInfo, err := repoClient.GenerateManifest(context.Background(), &repository.ManifestRequest{
Repo: repo,
Environment: app.Spec.Source.Environment,
Path: app.Spec.Source.Path,
Environment: a.Spec.Source.Environment,
Path: a.Spec.Source.Path,
Revision: revision,
ComponentParameterOverrides: overrides,
AppLabel: app.Name,
AppLabel: a.Name,
})
if err != nil {
return nil, err
@@ -145,12 +170,37 @@ func (s *Server) GetManifests(ctx context.Context, q *ManifestQuery) (*repositor
// Get returns an application by name
func (s *Server) Get(ctx context.Context, q *ApplicationQuery) (*appv1.Application, error) {
return s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
appIf := s.appclientset.ArgoprojV1alpha1().Applications(s.ns)
a, err := appIf.Get(*q.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "get", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
if q.Refresh {
_, err = argoutil.RefreshApp(appIf, *q.Name)
if err != nil {
return nil, err
}
a, err = argoutil.WaitForRefresh(appIf, *q.Name, nil)
if err != nil {
return nil, err
}
}
return a, nil
}
// ListResourceEvents returns a list of event resources
func (s *Server) ListResourceEvents(ctx context.Context, q *ApplicationResourceEventsQuery) (*v1.EventList, error) {
config, namespace, err := s.getApplicationClusterConfig(*q.AppName)
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications/events", "get", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
config, namespace, err := s.getApplicationClusterConfig(*q.Name)
if err != nil {
return nil, err
}
@@ -160,8 +210,8 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *ApplicationResourceE
}
fieldSelector := fields.SelectorFromSet(map[string]string{
"involvedObject.name": *q.ResName,
"involvedObject.uid": *q.ResUid,
"involvedObject.name": q.ResourceName,
"involvedObject.uid": q.ResourceUID,
"involvedObject.namespace": namespace,
}).String()
@@ -172,7 +222,11 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *ApplicationResourceE
}
// Update updates an application
func (s *Server) Update(ctx context.Context, a *appv1.Application) (*appv1.Application, error) {
func (s *Server) Update(ctx context.Context, q *ApplicationUpdateRequest) (*appv1.Application, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "update", appRBACName(*q.Application)) {
return nil, grpc.ErrPermissionDenied
}
a := q.Application
err := s.validateApp(ctx, &a.Spec)
if err != nil {
return nil, err
@@ -181,8 +235,15 @@ func (s *Server) Update(ctx context.Context, a *appv1.Application) (*appv1.Appli
}
// UpdateSpec updates an application spec
func (s *Server) UpdateSpec(ctx context.Context, q *ApplicationSpecRequest) (*appv1.ApplicationSpec, error) {
err := s.validateApp(ctx, &q.Spec)
func (s *Server) UpdateSpec(ctx context.Context, q *ApplicationUpdateSpecRequest) (*appv1.ApplicationSpec, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "update", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
err = s.validateApp(ctx, &q.Spec)
if err != nil {
return nil, err
}
@@ -192,32 +253,34 @@ func (s *Server) UpdateSpec(ctx context.Context, q *ApplicationSpecRequest) (*ap
if err != nil {
return nil, err
}
_, err = s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Patch(*q.AppName, types.MergePatchType, patch)
_, err = s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Patch(*q.Name, types.MergePatchType, patch)
return &q.Spec, err
}
// Delete removes an application and all associated resources
func (s *Server) Delete(ctx context.Context, q *DeleteApplicationRequest) (*ApplicationResponse, error) {
func (s *Server) Delete(ctx context.Context, q *ApplicationDeleteRequest) (*ApplicationResponse, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil && !apierr.IsNotFound(err) {
return nil, err
}
if q.Cascade != nil {
if *q.Cascade != a.CascadedDeletion() {
a.SetCascadedDeletion(*q.Cascade)
patch, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"finalizers": a.Finalizers,
},
})
if err != nil {
return nil, err
}
_, err = s.appclientset.ArgoprojV1alpha1().Applications(a.Namespace).Patch(a.Name, types.MergePatchType, patch)
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "delete", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
if q.Cascade != nil && *q.Cascade != a.CascadedDeletion() {
a.SetCascadedDeletion(*q.Cascade)
patch, err := json.Marshal(map[string]interface{}{
"metadata": map[string]interface{}{
"finalizers": a.Finalizers,
},
})
if err != nil {
return nil, err
}
_, err = s.appclientset.ArgoprojV1alpha1().Applications(a.Namespace).Patch(a.Name, types.MergePatchType, patch)
if err != nil {
return nil, err
}
}
@@ -234,14 +297,19 @@ func (s *Server) Watch(q *ApplicationQuery, ws ApplicationService_WatchServer) e
if err != nil {
return err
}
claims := ws.Context().Value("claims")
done := make(chan bool)
go func() {
for next := range w.ResultChan() {
app := *next.Object.(*appv1.Application)
if q.Name == nil || *q.Name == "" || *q.Name == app.Name {
a := *next.Object.(*appv1.Application)
if q.Name == nil || *q.Name == "" || *q.Name == a.Name {
if !s.enf.EnforceClaims(claims, "applications", "get", appRBACName(a)) {
// do not emit apps user does not have accessing
continue
}
err = ws.Send(&appv1.ApplicationWatchEvent{
Type: next.Type,
Application: app,
Application: a,
})
if err != nil {
log.Warnf("Unable to send stream message: %v", err)
@@ -356,7 +424,7 @@ func (s *Server) ensurePodBelongsToApp(applicationName string, podName, namespac
if err != nil {
return err
}
wrongPodError := fmt.Errorf("pod %s does not belong to application %s", podName, applicationName)
wrongPodError := status.Errorf(codes.InvalidArgument, "pod %s does not belong to application %s", podName, applicationName)
if pod.Labels == nil {
return wrongPodError
}
@@ -366,8 +434,17 @@ func (s *Server) ensurePodBelongsToApp(applicationName string, podName, namespac
return nil
}
func (s *Server) DeletePod(ctx context.Context, q *DeletePodQuery) (*ApplicationResponse, error) {
config, namespace, err := s.getApplicationClusterConfig(*q.ApplicationName)
func (s *Server) DeletePod(ctx context.Context, q *ApplicationDeletePodRequest) (*ApplicationResponse, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications/pods", "delete", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
config, namespace, err := s.getApplicationClusterConfig(*q.Name)
if err != nil {
return nil, err
}
@@ -375,7 +452,7 @@ func (s *Server) DeletePod(ctx context.Context, q *DeletePodQuery) (*Application
if err != nil {
return nil, err
}
err = s.ensurePodBelongsToApp(*q.ApplicationName, *q.PodName, namespace, kubeClientset)
err = s.ensurePodBelongsToApp(*q.Name, *q.PodName, namespace, kubeClientset)
if err != nil {
return nil, err
}
@@ -386,8 +463,15 @@ func (s *Server) DeletePod(ctx context.Context, q *DeletePodQuery) (*Application
return &ApplicationResponse{}, nil
}
func (s *Server) PodLogs(q *PodLogsQuery, ws ApplicationService_PodLogsServer) error {
config, namespace, err := s.getApplicationClusterConfig(*q.ApplicationName)
func (s *Server) PodLogs(q *ApplicationPodLogsQuery, ws ApplicationService_PodLogsServer) error {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*q.Name, metav1.GetOptions{})
if err != nil {
return err
}
if !s.enf.EnforceClaims(ws.Context().Value("claims"), "applications/logs", "get", appRBACName(*a)) {
return grpc.ErrPermissionDenied
}
config, namespace, err := s.getApplicationClusterConfig(*q.Name)
if err != nil {
return err
}
@@ -395,7 +479,7 @@ func (s *Server) PodLogs(q *PodLogsQuery, ws ApplicationService_PodLogsServer) e
if err != nil {
return err
}
err = s.ensurePodBelongsToApp(*q.ApplicationName, *q.PodName, namespace, kubeClientset)
err = s.ensurePodBelongsToApp(*q.Name, *q.PodName, namespace, kubeClientset)
if err != nil {
return err
}
@@ -453,11 +537,11 @@ func (s *Server) PodLogs(q *PodLogsQuery, ws ApplicationService_PodLogsServer) e
}
func (s *Server) getApplicationDestination(ctx context.Context, name string) (string, string, error) {
app, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(name, metav1.GetOptions{})
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(name, metav1.GetOptions{})
if err != nil {
return "", "", err
}
server, namespace := app.Spec.Destination.Server, app.Spec.Destination.Namespace
server, namespace := a.Spec.Destination.Server, a.Spec.Destination.Namespace
return server, namespace, nil
}
@@ -472,6 +556,13 @@ func (s *Server) getRepo(ctx context.Context, repoURL string) *appv1.Repository
// Sync syncs an application to its target state
func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*appv1.Application, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*syncReq.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "sync", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
return s.setAppOperation(ctx, *syncReq.Name, func(app *appv1.Application) (*appv1.Operation, error) {
return &appv1.Operation{
Sync: &appv1.SyncOperation{
@@ -484,6 +575,13 @@ func (s *Server) Sync(ctx context.Context, syncReq *ApplicationSyncRequest) (*ap
}
func (s *Server) Rollback(ctx context.Context, rollbackReq *ApplicationRollbackRequest) (*appv1.Application, error) {
a, err := s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Get(*rollbackReq.Name, metav1.GetOptions{})
if err != nil {
return nil, err
}
if !s.enf.EnforceClaims(ctx.Value("claims"), "applications", "rollback", appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
return s.setAppOperation(ctx, *rollbackReq.Name, func(app *appv1.Application) (*appv1.Operation, error) {
return &appv1.Operation{
Rollback: &appv1.RollbackOperation{
@@ -510,7 +608,7 @@ func (s *Server) setAppOperation(ctx context.Context, appName string, operationC
}
a.Operation = op
a.Status.OperationState = nil
_, err = s.Update(ctx, a)
_, err = s.appclientset.ArgoprojV1alpha1().Applications(s.ns).Update(a)
if err != nil && apierr.IsConflict(err) {
log.Warnf("Failed to set operation for app '%s' due to update conflict. Retrying again...", appName)
} else {

File diff suppressed because it is too large Load Diff

View File

@@ -12,7 +12,6 @@ import (
"io"
"net/http"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
@@ -47,7 +46,7 @@ func request_ApplicationService_List_0(ctx context.Context, marshaler runtime.Ma
}
var (
filter_ApplicationService_ListResourceEvents_0 = &utilities.DoubleArray{Encoding: map[string]int{"appName": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
filter_ApplicationService_ListResourceEvents_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_ApplicationService_ListResourceEvents_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
@@ -61,15 +60,15 @@ func request_ApplicationService_ListResourceEvents_0(ctx context.Context, marsha
_ = err
)
val, ok = pathParams["appName"]
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "appName")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.AppName, err = runtime.StringP(val)
protoReq.Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "appName", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ApplicationService_ListResourceEvents_0); err != nil {
@@ -106,11 +105,19 @@ func request_ApplicationService_Watch_0(ctx context.Context, marshaler runtime.M
}
var (
filter_ApplicationService_Create_0 = &utilities.DoubleArray{Encoding: map[string]int{"application": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_ApplicationService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq v1alpha1.Application
var protoReq ApplicationCreateRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Application); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ApplicationService_Create_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -119,6 +126,10 @@ func request_ApplicationService_Create_0(ctx context.Context, marshaler runtime.
}
var (
filter_ApplicationService_Get_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_ApplicationService_Get_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ApplicationQuery
var metadata runtime.ServerMetadata
@@ -141,17 +152,21 @@ func request_ApplicationService_Get_0(ctx context.Context, marshaler runtime.Mar
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ApplicationService_Get_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.Get(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
var (
filter_ApplicationService_GetManifests_0 = &utilities.DoubleArray{Encoding: map[string]int{"appName": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
filter_ApplicationService_GetManifests_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_ApplicationService_GetManifests_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ManifestQuery
var protoReq ApplicationManifestQuery
var metadata runtime.ServerMetadata
var (
@@ -161,15 +176,15 @@ func request_ApplicationService_GetManifests_0(ctx context.Context, marshaler ru
_ = err
)
val, ok = pathParams["appName"]
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "appName")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.AppName, err = runtime.StringP(val)
protoReq.Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "appName", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_ApplicationService_GetManifests_0); err != nil {
@@ -182,10 +197,10 @@ func request_ApplicationService_GetManifests_0(ctx context.Context, marshaler ru
}
func request_ApplicationService_Update_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq v1alpha1.Application
var protoReq ApplicationUpdateRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Application); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -196,15 +211,15 @@ func request_ApplicationService_Update_0(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["metadata.name"]
val, ok = pathParams["application.metadata.name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "metadata.name")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "application.metadata.name")
}
protoReq.GetMetadata().Name, err = runtime.StringP(val)
protoReq.GetApplication().GetMetadata().Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "metadata.name", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "application.metadata.name", err)
}
msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -213,10 +228,10 @@ func request_ApplicationService_Update_0(ctx context.Context, marshaler runtime.
}
func request_ApplicationService_UpdateSpec_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ApplicationSpecRequest
var protoReq ApplicationUpdateSpecRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Spec); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -227,15 +242,15 @@ func request_ApplicationService_UpdateSpec_0(ctx context.Context, marshaler runt
_ = err
)
val, ok = pathParams["appName"]
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "appName")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.AppName, err = runtime.StringP(val)
protoReq.Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "appName", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := client.UpdateSpec(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
@@ -248,7 +263,7 @@ var (
)
func request_ApplicationService_Delete_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeleteApplicationRequest
var protoReq ApplicationDeleteRequest
var metadata runtime.ServerMetadata
var (
@@ -341,7 +356,7 @@ func request_ApplicationService_Rollback_0(ctx context.Context, marshaler runtim
}
func request_ApplicationService_DeletePod_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq DeletePodQuery
var protoReq ApplicationDeletePodRequest
var metadata runtime.ServerMetadata
var (
@@ -351,15 +366,15 @@ func request_ApplicationService_DeletePod_0(ctx context.Context, marshaler runti
_ = err
)
val, ok = pathParams["applicationName"]
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "applicationName")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.ApplicationName, err = runtime.StringP(val)
protoReq.Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "applicationName", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
val, ok = pathParams["podName"]
@@ -379,11 +394,11 @@ func request_ApplicationService_DeletePod_0(ctx context.Context, marshaler runti
}
var (
filter_ApplicationService_PodLogs_0 = &utilities.DoubleArray{Encoding: map[string]int{"applicationName": 0, "podName": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
filter_ApplicationService_PodLogs_0 = &utilities.DoubleArray{Encoding: map[string]int{"name": 0, "podName": 1}, Base: []int{1, 1, 2, 0, 0}, Check: []int{0, 1, 1, 2, 3}}
)
func request_ApplicationService_PodLogs_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (ApplicationService_PodLogsClient, runtime.ServerMetadata, error) {
var protoReq PodLogsQuery
var protoReq ApplicationPodLogsQuery
var metadata runtime.ServerMetadata
var (
@@ -393,15 +408,15 @@ func request_ApplicationService_PodLogs_0(ctx context.Context, marshaler runtime
_ = err
)
val, ok = pathParams["applicationName"]
val, ok = pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "applicationName")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.ApplicationName, err = runtime.StringP(val)
protoReq.Name, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "applicationName", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
val, ok = pathParams["podName"]
@@ -853,7 +868,7 @@ func RegisterApplicationServiceHandlerClient(ctx context.Context, mux *runtime.S
var (
pattern_ApplicationService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "applications"}, ""))
pattern_ApplicationService_ListResourceEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "appName", "events"}, ""))
pattern_ApplicationService_ListResourceEvents_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "name", "events"}, ""))
pattern_ApplicationService_Watch_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "stream", "applications"}, ""))
@@ -861,11 +876,11 @@ var (
pattern_ApplicationService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "name"}, ""))
pattern_ApplicationService_GetManifests_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "appName", "manifests"}, ""))
pattern_ApplicationService_GetManifests_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "name", "manifests"}, ""))
pattern_ApplicationService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "metadata.name"}, ""))
pattern_ApplicationService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "application.metadata.name"}, ""))
pattern_ApplicationService_UpdateSpec_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "appName", "spec"}, ""))
pattern_ApplicationService_UpdateSpec_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "name", "spec"}, ""))
pattern_ApplicationService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "applications", "name"}, ""))
@@ -873,9 +888,9 @@ var (
pattern_ApplicationService_Rollback_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "applications", "name", "rollback"}, ""))
pattern_ApplicationService_DeletePod_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "applications", "applicationName", "pods", "podName"}, ""))
pattern_ApplicationService_DeletePod_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5}, []string{"api", "v1", "applications", "name", "pods", "podName"}, ""))
pattern_ApplicationService_PodLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"api", "v1", "applications", "applicationName", "pods", "podName", "logs"}, ""))
pattern_ApplicationService_PodLogs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4, 1, 0, 4, 1, 5, 5, 2, 6}, []string{"api", "v1", "applications", "name", "pods", "podName", "logs"}, ""))
)
var (

View File

@@ -17,24 +17,34 @@ import "github.com/argoproj/argo-cd/reposerver/repository/repository.proto";
// ApplicationQuery is a query for application resources
message ApplicationQuery {
optional string name = 1;
optional bool refresh = 2 [(gogoproto.nullable) = false];
}
// ApplicationEventsQuery is a query for application resource events
message ApplicationResourceEventsQuery {
required string appName = 1;
required string resName = 2;
required string resUid = 3;
required string name = 1;
required string resourceName = 2 [(gogoproto.nullable) = false];
required string resourceUID = 3 [(gogoproto.nullable) = false];
}
// ManifestQuery is a query for manifest resources
message ManifestQuery {
required string appName = 1;
optional string revision = 2;
message ApplicationManifestQuery {
required string name = 1;
optional string revision = 2 [(gogoproto.nullable) = false];
}
message ApplicationResponse {}
message DeleteApplicationRequest {
message ApplicationCreateRequest {
required github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application application = 1 [(gogoproto.nullable) = false];
optional bool upsert = 2;
}
message ApplicationUpdateRequest {
required github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application application = 1;
}
message ApplicationDeleteRequest {
required string name = 1;
optional bool cascade = 2;
}
@@ -47,9 +57,9 @@ message ApplicationSyncRequest {
required bool prune = 4 [(gogoproto.nullable) = false];
}
// ApplicationSpecRequest is a request to update application spec
message ApplicationSpecRequest {
required string appName = 1;
// ApplicationUpdateSpecRequest is a request to update application spec
message ApplicationUpdateSpecRequest {
required string name = 1;
required github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSpec spec = 2 [(gogoproto.nullable) = false];
}
@@ -60,13 +70,13 @@ message ApplicationRollbackRequest {
required bool prune = 4 [(gogoproto.nullable) = false];
}
message DeletePodQuery {
required string applicationName = 1;
message ApplicationDeletePodRequest {
required string name = 1;
required string podName = 2;
}
message PodLogsQuery {
required string applicationName = 1;
message ApplicationPodLogsQuery {
required string name = 1;
required string podName = 2;
required string container = 3 [(gogoproto.nullable) = false];
required int64 sinceSeconds = 4 [(gogoproto.nullable) = false];
@@ -90,7 +100,7 @@ service ApplicationService {
// ListResourceEvents returns a list of event resources
rpc ListResourceEvents(ApplicationResourceEventsQuery) returns (k8s.io.api.core.v1.EventList) {
option (google.api.http).get = "/api/v1/applications/{appName}/events";
option (google.api.http).get = "/api/v1/applications/{name}/events";
}
// Watch returns stream of application change events.
@@ -99,10 +109,10 @@ service ApplicationService {
}
// Create creates an application
rpc Create(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) {
rpc Create(ApplicationCreateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) {
option (google.api.http) = {
post: "/api/v1/applications"
body: "*"
body: "application"
};
}
@@ -112,28 +122,28 @@ service ApplicationService {
}
// GetManifests returns application manifests
rpc GetManifests(ManifestQuery) returns (repository.ManifestResponse) {
option (google.api.http).get = "/api/v1/applications/{appName}/manifests";
rpc GetManifests(ApplicationManifestQuery) returns (repository.ManifestResponse) {
option (google.api.http).get = "/api/v1/applications/{name}/manifests";
}
// Update updates an application
rpc Update(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) {
rpc Update(ApplicationUpdateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) {
option (google.api.http) = {
put: "/api/v1/applications/{metadata.name}"
body: "*"
put: "/api/v1/applications/{application.metadata.name}"
body: "application"
};
}
// Update updates an application spec
rpc UpdateSpec(ApplicationSpecRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSpec) {
rpc UpdateSpec(ApplicationUpdateSpecRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSpec) {
option (google.api.http) = {
put: "/api/v1/applications/{appName}/spec"
body: "*"
put: "/api/v1/applications/{name}/spec"
body: "spec"
};
}
// Delete deletes an application
rpc Delete(DeleteApplicationRequest) returns (ApplicationResponse) {
rpc Delete(ApplicationDeleteRequest) returns (ApplicationResponse) {
option (google.api.http).delete = "/api/v1/applications/{name}";
}
@@ -154,12 +164,12 @@ service ApplicationService {
}
// PodLogs returns stream of log entries for the specified pod. Pod
rpc DeletePod(DeletePodQuery) returns (ApplicationResponse) {
option (google.api.http).delete = "/api/v1/applications/{applicationName}/pods/{podName}";
rpc DeletePod(ApplicationDeletePodRequest) returns (ApplicationResponse) {
option (google.api.http).delete = "/api/v1/applications/{name}/pods/{podName}";
}
// PodLogs returns stream of log entries for the specified pod. Pod
rpc PodLogs(PodLogsQuery) returns (stream LogEntry) {
option (google.api.http).get = "/api/v1/applications/{applicationName}/pods/{podName}/logs";
rpc PodLogs(ApplicationPodLogsQuery) returns (stream LogEntry) {
option (google.api.http).get = "/api/v1/applications/{name}/pods/{podName}/logs";
}
}

View File

@@ -1,21 +1,27 @@
package cluster
import (
"github.com/argoproj/argo-cd/util/db"
"fmt"
"golang.org/x/net/context"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"golang.org/x/net/context"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/grpc"
"github.com/argoproj/argo-cd/util/rbac"
)
// Server provides a Cluster service
type Server struct {
db db.ArgoDB
db db.ArgoDB
enf *rbac.Enforcer
}
// NewServer returns a new instance of the Cluster service
func NewServer(db db.ArgoDB) *Server {
func NewServer(db db.ArgoDB, enf *rbac.Enforcer) *Server {
return &Server{
db: db,
db: db,
enf: enf,
}
}
@@ -23,38 +29,49 @@ func NewServer(db db.ArgoDB) *Server {
func (s *Server) List(ctx context.Context, q *ClusterQuery) (*appv1.ClusterList, error) {
clusterList, err := s.db.ListClusters(ctx)
if clusterList != nil {
for i, clust := range clusterList.Items {
clusterList.Items[i] = *redact(&clust)
newItems := make([]appv1.Cluster, 0)
for _, clust := range clusterList.Items {
if s.enf.EnforceClaims(ctx.Value("claims"), "clusters", "get", fmt.Sprintf("*/%s", clust.Server)) {
newItems = append(newItems, *redact(&clust))
}
}
clusterList.Items = newItems
}
return clusterList, err
}
// Create creates a cluster
func (s *Server) Create(ctx context.Context, c *appv1.Cluster) (*appv1.Cluster, error) {
clust, err := s.db.CreateCluster(ctx, c)
func (s *Server) Create(ctx context.Context, q *ClusterCreateRequest) (*appv1.Cluster, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "clusters", "create", fmt.Sprintf("*/%s", q.Cluster.Server)) {
return nil, grpc.ErrPermissionDenied
}
clust, err := s.db.CreateCluster(ctx, q.Cluster)
return redact(clust), err
}
// Get returns a cluster from a query
func (s *Server) Get(ctx context.Context, q *ClusterQuery) (*appv1.Cluster, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "clusters", "get", fmt.Sprintf("*/%s", q.Server)) {
return nil, grpc.ErrPermissionDenied
}
clust, err := s.db.GetCluster(ctx, q.Server)
return redact(clust), err
}
// Update updates a cluster
func (s *Server) Update(ctx context.Context, c *appv1.Cluster) (*appv1.Cluster, error) {
clust, err := s.db.UpdateCluster(ctx, c)
func (s *Server) Update(ctx context.Context, q *ClusterUpdateRequest) (*appv1.Cluster, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "clusters", "update", fmt.Sprintf("*/%s", q.Cluster.Server)) {
return nil, grpc.ErrPermissionDenied
}
clust, err := s.db.UpdateCluster(ctx, q.Cluster)
return redact(clust), err
}
// UpdateREST updates a cluster (special handler intended to be used only by the gRPC gateway)
func (s *Server) UpdateREST(ctx context.Context, r *ClusterUpdateRequest) (*appv1.Cluster, error) {
return s.Update(ctx, r.Cluster)
}
// Delete deletes a cluster by name
func (s *Server) Delete(ctx context.Context, q *ClusterQuery) (*ClusterResponse, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "clusters", "delete", fmt.Sprintf("*/%s", q.Server)) {
return nil, grpc.ErrPermissionDenied
}
err := s.db.DeleteCluster(ctx, q.Server)
return &ClusterResponse{}, err
}

View File

@@ -14,6 +14,7 @@
It has these top-level messages:
ClusterQuery
ClusterResponse
ClusterCreateRequest
ClusterUpdateRequest
*/
package cluster
@@ -67,22 +68,30 @@ func (m *ClusterResponse) String() string { return proto.CompactTextS
func (*ClusterResponse) ProtoMessage() {}
func (*ClusterResponse) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{1} }
type ClusterCreateRequest struct {
Cluster *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster `protobuf:"bytes,1,opt,name=cluster" json:"cluster,omitempty"`
}
func (m *ClusterCreateRequest) Reset() { *m = ClusterCreateRequest{} }
func (m *ClusterCreateRequest) String() string { return proto.CompactTextString(m) }
func (*ClusterCreateRequest) ProtoMessage() {}
func (*ClusterCreateRequest) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{2} }
func (m *ClusterCreateRequest) GetCluster() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster {
if m != nil {
return m.Cluster
}
return nil
}
type ClusterUpdateRequest struct {
Server string `protobuf:"bytes,1,opt,name=server,proto3" json:"server,omitempty"`
Cluster *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster `protobuf:"bytes,2,opt,name=cluster" json:"cluster,omitempty"`
Cluster *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster `protobuf:"bytes,1,opt,name=cluster" json:"cluster,omitempty"`
}
func (m *ClusterUpdateRequest) Reset() { *m = ClusterUpdateRequest{} }
func (m *ClusterUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*ClusterUpdateRequest) ProtoMessage() {}
func (*ClusterUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{2} }
func (m *ClusterUpdateRequest) GetServer() string {
if m != nil {
return m.Server
}
return ""
}
func (*ClusterUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorCluster, []int{3} }
func (m *ClusterUpdateRequest) GetCluster() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster {
if m != nil {
@@ -94,6 +103,7 @@ func (m *ClusterUpdateRequest) GetCluster() *github_com_argoproj_argo_cd_pkg_api
func init() {
proto.RegisterType((*ClusterQuery)(nil), "cluster.ClusterQuery")
proto.RegisterType((*ClusterResponse)(nil), "cluster.ClusterResponse")
proto.RegisterType((*ClusterCreateRequest)(nil), "cluster.ClusterCreateRequest")
proto.RegisterType((*ClusterUpdateRequest)(nil), "cluster.ClusterUpdateRequest")
}
@@ -111,13 +121,11 @@ type ClusterServiceClient interface {
// List returns list of clusters
List(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ClusterList, error)
// Create creates a cluster
Create(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
Create(ctx context.Context, in *ClusterCreateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Get returns a cluster by server address
Get(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Update updates a cluster
Update(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Update updates a cluster (special handler intended to be used only by the gRPC gateway)
UpdateREST(ctx context.Context, in *ClusterUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
Update(ctx context.Context, in *ClusterUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Delete updates a cluster
Delete(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*ClusterResponse, error)
}
@@ -139,7 +147,7 @@ func (c *clusterServiceClient) List(ctx context.Context, in *ClusterQuery, opts
return out, nil
}
func (c *clusterServiceClient) Create(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error) {
func (c *clusterServiceClient) Create(ctx context.Context, in *ClusterCreateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster)
err := grpc.Invoke(ctx, "/cluster.ClusterService/Create", in, out, c.cc, opts...)
if err != nil {
@@ -157,7 +165,7 @@ func (c *clusterServiceClient) Get(ctx context.Context, in *ClusterQuery, opts .
return out, nil
}
func (c *clusterServiceClient) Update(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error) {
func (c *clusterServiceClient) Update(ctx context.Context, in *ClusterUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster)
err := grpc.Invoke(ctx, "/cluster.ClusterService/Update", in, out, c.cc, opts...)
if err != nil {
@@ -166,15 +174,6 @@ func (c *clusterServiceClient) Update(ctx context.Context, in *github_com_argopr
return out, nil
}
func (c *clusterServiceClient) UpdateREST(ctx context.Context, in *ClusterUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster)
err := grpc.Invoke(ctx, "/cluster.ClusterService/UpdateREST", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *clusterServiceClient) Delete(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*ClusterResponse, error) {
out := new(ClusterResponse)
err := grpc.Invoke(ctx, "/cluster.ClusterService/Delete", in, out, c.cc, opts...)
@@ -190,13 +189,11 @@ type ClusterServiceServer interface {
// List returns list of clusters
List(context.Context, *ClusterQuery) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.ClusterList, error)
// Create creates a cluster
Create(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
Create(context.Context, *ClusterCreateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Get returns a cluster by server address
Get(context.Context, *ClusterQuery) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Update updates a cluster
Update(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Update updates a cluster (special handler intended to be used only by the gRPC gateway)
UpdateREST(context.Context, *ClusterUpdateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
Update(context.Context, *ClusterUpdateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster, error)
// Delete updates a cluster
Delete(context.Context, *ClusterQuery) (*ClusterResponse, error)
}
@@ -224,7 +221,7 @@ func _ClusterService_List_Handler(srv interface{}, ctx context.Context, dec func
}
func _ClusterService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster)
in := new(ClusterCreateRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -236,7 +233,7 @@ func _ClusterService_Create_Handler(srv interface{}, ctx context.Context, dec fu
FullMethod: "/cluster.ClusterService/Create",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClusterServiceServer).Create(ctx, req.(*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster))
return srv.(ClusterServiceServer).Create(ctx, req.(*ClusterCreateRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -260,7 +257,7 @@ func _ClusterService_Get_Handler(srv interface{}, ctx context.Context, dec func(
}
func _ClusterService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster)
in := new(ClusterUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -272,25 +269,7 @@ func _ClusterService_Update_Handler(srv interface{}, ctx context.Context, dec fu
FullMethod: "/cluster.ClusterService/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClusterServiceServer).Update(ctx, req.(*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster))
}
return interceptor(ctx, in, info, handler)
}
func _ClusterService_UpdateREST_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ClusterUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClusterServiceServer).UpdateREST(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cluster.ClusterService/UpdateREST",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClusterServiceServer).UpdateREST(ctx, req.(*ClusterUpdateRequest))
return srv.(ClusterServiceServer).Update(ctx, req.(*ClusterUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -333,10 +312,6 @@ var _ClusterService_serviceDesc = grpc.ServiceDesc{
MethodName: "Update",
Handler: _ClusterService_Update_Handler,
},
{
MethodName: "UpdateREST",
Handler: _ClusterService_UpdateREST_Handler,
},
{
MethodName: "Delete",
Handler: _ClusterService_Delete_Handler,
@@ -388,6 +363,34 @@ func (m *ClusterResponse) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *ClusterCreateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *ClusterCreateRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Cluster != nil {
dAtA[i] = 0xa
i++
i = encodeVarintCluster(dAtA, i, uint64(m.Cluster.Size()))
n1, err := m.Cluster.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
}
return i, nil
}
func (m *ClusterUpdateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -403,21 +406,15 @@ func (m *ClusterUpdateRequest) MarshalTo(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Server) > 0 {
if m.Cluster != nil {
dAtA[i] = 0xa
i++
i = encodeVarintCluster(dAtA, i, uint64(len(m.Server)))
i += copy(dAtA[i:], m.Server)
}
if m.Cluster != nil {
dAtA[i] = 0x12
i++
i = encodeVarintCluster(dAtA, i, uint64(m.Cluster.Size()))
n1, err := m.Cluster.MarshalTo(dAtA[i:])
n2, err := m.Cluster.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n1
i += n2
}
return i, nil
}
@@ -447,13 +444,19 @@ func (m *ClusterResponse) Size() (n int) {
return n
}
func (m *ClusterCreateRequest) Size() (n int) {
var l int
_ = l
if m.Cluster != nil {
l = m.Cluster.Size()
n += 1 + l + sovCluster(uint64(l))
}
return n
}
func (m *ClusterUpdateRequest) Size() (n int) {
var l int
_ = l
l = len(m.Server)
if l > 0 {
n += 1 + l + sovCluster(uint64(l))
}
if m.Cluster != nil {
l = m.Cluster.Size()
n += 1 + l + sovCluster(uint64(l))
@@ -603,6 +606,89 @@ func (m *ClusterResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *ClusterCreateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCluster
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: ClusterCreateRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: ClusterCreateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cluster", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCluster
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthCluster
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Cluster == nil {
m.Cluster = &github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Cluster{}
}
if err := m.Cluster.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipCluster(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthCluster
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *ClusterUpdateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -633,35 +719,6 @@ func (m *ClusterUpdateRequest) Unmarshal(dAtA []byte) error {
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Server", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowCluster
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthCluster
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Server = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Cluster", wireType)
}
@@ -823,35 +880,34 @@ var (
func init() { proto.RegisterFile("server/cluster/cluster.proto", fileDescriptorCluster) }
var fileDescriptorCluster = []byte{
// 470 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x54, 0x4d, 0x6b, 0x15, 0x31,
0x14, 0x35, 0x55, 0x46, 0x8c, 0xe2, 0x47, 0x68, 0xe5, 0x39, 0xad, 0x8f, 0x3a, 0x88, 0x94, 0x07,
0x26, 0xbc, 0xba, 0x29, 0x5d, 0xb6, 0x7e, 0x20, 0xb8, 0xf1, 0x55, 0x37, 0x52, 0x90, 0x74, 0xe6,
0x92, 0x8e, 0x6f, 0x9c, 0xc4, 0x24, 0x33, 0x20, 0x22, 0x82, 0x6e, 0x5d, 0xe9, 0xd2, 0xdf, 0xe0,
0xff, 0x70, 0x29, 0xb8, 0x71, 0x29, 0x0f, 0x7f, 0x88, 0x4c, 0x26, 0xb1, 0xed, 0x2b, 0xe3, 0xc6,
0x59, 0x74, 0x35, 0xc9, 0x4d, 0xe6, 0x9c, 0x7b, 0xce, 0xbd, 0xb9, 0x78, 0xc5, 0x80, 0xae, 0x41,
0xb3, 0xb4, 0xa8, 0x8c, 0x3d, 0xf8, 0x52, 0xa5, 0xa5, 0x95, 0xe4, 0xac, 0xdf, 0xc6, 0x8b, 0x42,
0x0a, 0xe9, 0x62, 0xac, 0x59, 0xb5, 0xc7, 0xf1, 0x8a, 0x90, 0x52, 0x14, 0xc0, 0xb8, 0xca, 0x19,
0x2f, 0x4b, 0x69, 0xb9, 0xcd, 0x65, 0x69, 0xfc, 0x69, 0x32, 0xdd, 0x30, 0x34, 0x97, 0xee, 0x34,
0x95, 0x1a, 0x58, 0x3d, 0x66, 0x02, 0x4a, 0xd0, 0xdc, 0x42, 0xe6, 0xef, 0x3c, 0x14, 0xb9, 0xdd,
0xaf, 0xf6, 0x68, 0x2a, 0x5f, 0x32, 0xae, 0x1d, 0xc5, 0x0b, 0xb7, 0xb8, 0x9d, 0x66, 0x4c, 0x4d,
0x45, 0xf3, 0xb3, 0x61, 0x5c, 0xa9, 0x22, 0x4f, 0x1d, 0x38, 0xab, 0xc7, 0xbc, 0x50, 0xfb, 0xfc,
0x18, 0x54, 0x72, 0x0b, 0x5f, 0xd8, 0x6e, 0xb3, 0x7d, 0x5c, 0x81, 0x7e, 0x4d, 0xae, 0xe2, 0xa8,
0xd5, 0x36, 0x40, 0xab, 0x68, 0xed, 0xdc, 0xc4, 0xef, 0x92, 0x2b, 0xf8, 0x92, 0xbf, 0x37, 0x01,
0xa3, 0x64, 0x69, 0x20, 0xf9, 0x88, 0xf0, 0xa2, 0x8f, 0x3d, 0x55, 0x19, 0xb7, 0x30, 0x81, 0x57,
0x15, 0x18, 0xdb, 0x85, 0x41, 0x76, 0x71, 0x70, 0x66, 0xb0, 0xb0, 0x8a, 0xd6, 0xce, 0xaf, 0x6f,
0xd1, 0x03, 0x21, 0x34, 0x08, 0x71, 0x8b, 0xe7, 0x69, 0x46, 0xd5, 0x54, 0xd0, 0x46, 0x08, 0x3d,
0x24, 0x84, 0x06, 0x21, 0x34, 0x64, 0x13, 0x20, 0xd7, 0x7f, 0x46, 0xf8, 0xa2, 0x0f, 0xee, 0x80,
0xae, 0xf3, 0x14, 0xc8, 0x3b, 0x7c, 0xe6, 0x51, 0x6e, 0x2c, 0x59, 0xa2, 0xa1, 0x40, 0x87, 0xb5,
0xc6, 0xf7, 0xff, 0x9f, 0xbe, 0x81, 0x4f, 0x06, 0xef, 0x7f, 0xfc, 0xfe, 0xbc, 0x40, 0xc8, 0x65,
0x57, 0xb4, 0x7a, 0x1c, 0xda, 0xc1, 0x90, 0xaf, 0x08, 0x47, 0xdb, 0x1a, 0xb8, 0x05, 0xd2, 0x83,
0xd6, 0xb8, 0x07, 0x8c, 0x64, 0xd9, 0x25, 0xbb, 0x94, 0x1c, 0x4b, 0x76, 0x13, 0x8d, 0xc8, 0x07,
0x84, 0x4f, 0x3f, 0x80, 0x4e, 0xc3, 0xfa, 0xe0, 0xbf, 0xe1, 0xf8, 0x97, 0xc9, 0xb5, 0x79, 0x7e,
0xf6, 0xa6, 0x6d, 0x93, 0xb7, 0xe4, 0x13, 0xc2, 0x51, 0xdb, 0x51, 0x27, 0xc6, 0xb5, 0x53, 0xe4,
0x0b, 0xc2, 0xd8, 0xb7, 0xf9, 0xbd, 0x9d, 0x27, 0xe4, 0xfa, 0xbc, 0x43, 0x47, 0x9e, 0x40, 0x2f,
0x9c, 0x23, 0xe7, 0xd4, 0xcd, 0xb8, 0xdb, 0xa9, 0xcd, 0xd0, 0xfc, 0x64, 0x17, 0x47, 0x77, 0xa1,
0x00, 0x0b, 0x5d, 0xa5, 0x1b, 0xcc, 0x87, 0xff, 0x3e, 0x63, 0x5f, 0x90, 0x51, 0x37, 0xcd, 0xd6,
0xc6, 0xb7, 0xd9, 0x10, 0x7d, 0x9f, 0x0d, 0xd1, 0xaf, 0xd9, 0x10, 0x3d, 0x1b, 0xfd, 0x6b, 0xfa,
0x1c, 0x1d, 0x8c, 0x7b, 0x91, 0x9b, 0x32, 0x77, 0xfe, 0x04, 0x00, 0x00, 0xff, 0xff, 0xac, 0xa0,
0x1d, 0x93, 0x31, 0x05, 0x00, 0x00,
// 454 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0xcd, 0xaa, 0x13, 0x31,
0x14, 0xc7, 0x89, 0x1f, 0x23, 0x46, 0xf1, 0x23, 0x5c, 0xa5, 0x8e, 0xd7, 0xe2, 0x9d, 0x85, 0xc8,
0x45, 0x13, 0x5a, 0x37, 0x17, 0x97, 0xf7, 0x8a, 0x22, 0xb8, 0xb1, 0xe2, 0x46, 0x0a, 0x92, 0xce,
0x1c, 0xd2, 0xb1, 0xe3, 0x24, 0x26, 0x99, 0x01, 0x11, 0x11, 0x74, 0xef, 0xc6, 0x07, 0x70, 0xeb,
0xa3, 0xb8, 0x14, 0x7c, 0x01, 0x29, 0x3e, 0x88, 0x4c, 0x26, 0xb1, 0x1f, 0x43, 0xdd, 0x58, 0xee,
0xaa, 0xc9, 0x49, 0x7a, 0xfe, 0xbf, 0xf3, 0xcf, 0x99, 0x83, 0x77, 0x0d, 0xe8, 0x1a, 0x34, 0x4b,
0x8b, 0xca, 0xd8, 0xc5, 0x2f, 0x55, 0x5a, 0x5a, 0x49, 0xce, 0xf8, 0x6d, 0xbc, 0x23, 0xa4, 0x90,
0x2e, 0xc6, 0x9a, 0x55, 0x7b, 0x1c, 0xef, 0x0a, 0x29, 0x45, 0x01, 0x8c, 0xab, 0x9c, 0xf1, 0xb2,
0x94, 0x96, 0xdb, 0x5c, 0x96, 0xc6, 0x9f, 0x26, 0xb3, 0x03, 0x43, 0x73, 0xe9, 0x4e, 0x53, 0xa9,
0x81, 0xd5, 0x03, 0x26, 0xa0, 0x04, 0xcd, 0x2d, 0x64, 0xfe, 0xce, 0x63, 0x91, 0xdb, 0x69, 0x35,
0xa1, 0xa9, 0x7c, 0xcd, 0xb8, 0x76, 0x12, 0xaf, 0xdc, 0xe2, 0x6e, 0x9a, 0x31, 0x35, 0x13, 0xcd,
0x9f, 0x0d, 0xe3, 0x4a, 0x15, 0x79, 0xea, 0x92, 0xb3, 0x7a, 0xc0, 0x0b, 0x35, 0xe5, 0x9d, 0x54,
0xc9, 0x2d, 0x7c, 0xfe, 0xa8, 0xa5, 0x7d, 0x5a, 0x81, 0x7e, 0x4b, 0xae, 0xe2, 0xa8, 0xad, 0xad,
0x87, 0x6e, 0xa2, 0xdb, 0x67, 0x47, 0x7e, 0x97, 0x5c, 0xc6, 0x17, 0xfd, 0xbd, 0x11, 0x18, 0x25,
0x4b, 0x03, 0x89, 0xc5, 0x3b, 0x3e, 0x74, 0xa4, 0x81, 0x5b, 0x18, 0xc1, 0x9b, 0x0a, 0x8c, 0x25,
0x63, 0x1c, 0x0c, 0x70, 0x39, 0xce, 0x0d, 0x0f, 0xe9, 0x82, 0x97, 0x06, 0x5e, 0xb7, 0x78, 0x99,
0x66, 0x54, 0xcd, 0x04, 0x6d, 0x78, 0xe9, 0x12, 0x2f, 0x0d, 0xbc, 0x34, 0x88, 0x86, 0x94, 0x4b,
0xaa, 0xcf, 0x55, 0x76, 0x5c, 0xaa, 0xc3, 0x6f, 0xa7, 0xf1, 0x05, 0x1f, 0x7c, 0x06, 0xba, 0xce,
0x53, 0x20, 0x1f, 0xf0, 0xa9, 0x27, 0xb9, 0xb1, 0xe4, 0x0a, 0x0d, 0xaf, 0xbf, 0x6c, 0x64, 0xfc,
0xf0, 0xff, 0xe5, 0x9b, 0xf4, 0x49, 0xef, 0xe3, 0xcf, 0xdf, 0x5f, 0x4e, 0x10, 0x72, 0xc9, 0x75,
0x44, 0x3d, 0x08, 0xbd, 0x66, 0xc8, 0x67, 0x84, 0xa3, 0xd6, 0x79, 0x72, 0x63, 0x9d, 0x61, 0xe5,
0x45, 0xe2, 0x2d, 0x58, 0x91, 0xec, 0x39, 0x8e, 0xeb, 0x49, 0x87, 0xe3, 0x7e, 0x30, 0x89, 0x7c,
0x42, 0xf8, 0xe4, 0x23, 0xd8, 0xe8, 0xc8, 0x16, 0x29, 0xc8, 0xb5, 0x75, 0x0a, 0xf6, 0xae, 0x6d,
0xd4, 0xf7, 0xe4, 0x2b, 0xc2, 0x51, 0xdb, 0x1a, 0x5d, 0x5b, 0x56, 0x5a, 0x66, 0x2b, 0x40, 0x43,
0x07, 0x74, 0x27, 0xde, 0xeb, 0x02, 0x05, 0x6d, 0x0f, 0xb6, 0xf0, 0x69, 0x8c, 0xa3, 0x07, 0x50,
0x80, 0x85, 0x4d, 0x4e, 0xf5, 0xd6, 0xc3, 0x7f, 0xbf, 0x39, 0x5f, 0xff, 0xfe, 0xe6, 0xfa, 0x0f,
0x0f, 0xbe, 0xcf, 0xfb, 0xe8, 0xc7, 0xbc, 0x8f, 0x7e, 0xcd, 0xfb, 0xe8, 0xc5, 0xfe, 0xbf, 0x46,
0xc5, 0xea, 0x14, 0x9b, 0x44, 0x6e, 0x24, 0xdc, 0xfb, 0x13, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x32,
0x83, 0x14, 0xde, 0x04, 0x00, 0x00,
}

View File

@@ -12,7 +12,6 @@ import (
"io"
"net/http"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
@@ -47,10 +46,10 @@ func request_ClusterService_List_0(ctx context.Context, marshaler runtime.Marsha
}
func request_ClusterService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq v1alpha1.Cluster
var protoReq ClusterCreateRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Cluster); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -86,7 +85,7 @@ func request_ClusterService_Get_0(ctx context.Context, marshaler runtime.Marshal
}
func request_ClusterService_UpdateREST_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
func request_ClusterService_Update_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ClusterUpdateRequest
var metadata runtime.ServerMetadata
@@ -101,18 +100,18 @@ func request_ClusterService_UpdateREST_0(ctx context.Context, marshaler runtime.
_ = err
)
val, ok = pathParams["server"]
val, ok = pathParams["cluster.server"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "server")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "cluster.server")
}
protoReq.Server, err = runtime.String(val)
err = runtime.PopulateFieldFromPath(&protoReq, "cluster.server", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "server", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "cluster.server", err)
}
msg, err := client.UpdateREST(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
@@ -269,7 +268,7 @@ func RegisterClusterServiceHandlerClient(ctx context.Context, mux *runtime.Serve
})
mux.Handle("PUT", pattern_ClusterService_UpdateREST_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("PUT", pattern_ClusterService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
if cn, ok := w.(http.CloseNotifier); ok {
@@ -287,14 +286,14 @@ func RegisterClusterServiceHandlerClient(ctx context.Context, mux *runtime.Serve
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_ClusterService_UpdateREST_0(rctx, inboundMarshaler, client, req, pathParams)
resp, md, err := request_ClusterService_Update_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_ClusterService_UpdateREST_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_ClusterService_Update_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -337,7 +336,7 @@ var (
pattern_ClusterService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "server"}, ""))
pattern_ClusterService_UpdateREST_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "server"}, ""))
pattern_ClusterService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "cluster.server"}, ""))
pattern_ClusterService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "server"}, ""))
)
@@ -349,7 +348,7 @@ var (
forward_ClusterService_Get_0 = runtime.ForwardResponseMessage
forward_ClusterService_UpdateREST_0 = runtime.ForwardResponseMessage
forward_ClusterService_Update_0 = runtime.ForwardResponseMessage
forward_ClusterService_Delete_0 = runtime.ForwardResponseMessage
)

View File

@@ -19,9 +19,12 @@ message ClusterQuery {
message ClusterResponse {}
message ClusterCreateRequest {
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster cluster = 1;
}
message ClusterUpdateRequest {
string server = 1;
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster cluster = 2;
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster cluster = 1;
}
// ClusterService
@@ -33,26 +36,22 @@ service ClusterService {
}
// Create creates a cluster
rpc Create(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
rpc Create(ClusterCreateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
option (google.api.http) = {
post: "/api/v1/clusters"
body: "*"
body: "cluster"
};
}
// Get returns a cluster by server address
rpc Get(ClusterQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
// Get returns a cluster by server address
rpc Get(ClusterQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
option (google.api.http).get = "/api/v1/clusters/{server}";
}
// Update updates a cluster
rpc Update(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
}
// Update updates a cluster (special handler intended to be used only by the gRPC gateway)
rpc UpdateREST(ClusterUpdateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
rpc Update(ClusterUpdateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Cluster) {
option (google.api.http) = {
put: "/api/v1/clusters/{server}"
put: "/api/v1/clusters/{cluster.server}"
body: "cluster"
};
}

View File

@@ -4,7 +4,6 @@ package mocks
import cluster "github.com/argoproj/argo-cd/server/cluster"
import context "context"
import mock "github.com/stretchr/testify/mock"
import v1 "k8s.io/api/core/v1"
import v1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
// ClusterServiceServer is an autogenerated mock type for the ClusterServiceServer type
@@ -13,11 +12,11 @@ type ClusterServiceServer struct {
}
// Create provides a mock function with given fields: _a0, _a1
func (_m *ClusterServiceServer) Create(_a0 context.Context, _a1 *v1alpha1.Cluster) (*v1alpha1.Cluster, error) {
func (_m *ClusterServiceServer) Create(_a0 context.Context, _a1 *cluster.ClusterCreateRequest) (*v1alpha1.Cluster, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Cluster
if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Cluster) *v1alpha1.Cluster); ok {
if rf, ok := ret.Get(0).(func(context.Context, *cluster.ClusterCreateRequest) *v1alpha1.Cluster); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
@@ -26,7 +25,7 @@ func (_m *ClusterServiceServer) Create(_a0 context.Context, _a1 *v1alpha1.Cluste
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1alpha1.Cluster) error); ok {
if rf, ok := ret.Get(1).(func(context.Context, *cluster.ClusterCreateRequest) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
@@ -104,54 +103,8 @@ func (_m *ClusterServiceServer) List(_a0 context.Context, _a1 *cluster.ClusterQu
return r0, r1
}
// ListPods provides a mock function with given fields: _a0, _a1
func (_m *ClusterServiceServer) ListPods(_a0 context.Context, _a1 *cluster.ClusterQuery) (*v1.PodList, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1.PodList
if rf, ok := ret.Get(0).(func(context.Context, *cluster.ClusterQuery) *v1.PodList); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1.PodList)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *cluster.ClusterQuery) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// Update provides a mock function with given fields: _a0, _a1
func (_m *ClusterServiceServer) Update(_a0 context.Context, _a1 *v1alpha1.Cluster) (*v1alpha1.Cluster, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Cluster
if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Cluster) *v1alpha1.Cluster); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.Cluster)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1alpha1.Cluster) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
}
return r0, r1
}
// UpdateREST provides a mock function with given fields: _a0, _a1
func (_m *ClusterServiceServer) UpdateREST(_a0 context.Context, _a1 *cluster.ClusterUpdateRequest) (*v1alpha1.Cluster, error) {
func (_m *ClusterServiceServer) Update(_a0 context.Context, _a1 *cluster.ClusterUpdateRequest) (*v1alpha1.Cluster, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Cluster

View File

@@ -12,11 +12,11 @@ type RepositoryServiceServer struct {
}
// Create provides a mock function with given fields: _a0, _a1
func (_m *RepositoryServiceServer) Create(_a0 context.Context, _a1 *v1alpha1.Repository) (*v1alpha1.Repository, error) {
func (_m *RepositoryServiceServer) Create(_a0 context.Context, _a1 *repository.RepoCreateRequest) (*v1alpha1.Repository, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Repository
if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Repository) *v1alpha1.Repository); ok {
if rf, ok := ret.Get(0).(func(context.Context, *repository.RepoCreateRequest) *v1alpha1.Repository); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
@@ -25,7 +25,7 @@ func (_m *RepositoryServiceServer) Create(_a0 context.Context, _a1 *v1alpha1.Rep
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1alpha1.Repository) error); ok {
if rf, ok := ret.Get(1).(func(context.Context, *repository.RepoCreateRequest) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
@@ -103,21 +103,21 @@ func (_m *RepositoryServiceServer) List(_a0 context.Context, _a1 *repository.Rep
return r0, r1
}
// Update provides a mock function with given fields: _a0, _a1
func (_m *RepositoryServiceServer) Update(_a0 context.Context, _a1 *v1alpha1.Repository) (*v1alpha1.Repository, error) {
// ListKsonnetApps provides a mock function with given fields: _a0, _a1
func (_m *RepositoryServiceServer) ListKsonnetApps(_a0 context.Context, _a1 *repository.RepoKsonnetQuery) (*repository.RepoKsonnetResponse, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Repository
if rf, ok := ret.Get(0).(func(context.Context, *v1alpha1.Repository) *v1alpha1.Repository); ok {
var r0 *repository.RepoKsonnetResponse
if rf, ok := ret.Get(0).(func(context.Context, *repository.RepoKsonnetQuery) *repository.RepoKsonnetResponse); ok {
r0 = rf(_a0, _a1)
} else {
if ret.Get(0) != nil {
r0 = ret.Get(0).(*v1alpha1.Repository)
r0 = ret.Get(0).(*repository.RepoKsonnetResponse)
}
}
var r1 error
if rf, ok := ret.Get(1).(func(context.Context, *v1alpha1.Repository) error); ok {
if rf, ok := ret.Get(1).(func(context.Context, *repository.RepoKsonnetQuery) error); ok {
r1 = rf(_a0, _a1)
} else {
r1 = ret.Error(1)
@@ -126,8 +126,8 @@ func (_m *RepositoryServiceServer) Update(_a0 context.Context, _a1 *v1alpha1.Rep
return r0, r1
}
// UpdateREST provides a mock function with given fields: _a0, _a1
func (_m *RepositoryServiceServer) UpdateREST(_a0 context.Context, _a1 *repository.RepoUpdateRequest) (*v1alpha1.Repository, error) {
// Update provides a mock function with given fields: _a0, _a1
func (_m *RepositoryServiceServer) Update(_a0 context.Context, _a1 *repository.RepoUpdateRequest) (*v1alpha1.Repository, error) {
ret := _m.Called(_a0, _a1)
var r0 *v1alpha1.Repository

View File

@@ -1,29 +1,37 @@
package repository
import (
"fmt"
"github.com/ghodss/yaml"
"golang.org/x/net/context"
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/reposerver"
"github.com/argoproj/argo-cd/reposerver/repository"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/db"
"github.com/ghodss/yaml"
"golang.org/x/net/context"
"github.com/argoproj/argo-cd/util/grpc"
"github.com/argoproj/argo-cd/util/rbac"
)
// Server provides a Repository service
type Server struct {
db db.ArgoDB
repoClientset reposerver.Clientset
enf *rbac.Enforcer
}
// NewServer returns a new instance of the Repository service
func NewServer(
repoClientset reposerver.Clientset,
db db.ArgoDB,
enf *rbac.Enforcer,
) *Server {
return &Server{
db: db,
repoClientset: repoClientset,
enf: enf,
}
}
@@ -31,15 +39,22 @@ func NewServer(
func (s *Server) List(ctx context.Context, q *RepoQuery) (*appsv1.RepositoryList, error) {
repoList, err := s.db.ListRepositories(ctx)
if repoList != nil {
for i, repo := range repoList.Items {
repoList.Items[i] = *redact(&repo)
newItems := make([]appsv1.Repository, 0)
for _, repo := range repoList.Items {
if s.enf.EnforceClaims(ctx.Value("claims"), "repositories", "get", fmt.Sprintf("*/%s", repo.Repo)) {
newItems = append(newItems, *redact(&repo))
}
}
repoList.Items = newItems
}
return repoList, err
}
// ListKsonnetApps returns list of Ksonnet apps in the repo
func (s *Server) ListKsonnetApps(ctx context.Context, q *RepoKsonnetQuery) (*RepoKsonnetResponse, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "repositories/apps", "get", fmt.Sprintf("*/%s", q.Repo)) {
return nil, grpc.ErrPermissionDenied
}
repo, err := s.db.GetRepository(ctx, q.Repo)
if err != nil {
return nil, err
@@ -80,6 +95,7 @@ func (s *Server) ListKsonnetApps(ctx context.Context, q *RepoKsonnetQuery) (*Rep
}
var appSpec KsonnetAppSpec
appSpec.Path = path
err = yaml.Unmarshal(getFileRes.Data, &appSpec)
if err == nil && appSpec.Name != "" && len(appSpec.Environments) > 0 {
out = append(out, &appSpec)
@@ -87,35 +103,42 @@ func (s *Server) ListKsonnetApps(ctx context.Context, q *RepoKsonnetQuery) (*Rep
}
return &RepoKsonnetResponse{
Data: out,
Items: out,
}, nil
}
// Create creates a repository
func (s *Server) Create(ctx context.Context, r *appsv1.Repository) (*appsv1.Repository, error) {
repo, err := s.db.CreateRepository(ctx, r)
func (s *Server) Create(ctx context.Context, q *RepoCreateRequest) (*appsv1.Repository, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "repositories", "create", fmt.Sprintf("*/%s", q.Repo.Repo)) {
return nil, grpc.ErrPermissionDenied
}
repo, err := s.db.CreateRepository(ctx, q.Repo)
return redact(repo), err
}
// Get returns a repository by URL
func (s *Server) Get(ctx context.Context, q *RepoQuery) (*appsv1.Repository, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "repositories", "get", fmt.Sprintf("*/%s", q.Repo)) {
return nil, grpc.ErrPermissionDenied
}
repo, err := s.db.GetRepository(ctx, q.Repo)
return redact(repo), err
}
// Update updates a repository
func (s *Server) Update(ctx context.Context, r *appsv1.Repository) (*appsv1.Repository, error) {
repo, err := s.db.UpdateRepository(ctx, r)
func (s *Server) Update(ctx context.Context, q *RepoUpdateRequest) (*appsv1.Repository, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "repositories", "update", fmt.Sprintf("*/%s", q.Repo.Repo)) {
return nil, grpc.ErrPermissionDenied
}
repo, err := s.db.UpdateRepository(ctx, q.Repo)
return redact(repo), err
}
// UpdateREST updates a repository (from a REST request)
func (s *Server) UpdateREST(ctx context.Context, r *RepoUpdateRequest) (*appsv1.Repository, error) {
return s.Update(ctx, r.Repo)
}
// Delete updates a repository
func (s *Server) Delete(ctx context.Context, q *RepoQuery) (*RepoResponse, error) {
if !s.enf.EnforceClaims(ctx.Value("claims"), "repositories", "delete", fmt.Sprintf("*/%s", q.Repo)) {
return nil, grpc.ErrPermissionDenied
}
err := s.db.DeleteRepository(ctx, q.Repo)
return &RepoResponse{}, err
}

View File

@@ -19,6 +19,7 @@
KsonnetEnvironmentDestination
RepoQuery
RepoResponse
RepoCreateRequest
RepoUpdateRequest
*/
package repository
@@ -74,7 +75,7 @@ func (m *RepoKsonnetQuery) GetRevision() string {
// RepoKsonnetResponse is a response for Repository contents matching a particular path
type RepoKsonnetResponse struct {
Data []*KsonnetAppSpec `protobuf:"bytes,1,rep,name=data" json:"data,omitempty"`
Items []*KsonnetAppSpec `protobuf:"bytes,1,rep,name=items" json:"items,omitempty"`
}
func (m *RepoKsonnetResponse) Reset() { *m = RepoKsonnetResponse{} }
@@ -82,9 +83,9 @@ func (m *RepoKsonnetResponse) String() string { return proto.CompactT
func (*RepoKsonnetResponse) ProtoMessage() {}
func (*RepoKsonnetResponse) Descriptor() ([]byte, []int) { return fileDescriptorRepository, []int{1} }
func (m *RepoKsonnetResponse) GetData() []*KsonnetAppSpec {
func (m *RepoKsonnetResponse) GetItems() []*KsonnetAppSpec {
if m != nil {
return m.Data
return m.Items
}
return nil
}
@@ -93,7 +94,8 @@ func (m *RepoKsonnetResponse) GetData() []*KsonnetAppSpec {
// This roughly reflects: ksonnet/ksonnet/metadata/app/schema.go
type KsonnetAppSpec struct {
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
Environments map[string]*KsonnetEnvironment `protobuf:"bytes,2,rep,name=environments" json:"environments,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"`
Environments map[string]*KsonnetEnvironment `protobuf:"bytes,3,rep,name=environments" json:"environments,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value"`
}
func (m *KsonnetAppSpec) Reset() { *m = KsonnetAppSpec{} }
@@ -108,6 +110,13 @@ func (m *KsonnetAppSpec) GetName() string {
return ""
}
func (m *KsonnetAppSpec) GetPath() string {
if m != nil {
return m.Path
}
return ""
}
func (m *KsonnetAppSpec) GetEnvironments() map[string]*KsonnetEnvironment {
if m != nil {
return m.Environments
@@ -212,22 +221,30 @@ func (m *RepoResponse) String() string { return proto.CompactTextStri
func (*RepoResponse) ProtoMessage() {}
func (*RepoResponse) Descriptor() ([]byte, []int) { return fileDescriptorRepository, []int{6} }
type RepoCreateRequest struct {
Repo *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
}
func (m *RepoCreateRequest) Reset() { *m = RepoCreateRequest{} }
func (m *RepoCreateRequest) String() string { return proto.CompactTextString(m) }
func (*RepoCreateRequest) ProtoMessage() {}
func (*RepoCreateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRepository, []int{7} }
func (m *RepoCreateRequest) GetRepo() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository {
if m != nil {
return m.Repo
}
return nil
}
type RepoUpdateRequest struct {
Url string `protobuf:"bytes,1,opt,name=url,proto3" json:"url,omitempty"`
Repo *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository `protobuf:"bytes,2,opt,name=repo" json:"repo,omitempty"`
Repo *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
}
func (m *RepoUpdateRequest) Reset() { *m = RepoUpdateRequest{} }
func (m *RepoUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*RepoUpdateRequest) ProtoMessage() {}
func (*RepoUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRepository, []int{7} }
func (m *RepoUpdateRequest) GetUrl() string {
if m != nil {
return m.Url
}
return ""
}
func (*RepoUpdateRequest) Descriptor() ([]byte, []int) { return fileDescriptorRepository, []int{8} }
func (m *RepoUpdateRequest) GetRepo() *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository {
if m != nil {
@@ -244,6 +261,7 @@ func init() {
proto.RegisterType((*KsonnetEnvironmentDestination)(nil), "repository.KsonnetEnvironmentDestination")
proto.RegisterType((*RepoQuery)(nil), "repository.RepoQuery")
proto.RegisterType((*RepoResponse)(nil), "repository.RepoResponse")
proto.RegisterType((*RepoCreateRequest)(nil), "repository.RepoCreateRequest")
proto.RegisterType((*RepoUpdateRequest)(nil), "repository.RepoUpdateRequest")
}
@@ -263,13 +281,11 @@ type RepositoryServiceClient interface {
// ListKsonnetApps returns list of Ksonnet apps in the repo
ListKsonnetApps(ctx context.Context, in *RepoKsonnetQuery, opts ...grpc.CallOption) (*RepoKsonnetResponse, error)
// Create creates a repo
Create(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
Create(ctx context.Context, in *RepoCreateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Get returns a repo by name
Get(ctx context.Context, in *RepoQuery, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Update updates a repo
Update(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Update updates a repo (special handler intended to be used only by the gRPC gateway)
UpdateREST(ctx context.Context, in *RepoUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
Update(ctx context.Context, in *RepoUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Delete updates a repo
Delete(ctx context.Context, in *RepoQuery, opts ...grpc.CallOption) (*RepoResponse, error)
}
@@ -300,7 +316,7 @@ func (c *repositoryServiceClient) ListKsonnetApps(ctx context.Context, in *RepoK
return out, nil
}
func (c *repositoryServiceClient) Create(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error) {
func (c *repositoryServiceClient) Create(ctx context.Context, in *RepoCreateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository)
err := grpc.Invoke(ctx, "/repository.RepositoryService/Create", in, out, c.cc, opts...)
if err != nil {
@@ -318,7 +334,7 @@ func (c *repositoryServiceClient) Get(ctx context.Context, in *RepoQuery, opts .
return out, nil
}
func (c *repositoryServiceClient) Update(ctx context.Context, in *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error) {
func (c *repositoryServiceClient) Update(ctx context.Context, in *RepoUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository)
err := grpc.Invoke(ctx, "/repository.RepositoryService/Update", in, out, c.cc, opts...)
if err != nil {
@@ -327,15 +343,6 @@ func (c *repositoryServiceClient) Update(ctx context.Context, in *github_com_arg
return out, nil
}
func (c *repositoryServiceClient) UpdateREST(ctx context.Context, in *RepoUpdateRequest, opts ...grpc.CallOption) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error) {
out := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository)
err := grpc.Invoke(ctx, "/repository.RepositoryService/UpdateREST", in, out, c.cc, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *repositoryServiceClient) Delete(ctx context.Context, in *RepoQuery, opts ...grpc.CallOption) (*RepoResponse, error) {
out := new(RepoResponse)
err := grpc.Invoke(ctx, "/repository.RepositoryService/Delete", in, out, c.cc, opts...)
@@ -353,13 +360,11 @@ type RepositoryServiceServer interface {
// ListKsonnetApps returns list of Ksonnet apps in the repo
ListKsonnetApps(context.Context, *RepoKsonnetQuery) (*RepoKsonnetResponse, error)
// Create creates a repo
Create(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
Create(context.Context, *RepoCreateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Get returns a repo by name
Get(context.Context, *RepoQuery) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Update updates a repo
Update(context.Context, *github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Update updates a repo (special handler intended to be used only by the gRPC gateway)
UpdateREST(context.Context, *RepoUpdateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
Update(context.Context, *RepoUpdateRequest) (*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository, error)
// Delete updates a repo
Delete(context.Context, *RepoQuery) (*RepoResponse, error)
}
@@ -405,7 +410,7 @@ func _RepositoryService_ListKsonnetApps_Handler(srv interface{}, ctx context.Con
}
func _RepositoryService_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository)
in := new(RepoCreateRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -417,7 +422,7 @@ func _RepositoryService_Create_Handler(srv interface{}, ctx context.Context, dec
FullMethod: "/repository.RepositoryService/Create",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RepositoryServiceServer).Create(ctx, req.(*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository))
return srv.(RepositoryServiceServer).Create(ctx, req.(*RepoCreateRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -441,7 +446,7 @@ func _RepositoryService_Get_Handler(srv interface{}, ctx context.Context, dec fu
}
func _RepositoryService_Update_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository)
in := new(RepoUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
@@ -453,25 +458,7 @@ func _RepositoryService_Update_Handler(srv interface{}, ctx context.Context, dec
FullMethod: "/repository.RepositoryService/Update",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RepositoryServiceServer).Update(ctx, req.(*github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository))
}
return interceptor(ctx, in, info, handler)
}
func _RepositoryService_UpdateREST_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(RepoUpdateRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(RepositoryServiceServer).UpdateREST(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/repository.RepositoryService/UpdateREST",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(RepositoryServiceServer).UpdateREST(ctx, req.(*RepoUpdateRequest))
return srv.(RepositoryServiceServer).Update(ctx, req.(*RepoUpdateRequest))
}
return interceptor(ctx, in, info, handler)
}
@@ -518,10 +505,6 @@ var _RepositoryService_serviceDesc = grpc.ServiceDesc{
MethodName: "Update",
Handler: _RepositoryService_Update_Handler,
},
{
MethodName: "UpdateREST",
Handler: _RepositoryService_UpdateREST_Handler,
},
{
MethodName: "Delete",
Handler: _RepositoryService_Delete_Handler,
@@ -576,8 +559,8 @@ func (m *RepoKsonnetResponse) MarshalTo(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Data) > 0 {
for _, msg := range m.Data {
if len(m.Items) > 0 {
for _, msg := range m.Items {
dAtA[i] = 0xa
i++
i = encodeVarintRepository(dAtA, i, uint64(msg.Size()))
@@ -612,9 +595,15 @@ func (m *KsonnetAppSpec) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintRepository(dAtA, i, uint64(len(m.Name)))
i += copy(dAtA[i:], m.Name)
}
if len(m.Path) > 0 {
dAtA[i] = 0x12
i++
i = encodeVarintRepository(dAtA, i, uint64(len(m.Path)))
i += copy(dAtA[i:], m.Path)
}
if len(m.Environments) > 0 {
for k, _ := range m.Environments {
dAtA[i] = 0x12
dAtA[i] = 0x1a
i++
v := m.Environments[k]
msgSize := 0
@@ -761,6 +750,34 @@ func (m *RepoResponse) MarshalTo(dAtA []byte) (int, error) {
return i, nil
}
func (m *RepoCreateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
n, err := m.MarshalTo(dAtA)
if err != nil {
return nil, err
}
return dAtA[:n], nil
}
func (m *RepoCreateRequest) MarshalTo(dAtA []byte) (int, error) {
var i int
_ = i
var l int
_ = l
if m.Repo != nil {
dAtA[i] = 0xa
i++
i = encodeVarintRepository(dAtA, i, uint64(m.Repo.Size()))
n3, err := m.Repo.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n3
}
return i, nil
}
func (m *RepoUpdateRequest) Marshal() (dAtA []byte, err error) {
size := m.Size()
dAtA = make([]byte, size)
@@ -776,21 +793,15 @@ func (m *RepoUpdateRequest) MarshalTo(dAtA []byte) (int, error) {
_ = i
var l int
_ = l
if len(m.Url) > 0 {
if m.Repo != nil {
dAtA[i] = 0xa
i++
i = encodeVarintRepository(dAtA, i, uint64(len(m.Url)))
i += copy(dAtA[i:], m.Url)
}
if m.Repo != nil {
dAtA[i] = 0x12
i++
i = encodeVarintRepository(dAtA, i, uint64(m.Repo.Size()))
n3, err := m.Repo.MarshalTo(dAtA[i:])
n4, err := m.Repo.MarshalTo(dAtA[i:])
if err != nil {
return 0, err
}
i += n3
i += n4
}
return i, nil
}
@@ -821,8 +832,8 @@ func (m *RepoKsonnetQuery) Size() (n int) {
func (m *RepoKsonnetResponse) Size() (n int) {
var l int
_ = l
if len(m.Data) > 0 {
for _, e := range m.Data {
if len(m.Items) > 0 {
for _, e := range m.Items {
l = e.Size()
n += 1 + l + sovRepository(uint64(l))
}
@@ -837,6 +848,10 @@ func (m *KsonnetAppSpec) Size() (n int) {
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
l = len(m.Path)
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
if len(m.Environments) > 0 {
for k, v := range m.Environments {
_ = k
@@ -905,13 +920,19 @@ func (m *RepoResponse) Size() (n int) {
return n
}
func (m *RepoCreateRequest) Size() (n int) {
var l int
_ = l
if m.Repo != nil {
l = m.Repo.Size()
n += 1 + l + sovRepository(uint64(l))
}
return n
}
func (m *RepoUpdateRequest) Size() (n int) {
var l int
_ = l
l = len(m.Url)
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
if m.Repo != nil {
l = m.Repo.Size()
n += 1 + l + sovRepository(uint64(l))
@@ -1071,7 +1092,7 @@ func (m *RepoKsonnetResponse) Unmarshal(dAtA []byte) error {
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Data", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field Items", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
@@ -1095,8 +1116,8 @@ func (m *RepoKsonnetResponse) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Data = append(m.Data, &KsonnetAppSpec{})
if err := m.Data[len(m.Data)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
m.Items = append(m.Items, &KsonnetAppSpec{})
if err := m.Items[len(m.Items)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
@@ -1180,6 +1201,35 @@ func (m *KsonnetAppSpec) Unmarshal(dAtA []byte) error {
m.Name = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Path", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRepository
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Path = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Environments", wireType)
}
@@ -1730,6 +1780,89 @@ func (m *RepoResponse) Unmarshal(dAtA []byte) error {
}
return nil
}
func (m *RepoCreateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
for iNdEx < l {
preIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
wireType := int(wire & 0x7)
if wireType == 4 {
return fmt.Errorf("proto: RepoCreateRequest: wiretype end group for non-group")
}
if fieldNum <= 0 {
return fmt.Errorf("proto: RepoCreateRequest: illegal tag %d (wire type %d)", fieldNum, wire)
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Repo", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthRepository
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Repo == nil {
m.Repo = &github_com_argoproj_argo_cd_pkg_apis_application_v1alpha1.Repository{}
}
if err := m.Repo.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipRepository(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthRepository
}
if (iNdEx + skippy) > l {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
if iNdEx > l {
return io.ErrUnexpectedEOF
}
return nil
}
func (m *RepoUpdateRequest) Unmarshal(dAtA []byte) error {
l := len(dAtA)
iNdEx := 0
@@ -1760,35 +1893,6 @@ func (m *RepoUpdateRequest) Unmarshal(dAtA []byte) error {
}
switch fieldNum {
case 1:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Url", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRepository
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Url = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 2:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Repo", wireType)
}
@@ -1950,52 +2054,51 @@ var (
func init() { proto.RegisterFile("server/repository/repository.proto", fileDescriptorRepository) }
var fileDescriptorRepository = []byte{
// 740 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x56, 0xcd, 0x6e, 0xd3, 0x40,
0x10, 0x66, 0x93, 0x10, 0xe8, 0xb6, 0x2a, 0xed, 0x52, 0xaa, 0x60, 0xd2, 0xb4, 0x32, 0x1c, 0x4a,
0x45, 0x6d, 0xb5, 0x70, 0xa8, 0xca, 0x89, 0xd2, 0x08, 0x55, 0xe5, 0x00, 0x2e, 0x45, 0x82, 0x03,
0xd5, 0xd6, 0x19, 0xb9, 0x26, 0xae, 0x77, 0xd9, 0xdd, 0x58, 0x8a, 0x50, 0x25, 0xc4, 0x01, 0x71,
0xe7, 0xc2, 0x81, 0x17, 0xe0, 0x09, 0x78, 0x05, 0x8e, 0x48, 0x1c, 0xb8, 0xa2, 0x8a, 0x37, 0xe0,
0x05, 0xd0, 0xae, 0x9d, 0xc4, 0x6d, 0x7e, 0x4e, 0x39, 0x70, 0x9b, 0x9d, 0xfd, 0x76, 0xe6, 0xdb,
0x6f, 0x66, 0xbc, 0xc6, 0xb6, 0x04, 0x91, 0x80, 0x70, 0x05, 0x70, 0x26, 0x43, 0xc5, 0x44, 0x3b,
0x67, 0x3a, 0x5c, 0x30, 0xc5, 0x08, 0xee, 0x79, 0xac, 0xb9, 0x80, 0x05, 0xcc, 0xb8, 0x5d, 0x6d,
0xa5, 0x08, 0xab, 0x1a, 0x30, 0x16, 0x44, 0xe0, 0x52, 0x1e, 0xba, 0x34, 0x8e, 0x99, 0xa2, 0x2a,
0x64, 0xb1, 0xcc, 0x76, 0xed, 0xe6, 0x86, 0x74, 0x42, 0x66, 0x76, 0x7d, 0x26, 0xc0, 0x4d, 0xd6,
0xdc, 0x00, 0x62, 0x10, 0x54, 0x41, 0x23, 0xc3, 0xec, 0x04, 0xa1, 0x3a, 0x6a, 0x1d, 0x3a, 0x3e,
0x3b, 0x76, 0xa9, 0x30, 0x29, 0x5e, 0x1b, 0x63, 0xd5, 0x6f, 0xb8, 0xbc, 0x19, 0xe8, 0xc3, 0xd2,
0xa5, 0x9c, 0x47, 0xa1, 0x6f, 0x82, 0xbb, 0xc9, 0x1a, 0x8d, 0xf8, 0x11, 0xed, 0x0b, 0x65, 0x6f,
0xe1, 0x19, 0x0f, 0x38, 0xdb, 0x95, 0x2c, 0x8e, 0x41, 0x3d, 0x6d, 0x81, 0x68, 0x13, 0x82, 0x4b,
0xfa, 0x12, 0x15, 0xb4, 0x84, 0x96, 0x27, 0x3c, 0x63, 0x13, 0x0b, 0x5f, 0x16, 0x90, 0x84, 0x32,
0x64, 0x71, 0xa5, 0x60, 0xfc, 0xdd, 0xb5, 0x5d, 0xc7, 0x57, 0x73, 0x31, 0x3c, 0x90, 0x9c, 0xc5,
0x12, 0x88, 0x83, 0x4b, 0x0d, 0xaa, 0x68, 0x05, 0x2d, 0x15, 0x97, 0x27, 0xd7, 0x2d, 0x27, 0x27,
0x55, 0x06, 0x7d, 0xc0, 0xf9, 0x1e, 0x07, 0xdf, 0x33, 0x38, 0xfb, 0x17, 0xc2, 0xd3, 0x67, 0x37,
0x34, 0x93, 0x98, 0x1e, 0x43, 0x87, 0x89, 0xb6, 0xc9, 0x13, 0x3c, 0x05, 0x71, 0x12, 0x0a, 0x16,
0x1f, 0x43, 0xac, 0x64, 0xa5, 0x60, 0xc2, 0xdf, 0x19, 0x1e, 0xde, 0xa9, 0xe7, 0xe0, 0xf5, 0x58,
0x89, 0xb6, 0x77, 0x26, 0x82, 0x75, 0x80, 0x67, 0xfb, 0x20, 0x64, 0x06, 0x17, 0x9b, 0xd0, 0xce,
0x32, 0x6b, 0x93, 0xdc, 0xc3, 0x17, 0x13, 0x1a, 0xb5, 0xc0, 0xdc, 0x7f, 0x72, 0xbd, 0x36, 0x20,
0x63, 0x2e, 0x8c, 0x97, 0x82, 0x37, 0x0b, 0x1b, 0xc8, 0xfe, 0x8a, 0x30, 0xe9, 0x47, 0x0c, 0xbc,
0x5d, 0x0d, 0xe3, 0xe6, 0x86, 0x7c, 0x0e, 0x22, 0xa7, 0x74, 0xce, 0xa3, 0xcf, 0x70, 0xaa, 0x8e,
0x2a, 0xc5, 0xf4, 0x8c, 0xb6, 0xc9, 0x2e, 0x9e, 0x6c, 0x80, 0x54, 0x61, 0x6c, 0x6a, 0x5d, 0x29,
0x19, 0x7a, 0xb7, 0x47, 0xd3, 0xdb, 0xee, 0x1d, 0xf0, 0xf2, 0xa7, 0xed, 0x7d, 0xbc, 0x30, 0x12,
0x4d, 0xe6, 0x71, 0x39, 0x1d, 0x83, 0x8c, 0x77, 0xb6, 0x22, 0x55, 0x3c, 0xa1, 0x6f, 0x20, 0x39,
0xf5, 0x21, 0x23, 0xde, 0x73, 0xd8, 0x8b, 0x78, 0x42, 0xf7, 0xc8, 0xd0, 0x06, 0xb3, 0xa7, 0xf1,
0x94, 0x06, 0x74, 0xba, 0xc7, 0x7e, 0x87, 0xf0, 0xac, 0x76, 0xec, 0xf3, 0x06, 0x55, 0xe0, 0xc1,
0x9b, 0x16, 0x48, 0xa5, 0xab, 0xd2, 0x12, 0x51, 0xa7, 0x2a, 0x2d, 0x11, 0x91, 0x17, 0x59, 0xac,
0xb4, 0x28, 0x75, 0xa7, 0x37, 0x1a, 0x4e, 0x67, 0x34, 0x8c, 0x71, 0xe0, 0x37, 0x1c, 0xde, 0x0c,
0x1c, 0x3d, 0x1a, 0x4e, 0x6e, 0x34, 0x9c, 0xce, 0x68, 0x38, 0x5e, 0x57, 0xaf, 0x94, 0xd2, 0xfa,
0xdf, 0x4b, 0x29, 0x85, 0xd4, 0xb9, 0x07, 0x22, 0x09, 0x7d, 0x20, 0x1f, 0x10, 0x2e, 0x3d, 0x0e,
0xa5, 0x22, 0xd7, 0xf2, 0x0a, 0x77, 0x2f, 0x67, 0xed, 0x8c, 0x85, 0x82, 0xce, 0x60, 0x57, 0xdf,
0xff, 0xfc, 0xf3, 0xa9, 0x30, 0x4f, 0xe6, 0xcc, 0xd7, 0x20, 0x59, 0xeb, 0x7d, 0x6d, 0x42, 0x90,
0x24, 0xc1, 0x57, 0x34, 0xaa, 0xd7, 0xec, 0x92, 0x54, 0xcf, 0x53, 0xca, 0xcf, 0xb5, 0xb5, 0x38,
0x64, 0xb7, 0xab, 0xf9, 0x2d, 0x93, 0xaf, 0x46, 0xaa, 0x83, 0xf2, 0xb9, 0xcd, 0x14, 0x4d, 0xbe,
0x21, 0x5c, 0x7e, 0x28, 0x80, 0x2a, 0x20, 0xe3, 0x91, 0xdb, 0x1a, 0x4f, 0x18, 0x7b, 0xd1, 0xd0,
0xbf, 0x6e, 0x0f, 0x94, 0x6b, 0x13, 0xad, 0x90, 0x8f, 0x08, 0x17, 0x1f, 0xc1, 0xd0, 0xca, 0x8d,
0x89, 0xc6, 0x4d, 0x43, 0x63, 0x81, 0xdc, 0x18, 0xa8, 0xe2, 0x5b, 0xbd, 0x3a, 0x21, 0x9f, 0x11,
0x2e, 0xa7, 0xad, 0xfd, 0x9f, 0x89, 0x78, 0x81, 0x7c, 0x41, 0x18, 0x67, 0x53, 0x57, 0xdf, 0x7b,
0x46, 0x16, 0xce, 0x8b, 0x75, 0x66, 0x22, 0xc7, 0x95, 0x76, 0xd9, 0x88, 0x66, 0x5b, 0xd6, 0x60,
0xd1, 0x5a, 0x22, 0x3a, 0xd9, 0x4c, 0x5f, 0xa2, 0x57, 0xb8, 0xbc, 0x0d, 0x11, 0x28, 0x18, 0x56,
0xc6, 0xca, 0x79, 0x77, 0xb7, 0xbf, 0xb3, 0xca, 0xac, 0x8c, 0xaa, 0xcc, 0xd6, 0xfd, 0xef, 0xa7,
0x35, 0xf4, 0xe3, 0xb4, 0x86, 0x7e, 0x9f, 0xd6, 0xd0, 0xcb, 0xd5, 0x51, 0x4f, 0x6d, 0xdf, 0xef,
0xc0, 0x61, 0xd9, 0xbc, 0xaa, 0x77, 0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0xa3, 0x80, 0x63, 0xc1,
0x2a, 0x08, 0x00, 0x00,
// 726 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0xcd, 0x6e, 0xd3, 0x4a,
0x14, 0x96, 0x9b, 0x36, 0xba, 0x3d, 0xa9, 0x7a, 0xdb, 0xb9, 0xbd, 0x55, 0xe4, 0x9b, 0xa6, 0x95,
0xab, 0x2b, 0xf5, 0x5e, 0xa8, 0x4d, 0x03, 0x8b, 0xaa, 0xac, 0x28, 0xad, 0xaa, 0xaa, 0x2c, 0xc0,
0x55, 0x91, 0x60, 0x41, 0xe5, 0x3a, 0x47, 0xae, 0x49, 0x32, 0x33, 0xcc, 0x4c, 0x2c, 0x45, 0xa8,
0x1b, 0x16, 0x88, 0x35, 0xec, 0xd9, 0xf3, 0x0e, 0x3c, 0x00, 0x4b, 0x24, 0x5e, 0x00, 0x55, 0xec,
0x78, 0x09, 0x34, 0x63, 0x27, 0x71, 0x9a, 0x9f, 0x55, 0xc4, 0xee, 0xcc, 0x99, 0x6f, 0xce, 0xf7,
0xf9, 0x9b, 0x73, 0xc6, 0xe0, 0x48, 0x14, 0x09, 0x0a, 0x4f, 0x20, 0x67, 0x32, 0x56, 0x4c, 0x74,
0x72, 0xa1, 0xcb, 0x05, 0x53, 0x8c, 0x40, 0x3f, 0x63, 0xaf, 0x44, 0x2c, 0x62, 0x26, 0xed, 0xe9,
0x28, 0x45, 0xd8, 0x95, 0x88, 0xb1, 0xa8, 0x89, 0x5e, 0xc0, 0x63, 0x2f, 0xa0, 0x94, 0xa9, 0x40,
0xc5, 0x8c, 0xca, 0x6c, 0xd7, 0x69, 0xec, 0x4a, 0x37, 0x66, 0x66, 0x37, 0x64, 0x02, 0xbd, 0x64,
0xc7, 0x8b, 0x90, 0xa2, 0x08, 0x14, 0xd6, 0x33, 0xcc, 0x71, 0x14, 0xab, 0xcb, 0xf6, 0x85, 0x1b,
0xb2, 0x96, 0x17, 0x08, 0x43, 0xf1, 0xd2, 0x04, 0xdb, 0x61, 0xdd, 0xe3, 0x8d, 0x48, 0x1f, 0x96,
0x5e, 0xc0, 0x79, 0x33, 0x0e, 0x4d, 0x71, 0x2f, 0xd9, 0x09, 0x9a, 0xfc, 0x32, 0x18, 0x2a, 0xe5,
0xec, 0xc3, 0x92, 0x8f, 0x9c, 0x9d, 0x48, 0x46, 0x29, 0xaa, 0x27, 0x6d, 0x14, 0x1d, 0x42, 0x60,
0x56, 0x7f, 0x44, 0xd9, 0xda, 0xb0, 0xb6, 0xe6, 0x7d, 0x13, 0x13, 0x1b, 0xfe, 0x10, 0x98, 0xc4,
0x32, 0x66, 0xb4, 0x3c, 0x63, 0xf2, 0xbd, 0xb5, 0x73, 0x04, 0x7f, 0xe5, 0x6a, 0xf8, 0x28, 0x39,
0xa3, 0x12, 0xc9, 0x1d, 0x98, 0x8b, 0x15, 0xb6, 0x64, 0xd9, 0xda, 0x28, 0x6c, 0x95, 0x6a, 0xb6,
0x9b, 0xf3, 0x2a, 0xc3, 0x3e, 0xe0, 0xfc, 0x94, 0x63, 0xe8, 0xa7, 0x40, 0xe7, 0xa7, 0x05, 0x8b,
0x83, 0x3b, 0x5a, 0x0b, 0x0d, 0x5a, 0xd8, 0xd5, 0xa2, 0x63, 0x9d, 0xe3, 0x81, 0xba, 0xcc, 0x74,
0x98, 0x98, 0x3c, 0x86, 0x05, 0xa4, 0x49, 0x2c, 0x18, 0x6d, 0x21, 0x55, 0xb2, 0x5c, 0x30, 0x9c,
0xb7, 0xc7, 0x73, 0xba, 0x87, 0x39, 0xf8, 0x21, 0x55, 0xa2, 0xe3, 0x0f, 0x54, 0xb0, 0xcf, 0x61,
0x79, 0x08, 0x42, 0x96, 0xa0, 0xd0, 0xc0, 0x4e, 0xa6, 0x46, 0x87, 0xe4, 0x1e, 0xcc, 0x25, 0x41,
0xb3, 0x8d, 0x46, 0x4d, 0xa9, 0x56, 0x1d, 0xc1, 0x98, 0x2b, 0xe3, 0xa7, 0xe0, 0xbd, 0x99, 0x5d,
0xcb, 0xf9, 0x64, 0x01, 0x19, 0x46, 0x8c, 0xfc, 0xe2, 0x2a, 0x40, 0x63, 0x57, 0x3e, 0x45, 0x91,
0xf3, 0x3f, 0x97, 0xe9, 0x39, 0x52, 0xc8, 0x39, 0x72, 0x02, 0xa5, 0x3a, 0x4a, 0x15, 0x53, 0xd3,
0x01, 0xe5, 0x59, 0x23, 0xef, 0xbf, 0xc9, 0xf2, 0x0e, 0xfa, 0x07, 0xfc, 0xfc, 0x69, 0xe7, 0x0c,
0xd6, 0x26, 0xa2, 0xc9, 0x2a, 0x14, 0xd3, 0xe1, 0xc8, 0x74, 0x67, 0x2b, 0x52, 0x81, 0x79, 0xfd,
0x05, 0x92, 0x07, 0x21, 0x66, 0xc2, 0xfb, 0x09, 0x67, 0x1d, 0xe6, 0x75, 0xe7, 0x8c, 0x6d, 0x3b,
0x67, 0x11, 0x16, 0x34, 0xa0, 0xdb, 0x53, 0x0e, 0x85, 0x65, 0xbd, 0x7e, 0x28, 0x30, 0x50, 0xe8,
0xe3, 0xab, 0x36, 0x4a, 0x45, 0x9e, 0xe5, 0x0e, 0x96, 0x6a, 0x87, 0x6e, 0x7f, 0x3a, 0xdc, 0xee,
0x74, 0x98, 0xe0, 0x3c, 0xac, 0xbb, 0xbc, 0x11, 0xb9, 0x7a, 0x3a, 0xdc, 0xdc, 0x74, 0xb8, 0xdd,
0xe9, 0x70, 0xfd, 0x9e, 0x39, 0x19, 0x7f, 0xc6, 0x77, 0xc6, 0xeb, 0xbf, 0x85, 0xaf, 0xf6, 0xb9,
0x98, 0x12, 0xa6, 0xc9, 0x53, 0x14, 0x49, 0x1c, 0x22, 0x79, 0x6b, 0xc1, 0xec, 0xa3, 0x58, 0x2a,
0xf2, 0x77, 0xfe, 0xfa, 0x7a, 0xce, 0xd9, 0xc7, 0x53, 0x91, 0xa0, 0x19, 0x9c, 0xca, 0x9b, 0x6f,
0x3f, 0x3e, 0xcc, 0xac, 0x92, 0x15, 0xf3, 0x00, 0x25, 0x3b, 0xfd, 0x07, 0x2e, 0x46, 0x49, 0xae,
0xe0, 0x4f, 0x8d, 0xea, 0x4f, 0x92, 0x24, 0x95, 0x9b, 0x92, 0xf2, 0x4f, 0x89, 0xbd, 0x3e, 0x66,
0xb7, 0x77, 0xa1, 0xb7, 0x0c, 0xdf, 0xbf, 0x64, 0x73, 0x14, 0x9f, 0xf7, 0x5a, 0xaf, 0xae, 0xbc,
0x46, 0x7a, 0x88, 0xbc, 0xb7, 0xa0, 0x98, 0x5e, 0x3d, 0x59, 0xbb, 0x59, 0x78, 0xa0, 0x25, 0xec,
0xe9, 0x5c, 0x8a, 0xe3, 0x18, 0x75, 0x15, 0x67, 0xa4, 0x1b, 0x7b, 0xe9, 0xcb, 0xf8, 0xce, 0x82,
0xc2, 0x11, 0x8e, 0xbd, 0x9b, 0x29, 0x29, 0xd9, 0x34, 0x4a, 0xd6, 0xc8, 0x3f, 0x13, 0x7c, 0x22,
0x1f, 0x2d, 0x28, 0xa6, 0xad, 0x3a, 0xec, 0xcf, 0x40, 0x0b, 0x4f, 0x4b, 0x95, 0x6b, 0x54, 0x6d,
0xd9, 0x1b, 0xe3, 0x55, 0x19, 0x1d, 0x57, 0x99, 0x57, 0x2f, 0xa0, 0x78, 0x80, 0x4d, 0x54, 0x38,
0xce, 0xad, 0xf2, 0xcd, 0x74, 0xaf, 0x51, 0x32, 0x03, 0xfe, 0x9f, 0x64, 0xc0, 0xfe, 0xfd, 0x2f,
0xd7, 0x55, 0xeb, 0xeb, 0x75, 0xd5, 0xfa, 0x7e, 0x5d, 0xb5, 0x9e, 0x6f, 0x4f, 0xfa, 0x4d, 0x0e,
0xfd, 0xca, 0x2f, 0x8a, 0xe6, 0x8f, 0x78, 0xf7, 0x57, 0x00, 0x00, 0x00, 0xff, 0xff, 0x30, 0xd9,
0x2b, 0xac, 0xe6, 0x07, 0x00, 0x00,
}

View File

@@ -12,7 +12,6 @@ import (
"io"
"net/http"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/golang/protobuf/proto"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
"github.com/grpc-ecosystem/grpc-gateway/utilities"
@@ -47,13 +46,31 @@ func request_RepositoryService_List_0(ctx context.Context, marshaler runtime.Mar
}
var (
filter_RepositoryService_ListKsonnetApps_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
filter_RepositoryService_ListKsonnetApps_0 = &utilities.DoubleArray{Encoding: map[string]int{"repo": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_RepositoryService_ListKsonnetApps_0(ctx context.Context, marshaler runtime.Marshaler, client RepositoryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RepoKsonnetQuery
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["repo"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "repo")
}
protoReq.Repo, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "repo", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.URL.Query(), filter_RepositoryService_ListKsonnetApps_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -64,10 +81,10 @@ func request_RepositoryService_ListKsonnetApps_0(ctx context.Context, marshaler
}
func request_RepositoryService_Create_0(ctx context.Context, marshaler runtime.Marshaler, client RepositoryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq v1alpha1.Repository
var protoReq RepoCreateRequest
var metadata runtime.ServerMetadata
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq); err != nil {
if err := marshaler.NewDecoder(req.Body).Decode(&protoReq.Repo); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
@@ -103,7 +120,7 @@ func request_RepositoryService_Get_0(ctx context.Context, marshaler runtime.Mars
}
func request_RepositoryService_UpdateREST_0(ctx context.Context, marshaler runtime.Marshaler, client RepositoryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
func request_RepositoryService_Update_0(ctx context.Context, marshaler runtime.Marshaler, client RepositoryServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq RepoUpdateRequest
var metadata runtime.ServerMetadata
@@ -118,18 +135,18 @@ func request_RepositoryService_UpdateREST_0(ctx context.Context, marshaler runti
_ = err
)
val, ok = pathParams["url"]
val, ok = pathParams["repo.repo"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "url")
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "repo.repo")
}
protoReq.Url, err = runtime.String(val)
err = runtime.PopulateFieldFromPath(&protoReq, "repo.repo", val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "url", err)
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "repo.repo", err)
}
msg, err := client.UpdateREST(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
msg, err := client.Update(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
@@ -315,7 +332,7 @@ func RegisterRepositoryServiceHandlerClient(ctx context.Context, mux *runtime.Se
})
mux.Handle("PUT", pattern_RepositoryService_UpdateREST_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
mux.Handle("PUT", pattern_RepositoryService_Update_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
if cn, ok := w.(http.CloseNotifier); ok {
@@ -333,14 +350,14 @@ func RegisterRepositoryServiceHandlerClient(ctx context.Context, mux *runtime.Se
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_RepositoryService_UpdateREST_0(rctx, inboundMarshaler, client, req, pathParams)
resp, md, err := request_RepositoryService_Update_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_RepositoryService_UpdateREST_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
forward_RepositoryService_Update_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
@@ -379,13 +396,13 @@ func RegisterRepositoryServiceHandlerClient(ctx context.Context, mux *runtime.Se
var (
pattern_RepositoryService_List_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "repositories"}, ""))
pattern_RepositoryService_ListKsonnetApps_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"api", "v1", "repositories", "ksonnet"}, ""))
pattern_RepositoryService_ListKsonnetApps_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "repositories", "repo", "ksonnet"}, ""))
pattern_RepositoryService_Create_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "repositories"}, ""))
pattern_RepositoryService_Get_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "repo"}, ""))
pattern_RepositoryService_UpdateREST_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "url"}, ""))
pattern_RepositoryService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "repo.repo"}, ""))
pattern_RepositoryService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "repositories", "repo"}, ""))
)
@@ -399,7 +416,7 @@ var (
forward_RepositoryService_Get_0 = runtime.ForwardResponseMessage
forward_RepositoryService_UpdateREST_0 = runtime.ForwardResponseMessage
forward_RepositoryService_Update_0 = runtime.ForwardResponseMessage
forward_RepositoryService_Delete_0 = runtime.ForwardResponseMessage
)

View File

@@ -19,14 +19,15 @@ message RepoKsonnetQuery {
// RepoKsonnetResponse is a response for Repository contents matching a particular path
message RepoKsonnetResponse {
repeated KsonnetAppSpec data = 1;
repeated KsonnetAppSpec items = 1;
}
// KsonnetAppSpec contains Ksonnet app response
// This roughly reflects: ksonnet/ksonnet/metadata/app/schema.go
message KsonnetAppSpec {
string name = 1;
map<string, KsonnetEnvironment> environments = 2;
string name = 1;
string path = 2;
map<string, KsonnetEnvironment> environments = 3;
}
message KsonnetEnvironment {
@@ -54,9 +55,12 @@ message RepoQuery {
message RepoResponse {}
message RepoCreateRequest {
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
}
message RepoUpdateRequest {
string url = 1;
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 2;
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
}
// RepositoryService
@@ -69,30 +73,26 @@ service RepositoryService {
// ListKsonnetApps returns list of Ksonnet apps in the repo
rpc ListKsonnetApps(RepoKsonnetQuery) returns (RepoKsonnetResponse) {
option (google.api.http).get = "/api/v1/repositories/ksonnet";
option (google.api.http).get = "/api/v1/repositories/{repo}/ksonnet";
}
// Create creates a repo
rpc Create(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
rpc Create(RepoCreateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
option (google.api.http) = {
post: "/api/v1/repositories"
body: "*"
body: "repo"
};
}
// Get returns a repo by name
rpc Get(RepoQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
// Get returns a repo by name
rpc Get(RepoQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
option (google.api.http).get = "/api/v1/repositories/{repo}";
}
// Update updates a repo
rpc Update(github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
}
// Update updates a repo (special handler intended to be used only by the gRPC gateway)
rpc UpdateREST(RepoUpdateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
rpc Update(RepoUpdateRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository) {
option (google.api.http) = {
put: "/api/v1/repositories/{url}"
put: "/api/v1/repositories/{repo.repo}"
body: "repo"
};
}

View File

@@ -6,9 +6,28 @@ import (
"fmt"
"net"
"net/http"
"net/url"
"os"
"strings"
"time"
"github.com/gobuffalo/packr"
golang_proto "github.com/golang/protobuf/proto"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
log "github.com/sirupsen/logrus"
"github.com/soheilhy/cmux"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/status"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
argocd "github.com/argoproj/argo-cd"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
@@ -26,24 +45,11 @@ import (
dexutil "github.com/argoproj/argo-cd/util/dex"
grpc_util "github.com/argoproj/argo-cd/util/grpc"
jsonutil "github.com/argoproj/argo-cd/util/json"
"github.com/argoproj/argo-cd/util/rbac"
util_session "github.com/argoproj/argo-cd/util/session"
settings_util "github.com/argoproj/argo-cd/util/settings"
tlsutil "github.com/argoproj/argo-cd/util/tls"
"github.com/argoproj/argo-cd/util/webhook"
golang_proto "github.com/golang/protobuf/proto"
grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
grpc_auth "github.com/grpc-ecosystem/go-grpc-middleware/auth"
grpc_logrus "github.com/grpc-ecosystem/go-grpc-middleware/logging/logrus"
"github.com/grpc-ecosystem/grpc-gateway/runtime"
log "github.com/sirupsen/logrus"
"github.com/soheilhy/cmux"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/reflection"
"google.golang.org/grpc/status"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
)
var (
@@ -58,6 +64,17 @@ var backoff = wait.Backoff{
Jitter: 0.1,
}
var (
box = packr.NewBox("../util/rbac")
builtinPolicy string
)
func init() {
var err error
builtinPolicy, err = box.MustString("builtin-policy.csv")
errors.CheckError(err)
}
// ArgoCDServer is the API server for ArgoCD
type ArgoCDServer struct {
ArgoCDServerOpts
@@ -67,6 +84,7 @@ type ArgoCDServer struct {
log *log.Entry
sessionMgr *util_session.SessionManager
settingsMgr *settings_util.SettingsManager
enf *rbac.Enforcer
// stopCh is the channel which when closed, will shutdown the ArgoCD server
stopCh chan struct{}
@@ -86,16 +104,21 @@ type ArgoCDServerOpts struct {
func NewServer(opts ArgoCDServerOpts) *ArgoCDServer {
settingsMgr := settings_util.NewSettingsManager(opts.KubeClientset, opts.Namespace)
settings, err := settingsMgr.GetSettings()
if err != nil {
log.Fatal(err)
}
errors.CheckError(err)
sessionMgr := util_session.NewSessionManager(settings)
enf := rbac.NewEnforcer(opts.KubeClientset, opts.Namespace, common.ArgoCDRBACConfigMapName, nil)
enf.EnableEnforce(!opts.DisableAuth)
err = enf.SetBuiltinPolicy(builtinPolicy)
errors.CheckError(err)
enf.EnableLog(os.Getenv(common.EnvVarRBACDebug) == "1")
return &ArgoCDServer{
ArgoCDServerOpts: opts,
log: log.NewEntry(log.New()),
settings: settings,
sessionMgr: sessionMgr,
settingsMgr: settingsMgr,
enf: enf,
}
}
@@ -162,8 +185,8 @@ func (a *ArgoCDServer) Run(ctx context.Context, port int) {
go func() { a.checkServeErr("httpsS", httpsS.Serve(httpsL)) }()
go func() { a.checkServeErr("tlsm", tlsm.Serve()) }()
}
go a.initializeOIDCClientApp()
go a.watchSettings(ctx)
go a.rbacPolicyLoader(ctx)
go func() { a.checkServeErr("tcpm", tcpm.Serve()) }()
a.stopCh = make(chan struct{})
@@ -206,6 +229,10 @@ func (a *ArgoCDServer) watchSettings(ctx context.Context) {
prevGitHubSecret := a.settings.WebhookGitHubSecret
prevGitLabSecret := a.settings.WebhookGitLabSecret
prevBitBucketUUID := a.settings.WebhookBitbucketUUID
var prevCert, prevCertKey string
if a.settings.Certificate != nil {
prevCert, prevCertKey = tlsutil.EncodeX509KeyPairString(*a.settings.Certificate)
}
for {
<-updateCh
@@ -227,6 +254,14 @@ func (a *ArgoCDServer) watchSettings(ctx context.Context) {
log.Infof("bitbucket uuid modified. restarting")
break
}
var newCert, newCertKey string
if a.settings.Certificate != nil {
newCert, newCertKey = tlsutil.EncodeX509KeyPairString(*a.settings.Certificate)
}
if newCert != prevCert || newCertKey != prevCertKey {
log.Infof("tls certificate modified. restarting")
break
}
}
log.Info("shutting down settings watch")
a.Shutdown()
@@ -234,29 +269,9 @@ func (a *ArgoCDServer) watchSettings(ctx context.Context) {
close(updateCh)
}
// initializeOIDCClientApp initializes the OIDC Client application, querying the well known oidc
// configuration path. Because ArgoCD is a OIDC client to itself, we have a chicken-and-egg problem
// of (1) serving dex over HTTP, and (2) querying the OIDC provider (ourselves) to initialize the
// app (HTTP GET http://example-argocd.com/api/dex/.well-known/openid-configuration)
// This method is expected to be invoked right after we start listening over HTTP
func (a *ArgoCDServer) initializeOIDCClientApp() {
if !a.settings.IsSSOConfigured() {
return
}
// wait for dex to become ready
dexClient, err := dexutil.NewDexClient()
func (a *ArgoCDServer) rbacPolicyLoader(ctx context.Context) {
err := a.enf.RunPolicyLoader(ctx)
errors.CheckError(err)
dexClient.WaitUntilReady()
var realErr error
_ = wait.ExponentialBackoff(backoff, func() (bool, error) {
_, realErr = a.sessionMgr.OIDCProvider()
if realErr != nil {
a.log.Warnf("failed to initialize client app: %v", realErr)
return false, nil
}
return true, nil
})
errors.CheckError(realErr)
}
func (a *ArgoCDServer) useTLS() bool {
@@ -277,6 +292,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
grpc_util.PanicLoggerStreamServerInterceptor(a.log),
)))
sOpts = append(sOpts, grpc.UnaryInterceptor(grpc_middleware.ChainUnaryServer(
bug21955WorkaroundInterceptor,
grpc_logrus.UnaryServerInterceptor(a.log),
grpc_auth.UnaryServerInterceptor(a.authenticate),
grpc_util.ErrorCodeUnaryServerInterceptor(),
@@ -285,10 +301,10 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
grpcS := grpc.NewServer(sOpts...)
db := db.NewDB(a.Namespace, a.KubeClientset)
clusterService := cluster.NewServer(db)
repoService := repository.NewServer(a.RepoClientset, db)
clusterService := cluster.NewServer(db, a.enf)
repoService := repository.NewServer(a.RepoClientset, db, a.enf)
sessionService := session.NewServer(a.sessionMgr)
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.RepoClientset, db)
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.RepoClientset, db, a.enf)
settingsService := settings.NewServer(a.settingsMgr)
version.RegisterVersionServiceServer(grpcS, &version.Server{})
cluster.RegisterClusterServiceServer(grpcS, clusterService)
@@ -322,7 +338,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int) *http.Server
mux := http.NewServeMux()
httpS := http.Server{
Addr: endpoint,
Handler: mux,
Handler: &bug21955Workaround{handler: mux},
}
var dOpts []grpc.DialOption
if a.useTLS() {
@@ -437,11 +453,12 @@ func (a *ArgoCDServer) authenticate(ctx context.Context) (context.Context, error
if tokenString == "" {
return ctx, ErrNoSession
}
_, err := a.sessionMgr.VerifyToken(tokenString)
claims, err := a.sessionMgr.VerifyToken(tokenString)
if err != nil {
return ctx, status.Errorf(codes.Unauthenticated, "invalid session: %v", err)
}
// TODO: when we care about user groups, we will want to put the claims into the context
// Add claims to the context to inspect for RBAC
ctx = context.WithValue(ctx, "claims", claims)
return ctx, nil
}
@@ -469,3 +486,65 @@ func getToken(md metadata.MD) string {
}
return ""
}
// Workaround for https://github.com/golang/go/issues/21955 to support escaped URLs in URL path.
type bug21955Workaround struct {
handler http.Handler
}
func (bf *bug21955Workaround) ServeHTTP(w http.ResponseWriter, r *http.Request) {
paths := map[string][]string{
"/api/v1/repositories/": {"ksonnet"},
"/api/v1/clusters/": {},
}
for path, subPaths := range paths {
if strings.Index(r.URL.Path, path) > -1 {
postfix := ""
for _, subPath := range subPaths {
if strings.LastIndex(r.URL.Path, subPath) == len(r.URL.Path)-len(subPath) {
postfix = "/" + subPath
r.URL.Path = r.URL.Path[0 : len(r.URL.Path)-len(subPath)-1]
break
}
}
r.URL.Path = path + url.QueryEscape(r.URL.Path[len(path):]) + postfix
break
}
}
bf.handler.ServeHTTP(w, r)
}
func bug21955WorkaroundInterceptor(ctx context.Context, req interface{}, _ *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
if rq, ok := req.(*repository.RepoQuery); ok {
repo, err := url.QueryUnescape(rq.Repo)
if err != nil {
return nil, err
}
rq.Repo = repo
} else if rk, ok := req.(*repository.RepoKsonnetQuery); ok {
repo, err := url.QueryUnescape(rk.Repo)
if err != nil {
return nil, err
}
rk.Repo = repo
} else if ru, ok := req.(*repository.RepoUpdateRequest); ok {
repo, err := url.QueryUnescape(ru.Repo.Repo)
if err != nil {
return nil, err
}
ru.Repo.Repo = repo
} else if cq, ok := req.(*cluster.ClusterQuery); ok {
server, err := url.QueryUnescape(cq.Server)
if err != nil {
return nil, err
}
cq.Server = server
} else if cu, ok := req.(*cluster.ClusterUpdateRequest); ok {
server, err := url.QueryUnescape(cu.Cluster.Server)
if err != nil {
return nil, err
}
cu.Cluster.Server = server
}
return handler(ctx, req)
}

View File

@@ -2,13 +2,13 @@ package session
import (
"context"
"encoding/json"
"fmt"
sessionmgr "github.com/argoproj/argo-cd/util/session"
jwt "github.com/dgrijalva/jwt-go"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"github.com/argoproj/argo-cd/util/jwt"
sessionmgr "github.com/argoproj/argo-cd/util/session"
)
// Server provides a Session service
@@ -46,7 +46,7 @@ func (s *Server) Create(ctx context.Context, q *SessionCreateRequest) (*SessionR
if err != nil {
return nil, err
}
claims, err := MapClaims(claimsIf)
claims, err := jwt.MapClaims(claimsIf)
if err != nil {
return nil, err
}
@@ -72,17 +72,3 @@ func (s *Server) Delete(ctx context.Context, q *SessionDeleteRequest) (*SessionR
func (s *Server) AuthFuncOverride(ctx context.Context, fullMethodName string) (context.Context, error) {
return ctx, nil
}
// MapClaims converts a jwt.Claims to a MapClaims
func MapClaims(claims jwt.Claims) (jwt.MapClaims, error) {
claimsBytes, err := json.Marshal(claims)
if err != nil {
return nil, err
}
var mapClaims jwt.MapClaims
err = json.Unmarshal(claimsBytes, &mapClaims)
if err != nil {
return nil, err
}
return mapClaims, nil
}

View File

@@ -14,7 +14,7 @@ message SettingsQuery {
}
message Settings {
string url = 1 [(gogoproto.customname) = "URL"];;
string url = 1 [(gogoproto.customname) = "URL"];
DexConfig dexConfig = 2;
}

View File

@@ -1,7 +1,6 @@
package e2e
import (
"context"
"strconv"
"testing"
"time"
@@ -18,9 +17,7 @@ import (
)
func TestAppManagement(t *testing.T) {
testApp := &v1alpha1.Application{
ObjectMeta: metav1.ObjectMeta{GenerateName: "e2e-test"},
Spec: v1alpha1.ApplicationSpec{
Source: v1alpha1.ApplicationSource{
RepoURL: "https://github.com/argoproj/argo-cd.git", Path: ".", Environment: "minikube",
@@ -72,20 +69,12 @@ func TestAppManagement(t *testing.T) {
})
t.Run("TestTrackAppStateAndSyncApp", func(t *testing.T) {
ctrl := fixture.CreateController()
ctx, cancel := context.WithCancel(context.Background())
go ctrl.Run(ctx, 1, 1)
defer cancel()
// create app and ensure it reaches OutOfSync state
app := fixture.CreateApp(t, testApp)
WaitUntil(t, func() (done bool, err error) {
app, err = fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Get(app.ObjectMeta.Name, metav1.GetOptions{})
return err == nil && app.Status.ComparisonResult.Status != v1alpha1.ComparisonStatusUnknown, err
})
assert.Equal(t, v1alpha1.ComparisonStatusOutOfSync, app.Status.ComparisonResult.Status)
// sync app and make sure it reaches InSync state
_, err := fixture.RunCli("app", "sync", app.Name)
if err != nil {
@@ -103,30 +92,30 @@ func TestAppManagement(t *testing.T) {
t.Run("TestAppRollbackSuccessful", func(t *testing.T) {
appWithHistory := testApp.DeepCopy()
appWithHistory.Status.History = []v1alpha1.DeploymentInfo{{
ID: 1,
Revision: "abc",
}, {
ID: 2,
Revision: "cdb",
}}
ctrl := fixture.CreateController()
ctx, cancel := context.WithCancel(context.Background())
go ctrl.Run(ctx, 1, 1)
defer cancel()
// create app and ensure it reaches OutOfSync state
// create app and ensure it's comparion status is not ComparisonStatusUnknown
app := fixture.CreateApp(t, appWithHistory)
app.Status.History = []v1alpha1.DeploymentInfo{{
ID: 1,
Revision: "abc",
ComponentParameterOverrides: app.Spec.Source.ComponentParameterOverrides,
}, {
ID: 2,
Revision: "cdb",
ComponentParameterOverrides: app.Spec.Source.ComponentParameterOverrides,
}}
app, err := fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Update(app)
if err != nil {
t.Fatalf("Unable to update app %v", err)
}
WaitUntil(t, func() (done bool, err error) {
app, err = fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Get(app.ObjectMeta.Name, metav1.GetOptions{})
return err == nil && app.Status.ComparisonResult.Status != v1alpha1.ComparisonStatusUnknown, err
})
assert.Equal(t, v1alpha1.ComparisonStatusOutOfSync, app.Status.ComparisonResult.Status)
// sync app and make sure it reaches InSync state
_, err := fixture.RunCli("app", "rollback", app.Name, "1")
_, err = fixture.RunCli("app", "rollback", app.Name, "1")
if err != nil {
t.Fatalf("Unable to sync app %v", err)
}
@@ -146,11 +135,6 @@ func TestAppManagement(t *testing.T) {
invalidApp := testApp.DeepCopy()
invalidApp.Spec.Destination.Server = "https://not-registered-cluster/api"
ctrl := fixture.CreateController()
ctx, cancel := context.WithCancel(context.Background())
go ctrl.Run(ctx, 1, 1)
defer cancel()
app := fixture.CreateApp(t, invalidApp)
WaitUntil(t, func() (done bool, err error) {
@@ -165,4 +149,39 @@ func TestAppManagement(t *testing.T) {
assert.Equal(t, v1alpha1.ComparisonStatusError, app.Status.ComparisonResult.Status)
})
t.Run("TestArgoCDWaitEnsureAppIsNotCrashing", func(t *testing.T) {
updatedApp := testApp.DeepCopy()
// deploy app and make sure it is healthy
app := fixture.CreateApp(t, updatedApp)
_, err := fixture.RunCli("app", "sync", app.Name)
if err != nil {
t.Fatalf("Unable to sync app %v", err)
}
WaitUntil(t, func() (done bool, err error) {
app, err = fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Get(app.ObjectMeta.Name, metav1.GetOptions{})
return err == nil && app.Status.ComparisonResult.Status == v1alpha1.ComparisonStatusSynced && app.Status.Health.Status == v1alpha1.HealthStatusHealthy, err
})
// deploy app which fails and make sure it became unhealthy
app.Spec.Source.ComponentParameterOverrides = append(
app.Spec.Source.ComponentParameterOverrides,
v1alpha1.ComponentParameter{Name: "command", Value: "wrong-command", Component: "guestbook-ui"})
_, err = fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Update(app)
if err != nil {
t.Fatalf("Unable to set app parameter %v", err)
}
_, err = fixture.RunCli("app", "sync", app.Name)
if err != nil {
t.Fatalf("Unable to sync app %v", err)
}
WaitUntil(t, func() (done bool, err error) {
app, err = fixture.AppClient.ArgoprojV1alpha1().Applications(fixture.Namespace).Get(app.ObjectMeta.Name, metav1.GetOptions{})
return err == nil && app.Status.ComparisonResult.Status == v1alpha1.ComparisonStatusSynced && app.Status.Health.Status == v1alpha1.HealthStatusDegraded, err
})
})
}

View File

@@ -1,8 +1,8 @@
package e2e
import (
"bytes"
"context"
"encoding/json"
"fmt"
"log"
"net"
@@ -11,7 +11,16 @@ import (
"testing"
"time"
"encoding/json"
"k8s.io/api/core/v1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"strings"
"github.com/argoproj/argo-cd/cmd/argocd/commands"
"github.com/argoproj/argo-cd/common"
@@ -29,15 +38,8 @@ import (
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/git"
"github.com/argoproj/argo-cd/util/rbac"
"github.com/argoproj/argo-cd/util/settings"
"k8s.io/api/core/v1"
apiextensionsclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
)
const (
@@ -55,6 +57,7 @@ type Fixture struct {
InstanceID string
RepoServerAddress string
ApiServerAddress string
Enforcer *rbac.Enforcer
tearDownCallback func()
}
@@ -93,6 +96,19 @@ func (f *Fixture) setup() error {
}
installer.InstallApplicationCRD()
cm := v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: common.ArgoCDRBACConfigMapName,
},
Data: map[string]string{
rbac.ConfigMapPolicyDefaultKey: "role:admin",
},
}
_, err = f.KubeClient.CoreV1().ConfigMaps(f.Namespace).Create(&cm)
if err != nil {
return err
}
settingsMgr := settings.NewSettingsManager(f.KubeClient, f.Namespace)
err = settingsMgr.SaveSettings(&settings.ArgoCDSettings{})
if err != nil {
@@ -128,22 +144,11 @@ func (f *Fixture) setup() error {
})
ctx, cancel := context.WithCancel(context.Background())
go func() {
err = repoServerGRPC.Serve(repoServerListener)
}()
go func() {
apiServer.Run(ctx, apiServerPort)
}()
f.tearDownCallback = func() {
cancel()
repoServerGRPC.Stop()
}
if err != nil {
return err
}
return waitUntilE(func() (done bool, err error) {
err = waitUntilE(func() (done bool, err error) {
clientset, err := f.NewApiClientset()
if err != nil {
return false, nil
@@ -156,6 +161,22 @@ func (f *Fixture) setup() error {
_, err = appClient.List(context.Background(), &application.ApplicationQuery{})
return err == nil, nil
})
ctrl := f.createController()
ctrlCtx, cancelCtrl := context.WithCancel(context.Background())
go ctrl.Run(ctrlCtx, 1, 1)
go func() {
err = repoServerGRPC.Serve(repoServerListener)
}()
f.tearDownCallback = func() {
cancel()
cancelCtrl()
repoServerGRPC.Stop()
}
return err
}
func (f *Fixture) ensureClusterRegistered() error {
@@ -170,7 +191,8 @@ func (f *Fixture) ensureClusterRegistered() error {
// Install RBAC resources for managing the cluster
managerBearerToken := common.InstallClusterManagerRBAC(conf)
clst := commands.NewCluster(f.Config.Host, conf, managerBearerToken)
_, err = cluster.NewServer(f.DB).Create(context.Background(), clst)
clstCreateReq := cluster.ClusterCreateRequest{Cluster: clst}
_, err = cluster.NewServer(f.DB, f.Enforcer).Create(context.Background(), &clstCreateReq)
return err
}
@@ -232,6 +254,8 @@ func NewFixture() (*Fixture, error) {
return nil, err
}
db := db.NewDB(namespace, kubeClient)
enforcer := rbac.NewEnforcer(kubeClient, namespace, common.ArgoCDRBACConfigMapName, nil)
enforcer.SetDefaultRole("role:admin")
fixture := &Fixture{
Config: config,
@@ -241,6 +265,7 @@ func NewFixture() (*Fixture, error) {
KubeClient: kubeClient,
Namespace: namespace,
InstanceID: namespace,
Enforcer: enforcer,
}
err = fixture.setup()
if err != nil {
@@ -251,6 +276,8 @@ func NewFixture() (*Fixture, error) {
// CreateApp creates application with appropriate controller instance id.
func (f *Fixture) CreateApp(t *testing.T, application *v1alpha1.Application) *v1alpha1.Application {
application = application.DeepCopy()
application.Name = fmt.Sprintf("e2e-test-%v", time.Now().Unix())
labels := application.ObjectMeta.Labels
if labels == nil {
labels = make(map[string]string)
@@ -258,6 +285,10 @@ func (f *Fixture) CreateApp(t *testing.T, application *v1alpha1.Application) *v1
}
labels[common.LabelKeyApplicationControllerInstanceID] = f.InstanceID
application.Spec.Source.ComponentParameterOverrides = append(
application.Spec.Source.ComponentParameterOverrides,
v1alpha1.ComponentParameter{Name: "name", Value: application.Name, Component: "guestbook-ui"})
app, err := f.AppClient.ArgoprojV1alpha1().Applications(f.Namespace).Create(application)
if err != nil {
t.Fatal(fmt.Sprintf("Unable to create app %v", err))
@@ -265,8 +296,8 @@ func (f *Fixture) CreateApp(t *testing.T, application *v1alpha1.Application) *v1
return app
}
// CreateController creates new controller instance
func (f *Fixture) CreateController() *controller.ApplicationController {
// createController creates new controller instance
func (f *Fixture) createController() *controller.ApplicationController {
appStateManager := controller.NewAppStateManager(
f.DB, f.AppClient, reposerver.NewRepositoryServerClientset(f.RepoServerAddress), f.Namespace)
@@ -292,12 +323,21 @@ func (f *Fixture) NewApiClientset() (argocdclient.Client, error) {
}
func (f *Fixture) RunCli(args ...string) (string, error) {
cmd := commands.NewCommand()
cmd.SetArgs(append(args, "--server", f.ApiServerAddress, "--plaintext"))
output := new(bytes.Buffer)
cmd.SetOutput(output)
err := cmd.Execute()
return output.String(), err
args = append([]string{"run", "../../cmd/argocd/main.go"}, args...)
cmd := exec.Command("go", append(args, "--server", f.ApiServerAddress, "--plaintext")...)
outBytes, err := cmd.Output()
if err != nil {
exErr, ok := err.(*exec.ExitError)
if !ok {
return "", err
}
errOutput := string(exErr.Stderr)
if outBytes != nil {
errOutput = string(outBytes) + "\n" + errOutput
}
return "", fmt.Errorf(strings.TrimSpace(errOutput))
}
return string(outBytes), nil
}
func waitUntilE(condition wait.ConditionFunc) error {

View File

@@ -1,15 +1,22 @@
package argo
import (
"context"
"encoding/json"
"errors"
"fmt"
"time"
log "github.com/sirupsen/logrus"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"github.com/argoproj/argo-cd/common"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/pkg/client/clientset/versioned/typed/application/v1alpha1"
log "github.com/sirupsen/logrus"
apierr "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/types"
)
// RefreshApp updates the refresh annotation of an application to coerce the controller to process it
@@ -21,6 +28,11 @@ func RefreshApp(appIf v1alpha1.ApplicationInterface, name string) (*argoappv1.Ap
common.AnnotationKeyRefresh: refreshString,
},
},
"status": map[string]interface{}{
"comparisonResult": map[string]interface{}{
"comparedAt": nil,
},
},
}
var err error
patch, err := json.Marshal(metadata)
@@ -41,3 +53,54 @@ func RefreshApp(appIf v1alpha1.ApplicationInterface, name string) (*argoappv1.Ap
}
return nil, err
}
// WaitForRefresh watches a workflow until its comparison timestamp is after the refresh timestamp
func WaitForRefresh(appIf v1alpha1.ApplicationInterface, name string, timeout *time.Duration) (*argoappv1.Application, error) {
ctx := context.Background()
var cancel context.CancelFunc
if timeout != nil {
ctx, cancel = context.WithTimeout(ctx, *timeout)
defer cancel()
}
fieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", name))
listOpts := metav1.ListOptions{FieldSelector: fieldSelector.String()}
watchIf, err := appIf.Watch(listOpts)
if err != nil {
return nil, err
}
defer watchIf.Stop()
for {
select {
case <-ctx.Done():
err := ctx.Err()
if err != nil {
if err == context.DeadlineExceeded {
return nil, fmt.Errorf("Timed out (%v) waiting for application to refresh", timeout)
}
return nil, fmt.Errorf("Error waiting for refresh: %v", err)
}
return nil, fmt.Errorf("Application watch on %s closed", name)
case next := <-watchIf.ResultChan():
if next.Type == watch.Error {
errMsg := "Application watch completed with error"
if status, ok := next.Object.(*metav1.Status); ok {
errMsg = fmt.Sprintf("%s: %v", errMsg, status)
}
return nil, errors.New(errMsg)
}
app, ok := next.Object.(*argoappv1.Application)
if !ok {
return nil, fmt.Errorf("Application event object failed conversion: %v", next)
}
refreshTimestampStr := app.ObjectMeta.Annotations[common.AnnotationKeyRefresh]
refreshTimestamp, err := time.Parse(time.RFC3339, refreshTimestampStr)
if err != nil {
return nil, fmt.Errorf("Unable to parse '%s': %v", common.AnnotationKeyRefresh, err)
}
if app.Status.ComparisonResult.ComparedAt.After(refreshTimestamp) {
return app, nil
}
}
}
}

View File

@@ -1,11 +1,18 @@
package argo
import (
"strings"
"testing"
"time"
"github.com/stretchr/testify/assert"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/watch"
"github.com/argoproj/argo-cd/common"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned/fake"
"github.com/stretchr/testify/assert"
testcore "k8s.io/client-go/testing"
)
func TestRefreshApp(t *testing.T) {
@@ -21,3 +28,34 @@ func TestRefreshApp(t *testing.T) {
//_, ok := newApp.Annotations[common.AnnotationKeyRefresh]
//assert.True(t, ok)
}
func TestWaitForRefresh(t *testing.T) {
appClientset := appclientset.NewSimpleClientset()
// Verify timeout
appIf := appClientset.ArgoprojV1alpha1().Applications("default")
oneHundredMs := 100 * time.Millisecond
app, err := WaitForRefresh(appIf, "test-app", &oneHundredMs)
assert.NotNil(t, err)
assert.Nil(t, app)
assert.Contains(t, strings.ToLower(err.Error()), "timed out")
// Verify success
var testApp argoappv1.Application
testApp.Name = "test-app"
testApp.Namespace = "default"
testApp.ObjectMeta.Annotations = map[string]string{
common.AnnotationKeyRefresh: time.Now().UTC().Format(time.RFC3339),
}
testApp.Status.ComparisonResult.ComparedAt = metav1.Time{Time: time.Now().UTC()}
appClientset = appclientset.NewSimpleClientset()
appIf = appClientset.ArgoprojV1alpha1().Applications("default")
watcher := watch.NewFake()
appClientset.PrependWatchReactor("applications", testcore.DefaultWatchReactor(watcher, nil))
// simulate add/update/delete watch events
go watcher.Add(&testApp)
app, err = WaitForRefresh(appIf, "test-app", &oneHundredMs)
assert.Nil(t, err)
assert.NotNil(t, app)
}

View File

@@ -39,7 +39,7 @@ func (s *db) ListClusters(ctx context.Context) (*appv1.ClusterList, error) {
Items: make([]appv1.Cluster, len(clusterSecrets.Items)),
}
for i, clusterSecret := range clusterSecrets.Items {
clusterList.Items[i] = *secretToCluster(&clusterSecret)
clusterList.Items[i] = *SecretToCluster(&clusterSecret)
}
return &clusterList, nil
}
@@ -50,7 +50,10 @@ func (s *db) CreateCluster(ctx context.Context, c *appv1.Cluster) (*appv1.Cluste
if err != nil {
return nil, err
}
secName := serverToSecretName(c.Server)
secName, err := serverToSecretName(c.Server)
if err != nil {
return nil, err
}
clusterSecret := &apiv1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secName,
@@ -67,7 +70,7 @@ func (s *db) CreateCluster(ctx context.Context, c *appv1.Cluster) (*appv1.Cluste
}
return nil, err
}
return secretToCluster(clusterSecret), nil
return SecretToCluster(clusterSecret), nil
}
// ClusterEvent contains information about cluster event
@@ -96,7 +99,7 @@ func (s *db) WatchClusters(ctx context.Context, callback func(*ClusterEvent)) er
}()
for next := range w.ResultChan() {
secret := next.Object.(*apiv1.Secret)
cluster := secretToCluster(secret)
cluster := SecretToCluster(secret)
callback(&ClusterEvent{
Type: next.Type,
Cluster: cluster,
@@ -106,7 +109,10 @@ func (s *db) WatchClusters(ctx context.Context, callback func(*ClusterEvent)) er
}
func (s *db) getClusterSecret(server string) (*apiv1.Secret, error) {
secName := serverToSecretName(server)
secName, err := serverToSecretName(server)
if err != nil {
return nil, err
}
clusterSecret, err := s.kubeclientset.CoreV1().Secrets(s.ns).Get(secName, metav1.GetOptions{})
if err != nil {
if apierr.IsNotFound(err) {
@@ -123,7 +129,7 @@ func (s *db) GetCluster(ctx context.Context, server string) (*appv1.Cluster, err
if err != nil {
return nil, err
}
return secretToCluster(clusterSecret), nil
return SecretToCluster(clusterSecret), nil
}
// UpdateCluster updates a cluster
@@ -141,26 +147,29 @@ func (s *db) UpdateCluster(ctx context.Context, c *appv1.Cluster) (*appv1.Cluste
if err != nil {
return nil, err
}
return secretToCluster(clusterSecret), nil
return SecretToCluster(clusterSecret), nil
}
// Delete deletes a cluster by name
func (s *db) DeleteCluster(ctx context.Context, name string) error {
secName := serverToSecretName(name)
secName, err := serverToSecretName(name)
if err != nil {
return err
}
return s.kubeclientset.CoreV1().Secrets(s.ns).Delete(secName, &metav1.DeleteOptions{})
}
// serverToSecretName hashes server address to the secret name using a formula.
// Part of the server address is incorporated for debugging purposes
func serverToSecretName(server string) string {
func serverToSecretName(server string) (string, error) {
serverURL, err := url.ParseRequestURI(server)
if err != nil {
panic(err)
return "", err
}
h := fnv.New32a()
_, _ = h.Write([]byte(server))
host := strings.ToLower(strings.Split(serverURL.Host, ":")[0])
return fmt.Sprintf("cluster-%s-%v", host, h.Sum32())
return fmt.Sprintf("cluster-%s-%v", host, h.Sum32()), nil
}
// clusterToStringData converts a cluster object to string data for serialization to a secret
@@ -180,17 +189,18 @@ func clusterToStringData(c *appv1.Cluster) map[string]string {
return stringData
}
// secretToCluster converts a secret into a repository object
func secretToCluster(s *apiv1.Secret) *appv1.Cluster {
// SecretToCluster converts a secret into a repository object
func SecretToCluster(s *apiv1.Secret) *appv1.Cluster {
var config appv1.ClusterConfig
err := json.Unmarshal(s.Data["config"], &config)
if err != nil {
panic(err)
}
cluster := appv1.Cluster{
Server: string(s.Data["server"]),
Name: string(s.Data["name"]),
Config: config,
Server: string(s.Data["server"]),
Name: string(s.Data["name"]),
Config: config,
ConnectionState: ConnectionStateFromAnnotations(s.Annotations),
}
return &cluster
}

View File

@@ -1,8 +1,13 @@
package db
import (
"time"
"github.com/argoproj/argo-cd/common"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
log "github.com/sirupsen/logrus"
"golang.org/x/net/context"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
@@ -44,3 +49,39 @@ func NewDB(namespace string, kubeclientset kubernetes.Interface) ArgoDB {
kubeclientset: kubeclientset,
}
}
func AnnotationsFromConnectionState(connectionState *appv1.ConnectionState) map[string]string {
attemptedAtStr := ""
if connectionState.ModifiedAt != nil {
attemptedAtStr = connectionState.ModifiedAt.Format(time.RFC3339)
}
return map[string]string{
common.AnnotationConnectionMessage: connectionState.Message,
common.AnnotationConnectionStatus: connectionState.Status,
common.AnnotationConnectionModifiedAt: attemptedAtStr,
}
}
func ConnectionStateFromAnnotations(annotations map[string]string) appv1.ConnectionState {
status := annotations[common.AnnotationConnectionStatus]
if status == "" {
status = appv1.ConnectionStatusUnknown
}
attemptedAtStr := annotations[common.AnnotationConnectionModifiedAt]
var attemptedAtMetaTimePtr *metav1.Time
if attemptedAtStr != "" {
attemptedAtTime, err := time.Parse(time.RFC3339, attemptedAtStr)
if err != nil {
log.Warnf("Unable to parse connection status attemptedAt time")
} else {
attemptedAtMetaTime := metav1.NewTime(attemptedAtTime)
attemptedAtMetaTimePtr = &attemptedAtMetaTime
}
}
return appv1.ConnectionState{
Status: status,
Message: annotations[common.AnnotationConnectionMessage],
ModifiedAt: attemptedAtMetaTimePtr,
}
}

View File

@@ -36,7 +36,7 @@ func (s *db) ListRepositories(ctx context.Context) (*appsv1.RepositoryList, erro
Items: make([]appsv1.Repository, len(repoSecrets.Items)),
}
for i, repoSec := range repoSecrets.Items {
repoList.Items[i] = *secretToRepo(&repoSec)
repoList.Items[i] = *SecretToRepo(&repoSec)
}
return &repoList, nil
}
@@ -68,7 +68,7 @@ func (s *db) CreateRepository(ctx context.Context, r *appsv1.Repository) (*appsv
}
return nil, err
}
return secretToRepo(repoSecret), nil
return SecretToRepo(repoSecret), nil
}
// GetRepository returns a repository by URL
@@ -77,7 +77,7 @@ func (s *db) GetRepository(ctx context.Context, name string) (*appsv1.Repository
if err != nil {
return nil, err
}
return secretToRepo(repoSecret), nil
return SecretToRepo(repoSecret), nil
}
// UpdateRepository updates a repository
@@ -95,7 +95,7 @@ func (s *db) UpdateRepository(ctx context.Context, r *appsv1.Repository) (*appsv
if err != nil {
return nil, err
}
return secretToRepo(repoSecret), nil
return SecretToRepo(repoSecret), nil
}
// Delete updates a repository
@@ -123,7 +123,8 @@ func repoURLToSecretName(repo string) string {
h := fnv.New32a()
_, _ = h.Write([]byte(repo))
parts := strings.Split(strings.TrimSuffix(repo, ".git"), "/")
return fmt.Sprintf("repo-%s-%v", parts[len(parts)-1], h.Sum32())
shortName := strings.Replace(parts[len(parts)-1], "_", "-", -1)
return fmt.Sprintf("repo-%s-%v", shortName, h.Sum32())
}
// repoToStringData converts a repository object to string data for serialization to a secret
@@ -136,13 +137,14 @@ func repoToStringData(r *appsv1.Repository) map[string]string {
}
}
// secretToRepo converts a secret into a repository object, optionally redacting sensitive information
func secretToRepo(s *apiv1.Secret) *appsv1.Repository {
// SecretToRepo converts a secret into a repository object, optionally redacting sensitive information
func SecretToRepo(s *apiv1.Secret) *appsv1.Repository {
repo := appsv1.Repository{
Repo: string(s.Data["repository"]),
Username: string(s.Data["username"]),
Password: string(s.Data["password"]),
SSHPrivateKey: string(s.Data["sshPrivateKey"]),
Repo: string(s.Data["repository"]),
Username: string(s.Data["username"]),
Password: string(s.Data["password"]),
SSHPrivateKey: string(s.Data["sshPrivateKey"]),
ConnectionState: ConnectionStateFromAnnotations(s.Annotations),
}
return &repo
}

View File

@@ -8,6 +8,7 @@ func TestRepoURLToSecretName(t *testing.T) {
"https://github.com/argoproj/ARGO-cd": "repo-argo-cd-821842295",
"https://github.com/argoproj/argo-cd": "repo-argo-cd-821842295",
"https://github.com/argoproj/argo-cd.git": "repo-argo-cd-821842295",
"https://github.com/argoproj/argo_cd.git": "repo-argo-cd-1049844989",
"ssh://git@github.com/argoproj/argo-cd.git": "repo-argo-cd-1019298066",
}

View File

@@ -12,17 +12,18 @@ import (
"os"
"time"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/session"
"github.com/argoproj/argo-cd/util/settings"
"github.com/coreos/dex/api"
oidc "github.com/coreos/go-oidc"
jwt "github.com/dgrijalva/jwt-go"
log "github.com/sirupsen/logrus"
"golang.org/x/oauth2"
"google.golang.org/grpc"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/session"
"github.com/argoproj/argo-cd/util/settings"
)
const (
@@ -141,15 +142,18 @@ func NewClientApp(settings *settings.ArgoCDSettings, sessionMgr *session.Session
return &a, nil
}
func (a *ClientApp) oauth2Config(scopes []string) *oauth2.Config {
provider, _ := a.sessionMgr.OIDCProvider()
func (a *ClientApp) oauth2Config(scopes []string) (*oauth2.Config, error) {
provider, err := a.sessionMgr.OIDCProvider()
if err != nil {
return nil, err
}
return &oauth2.Config{
ClientID: a.clientID,
ClientSecret: a.clientSecret,
Endpoint: provider.Endpoint(),
Scopes: scopes,
RedirectURL: a.redirectURI,
}
}, nil
}
var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
@@ -196,18 +200,23 @@ func (a *ClientApp) verifyAppState(state string) (*appState, error) {
}
func (a *ClientApp) HandleLogin(w http.ResponseWriter, r *http.Request) {
var authCodeURL string
var opts []oauth2.AuthCodeOption
returnURL := r.FormValue("return_url")
scopes := []string{"openid", "profile", "email", "groups"}
appState := a.generateAppState(returnURL)
if r.FormValue("offline_access") != "yes" {
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(appState)
// no-op
} else if a.sessionMgr.OfflineAsScope() {
scopes = append(scopes, "offline_access")
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(appState)
} else {
authCodeURL = a.oauth2Config(scopes).AuthCodeURL(appState, oauth2.AccessTypeOffline)
opts = append(opts, oauth2.AccessTypeOffline)
}
oauth2Config, err := a.oauth2Config(scopes)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
authCodeURL := oauth2Config.AuthCodeURL(appState, opts...)
http.Redirect(w, r, authCodeURL, http.StatusSeeOther)
}
@@ -219,7 +228,11 @@ func (a *ClientApp) HandleCallback(w http.ResponseWriter, r *http.Request) {
)
ctx := oidc.ClientContext(r.Context(), a.client)
oauth2Config := a.oauth2Config(nil)
oauth2Config, err := a.oauth2Config(nil)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
switch r.Method {
case "GET":
// Authorization redirect callback from OAuth2 auth flow.

View File

@@ -29,7 +29,7 @@ type DiffResultList struct {
// "kubectl.kubernetes.io/last-applied-configuration", then perform a three way diff.
func Diff(config, live *unstructured.Unstructured) *DiffResult {
orig := getLastAppliedConfigAnnotation(live)
if orig != nil {
if orig != nil && config != nil {
return ThreeWayDiff(orig, config, live)
}
return TwoWayDiff(config, live)
@@ -147,6 +147,53 @@ func getLastAppliedConfigAnnotation(live *unstructured.Unstructured) *unstructur
return &obj
}
// MatchObjectLists takes two possibly disjoint lists of Unstructured objects, and returns two new
// lists of equal lengths, filled out with nils from missing objects in the opposite list.
// These lists can then be passed into DiffArray for comparison
func MatchObjectLists(leftObjs, rightObjs []*unstructured.Unstructured) ([]*unstructured.Unstructured, []*unstructured.Unstructured) {
newLeftObjs := make([]*unstructured.Unstructured, 0)
newRightObjs := make([]*unstructured.Unstructured, 0)
for _, left := range leftObjs {
if left == nil {
continue
}
newLeftObjs = append(newLeftObjs, left)
right := objByKindName(rightObjs, left.GetKind(), left.GetName())
newRightObjs = append(newRightObjs, right)
}
for _, right := range rightObjs {
if right == nil {
continue
}
left := objByKindName(leftObjs, right.GetKind(), right.GetName())
if left != nil {
// object exists in both list. this object was already appended to both lists in the
// first for/loop
continue
}
// if we get here, we found a right which doesn't exist in the left object list.
// append a nil to the left object list
newLeftObjs = append(newLeftObjs, nil)
newRightObjs = append(newRightObjs, right)
}
return newLeftObjs, newRightObjs
}
func objByKindName(objs []*unstructured.Unstructured, kind, name string) *unstructured.Unstructured {
for _, obj := range objs {
if obj == nil {
continue
}
if obj.GetKind() == kind && obj.GetName() == name {
return obj
}
}
return nil
}
// DiffArray performs a diff on a list of unstructured objects. Objects are expected to match
// environments
func DiffArray(configArray, liveArray []*unstructured.Unstructured) (*DiffResultList, error) {

View File

@@ -98,10 +98,12 @@ func TestRepo(repo, username, password string, sshPrivateKey string) error {
cmd.Env = env
_, err = cmd.Output()
if err != nil {
exErr := err.(*exec.ExitError)
errOutput := strings.Split(string(exErr.Stderr), "\n")[0]
errOutput = redactPassword(errOutput, password)
return fmt.Errorf("%s: %s", repo, errOutput)
if exErr, ok := err.(*exec.ExitError); ok {
errOutput := strings.Split(string(exErr.Stderr), "\n")[0]
errOutput = redactPassword(errOutput, password)
return fmt.Errorf("%s: %s", repo, errOutput)
}
return err
}
return nil
}

View File

@@ -15,6 +15,10 @@ import (
"google.golang.org/grpc/status"
)
var (
ErrPermissionDenied = status.Errorf(codes.PermissionDenied, "permission denied")
)
// PanicLoggerUnaryServerInterceptor returns a new unary server interceptor for recovering from panics and returning error
func PanicLoggerUnaryServerInterceptor(log *logrus.Entry) grpc.UnaryServerInterceptor {
return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (_ interface{}, err error) {

51
util/jwt/jwt.go Normal file
View File

@@ -0,0 +1,51 @@
package jwt
import (
"encoding/json"
jwtgo "github.com/dgrijalva/jwt-go"
)
// MapClaims converts a jwt.Claims to a MapClaims
func MapClaims(claims jwtgo.Claims) (jwtgo.MapClaims, error) {
claimsBytes, err := json.Marshal(claims)
if err != nil {
return nil, err
}
var mapClaims jwtgo.MapClaims
err = json.Unmarshal(claimsBytes, &mapClaims)
if err != nil {
return nil, err
}
return mapClaims, nil
}
// GetField extracts a field from the claims as a string
func GetField(claims jwtgo.MapClaims, fieldName string) string {
if fieldIf, ok := claims[fieldName]; ok {
if field, ok := fieldIf.(string); ok {
return field
}
}
return ""
}
// GetGroups extracts the groups from a claims
func GetGroups(claims jwtgo.MapClaims) []string {
groups := make([]string, 0)
groupsIf, ok := claims["groups"]
if !ok {
return groups
}
groupIfList, ok := groupsIf.([]interface{})
if !ok {
return groups
}
for _, groupIf := range groupIfList {
group, ok := groupIf.(string)
if ok {
groups = append(groups, group)
}
}
return groups
}

View File

@@ -93,6 +93,34 @@ func MustToUnstructured(obj interface{}) *unstructured.Unstructured {
return uObj
}
// SetLabel sets our app labels against an unstructured object
func SetLabel(target *unstructured.Unstructured, key, val string) error {
labels := target.GetLabels()
if labels == nil {
labels = make(map[string]string)
}
labels[key] = val
target.SetLabels(labels)
// special case for deployment: make sure that derived replicaset and pod has application label
if target.GetKind() == DeploymentKind {
labels, ok, err := unstructured.NestedMap(target.UnstructuredContent(), "spec", "template", "metadata", "labels")
if err != nil {
return err
}
if ok {
if labels == nil {
labels = make(map[string]interface{})
}
labels[key] = val
}
err = unstructured.SetNestedMap(target.UnstructuredContent(), labels, "spec", "template", "metadata", "labels")
if err != nil {
return err
}
}
return nil
}
// GetCachedServerResources discovers API resources supported by a Kube API server.
// Caches the results for apiResourceCacheDuration (per host)
func GetCachedServerResources(host string, disco discovery.DiscoveryInterface) ([]*metav1.APIResourceList, error) {

View File

@@ -0,0 +1,28 @@
# Built-in policy which defines two roles: role:readonly and role:admin,
# and additionally assigns the admin user to the role:admin role.
# The policy format is:
# p, <user/group>, <resource>, <action>, <project>/<object>
p, role:readonly, applications, get, */*
p, role:readonly, applications/events, get, */*
p, role:readonly, applications/manifests, get, */*
p, role:readonly, applications/logs, get, */*
p, role:readonly, clusters, get, */*
p, role:readonly, repositories, get, */*
p, role:readonly, repositories/apps, get, */*
p, role:admin, applications, create, */*
p, role:admin, applications, update, */*
p, role:admin, applications, delete, */*
p, role:admin, applications, sync, */*
p, role:admin, applications, rollback, */*
p, role:admin, applications/pods, delete, */*
p, role:admin, clusters, create, */*
p, role:admin, clusters, update, */*
p, role:admin, clusters, delete, */*
p, role:admin, repositories, create, */*
p, role:admin, repositories, update, */*
p, role:admin, repositories, delete, */*
g, role:admin, role:readonly
g, admin, role:admin
1 # Built-in policy which defines two roles: role:readonly and role:admin,
2 # and additionally assigns the admin user to the role:admin role.
3 # The policy format is:
4 # p, <user/group>, <resource>, <action>, <project>/<object>
5 p, role:readonly, applications, get, */*
6 p, role:readonly, applications/events, get, */*
7 p, role:readonly, applications/manifests, get, */*
8 p, role:readonly, applications/logs, get, */*
9 p, role:readonly, clusters, get, */*
10 p, role:readonly, repositories, get, */*
11 p, role:readonly, repositories/apps, get, */*
12 p, role:admin, applications, create, */*
13 p, role:admin, applications, update, */*
14 p, role:admin, applications, delete, */*
15 p, role:admin, applications, sync, */*
16 p, role:admin, applications, rollback, */*
17 p, role:admin, applications/pods, delete, */*
18 p, role:admin, clusters, create, */*
19 p, role:admin, clusters, update, */*
20 p, role:admin, clusters, delete, */*
21 p, role:admin, repositories, create, */*
22 p, role:admin, repositories, update, */*
23 p, role:admin, repositories, delete, */*
24 g, role:admin, role:readonly
25 g, admin, role:admin

14
util/rbac/model.conf Normal file
View File

@@ -0,0 +1,14 @@
[request_definition]
r = sub, res, act, obj
[policy_definition]
p = sub, res, act, obj
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch(r.res, p.res) && keyMatch(r.act, p.act) && keyMatch(r.obj, p.obj)

215
util/rbac/rbac.go Normal file
View File

@@ -0,0 +1,215 @@
package rbac
import (
"context"
"fmt"
"time"
"github.com/casbin/casbin"
"github.com/casbin/casbin/model"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gobuffalo/packr"
scas "github.com/qiangmzsx/string-adapter"
log "github.com/sirupsen/logrus"
apiv1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
v1 "k8s.io/client-go/informers/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
jwtutil "github.com/argoproj/argo-cd/util/jwt"
)
const (
ConfigMapPolicyCSVKey = "policy.csv"
ConfigMapPolicyDefaultKey = "policy.default"
builtinModelFile = "model.conf"
defaultRBACSyncPeriod = 10 * time.Minute
)
// ClaimsEnforcerFunc is func template
type ClaimsEnforcerFunc func(rvals ...interface{}) bool
type Enforcer struct {
*casbin.Enforcer
clientset kubernetes.Interface
namespace string
configmap string
claimsEnforcerFunc ClaimsEnforcerFunc
model model.Model
defaultRole string
builtinPolicy string
userDefinedPolicy string
}
func NewEnforcer(clientset kubernetes.Interface, namespace, configmap string, claimsEnforcer ClaimsEnforcerFunc) *Enforcer {
box := packr.NewBox(".")
modelConf := box.String(builtinModelFile)
model := casbin.NewModel(modelConf)
enf := casbin.Enforcer{}
enf.EnableLog(false)
return &Enforcer{
Enforcer: &enf,
clientset: clientset,
namespace: namespace,
configmap: configmap,
model: model,
claimsEnforcerFunc: claimsEnforcer,
}
}
// SetDefaultRole sets a default role to use during enforcement. Will fall back to this role if
// normal enforcement fails
func (e *Enforcer) SetDefaultRole(roleName string) {
e.defaultRole = roleName
}
// SetClaimsEnforcerFunc sets a claims enforce function during enforcement. The claims enforce function
// can extract claims from JWT token and do the proper enforcement based on user, group or any information
// available in the input parameter list
func (e *Enforcer) SetClaimsEnforcerFunc(claimsEnforcer ClaimsEnforcerFunc) {
e.claimsEnforcerFunc = claimsEnforcer
}
// Enforce is a wrapper around casbin.Enforce to additionally enforce a default role
func (e *Enforcer) Enforce(rvals ...interface{}) bool {
if e.Enforcer.Enforce(rvals...) {
return true
}
if e.defaultRole == "" {
return false
}
rvals = append([]interface{}{e.defaultRole}, rvals[1:]...)
return e.Enforcer.Enforce(rvals...)
}
// EnforceClaims checks if the first value is a jwt.Claims and runs enforce against its groups and sub
func (e *Enforcer) EnforceClaims(rvals ...interface{}) bool {
// Use default claims enforcer if it is nil
if e.claimsEnforcerFunc == nil {
return e.defaultEnforceClaims(rvals...)
}
return e.claimsEnforcerFunc(rvals...)
}
func (e *Enforcer) defaultEnforceClaims(rvals ...interface{}) bool {
claims, ok := rvals[0].(jwt.Claims)
if !ok {
if rvals[0] == nil {
vals := append([]interface{}{""}, rvals[1:]...)
return e.Enforce(vals...)
}
return e.Enforce(rvals...)
}
mapClaims, err := jwtutil.MapClaims(claims)
if err != nil {
vals := append([]interface{}{""}, rvals[1:]...)
return e.Enforce(vals...)
}
groups := jwtutil.GetGroups(mapClaims)
for _, group := range groups {
vals := append([]interface{}{group}, rvals[1:]...)
if e.Enforcer.Enforce(vals...) {
return true
}
}
user := jwtutil.GetField(mapClaims, "sub")
vals := append([]interface{}{user}, rvals[1:]...)
return e.Enforce(vals...)
}
// SetBuiltinPolicy sets a built-in policy, which augments any user defined policies
func (e *Enforcer) SetBuiltinPolicy(policy string) error {
sa := scas.NewAdapter(fmt.Sprintf("%s\n%s", policy, e.userDefinedPolicy))
enf, err := casbin.NewEnforcerSafe(e.model, sa)
if err != nil {
return fmt.Errorf("failed to update enforcer: %v", err)
}
e.builtinPolicy = policy
e.Enforcer = enf
return nil
}
// SetUserPolicy sets a user policy, augmenting the built-in policy
func (e *Enforcer) SetUserPolicy(policy string) error {
sa := scas.NewAdapter(fmt.Sprintf("%s\n%s", e.builtinPolicy, policy))
enf, err := casbin.NewEnforcerSafe(e.model, sa)
if err != nil {
return fmt.Errorf("failed to update enforcer: %v", err)
}
e.userDefinedPolicy = policy
e.Enforcer = enf
return nil
}
// newInformers returns an informer which watches updates on the rbac configmap
func (e *Enforcer) newInformer() cache.SharedIndexInformer {
tweakConfigMap := func(options *metav1.ListOptions) {
cmFieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", e.configmap))
options.FieldSelector = cmFieldSelector.String()
}
return v1.NewFilteredConfigMapInformer(e.clientset, e.namespace, defaultRBACSyncPeriod, cache.Indexers{}, tweakConfigMap)
}
// RunPolicyLoader runs the policy loader which watches policy updates from the configmap and reloads them
func (e *Enforcer) RunPolicyLoader(ctx context.Context) error {
cm, err := e.clientset.CoreV1().ConfigMaps(e.namespace).Get(e.configmap, metav1.GetOptions{})
if err != nil {
if !apierr.IsNotFound(err) {
return err
}
} else {
err = e.syncUpdate(cm)
if err != nil {
return err
}
}
e.runInformer(ctx)
return nil
}
func (e *Enforcer) runInformer(ctx context.Context) {
cmInformer := e.newInformer()
cmInformer.AddEventHandler(
cache.ResourceEventHandlerFuncs{
AddFunc: func(obj interface{}) {
if cm, ok := obj.(*apiv1.ConfigMap); ok {
err := e.syncUpdate(cm)
if err != nil {
log.Error(err)
}
}
},
UpdateFunc: func(old, new interface{}) {
oldCM := old.(*apiv1.ConfigMap)
newCM := new.(*apiv1.ConfigMap)
if oldCM.ResourceVersion == newCM.ResourceVersion {
return
}
log.Infof("%s updated", e.configmap)
err := e.syncUpdate(newCM)
if err != nil {
log.Error(err)
}
},
},
)
log.Info("Starting rbac config informer")
cmInformer.Run(ctx.Done())
log.Info("rbac configmap informer cancelled")
}
// syncUpdate updates the enforcer
func (e *Enforcer) syncUpdate(cm *apiv1.ConfigMap) error {
e.SetDefaultRole(cm.Data[ConfigMapPolicyDefaultKey])
policyCSV, ok := cm.Data[ConfigMapPolicyCSVKey]
if !ok {
policyCSV = ""
}
return e.SetUserPolicy(policyCSV)
}

258
util/rbac/rbac_test.go Normal file
View File

@@ -0,0 +1,258 @@
package rbac
import (
"context"
"testing"
"time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/gobuffalo/packr"
log "github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes/fake"
)
const (
fakeConfgMapName = "fake-cm"
fakeNamespace = "fake-ns"
builtinPolicyFile = "builtin-policy.csv"
)
var box packr.Box
func init() {
box = packr.NewBox(".")
}
func fakeConfigMap(policy ...string) *apiv1.ConfigMap {
cm := apiv1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: fakeConfgMapName,
Namespace: fakeNamespace,
},
Data: make(map[string]string),
}
if len(policy) > 0 {
cm.Data[ConfigMapPolicyCSVKey] = policy[0]
}
return &cm
}
// TestBuiltinPolicyEnforcer tests the builtin policy rules
func TestBuiltinPolicyEnforcer(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
// Without setting builtin policy, this should fail
assert.False(t, enf.Enforce("admin", "applications", "get", "foo/bar"))
// now set builtin policy
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
allowed := [][]interface{}{
{"admin", "applications", "get", "foo/bar"},
{"admin", "applications", "delete", "foo/bar"},
{"role:readonly", "applications", "get", "foo/bar"},
{"role:admin", "applications", "get", "foo/bar"},
{"role:admin", "applications", "delete", "foo/bar"},
}
for _, a := range allowed {
if !assert.True(t, enf.Enforce(a...)) {
log.Errorf("%s: expected true, got false", a)
}
}
disallowed := [][]interface{}{
{"role:readonly", "applications", "create", "foo/bar"},
{"role:readonly", "applications", "delete", "foo/bar"},
}
for _, a := range disallowed {
if !assert.False(t, enf.Enforce(a...)) {
log.Errorf("%s: expected false, got true", a)
}
}
}
// TestPolicyInformer verifies the informer will get updated with a new configmap
func TestPolicyInformer(t *testing.T) {
cm := fakeConfigMap()
kubeclientset := fake.NewSimpleClientset(cm)
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
go enf.runInformer(ctx)
// wait until the policy loads
loaded := false
for i := 1; i <= 20; i++ {
if enf.Enforce("admin", "applications", "delete", "foo/bar") {
loaded = true
break
}
time.Sleep(50 * time.Millisecond)
}
assert.True(t, loaded)
// update the configmap and update policy
cm.Data[ConfigMapPolicyCSVKey] = "p, admin, applications, delete, */*"
err := enf.syncUpdate(cm)
assert.Nil(t, err)
assert.True(t, enf.Enforce("admin", "applications", "delete", "foo/bar"))
}
// TestResourceActionWildcards verifies the ability to use wildcards in resources and actions
func TestResourceActionWildcards(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
policy := `
p, alice, *, get, foo/obj
p, bob, repositories, *, foo/obj
p, cathy, *, *, foo/obj
p, dave, applications, get, foo/obj
p, dave, applications/*, get, foo/obj
`
enf.SetUserPolicy(policy)
// Verify the resource wildcard
assert.True(t, enf.Enforce("alice", "applications", "get", "foo/obj"))
assert.True(t, enf.Enforce("alice", "applications/pods", "get", "foo/obj"))
assert.False(t, enf.Enforce("alice", "applications/pods", "delete", "foo/obj"))
// Verify action wildcards work
assert.True(t, enf.Enforce("bob", "repositories", "get", "foo/obj"))
assert.True(t, enf.Enforce("bob", "repositories", "delete", "foo/obj"))
assert.False(t, enf.Enforce("bob", "applications", "get", "foo/obj"))
// Verify resource and action wildcards work in conjunction
assert.True(t, enf.Enforce("cathy", "repositories", "get", "foo/obj"))
assert.True(t, enf.Enforce("cathy", "repositories", "delete", "foo/obj"))
assert.True(t, enf.Enforce("cathy", "applications", "get", "foo/obj"))
assert.True(t, enf.Enforce("cathy", "applications/pods", "delete", "foo/obj"))
// Verify wildcards with sub-resources
assert.True(t, enf.Enforce("dave", "applications", "get", "foo/obj"))
assert.True(t, enf.Enforce("dave", "applications/logs", "get", "foo/obj"))
}
// TestProjectIsolationEnforcement verifies the ability to create Project specific policies
func TestProjectIsolationEnforcement(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
policy := `
p, role:foo-admin, *, *, foo/*
p, role:bar-admin, *, *, bar/*
g, alice, role:foo-admin
g, bob, role:bar-admin
`
enf.SetBuiltinPolicy(policy)
// verify alice can only affect objects in foo and not bar,
// and that bob can only affect objects in bar and not foo
assert.True(t, enf.Enforce("bob", "applications", "delete", "bar/obj"))
assert.False(t, enf.Enforce("bob", "applications", "delete", "foo/obj"))
assert.True(t, enf.Enforce("alice", "applications", "delete", "foo/obj"))
assert.False(t, enf.Enforce("alice", "applications", "delete", "bar/obj"))
}
// TestProjectReadOnly verifies the ability to have a read only role in a Project
func TestProjectReadOnly(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
policy := `
p, role:foo-readonly, *, get, foo/*
g, alice, role:foo-readonly
`
enf.SetBuiltinPolicy(policy)
assert.True(t, enf.Enforce("alice", "applications", "get", "foo/obj"))
assert.False(t, enf.Enforce("alice", "applications", "delete", "bar/obj"))
assert.False(t, enf.Enforce("alice", "applications", "get", "bar/obj"))
assert.False(t, enf.Enforce("bob", "applications", "get", "foo/obj"))
}
func TestEnforceClaims(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
policy := `
g, org2:team2, role:admin
g, bob, role:admin
`
enf.SetUserPolicy(policy)
allowed := []jwt.Claims{
jwt.MapClaims{"groups": []string{"org1:team1", "org2:team2"}},
jwt.StandardClaims{Subject: "admin"},
}
for _, c := range allowed {
if !assert.True(t, enf.EnforceClaims(c, "applications", "delete", "foo/obj")) {
log.Errorf("%v: expected true, got false", c)
}
}
disallowed := []jwt.Claims{
jwt.MapClaims{"groups": []string{"org3:team3"}},
jwt.StandardClaims{Subject: "nobody"},
}
for _, c := range disallowed {
if !assert.False(t, enf.EnforceClaims(c, "applications", "delete", "foo/obj")) {
log.Errorf("%v: expected true, got false", c)
}
}
}
// TestDefaultRole tests the ability to set a default role
func TestDefaultRole(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
claims := jwt.MapClaims{"groups": []string{"org1:team1", "org2:team2"}}
assert.False(t, enf.Enforce("bob", "applications", "get", "foo/bar"))
assert.False(t, enf.EnforceClaims(claims, "applications", "get", "foo/bar"))
// after setting the default role to be the read-only role, this should now pass
enf.SetDefaultRole("role:readonly")
assert.True(t, enf.Enforce("bob", "applications", "get", "foo/bar"))
assert.True(t, enf.EnforceClaims(claims, "applications", "get", "foo/bar"))
}
// TestURLAsObjectName tests the ability to have a URL as an object name
func TestURLAsObjectName(t *testing.T) {
kubeclientset := fake.NewSimpleClientset()
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
err := enf.syncUpdate(fakeConfigMap())
assert.Nil(t, err)
policy := `
p, alice, repositories, *, foo/*
p, bob, repositories, *, foo/https://github.com/argoproj/argo-cd.git
p, cathy, repositories, *, foo/*
`
enf.SetUserPolicy(policy)
assert.True(t, enf.Enforce("alice", "repositories", "delete", "foo/https://github.com/argoproj/argo-cd.git"))
assert.True(t, enf.Enforce("alice", "repositories", "delete", "foo/https://github.com/golang/go.git"))
assert.True(t, enf.Enforce("bob", "repositories", "delete", "foo/https://github.com/argoproj/argo-cd.git"))
assert.False(t, enf.Enforce("bob", "repositories", "delete", "foo/https://github.com/golang/go.git"))
}
func TestEnforceNilClaims(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(fakeConfigMap())
enf := NewEnforcer(kubeclientset, fakeNamespace, fakeConfgMapName, nil)
enf.SetBuiltinPolicy(box.String(builtinPolicyFile))
assert.False(t, enf.EnforceClaims(nil, "applications", "get", "foo/obj"))
enf.SetDefaultRole("role:readonly")
assert.True(t, enf.EnforceClaims(nil, "applications", "get", "foo/obj"))
}

View File

@@ -197,7 +197,11 @@ func MakeCookieMetadata(key, value string, flags ...string) string {
return strings.Join(components, "; ")
}
// OIDCProvider lazily returns the OIDC provider
// OIDCProvider lazily initializes and returns the OIDC provider, querying the well known oidc
// configuration path (http://example-argocd.com/api/dex/.well-known/openid-configuration).
// We have to initialize the proviver lazily since ArgoCD is an OIDC client to itself, which
// presents a chicken-and-egg problem of (1) serving dex over HTTP, and (2) querying the OIDC
// provider (ourselves) to initialize the app.
func (mgr *SessionManager) OIDCProvider() (*oidc.Provider, error) {
if mgr.provider != nil {
return mgr.provider, nil

View File

@@ -27,24 +27,24 @@ import (
type ArgoCDSettings struct {
// URL is the externally facing URL users will visit to reach ArgoCD.
// The value here is used when configuring SSO. Omitting this value will disable SSO.
URL string
URL string `json:"url,omitempty"`
// DexConfig is contains portions of a dex config yaml
DexConfig string
DexConfig string `json:"dexConfig,omitempty"`
// LocalUsers holds users local to (stored on) the server. This is to be distinguished from any potential alternative future login providers (LDAP, SAML, etc.) that might ever be added.
LocalUsers map[string]string
LocalUsers map[string]string `json:"localUsers,omitempty"`
// ServerSignature holds the key used to generate JWT tokens.
ServerSignature []byte
ServerSignature []byte `json:"serverSignature,omitempty"`
// Certificate holds the certificate/private key for the ArgoCD API server.
// If nil, will run insecure without TLS.
Certificate *tls.Certificate
Certificate *tls.Certificate `json:"-"`
// WebhookGitLabSecret holds the shared secret for authenticating GitHub webhook events
WebhookGitHubSecret string
WebhookGitHubSecret string `json:"webhookGitHubSecret,omitempty"`
// WebhookGitLabSecret holds the shared secret for authenticating GitLab webhook events
WebhookGitLabSecret string
WebhookGitLabSecret string `json:"webhookGitLabSecret,omitempty"`
// WebhookBitbucketUUID holds the UUID for authenticating Bitbucket webhook events
WebhookBitbucketUUID string
WebhookBitbucketUUID string `json:"webhookBitbucketUUID,omitempty"`
// Secrets holds all secrets in argocd-secret as a map[string]string
Secrets map[string]string
Secrets map[string]string `json:"secrets,omitempty"`
}
const (
@@ -200,9 +200,9 @@ func (mgr *SettingsManager) SaveSettings(settings *ArgoCDSettings) error {
argoCDSecret.StringData[settingsWebhookBitbucketUUIDKey] = settings.WebhookBitbucketUUID
}
if settings.Certificate != nil {
certBytes, keyBytes := tlsutil.EncodeX509KeyPair(*settings.Certificate)
argoCDSecret.StringData[settingServerCertificate] = string(certBytes)
argoCDSecret.StringData[settingServerPrivateKey] = string(keyBytes)
cert, key := tlsutil.EncodeX509KeyPairString(*settings.Certificate)
argoCDSecret.StringData[settingServerCertificate] = cert
argoCDSecret.StringData[settingServerPrivateKey] = key
} else {
delete(argoCDSecret.Data, settingServerCertificate)
delete(argoCDSecret.Data, settingServerPrivateKey)

View File

@@ -172,9 +172,15 @@ func GenerateX509KeyPair(opts CertOptions) (*tls.Certificate, error) {
return &cert, nil
}
// EncodeX509KeyPair encodes a TLS Certificate into its pem encoded for storage
// EncodeX509KeyPair encodes a TLS Certificate into its pem encoded format for storage
func EncodeX509KeyPair(cert tls.Certificate) ([]byte, []byte) {
certpem := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: cert.Certificate[0]})
keypem := pem.EncodeToMemory(pemBlockForKey(cert.PrivateKey))
return certpem, keypem
}
// EncodeX509KeyPairString encodes a TLS Certificate into its pem encoded string format
func EncodeX509KeyPairString(cert tls.Certificate) (string, string) {
certpem, keypem := EncodeX509KeyPair(cert)
return string(certpem), string(keypem)
}