Compare commits

...

43 Commits

Author SHA1 Message Date
argo-bot
90cc56c3a9 Bump version to 1.7.5 2020-09-15 22:52:35 +00:00
argo-bot
ae06a3c584 Bump version to 1.7.5 2020-09-15 22:52:26 +00:00
May Zhang
1633312d6a fix: app create with -f should not ignore other options (#4322) 2020-09-14 17:14:32 -07:00
Alexander Matyushentsev
6dc9624b34 fix: limit concurrent list requests accross all clusters (#4328) 2020-09-14 16:27:26 -07:00
Alexander Matyushentsev
4c715cff98 fix: fix possible deadlock in /v1/api/stream/applications and /v1/api/application APIs (#4315) 2020-09-11 20:50:54 -07:00
Alexander Matyushentsev
37c34f4f4d fix: WatchResourceTree does not enforce RBAC (#4311) 2020-09-11 20:50:51 -07:00
Alexander Matyushentsev
9bbee762b6 fix: app refresh API should use app resource version (#4303) 2020-09-11 20:50:48 -07:00
Alexander Matyushentsev
1f88d3277a fix: use informer instead of k8s watch to ensure app is refreshed (#4290) 2020-09-11 20:50:41 -07:00
argo-bot
f8cbd6bf43 Bump version to 1.7.4 2020-09-05 02:35:26 +00:00
argo-bot
8afbccd8f6 Bump version to 1.7.4 2020-09-05 02:35:17 +00:00
Alexander Matyushentsev
b06536de42 fix: automatically stop watch API requests when page is hidden (#4269) 2020-09-04 14:37:06 -07:00
Alexander Matyushentsev
28e82bccea fix: upgrade gitops-engine dependency (issues #4242, #1881) (#4268) 2020-09-04 14:20:53 -07:00
Alexander Matyushentsev
b815759112 fix: application stream API should not return 'ADDED' events if resource version is provided (#4260) 2020-09-04 14:20:14 -07:00
Mikhail Mazurskiy
37ef7f43e8 fix: return parsing error (#3942)
Don't assume that a file is not a Kubernetes
resource if there was no previous objects parsed
2020-09-04 14:20:03 -07:00
Alexander Matyushentsev
0c511ca6b7 fix: JS error when using cluster filter in the /application view (#4247) 2020-09-04 14:20:00 -07:00
Alexander Matyushentsev
79849a1388 fix: improve applications list page client side performance (#4244) 2020-09-02 16:02:10 -07:00
argo-bot
b4c79ccb88 Bump version to 1.7.3 2020-09-01 23:07:14 +00:00
argo-bot
3d91e911cf Bump version to 1.7.3 2020-09-01 23:07:04 +00:00
Alexander Matyushentsev
4f92c28eea fix: application details page crash when app is deleted (#4229) 2020-09-01 15:26:48 -07:00
Alexander Matyushentsev
d08dba171e fix: api-server unnecessary normalize projects on every start (#4219) 2020-09-01 13:09:05 -07:00
Alexander Matyushentsev
fe9d71d47a refactor: load only project names in UI (#4217) 2020-09-01 13:08:58 -07:00
jannfis
79ffa9fb9f fix: Re-create already initialized ARGOCD_GNUPGHOME on startup (#4214) (#4223) 2020-09-01 13:08:45 -07:00
Alexander Matyushentsev
918a19d69c feat: support gzip compression in api server (#4218) 2020-09-01 10:50:08 -07:00
chrisob
ed77b994e3 fix: Add openshift as a dex connector type which requires a redirectURI (#4222) 2020-09-01 10:33:29 -07:00
Alexander Matyushentsev
fba91aec51 refactor: Replace status.observedAt with redis pub/sub channels for resource tree updates (#1340) (#4208) 2020-08-31 14:01:10 -07:00
Alexander Matyushentsev
8a7fa9d665 fix: cache inconsistency of child resources (#4053) (#4202) 2020-08-31 14:01:05 -07:00
Oleg Sucharevich
26fda7ce52 feat: do not include kube-api check in application liveness flow (#4163)
* feat: do not include kube-api liveness check in application liveness flow
2020-08-31 14:01:01 -07:00
argo-bot
c342d3fc9c Bump version to 1.7.2 2020-08-27 23:24:41 +00:00
argo-bot
32b32290a9 Bump version to 1.7.2 2020-08-27 23:24:31 +00:00
Alexander Matyushentsev
0635f2faef fix: upgrade github.com/evanphx/json-patch to v4.9.0 (#4189) 2020-08-27 15:22:38 -07:00
Michael Barrientos
a3eabe8d95 fix: support for PKCE for cli login (#2932) (#4067) 2020-08-27 15:22:35 -07:00
argo-bot
da5fa74ca1 Bump version to 1.7.1 2020-08-26 21:01:36 +00:00
argo-bot
f711f95162 Bump version to 1.7.1 2020-08-26 21:01:27 +00:00
Alexander Matyushentsev
86c6c0b329 fix: Unable to create project JWT token on K8S v1.15 (#4165) 2020-08-26 11:07:22 -07:00
Alexander Matyushentsev
56520dc5d8 refactor: upgrade gitops-engine version (#4160) 2020-08-26 11:05:59 -07:00
argo-bot
24b93197e0 Bump version to 1.7.0 2020-08-25 18:47:27 +00:00
argo-bot
5a0bb5cefc Bump version to 1.7.0 2020-08-25 18:47:19 +00:00
May Zhang
4d59273383 fix: Badge links are not generating properly when using --rootpath (#4140)
* fix: Badge links are not generating properly when using --rootpath

* fix: fix lint error

* fix: use context.baseHref
2020-08-25 10:06:31 -07:00
Alexander Matyushentsev
4f3537d274 refactor: upgrade K8S client to v0.18.8 (#4149) 2020-08-25 09:27:17 -07:00
May Zhang
76e9e918d2 fix: UI setting auto sync causes erroneous config (#4118)
* fix: UI setting auto sync causes erroneous config

* fix: remove log
2020-08-25 09:27:14 -07:00
jannfis
b2decde4fe fix: Make GnuPG keyring independent of user ID within container (#4136)
* fix: Make GnuPG keyring independent of user ID within container

* Update unit test
2020-08-25 09:27:10 -07:00
argo-bot
4728412cc3 Bump version to 1.7.0-rc1 2020-08-15 19:20:12 +00:00
argo-bot
26b9331820 Bump version to 1.7.0-rc1 2020-08-15 19:20:03 +00:00
65 changed files with 1107 additions and 624 deletions

View File

@@ -1 +1 @@
1.7.0
1.7.5

View File

@@ -2227,6 +2227,56 @@
}
}
},
"/api/v1/stream/applications/{applicationName}/resource-tree": {
"get": {
"tags": [
"ApplicationService"
],
"summary": "Watch returns stream of application resource tree",
"operationId": "WatchResourceTree",
"parameters": [
{
"type": "string",
"name": "applicationName",
"in": "path",
"required": true
},
{
"type": "string",
"name": "namespace",
"in": "query"
},
{
"type": "string",
"name": "name",
"in": "query"
},
{
"type": "string",
"name": "version",
"in": "query"
},
{
"type": "string",
"name": "group",
"in": "query"
},
{
"type": "string",
"name": "kind",
"in": "query"
}
],
"responses": {
"200": {
"description": "A successful response.(streaming responses)",
"schema": {
"$ref": "#/x-stream-definitions/v1alpha1ApplicationTree"
}
}
}
}
},
"/api/version": {
"get": {
"tags": [

View File

@@ -58,6 +58,7 @@ func NewCommand() *cobra.Command {
repoServerAddress string
dexServerAddress string
disableAuth bool
enableGZip bool
tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error)
cacheSrc func() (*servercache.Cache, error)
frameOptions string
@@ -115,6 +116,7 @@ func NewCommand() *cobra.Command {
RepoClientset: repoclientset,
DexServerAddr: dexServerAddress,
DisableAuth: disableAuth,
EnableGZip: enableGZip,
TLSConfigCustomizer: tlsConfigCustomizer,
Cache: cache,
XFrameOptions: frameOptions,
@@ -146,6 +148,7 @@ func NewCommand() *cobra.Command {
command.Flags().StringVar(&repoServerAddress, "repo-server", common.DefaultRepoServerAddr, "Repo server address")
command.Flags().StringVar(&dexServerAddress, "dex-server", common.DefaultDexServerAddr, "Dex server address")
command.Flags().BoolVar(&disableAuth, "disable-auth", false, "Disable client authentication")
command.Flags().BoolVar(&enableGZip, "enable-gzip", false, "Enable GZIP compression")
command.AddCommand(cli.NewVersionCmd(cliName))
command.Flags().IntVar(&listenPort, "port", common.DefaultPortAPIServer, "Listen on given port")
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDAPIServerMetrics, "Start metrics on given port")

View File

@@ -9,7 +9,6 @@ import (
"sort"
"time"
"github.com/argoproj/gitops-engine/pkg/diff"
"github.com/argoproj/gitops-engine/pkg/utils/errors"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/ghodss/yaml"
@@ -147,7 +146,7 @@ func diffReconcileResults(res1 reconcileResults, res2 reconcileResults) error {
})
for _, item := range pairs {
printLine(item.name)
_ = diff.PrintDiff(item.name, item.first, item.second)
_ = cli.PrintDiff(item.name, item.first, item.second)
}
return nil

View File

@@ -12,7 +12,6 @@ import (
appclient "github.com/argoproj/argo-cd/pkg/client/clientset/versioned/typed/application/v1alpha1"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/gitops-engine/pkg/diff"
"github.com/argoproj/gitops-engine/pkg/utils/errors"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
"github.com/spf13/cobra"
@@ -70,7 +69,7 @@ func saveProject(updated v1alpha1.AppProject, orig v1alpha1.AppProject, projects
if err != nil {
return err
}
_ = diff.PrintDiff(updated.Name, target, live)
_ = cli.PrintDiff(updated.Name, target, live)
if !dryRun {
_, err = projectsIf.Update(context.Background(), &updated, v1.UpdateOptions{})
if err != nil {

View File

@@ -12,7 +12,6 @@ import (
"strings"
"text/tabwriter"
"github.com/argoproj/gitops-engine/pkg/diff"
healthutil "github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/errors"
"github.com/ghodss/yaml"
@@ -423,7 +422,7 @@ argocd-util settings resource-overrides ignore-differences ./deploy.yaml --argoc
}
_, _ = fmt.Printf("Following fields are ignored:\n\n")
_ = diff.PrintDiff(res.GetName(), &res, normalizedRes)
_ = cli.PrintDiff(res.GetName(), &res, normalizedRes)
})
},
}
@@ -538,7 +537,7 @@ argocd-util settings resource-overrides action run /tmp/deploy.yaml restart --ar
}
_, _ = fmt.Printf("Following fields have been changed:\n\n")
_ = diff.PrintDiff(res.GetName(), &res, modifiedRes)
_ = cli.PrintDiff(res.GetName(), &res, modifiedRes)
})
},
}

View File

@@ -151,8 +151,15 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
log.Fatalf("app name '%s' does not match app spec metadata.name '%s'", args[0], app.Name)
}
if appName != "" && appName != app.Name {
log.Fatalf("--name argument '%s' does not match app spec metadata.name '%s'", appName, app.Name)
app.Name = appName
}
if app.Name == "" {
log.Fatalf("app.Name is empty. --name argument can be used to provide app.Name")
}
setAppSpecOptions(c.Flags(), &app.Spec, &appOpts)
setParameterOverrides(&app, appOpts.parameters)
setLabels(&app, labels)
} else {
// read arguments
if len(args) == 1 {
@@ -1154,7 +1161,7 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}
foundDiffs = true
_ = diff.PrintDiff(item.key.Name, live, target)
_ = cli.PrintDiff(item.key.Name, live, target)
}
}
if foundDiffs {

View File

@@ -2,6 +2,8 @@ package commands
import (
"context"
"crypto/sha256"
"encoding/base64"
"fmt"
"net/http"
"os"
@@ -192,6 +194,11 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
completionChan <- errMsg
}
// PKCE implementation of https://tools.ietf.org/html/rfc7636
codeVerifier := rand.RandStringCharset(43, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~")
codeChallengeHash := sha256.Sum256([]byte(codeVerifier))
codeChallenge := base64.RawURLEncoding.EncodeToString(codeChallengeHash[:])
// Authorization redirect callback from OAuth2 auth flow.
// Handles both implicit and authorization code flow
callbackHandler := func(w http.ResponseWriter, r *http.Request) {
@@ -231,7 +238,8 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
handleErr(w, fmt.Sprintf("no code in request: %q", r.Form))
return
}
tok, err := oauth2conf.Exchange(ctx, code)
opts := []oauth2.AuthCodeOption{oauth2.SetAuthURLParam("code_verifier", codeVerifier)}
tok, err := oauth2conf.Exchange(ctx, code, opts...)
if err != nil {
handleErr(w, err.Error())
return
@@ -267,6 +275,8 @@ func oauth2Login(ctx context.Context, port int, oidcSettings *settingspkg.OIDCCo
switch grantType {
case oidcutil.GrantTypeAuthorizationCode:
opts = append(opts, oauth2.SetAuthURLParam("code_challenge", codeChallenge))
opts = append(opts, oauth2.SetAuthURLParam("code_challenge_method", "S256"))
url = oauth2conf.AuthCodeURL(stateNonce, opts...)
case oidcutil.GrantTypeImplicit:
url = oidcutil.ImplicitFlowURL(oauth2conf, stateNonce, opts...)

View File

@@ -177,8 +177,7 @@ func NewApplicationController(
})
metricsAddr := fmt.Sprintf("0.0.0.0:%d", metricsPort)
ctrl.metricsServer = metrics.NewMetricsServer(metricsAddr, appLister, func() error {
_, err := kubeClientset.Discovery().ServerVersion()
return err
return nil
})
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settingsMgr, kubectl, ctrl.metricsServer, ctrl.handleObjectUpdated)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectl, ctrl.settingsMgr, stateCache, projInformer, ctrl.metricsServer)
@@ -1031,8 +1030,6 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
appv1.ApplicationConditionComparisonError: true,
})
}
now := metav1.Now()
app.Status.ObservedAt = &now
ctrl.persistAppStatus(origApp, &app.Status)
return
}
@@ -1056,7 +1053,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
revision = app.Status.Sync.Revision
}
observedAt := metav1.Now()
now := metav1.Now()
compareResult := ctrl.appStateManager.CompareAppState(app, project, revision, app.Spec.Source, refreshType == appv1.RefreshTypeHard, localManifests)
for k, v := range compareResult.timings {
logCtx = logCtx.WithField(k, v.Milliseconds())
@@ -1089,9 +1086,8 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
}
if app.Status.ReconciledAt == nil || comparisonLevel == CompareWithLatest {
app.Status.ReconciledAt = &observedAt
app.Status.ReconciledAt = &now
}
app.Status.ObservedAt = &observedAt
app.Status.Sync = *compareResult.syncStatus
app.Status.Health = *compareResult.healthStatus
app.Status.Resources = compareResult.resources

View File

@@ -962,7 +962,7 @@ func TestUpdateReconciledAt(t *testing.T) {
_, updated, err = unstructured.NestedString(receivedPatch, "status", "observedAt")
assert.NoError(t, err)
assert.True(t, updated)
assert.False(t, updated)
})
t.Run("NotUpdatedOnPartialReconciliation", func(t *testing.T) {
@@ -978,7 +978,7 @@ func TestUpdateReconciledAt(t *testing.T) {
_, updated, err = unstructured.NestedString(receivedPatch, "status", "observedAt")
assert.NoError(t, err)
assert.True(t, updated)
assert.False(t, updated)
})
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/argoproj/gitops-engine/pkg/health"
"github.com/argoproj/gitops-engine/pkg/utils/kube"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -73,6 +74,8 @@ func NewLiveStateCache(
kubectl: kubectl,
settingsMgr: settingsMgr,
metricsServer: metricsServer,
// The default limit of 50 is chosen based on experiments.
listSemaphore: semaphore.NewWeighted(50),
}
}
@@ -89,6 +92,10 @@ type liveStateCache struct {
settingsMgr *settings.SettingsManager
metricsServer *metrics.MetricsServer
// listSemaphore is used to limit the number of concurrent memory consuming operations on the
// k8s list queries results across all clusters to avoid memory spikes during cache initialization.
listSemaphore *semaphore.Weighted
clusters map[string]clustercache.ClusterCache
cacheSettings cacheSettings
lock sync.RWMutex
@@ -232,6 +239,7 @@ func (c *liveStateCache) getCluster(server string) (clustercache.ClusterCache, e
}
clusterCache = clustercache.NewClusterCache(cluster.RESTConfig(),
clustercache.SetListSemaphore(c.listSemaphore),
clustercache.SetResyncTimeout(common.K8SClusterResyncDuration),
clustercache.SetSettings(cacheSettings.clusterSettings),
clustercache.SetNamespaces(cluster.Namespaces),

63
go.mod
View File

@@ -8,7 +8,7 @@ require (
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6 // indirect
github.com/alicebob/miniredis v2.5.0+incompatible
github.com/argoproj/gitops-engine v0.1.3-0.20200805021302-90979fe432d4
github.com/argoproj/gitops-engine v0.1.3-0.20200904164417-c04f859da9b2
github.com/argoproj/pkg v0.0.0-20200624215116-23e74cb168fe
github.com/casbin/casbin v1.9.1
github.com/chai2010/gettext-go v0.0.0-20170215093142-bf70f2a70fb1 // indirect
@@ -17,7 +17,7 @@ require (
github.com/docker/docker v17.12.0-ce-rc1.0.20200514230353-811a247d06e8+incompatible // indirect
github.com/docker/spdystream v0.0.0-20181023171402-6480d4af844c // indirect
github.com/dustin/go-humanize v1.0.0
github.com/evanphx/json-patch v4.5.0+incompatible
github.com/evanphx/json-patch v4.9.0+incompatible
github.com/fsnotify/fsnotify v1.4.7
github.com/ghodss/yaml v1.0.0
github.com/go-openapi/loads v0.19.4
@@ -33,7 +33,9 @@ require (
github.com/gomodule/redigo v2.0.0+incompatible // indirect
github.com/google/go-cmp v0.3.1
github.com/google/go-jsonnet v0.16.0
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
github.com/google/uuid v1.1.1
github.com/gorilla/handlers v1.5.0
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect
github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0
@@ -65,20 +67,21 @@ require (
gopkg.in/go-playground/webhooks.v5 v5.11.0
gopkg.in/src-d/go-git.v4 v4.13.1
gopkg.in/yaml.v2 v2.3.0
k8s.io/api v0.18.6
k8s.io/apiextensions-apiserver v0.18.6
k8s.io/apimachinery v0.18.6
k8s.io/api v0.18.8
k8s.io/apiextensions-apiserver v0.18.8
k8s.io/apimachinery v0.18.8
k8s.io/client-go v11.0.1-0.20190816222228-6d55c1b1f1ca+incompatible
k8s.io/code-generator v0.18.6
k8s.io/component-base v0.18.6
k8s.io/code-generator v0.18.8
k8s.io/component-base v0.18.8
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac // indirect
k8s.io/klog v1.0.0
k8s.io/klog/v2 v2.3.0 // indirect
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29
k8s.io/kubectl v0.18.6
k8s.io/kubernetes v1.18.6
k8s.io/kubectl v0.18.8
k8s.io/kubernetes v1.18.8
k8s.io/utils v0.0.0-20200619165400-6e3d28b6ed19
layeh.com/gopher-json v0.0.0-20190114024228-97fed8db8427
sigs.k8s.io/yaml v1.2.0
)
replace (
@@ -88,25 +91,25 @@ replace (
google.golang.org/grpc => google.golang.org/grpc v1.15.0
k8s.io/api => k8s.io/api v0.18.6
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.18.6
k8s.io/apimachinery => k8s.io/apimachinery v0.18.6
k8s.io/apiserver => k8s.io/apiserver v0.18.6
k8s.io/cli-runtime => k8s.io/cli-runtime v0.18.6
k8s.io/client-go => k8s.io/client-go v0.18.6
k8s.io/cloud-provider => k8s.io/cloud-provider v0.18.6
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.18.6
k8s.io/code-generator => k8s.io/code-generator v0.18.6
k8s.io/component-base => k8s.io/component-base v0.18.6
k8s.io/cri-api => k8s.io/cri-api v0.18.6
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.18.6
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.18.6
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.18.6
k8s.io/kube-proxy => k8s.io/kube-proxy v0.18.6
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.18.6
k8s.io/kubectl => k8s.io/kubectl v0.18.6
k8s.io/kubelet => k8s.io/kubelet v0.18.6
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.18.6
k8s.io/metrics => k8s.io/metrics v0.18.6
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.18.6
k8s.io/api => k8s.io/api v0.18.8
k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.18.8
k8s.io/apimachinery => k8s.io/apimachinery v0.18.8
k8s.io/apiserver => k8s.io/apiserver v0.18.8
k8s.io/cli-runtime => k8s.io/cli-runtime v0.18.8
k8s.io/client-go => k8s.io/client-go v0.18.8
k8s.io/cloud-provider => k8s.io/cloud-provider v0.18.8
k8s.io/cluster-bootstrap => k8s.io/cluster-bootstrap v0.18.8
k8s.io/code-generator => k8s.io/code-generator v0.18.8
k8s.io/component-base => k8s.io/component-base v0.18.8
k8s.io/cri-api => k8s.io/cri-api v0.18.8
k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.18.8
k8s.io/kube-aggregator => k8s.io/kube-aggregator v0.18.8
k8s.io/kube-controller-manager => k8s.io/kube-controller-manager v0.18.8
k8s.io/kube-proxy => k8s.io/kube-proxy v0.18.8
k8s.io/kube-scheduler => k8s.io/kube-scheduler v0.18.8
k8s.io/kubectl => k8s.io/kubectl v0.18.8
k8s.io/kubelet => k8s.io/kubelet v0.18.8
k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.18.8
k8s.io/metrics => k8s.io/metrics v0.18.8
k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.18.8
)

80
go.sum
View File

@@ -57,8 +57,8 @@ github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+Dx
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/argoproj/gitops-engine v0.1.3-0.20200805021302-90979fe432d4 h1:o5k/SkhxfmowXFdo1G729T7pF1oQ8mom7TMFrOtxDIA=
github.com/argoproj/gitops-engine v0.1.3-0.20200805021302-90979fe432d4/go.mod h1:8rDcKzsoaTXlDBBqUpgUD8VxKRDXeKKlHNEyo0TUlWM=
github.com/argoproj/gitops-engine v0.1.3-0.20200904164417-c04f859da9b2 h1:/tFET94tzxQ8Uz5fQBI4nqa3pI5JRfcHBLhiwcIJaBg=
github.com/argoproj/gitops-engine v0.1.3-0.20200904164417-c04f859da9b2/go.mod h1:jeiFokbkgLXjvx3eXB0MddyxsmftWsFTY7paLH4ZqCg=
github.com/argoproj/pkg v0.0.0-20200624215116-23e74cb168fe h1:HjTM7H8Z+J1xt340LNpH9q4jc8pXeqzkC8QKIjQphp4=
github.com/argoproj/pkg v0.0.0-20200624215116-23e74cb168fe/go.mod h1:2EZ44RG/CcgtPTwrRR0apOc7oU6UIw8GjCUJWZ8X3bM=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -154,9 +154,9 @@ github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT
github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg=
github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o=
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.5.0+incompatible h1:ouOWdg56aJriqS0huScTkVXPC5IcNrDCXZ6OoTAWu7M=
github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v0.0.0-20200808040245-162e5629780b/go.mod h1:NAJj0yf/KaRKURN6nyi7A9IZydMivZEm9oQLWNjfKDc=
github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
@@ -164,6 +164,8 @@ github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwo
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
@@ -340,6 +342,8 @@ github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTV
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/handlers v1.5.0 h1:4wjo3sf9azi99c8hTmyaxp9y5S+pFszsy3pP0rAw/lw=
github.com/gorilla/handlers v1.5.0/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q=
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
@@ -879,26 +883,26 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.2/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.18.6 h1:osqrAXbOQjkKIWDTjrqxWQ3w0GkKb1KA1XkUGHHYpeE=
k8s.io/api v0.18.6/go.mod h1:eeyxr+cwCjMdLAmr2W3RyDI0VvTawSg/3RFFBEnmZGI=
k8s.io/apiextensions-apiserver v0.18.6 h1:vDlk7cyFsDyfwn2rNAO2DbmUbvXy5yT5GE3rrqOzaMo=
k8s.io/apiextensions-apiserver v0.18.6/go.mod h1:lv89S7fUysXjLZO7ke783xOwVTm6lKizADfvUM/SS/M=
k8s.io/apimachinery v0.18.6 h1:RtFHnfGNfd1N0LeSrKCUznz5xtUP1elRGvHJbL3Ntag=
k8s.io/apimachinery v0.18.6/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
k8s.io/apiserver v0.18.6 h1:HcWwcOfhj4Yv6y2igP4ZUuovyPjVLGoZcG0Tsph4Mxo=
k8s.io/apiserver v0.18.6/go.mod h1:Zt2XvTHuaZjBz6EFYzpp+X4hTmgWGy8AthNVnTdm3Wg=
k8s.io/cli-runtime v0.18.6 h1:I8BkH5NyqMQ4zqUBmpXJ1LxIqpCH88H/1edPkPVWzjQ=
k8s.io/cli-runtime v0.18.6/go.mod h1:+G/WTNqHgUv636e5y7rhOQ7epUbRXnwmPnhOhD6t9uM=
k8s.io/client-go v0.18.6 h1:I+oWqJbibLSGsZj8Xs8F0aWVXJVIoUHWaaJV3kUN/Zw=
k8s.io/client-go v0.18.6/go.mod h1:/fwtGLjYMS1MaM5oi+eXhKwG+1UHidUEXRh6cNsdO0Q=
k8s.io/cloud-provider v0.18.6/go.mod h1:QnPLLdFkvtx1dEyVMaPUdzVWB+ECzEf+PA3DXwIr8bo=
k8s.io/cluster-bootstrap v0.18.6/go.mod h1:lnM1CXtPImlEBTh5874ZI+ofZzdIy1t2JV9Y+NxvojU=
k8s.io/code-generator v0.18.6 h1:QdfvGfs4gUCS1dru+rLbCKIFxYEV0IRfF8MXwY/ozLk=
k8s.io/code-generator v0.18.6/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/component-base v0.18.6 h1:Wd6cHGwJN2qpufnirVOB3oMhyhbioGsKEi5HeDBsV+s=
k8s.io/component-base v0.18.6/go.mod h1:knSVsibPR5K6EW2XOjEHik6sdU5nCvKMrzMt2D4In14=
k8s.io/cri-api v0.18.6/go.mod h1:OJtpjDvfsKoLGhvcc0qfygved0S0dGX56IJzPbqTG1s=
k8s.io/csi-translation-lib v0.18.6/go.mod h1:w13PRDbRWol3Z9lM3RjxRd5vi/R9wog1DQHAbzzuKOI=
k8s.io/api v0.18.8 h1:aIKUzJPb96f3fKec2lxtY7acZC9gQNDLVhfSGpxBAC4=
k8s.io/api v0.18.8/go.mod h1:d/CXqwWv+Z2XEG1LgceeDmHQwpUJhROPx16SlxJgERY=
k8s.io/apiextensions-apiserver v0.18.8 h1:pkqYPKTHa0/3lYwH7201RpF9eFm0lmZDFBNzhN+k/sA=
k8s.io/apiextensions-apiserver v0.18.8/go.mod h1:7f4ySEkkvifIr4+BRrRWriKKIJjPyg9mb/p63dJKnlM=
k8s.io/apimachinery v0.18.8 h1:jimPrycCqgx2QPearX3to1JePz7wSbVLq+7PdBTTwQ0=
k8s.io/apimachinery v0.18.8/go.mod h1:6sQd+iHEqmOtALqOFjSWp2KZ9F0wlU/nWm0ZgsYWMig=
k8s.io/apiserver v0.18.8 h1:Au4kMn8sb1zFdyKqc8iMHLsYLxRI6Y+iAhRNKKQtlBY=
k8s.io/apiserver v0.18.8/go.mod h1:12u5FuGql8Cc497ORNj79rhPdiXQC4bf53X/skR/1YM=
k8s.io/cli-runtime v0.18.8 h1:ycmbN3hs7CfkJIYxJAOB10iW7BVPmXGXkfEyiV9NJ+k=
k8s.io/cli-runtime v0.18.8/go.mod h1:7EzWiDbS9PFd0hamHHVoCY4GrokSTPSL32MA4rzIu0M=
k8s.io/client-go v0.18.8 h1:SdbLpIxk5j5YbFr1b7fq8S7mDgDjYmUxSbszyoesoDM=
k8s.io/client-go v0.18.8/go.mod h1:HqFqMllQ5NnQJNwjro9k5zMyfhZlOwpuTLVrxjkYSxU=
k8s.io/cloud-provider v0.18.8/go.mod h1:cn9AlzMPVIXA4HHLVbgGUigaQlZyHSZ7WAwDEFNrQSs=
k8s.io/cluster-bootstrap v0.18.8/go.mod h1:guq0Uc+QwazHgpS1yAw5Z7yUlBCtGppbgWQkbN3lxIY=
k8s.io/code-generator v0.18.8 h1:lgO1P1wjikEtzNvj7ia+x1VC4svJ28a/r0wnOLhhOTU=
k8s.io/code-generator v0.18.8/go.mod h1:TgNEVx9hCyPGpdtCWA34olQYLkh3ok9ar7XfSsr8b6c=
k8s.io/component-base v0.18.8 h1:BW5CORobxb6q5mb+YvdwQlyXXS6NVH5fDXWbU7tf2L8=
k8s.io/component-base v0.18.8/go.mod h1:00frPRDas29rx58pPCxNkhUfPbwajlyyvu8ruNgSErU=
k8s.io/cri-api v0.18.8/go.mod h1:OJtpjDvfsKoLGhvcc0qfygved0S0dGX56IJzPbqTG1s=
k8s.io/csi-translation-lib v0.18.8/go.mod h1:6cA6Btlzxy9s3QrS4BCZzQqclIWnTLr6Jx3H2ctAzY4=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac h1:sAvhNk5RRuc6FNYGqe7Ygz3PSo/2wGWbulskmzRX8Vs=
@@ -911,23 +915,23 @@ k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.3.0 h1:WmkrnW7fdrm0/DMClc+HIxtftvxVIPAhlVwMQo5yLco=
k8s.io/klog/v2 v2.3.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-aggregator v0.18.6 h1:xGP3oe0tAWEYnGWTnDPjXiIItekrnwDA2O7w0WqvGoo=
k8s.io/kube-aggregator v0.18.6/go.mod h1:MKm8inLHdeiXQJCl6UdmgMosRrqJgyxO2obTXOkey/s=
k8s.io/kube-controller-manager v0.18.6/go.mod h1:T+Ayh47y1IrvwDSUAh4QT/aIrRcKWlvgdqV5PHrMwNs=
k8s.io/kube-aggregator v0.18.8 h1:8VQxblQqRInpJ+DS2aGgbdWq6xP8UG/jzV6v8cFccOc=
k8s.io/kube-aggregator v0.18.8/go.mod h1:CyLoGZB+io8eEwnn+6RbV7QWJQhj8a3TBH8ZM8sLbhI=
k8s.io/kube-controller-manager v0.18.8/go.mod h1:IYZteddXJFD1TVgAw8eRP3c9OOA2WtHdXdE8aH6gXnc=
k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29 h1:NeQXVJ2XFSkRoPzRo8AId01ZER+j8oV4SZADT4iBOXQ=
k8s.io/kube-openapi v0.0.0-20200410145947-bcb3869e6f29/go.mod h1:F+5wygcW0wmRTnM3cOgIqGivxkwSWIWT5YdsDbeAOaU=
k8s.io/kube-proxy v0.18.6/go.mod h1:r3ScLxYTuskh8l2dDfAPdrFK3QnWIMsZI/+Bq5kkmWc=
k8s.io/kube-scheduler v0.18.6/go.mod h1:J+GApeR/QkU6eYonXir0i7+rcUVWzZPZbNHqjq4FpoQ=
k8s.io/kubectl v0.18.6 h1:IFPNuLPkZ59vSGQzynXY8XGz9yuOSRpkJupnobdYvO4=
k8s.io/kubectl v0.18.6/go.mod h1:3TLzFOrF9h4mlRPAvdNkDbs5NWspN4e0EnPnEB41CGo=
k8s.io/kubelet v0.18.6/go.mod h1:5e0PJYialWMWZgsYWJqI6zVW58y+MaQvmOQwEGFF4Xc=
k8s.io/kubernetes v1.18.6 h1:2rkR3ffvd5YVyPYU4LAUDCKoKQZtjuuj8ga15mbv96o=
k8s.io/kubernetes v1.18.6/go.mod h1:Efg82S+Ti02A/Mww53bxroc7IgzX2bgPsf6hT8gAs3M=
k8s.io/legacy-cloud-providers v0.18.6/go.mod h1:0bU6t0dTOd0YkcByIdjx7WD4ihApa+aUrTgVJpqciZU=
k8s.io/metrics v0.18.6/go.mod h1:iAwGeabusQNO3duHDM7BBExTUB8L+iq8PM7N9EtQw6g=
k8s.io/kube-proxy v0.18.8/go.mod h1:u4E8OsUpUzfZ9CEFf9rdLsbYiusZr8utbtF4WQrX+qs=
k8s.io/kube-scheduler v0.18.8/go.mod h1:OeliYiILv1XkSq0nmQjRewgt5NimKsTidZFEhfL5fqA=
k8s.io/kubectl v0.18.8 h1:qTkHCz21YmK0+S0oE6TtjtxmjeDP42gJcZJyRKsIenA=
k8s.io/kubectl v0.18.8/go.mod h1:PlEgIAjOMua4hDFTEkVf+W5M0asHUKfE4y7VDZkpLHM=
k8s.io/kubelet v0.18.8/go.mod h1:6z1jHCk0NPE6WshFStfqcgQ1bnD3tetcPmhC2915aio=
k8s.io/kubernetes v1.18.8 h1:wcpO1nbbcsRGNu7sQMROrPqtjPVMIlzWpRle5OFSoZQ=
k8s.io/kubernetes v1.18.8/go.mod h1:SU7bBi8ZNHRjqzNhY4U78gClS1O7Q7avCrfF5aSiDko=
k8s.io/legacy-cloud-providers v0.18.8/go.mod h1:tgp4xYf6lvjrWnjQwTOPvWQE9IVqSBGPF4on0IyICQE=
k8s.io/metrics v0.18.8/go.mod h1:j7JzZdiyhLP2BsJm/Fzjs+j5Lb1Y7TySjhPWqBPwRXA=
k8s.io/repo-infra v0.0.1-alpha.1/go.mod h1:wO1t9WaB99V80ljbeENTnayuEEwNZt7gECYh/CEyOJ8=
k8s.io/sample-apiserver v0.18.6/go.mod h1:NSRGjwumFclVpq8zewaqGVwiyIR7DQbLAE6wQZ0uljI=
k8s.io/sample-apiserver v0.18.8/go.mod h1:qXPfVwaZwM2owoSMNRRm9vw+HNJGLNsBpGckv1uxWy4=
k8s.io/system-validators v1.0.4/go.mod h1:HgSgTg4NAGNoYYjKsUyk52gdNi2PVDswQ9Iyn66R7NI=
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20200619165400-6e3d28b6ed19 h1:7Nu2dTj82c6IaWvL7hImJzcXoTPz1MsSCH7r+0m6rfo=

View File

@@ -46,6 +46,10 @@ func getCustomResourceDefinitions() map[string]*extensionsobj.CustomResourceDefi
// We need to completely remove validation of problematic fields such as creationTimestamp,
// which get marshalled to `null`, but are typed as as a `string` during Open API validation
removeValidation(un, "metadata.creationTimestamp")
// remove status validation for AppProject CRD as workaround for https://github.com/argoproj/argo-cd/issues/4158
if un.GetName() == "appprojects.argoproj.io" {
removeValidation(un, "status")
}
crd := toCRD(un)
crd.Labels = map[string]string{

View File

@@ -1,7 +1,7 @@
#!/bin/sh
# Update required versions of dependencies here whenever you change them in
# go.mod
kube_version=v0.18.6
kube_version=v0.18.8
grpc_version=v1.26.0
protobuf_version=v1.3.2
grpc_gateway_version=v1.9.5

View File

@@ -12,4 +12,4 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: latest
newTag: v1.7.5

View File

@@ -40,6 +40,8 @@ spec:
mountPath: /app/config/tls
- name: gpg-keys
mountPath: /app/config/gpg/source
- name: gpg-keyring
mountPath: /app/config/gpg/keys
volumes:
- name: ssh-known-hosts
configMap:
@@ -50,3 +52,5 @@ spec:
- name: gpg-keys
configMap:
name: argocd-gpg-keys-cm
- name: gpg-keyring
emptyDir: {}

View File

@@ -821,7 +821,7 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated without querying latest git state
description: 'ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field'
format: date-time
type: string
operationState:

View File

@@ -218,31 +218,6 @@ spec:
type: object
type: array
type: object
status:
description: AppProjectStatus contains information about appproj
properties:
jwtTokensByRole:
additionalProperties:
properties:
items:
items:
description: JWTToken holds the issuedAt and expiresAt values of a token
properties:
exp:
format: int64
type: integer
iat:
format: int64
type: integer
id:
type: string
required:
- iat
type: object
type: array
type: object
type: object
type: object
required:
- metadata
- spec

View File

@@ -18,4 +18,4 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: latest
newTag: v1.7.5

View File

@@ -922,8 +922,9 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
description: 'ObservedAt indicates when the application state was updated
without querying latest git state Deprecated: controller no longer
updates ObservedAt field'
format: date-time
type: string
operationState:
@@ -2109,32 +2110,6 @@ spec:
type: object
type: array
type: object
status:
description: AppProjectStatus contains information about appproj
properties:
jwtTokensByRole:
additionalProperties:
properties:
items:
items:
description: JWTToken holds the issuedAt and expiresAt values
of a token
properties:
exp:
format: int64
type: integer
iat:
format: int64
type: integer
id:
type: string
required:
- iat
type: object
type: array
type: object
type: object
type: object
required:
- metadata
- spec
@@ -3108,7 +3083,7 @@ spec:
- "10"
- --redis
- argocd-redis-ha-haproxy:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3164,7 +3139,7 @@ spec:
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -3214,7 +3189,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis-ha-haproxy:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -3232,6 +3207,8 @@ spec:
name: tls-certs
- mountPath: /app/config/gpg/source
name: gpg-keys
- mountPath: /app/config/gpg/keys
name: gpg-keyring
volumes:
- configMap:
name: argocd-ssh-known-hosts-cm
@@ -3242,6 +3219,8 @@ spec:
- configMap:
name: argocd-gpg-keys-cm
name: gpg-keys
- emptyDir: {}
name: gpg-keyring
---
apiVersion: apps/v1
kind: Deployment
@@ -3285,7 +3264,7 @@ spec:
env:
- name: ARGOCD_API_SERVER_REPLICAS
value: "2"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-server
ports:

View File

@@ -922,8 +922,9 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
description: 'ObservedAt indicates when the application state was updated
without querying latest git state Deprecated: controller no longer
updates ObservedAt field'
format: date-time
type: string
operationState:
@@ -2109,32 +2110,6 @@ spec:
type: object
type: array
type: object
status:
description: AppProjectStatus contains information about appproj
properties:
jwtTokensByRole:
additionalProperties:
properties:
items:
items:
description: JWTToken holds the issuedAt and expiresAt values
of a token
properties:
exp:
format: int64
type: integer
iat:
format: int64
type: integer
id:
type: string
required:
- iat
type: object
type: array
type: object
type: object
type: object
required:
- metadata
- spec
@@ -3023,7 +2998,7 @@ spec:
- "10"
- --redis
- argocd-redis-ha-haproxy:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -3079,7 +3054,7 @@ spec:
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -3129,7 +3104,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis-ha-haproxy:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -3147,6 +3122,8 @@ spec:
name: tls-certs
- mountPath: /app/config/gpg/source
name: gpg-keys
- mountPath: /app/config/gpg/keys
name: gpg-keyring
volumes:
- configMap:
name: argocd-ssh-known-hosts-cm
@@ -3157,6 +3134,8 @@ spec:
- configMap:
name: argocd-gpg-keys-cm
name: gpg-keys
- emptyDir: {}
name: gpg-keyring
---
apiVersion: apps/v1
kind: Deployment
@@ -3200,7 +3179,7 @@ spec:
env:
- name: ARGOCD_API_SERVER_REPLICAS
value: "2"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-server
ports:

View File

@@ -922,8 +922,9 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
description: 'ObservedAt indicates when the application state was updated
without querying latest git state Deprecated: controller no longer
updates ObservedAt field'
format: date-time
type: string
operationState:
@@ -2109,32 +2110,6 @@ spec:
type: object
type: array
type: object
status:
description: AppProjectStatus contains information about appproj
properties:
jwtTokensByRole:
additionalProperties:
properties:
items:
items:
description: JWTToken holds the issuedAt and expiresAt values
of a token
properties:
exp:
format: int64
type: integer
iat:
format: int64
type: integer
id:
type: string
required:
- iat
type: object
type: array
type: object
type: object
type: object
required:
- metadata
- spec
@@ -2608,7 +2583,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2664,7 +2639,7 @@ spec:
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2733,7 +2708,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -2751,6 +2726,8 @@ spec:
name: tls-certs
- mountPath: /app/config/gpg/source
name: gpg-keys
- mountPath: /app/config/gpg/keys
name: gpg-keyring
volumes:
- configMap:
name: argocd-ssh-known-hosts-cm
@@ -2761,6 +2738,8 @@ spec:
- configMap:
name: argocd-gpg-keys-cm
name: gpg-keys
- emptyDir: {}
name: gpg-keyring
---
apiVersion: apps/v1
kind: Deployment
@@ -2784,7 +2763,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-server
ports:

View File

@@ -922,8 +922,9 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
description: 'ObservedAt indicates when the application state was updated
without querying latest git state Deprecated: controller no longer
updates ObservedAt field'
format: date-time
type: string
operationState:
@@ -2109,32 +2110,6 @@ spec:
type: object
type: array
type: object
status:
description: AppProjectStatus contains information about appproj
properties:
jwtTokensByRole:
additionalProperties:
properties:
items:
items:
description: JWTToken holds the issuedAt and expiresAt values
of a token
properties:
exp:
format: int64
type: integer
iat:
format: int64
type: integer
id:
type: string
required:
- iat
type: object
type: array
type: object
type: object
type: object
required:
- metadata
- spec
@@ -2523,7 +2498,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2579,7 +2554,7 @@ spec:
- -n
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2648,7 +2623,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -2666,6 +2641,8 @@ spec:
name: tls-certs
- mountPath: /app/config/gpg/source
name: gpg-keys
- mountPath: /app/config/gpg/keys
name: gpg-keyring
volumes:
- configMap:
name: argocd-ssh-known-hosts-cm
@@ -2676,6 +2653,8 @@ spec:
- configMap:
name: argocd-gpg-keys-cm
name: gpg-keys
- emptyDir: {}
name: gpg-keyring
---
apiVersion: apps/v1
kind: Deployment
@@ -2699,7 +2678,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v1.7.5
imagePullPolicy: Always
name: argocd-server
ports:

View File

@@ -1898,140 +1898,142 @@ func init() {
}
var fileDescriptor_df6e82b174b5eaec = []byte{
// 2121 bytes of a gzipped FileDescriptorProto
// 2146 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x5a, 0xcd, 0x6f, 0x1c, 0x49,
0x15, 0xa7, 0xc6, 0x63, 0xcf, 0xf8, 0x39, 0xbb, 0xc9, 0xd6, 0x6e, 0x42, 0x6f, 0x67, 0xe2, 0x8c,
0x2a, 0x89, 0xe3, 0x38, 0x71, 0x4f, 0x6c, 0x02, 0x2c, 0x06, 0x29, 0xc4, 0x9b, 0xe0, 0x18, 0x9c,
0x60, 0xda, 0x09, 0x2b, 0x21, 0x21, 0xd4, 0xdb, 0x5d, 0x1e, 0x37, 0x9e, 0xe9, 0x6e, 0xba, 0x7b,
0x26, 0x1a, 0xa2, 0x1c, 0x58, 0x24, 0xc4, 0x01, 0x81, 0x10, 0x1c, 0x00, 0xf1, 0xb1, 0x82, 0x2b,
0x37, 0xe0, 0xc2, 0x61, 0x6f, 0xa0, 0x1c, 0x11, 0xbb, 0xe7, 0x08, 0x59, 0xfc, 0x01, 0x9c, 0x38,
0xa3, 0xaa, 0xae, 0xea, 0xae, 0x9e, 0xf4, 0xf4, 0x4c, 0xd6, 0xc3, 0x21, 0xb7, 0xa9, 0x57, 0xd5,
0xef, 0xfd, 0xde, 0x47, 0xfd, 0xaa, 0xea, 0x69, 0xe0, 0x62, 0x44, 0xc3, 0x3e, 0x0d, 0x5b, 0x56,
0x10, 0x74, 0x5c, 0xdb, 0x8a, 0x5d, 0xdf, 0x53, 0x7f, 0x1b, 0x41, 0xe8, 0xc7, 0x3e, 0x5e, 0x50,
0x44, 0xfa, 0x1b, 0x6d, 0xbf, 0xed, 0x73, 0x79, 0x8b, 0xfd, 0x4a, 0x96, 0xe8, 0x8d, 0xb6, 0xef,
0xb7, 0x3b, 0xb4, 0x65, 0x05, 0x6e, 0xcb, 0xf2, 0x3c, 0x3f, 0xe6, 0x8b, 0x23, 0x31, 0x4b, 0x0e,
0xdf, 0x8a, 0x0c, 0xd7, 0xe7, 0xb3, 0xb6, 0x1f, 0xd2, 0x56, 0x7f, 0xad, 0xd5, 0xa6, 0x1e, 0x0d,
0xad, 0x98, 0x3a, 0x62, 0xcd, 0x8d, 0x6c, 0x4d, 0xd7, 0xb2, 0x0f, 0x5c, 0x8f, 0x86, 0x83, 0x56,
0x70, 0xd8, 0x66, 0x82, 0xa8, 0xd5, 0xa5, 0xb1, 0x55, 0xf4, 0xd5, 0x76, 0xdb, 0x8d, 0x0f, 0x7a,
0xef, 0x1a, 0xb6, 0xdf, 0x6d, 0x59, 0x21, 0x07, 0xf6, 0x6d, 0xfe, 0x63, 0xd5, 0x76, 0xb2, 0xaf,
0x55, 0xf7, 0xfa, 0x6b, 0x56, 0x27, 0x38, 0xb0, 0x9e, 0x57, 0xb5, 0x59, 0xa6, 0x2a, 0xa4, 0x81,
0x2f, 0x62, 0xc5, 0x7f, 0xba, 0xb1, 0x1f, 0x0e, 0x94, 0x9f, 0x89, 0x0e, 0xf2, 0x57, 0x04, 0xa7,
0x6e, 0x65, 0xc6, 0xbe, 0xd6, 0xa3, 0xe1, 0x00, 0x63, 0xa8, 0x7a, 0x56, 0x97, 0x6a, 0xa8, 0x89,
0x96, 0xe7, 0x4d, 0xfe, 0x1b, 0x6b, 0x50, 0x0b, 0xe9, 0x7e, 0x48, 0xa3, 0x03, 0xad, 0xc2, 0xc5,
0x72, 0x88, 0x97, 0xa0, 0xc6, 0x2c, 0x53, 0x3b, 0xd6, 0x66, 0x9a, 0x33, 0xcb, 0xf3, 0x9b, 0x27,
0x8e, 0x9e, 0x9d, 0xaf, 0xef, 0x26, 0xa2, 0xc8, 0x94, 0x93, 0xd8, 0x80, 0x93, 0x21, 0x8d, 0xfc,
0x5e, 0x68, 0xd3, 0xaf, 0xd3, 0x30, 0x72, 0x7d, 0x4f, 0xab, 0x32, 0x4d, 0x9b, 0xd5, 0xa7, 0xcf,
0xce, 0x7f, 0xc2, 0x1c, 0x9e, 0xc4, 0x4d, 0xa8, 0x47, 0xb4, 0x43, 0xed, 0xd8, 0x0f, 0xb5, 0x59,
0x65, 0x61, 0x2a, 0x25, 0x5b, 0x70, 0xda, 0xa4, 0x7d, 0x97, 0xad, 0xbe, 0x47, 0x63, 0xcb, 0xb1,
0x62, 0x6b, 0xd8, 0x81, 0x4a, 0xea, 0x80, 0x0e, 0xf5, 0x50, 0x2c, 0xd6, 0x2a, 0x5c, 0x9e, 0x8e,
0x59, 0x14, 0x16, 0x95, 0x28, 0x98, 0x02, 0xc9, 0x9d, 0x3e, 0xf5, 0xe2, 0x68, 0xb4, 0xca, 0x75,
0x78, 0x4d, 0x82, 0xbe, 0x6f, 0x75, 0x69, 0x14, 0x58, 0x36, 0x4d, 0x74, 0x0b, 0xa8, 0xcf, 0x4f,
0xe3, 0x65, 0x38, 0xa1, 0x0a, 0xb5, 0x19, 0x65, 0x79, 0x6e, 0x06, 0x2f, 0xc1, 0x82, 0x1c, 0x3f,
0xdc, 0xbe, 0xad, 0x55, 0x95, 0x85, 0xea, 0x04, 0xd9, 0x05, 0x4d, 0xc1, 0x7e, 0xcf, 0xf2, 0xdc,
0x7d, 0x1a, 0xc5, 0xa3, 0x51, 0x37, 0x73, 0x81, 0x50, 0xe2, 0x9a, 0x86, 0xe3, 0x34, 0xbc, 0x9e,
0x8f, 0x46, 0xe0, 0x7b, 0x11, 0x25, 0x1f, 0xa0, 0x9c, 0xa5, 0xb7, 0x43, 0x6a, 0xc5, 0xd4, 0xa4,
0xdf, 0xe9, 0xd1, 0x28, 0xc6, 0x1e, 0xa8, 0x9b, 0x8e, 0x1b, 0x5c, 0x58, 0xff, 0x92, 0x91, 0x95,
0xa8, 0x21, 0x4b, 0x94, 0xff, 0xf8, 0x96, 0xed, 0x18, 0xc1, 0x61, 0xdb, 0x60, 0xd5, 0x6e, 0xa8,
0x1b, 0x58, 0x56, 0xbb, 0xa1, 0x58, 0x92, 0x5e, 0x2b, 0xeb, 0xf0, 0x19, 0x98, 0xeb, 0x05, 0x11,
0x0d, 0x63, 0xee, 0x43, 0xdd, 0x14, 0x23, 0x96, 0xe6, 0xbe, 0xd5, 0x71, 0x1d, 0x2b, 0x66, 0xb1,
0x65, 0x33, 0xe9, 0x98, 0xbc, 0x9f, 0x77, 0xe0, 0x61, 0xe0, 0x28, 0x0e, 0x1c, 0xfc, 0x1f, 0x1d,
0xc8, 0x43, 0x57, 0x21, 0x56, 0x86, 0x20, 0xde, 0xcd, 0x21, 0xbc, 0x4d, 0x3b, 0x34, 0x43, 0x58,
0x94, 0x4c, 0x0d, 0x6a, 0xb6, 0x15, 0xd9, 0x96, 0x23, 0x55, 0xc9, 0x21, 0x79, 0x5a, 0x85, 0x33,
0x8a, 0xaa, 0xbd, 0x81, 0x67, 0x97, 0x29, 0x1a, 0x5b, 0x15, 0xb8, 0x01, 0x73, 0x4e, 0x38, 0x30,
0x7b, 0x5e, 0x12, 0x57, 0x31, 0x2f, 0x64, 0x58, 0x87, 0xd9, 0x20, 0xec, 0x79, 0x94, 0xef, 0x69,
0x39, 0x99, 0x88, 0xb0, 0x0d, 0xf5, 0x28, 0x66, 0xcc, 0xd5, 0x1e, 0xf0, 0x9d, 0xbc, 0xb0, 0xbe,
0x75, 0x8c, 0xb8, 0x32, 0x4f, 0xf6, 0x84, 0x3a, 0x33, 0x55, 0x8c, 0x63, 0x98, 0x97, 0xbb, 0x22,
0xd2, 0x6a, 0xcd, 0x99, 0xe5, 0x85, 0xf5, 0xdd, 0x63, 0x5a, 0xf9, 0x6a, 0xc0, 0xf8, 0x56, 0x21,
0x04, 0xe1, 0x56, 0x66, 0x08, 0x37, 0x60, 0xbe, 0x2b, 0x76, 0x5c, 0xa4, 0xd5, 0x19, 0xfd, 0x99,
0x99, 0x00, 0x3f, 0x84, 0x59, 0xd7, 0xdb, 0xf7, 0x23, 0x6d, 0x9e, 0xe3, 0xb9, 0x79, 0x0c, 0x3c,
0xdb, 0xde, 0xbe, 0x6f, 0x26, 0xda, 0xb0, 0x07, 0xaf, 0x84, 0x34, 0x0e, 0x07, 0x32, 0x0a, 0x1a,
0xf0, 0xa0, 0xde, 0x3d, 0x86, 0x7a, 0x53, 0xd5, 0x67, 0xe6, 0xd5, 0x93, 0x3f, 0x23, 0x68, 0x3c,
0xb7, 0x6f, 0xf6, 0x02, 0x5a, 0x5a, 0x50, 0x0e, 0x54, 0xa3, 0x80, 0xda, 0x9c, 0x0f, 0x17, 0xd6,
0xbf, 0x3c, 0x9d, 0x8d, 0xc4, 0x8c, 0x8a, 0x24, 0x70, 0xed, 0xa5, 0xdb, 0xbd, 0x0b, 0x9f, 0x54,
0x3e, 0xdd, 0xb5, 0x62, 0xfb, 0xa0, 0x0c, 0x30, 0xab, 0x60, 0xb6, 0x26, 0xc7, 0xe0, 0x89, 0x08,
0x13, 0x98, 0xe7, 0x3f, 0x1e, 0x0c, 0x82, 0x3c, 0x65, 0x67, 0x62, 0xf2, 0x03, 0x04, 0xba, 0xba,
0xe7, 0xfd, 0x4e, 0xe7, 0x5d, 0xcb, 0x3e, 0x2c, 0x37, 0x59, 0x71, 0x1d, 0x6e, 0x6f, 0x66, 0x13,
0x98, 0xbe, 0xa3, 0x67, 0xe7, 0x2b, 0xdb, 0xb7, 0xcd, 0x8a, 0xeb, 0x7c, 0xfc, 0xed, 0x46, 0x3e,
0x1a, 0x02, 0x22, 0x8a, 0xb5, 0x0c, 0x08, 0x81, 0x79, 0xaf, 0xf0, 0x04, 0xcb, 0xc4, 0x2f, 0x70,
0x72, 0x2d, 0x42, 0xad, 0x9f, 0x9e, 0xf0, 0xd9, 0x22, 0x29, 0x64, 0xe0, 0xdb, 0xa1, 0xdf, 0x0b,
0xb4, 0x59, 0x35, 0xd2, 0x5c, 0x84, 0x35, 0xa8, 0x1e, 0xba, 0x9e, 0xa3, 0xcd, 0x29, 0x53, 0x5c,
0x42, 0x7e, 0x59, 0x81, 0xf3, 0x05, 0x6e, 0x8d, 0xcd, 0xeb, 0x4b, 0xe0, 0x5b, 0x56, 0x7b, 0xb5,
0x31, 0xb5, 0x57, 0x2f, 0xae, 0xbd, 0xff, 0x22, 0x68, 0x16, 0xc4, 0x66, 0xfc, 0xf9, 0xf1, 0x92,
0x04, 0x67, 0xdf, 0x0f, 0x6d, 0xaa, 0xd5, 0xd2, 0x5a, 0x47, 0x66, 0x22, 0x22, 0xff, 0x41, 0xa0,
0x49, 0x6f, 0x6f, 0xd9, 0xdc, 0xf7, 0x9e, 0xf7, 0xb2, 0x3b, 0xdc, 0x80, 0x39, 0x8b, 0xfb, 0x92,
0x2b, 0x07, 0x21, 0x23, 0x3f, 0x44, 0x70, 0x36, 0xef, 0x72, 0xb4, 0xe3, 0x46, 0xb1, 0xbc, 0xa6,
0x61, 0x17, 0x6a, 0xc9, 0xca, 0x48, 0x43, 0xfc, 0xd8, 0xd9, 0x3e, 0xd6, 0xb9, 0xa0, 0x1a, 0x92,
0xee, 0x09, 0xfd, 0xe4, 0x26, 0x9c, 0x2d, 0x24, 0x1a, 0x81, 0xa4, 0x09, 0x75, 0x79, 0x16, 0x26,
0x39, 0x90, 0x77, 0x0a, 0x29, 0x25, 0x7f, 0xab, 0xe4, 0x39, 0xda, 0x77, 0x76, 0xfc, 0x76, 0xc9,
0x8d, 0x7b, 0x92, 0xec, 0x69, 0x50, 0x0b, 0x7c, 0x27, 0x4b, 0x9c, 0x29, 0x87, 0xec, 0x6b, 0xdb,
0xf7, 0x62, 0x8b, 0x3d, 0xd5, 0x72, 0xf9, 0xca, 0xc4, 0x2c, 0xf7, 0x91, 0xeb, 0xd9, 0x74, 0x8f,
0xda, 0xbe, 0xe7, 0x44, 0x3c, 0x71, 0x33, 0x32, 0xf7, 0xea, 0x0c, 0xbe, 0x0b, 0xf3, 0x7c, 0xfc,
0xc0, 0xed, 0x52, 0x6d, 0x8e, 0x9f, 0xc0, 0x2b, 0x46, 0xf2, 0x26, 0x34, 0xd4, 0x37, 0x61, 0x16,
0x61, 0xf6, 0x26, 0x34, 0xfa, 0x6b, 0x06, 0xfb, 0xc2, 0xcc, 0x3e, 0x66, 0xb8, 0x62, 0xcb, 0xed,
0xec, 0xb8, 0x1e, 0xbf, 0xba, 0x64, 0x06, 0x33, 0x31, 0xab, 0x89, 0x7d, 0xbf, 0xd3, 0xf1, 0x1f,
0x71, 0x0a, 0x48, 0x8f, 0x83, 0x44, 0x46, 0xbe, 0x0b, 0xf5, 0x1d, 0xbf, 0x7d, 0xc7, 0x8b, 0xc3,
0x01, 0xab, 0x49, 0xe6, 0x0e, 0xf5, 0xf2, 0x41, 0x97, 0x42, 0x7c, 0x1f, 0xe6, 0x63, 0xb7, 0x4b,
0xf7, 0x62, 0xab, 0x1b, 0x88, 0xd3, 0xf9, 0x05, 0x70, 0xa7, 0xc8, 0xa4, 0x0a, 0xd2, 0x82, 0x37,
0xd3, 0x8b, 0xd2, 0x03, 0x1a, 0x76, 0x5d, 0xcf, 0x2a, 0xe5, 0x1c, 0xb2, 0x96, 0xab, 0x1a, 0x76,
0xd1, 0x7a, 0xc7, 0xf5, 0x1c, 0xff, 0xd1, 0xe8, 0xbc, 0x93, 0x7f, 0xe6, 0x1f, 0x68, 0xca, 0x37,
0x69, 0xb1, 0xdd, 0x85, 0x57, 0x58, 0x59, 0xf6, 0xa9, 0x98, 0x10, 0xc5, 0x4f, 0x72, 0x75, 0x5d,
0xa8, 0xc3, 0xcc, 0x7f, 0x88, 0x77, 0xe0, 0xa4, 0x15, 0x45, 0x6e, 0xdb, 0xa3, 0x8e, 0xd4, 0x55,
0x99, 0x58, 0xd7, 0xf0, 0xa7, 0xc9, 0x0d, 0x9d, 0xaf, 0xe0, 0xe5, 0xc8, 0x6f, 0xe8, 0x7c, 0x48,
0xbe, 0x8f, 0xe0, 0x74, 0xa1, 0x12, 0x16, 0x02, 0x4e, 0x0d, 0x22, 0x04, 0x82, 0x05, 0xeb, 0x91,
0x7d, 0x40, 0x9d, 0x5e, 0x87, 0xca, 0xf7, 0xab, 0x1c, 0xb3, 0x39, 0xa7, 0x97, 0x64, 0x40, 0xd4,
0x7c, 0x3a, 0xc6, 0x8b, 0x00, 0x5d, 0xcb, 0xeb, 0x59, 0x1d, 0x0e, 0xa1, 0xca, 0x21, 0x28, 0x12,
0xd2, 0x00, 0xbd, 0x28, 0x7d, 0xe2, 0xcd, 0xf7, 0x11, 0x82, 0x57, 0xe5, 0xbe, 0x16, 0xf9, 0x31,
0xe0, 0xa4, 0x12, 0x86, 0xfb, 0x69, 0xaa, 0x04, 0x31, 0x0f, 0x4f, 0x0e, 0xef, 0x59, 0x54, 0xbc,
0x67, 0x93, 0x9c, 0xcf, 0x28, 0xd3, 0xc9, 0x8e, 0xcf, 0x31, 0x2c, 0x2a, 0x65, 0x58, 0x34, 0x9a,
0x61, 0xd1, 0xd0, 0x5d, 0x62, 0x00, 0xda, 0x3d, 0xcb, 0xb3, 0xda, 0xd4, 0x49, 0x9d, 0x4b, 0x0b,
0xe9, 0x9b, 0x30, 0xeb, 0xc6, 0xb4, 0x2b, 0x0b, 0x68, 0x6b, 0x0a, 0xec, 0x79, 0xdb, 0xdd, 0xdf,
0x37, 0x13, 0xad, 0xeb, 0x1f, 0x36, 0x00, 0xab, 0x59, 0xa7, 0x61, 0xdf, 0xb5, 0x29, 0xfe, 0x09,
0x82, 0x2a, 0xa3, 0x71, 0x7c, 0x6e, 0x54, 0x91, 0xf1, 0xe8, 0xeb, 0x53, 0xba, 0x48, 0x33, 0x53,
0xa4, 0xf1, 0xde, 0x87, 0xff, 0xfe, 0x59, 0xe5, 0x0c, 0x7e, 0x83, 0xf7, 0xb9, 0xfa, 0x6b, 0x6a,
0xdb, 0x29, 0xc2, 0x3f, 0x42, 0x80, 0xc5, 0xc1, 0xa2, 0x74, 0x43, 0xf0, 0xd5, 0x51, 0xf8, 0x0a,
0xba, 0x26, 0xfa, 0x39, 0x85, 0x58, 0x0c, 0xdb, 0x0f, 0x29, 0xa3, 0x11, 0xbe, 0x80, 0x03, 0x58,
0xe1, 0x00, 0x2e, 0x62, 0x52, 0x04, 0xa0, 0xf5, 0x98, 0x15, 0xc0, 0x93, 0x16, 0x4d, 0xec, 0xfe,
0x0e, 0xc1, 0xec, 0x3b, 0xfc, 0x42, 0x34, 0x26, 0x42, 0xbb, 0xd3, 0x89, 0x10, 0xb7, 0xc5, 0xa1,
0x92, 0x0b, 0x1c, 0xe6, 0x39, 0x7c, 0x56, 0xc2, 0x8c, 0xe2, 0x90, 0x5a, 0xdd, 0x1c, 0xda, 0xeb,
0x08, 0xff, 0x1e, 0xc1, 0x5c, 0xd2, 0x14, 0xc1, 0x97, 0x46, 0x41, 0xcc, 0x35, 0x4d, 0xf4, 0x29,
0xb5, 0x17, 0xc8, 0x15, 0x0e, 0xf0, 0x02, 0x29, 0x4c, 0xe4, 0x46, 0xae, 0xf9, 0xf0, 0x53, 0x04,
0x33, 0x5b, 0x74, 0x6c, 0x99, 0x4d, 0x0b, 0xd9, 0x73, 0xa1, 0x2b, 0xc8, 0x30, 0xfe, 0x03, 0x82,
0x37, 0xb7, 0x68, 0x5c, 0x4c, 0xf0, 0x78, 0x79, 0x3c, 0xeb, 0x8a, 0x6a, 0xbb, 0x3a, 0xc1, 0xca,
0x94, 0xd9, 0x5a, 0x1c, 0xd9, 0x15, 0x7c, 0xb9, 0xac, 0xf6, 0xa2, 0x81, 0x67, 0x3f, 0x12, 0x38,
0xfe, 0x8e, 0xe0, 0xd4, 0x70, 0xbb, 0x11, 0xe7, 0x8f, 0x84, 0xc2, 0x6e, 0xa4, 0xfe, 0x95, 0x63,
0x31, 0x48, 0x5e, 0x23, 0xb9, 0xc5, 0x61, 0x7f, 0x1e, 0x7f, 0xae, 0x0c, 0xb6, 0xec, 0xd9, 0x44,
0xad, 0xc7, 0xf2, 0xe7, 0x13, 0xde, 0x91, 0xe6, 0x98, 0xdf, 0x43, 0x70, 0x62, 0x8b, 0xc6, 0xf7,
0xd2, 0x36, 0xc5, 0xc8, 0x6a, 0xcd, 0x35, 0x13, 0xf5, 0x86, 0xa1, 0xb4, 0x8f, 0xe5, 0x54, 0x1a,
0xcf, 0x55, 0x0e, 0xec, 0x32, 0xbe, 0x54, 0x06, 0x2c, 0x6b, 0x8d, 0x7c, 0x80, 0x60, 0x2e, 0x69,
0x24, 0x8c, 0x36, 0x9f, 0x6b, 0xd0, 0x4d, 0xad, 0x24, 0xef, 0x70, 0xa0, 0x37, 0xf5, 0xeb, 0xc5,
0x40, 0xd5, 0xef, 0x65, 0xc8, 0x0c, 0x8e, 0x3e, 0xbf, 0x91, 0xfe, 0x84, 0x00, 0xb2, 0x4e, 0x08,
0xbe, 0x52, 0xee, 0x84, 0xd2, 0x2d, 0xd1, 0xa7, 0xd8, 0x0b, 0x21, 0x06, 0x77, 0x66, 0x59, 0x6f,
0x96, 0x56, 0x71, 0x40, 0xed, 0x8d, 0xa4, 0x5f, 0xf2, 0x1b, 0x04, 0xb3, 0xfc, 0xc5, 0x8c, 0x2f,
0x8e, 0x02, 0xac, 0x3e, 0xa8, 0xa7, 0x16, 0xf4, 0x25, 0x8e, 0xb3, 0xb9, 0x5e, 0xc6, 0x03, 0x1b,
0x68, 0x05, 0xf7, 0x61, 0x2e, 0x79, 0xb4, 0x8e, 0xae, 0x8a, 0xdc, 0xa3, 0x56, 0x6f, 0x96, 0x1c,
0x47, 0x49, 0x61, 0x0a, 0x0a, 0x5a, 0x29, 0xa5, 0xa0, 0xf7, 0x11, 0x54, 0x19, 0x4b, 0xe0, 0x0b,
0x65, 0x1c, 0x32, 0xed, 0xa8, 0x5c, 0xe5, 0xd0, 0x2e, 0x91, 0xe6, 0x38, 0x0e, 0x62, 0xa1, 0xf9,
0x05, 0x82, 0x53, 0xc3, 0x97, 0x16, 0x7c, 0x76, 0x88, 0x7f, 0xd4, 0x9b, 0x9a, 0x9e, 0x0f, 0xe1,
0xa8, 0x0b, 0x0f, 0xf9, 0x22, 0x47, 0xb1, 0x81, 0xdf, 0x1a, 0xbb, 0x21, 0xee, 0xcb, 0x4d, 0xcc,
0x14, 0xad, 0x66, 0x5d, 0xd0, 0xbf, 0x20, 0x38, 0x21, 0xf5, 0x3e, 0x08, 0x29, 0x2d, 0x87, 0x35,
0xa5, 0xfa, 0x67, 0x86, 0xc8, 0x17, 0x38, 0xf6, 0xcf, 0xe0, 0x1b, 0x13, 0x62, 0x97, 0x98, 0x57,
0x63, 0x06, 0xf3, 0x8f, 0x08, 0xea, 0xb2, 0x4f, 0x87, 0x2f, 0x8f, 0xac, 0xa4, 0x7c, 0x27, 0x6f,
0x6a, 0xd9, 0x17, 0x27, 0x10, 0xb9, 0x58, 0x4a, 0xe5, 0xc2, 0x38, 0xab, 0x80, 0x9f, 0x23, 0xc0,
0xe9, 0x15, 0x3d, 0xbd, 0xb4, 0xe3, 0xa5, 0x9c, 0xa9, 0x91, 0x6f, 0x31, 0xfd, 0xf2, 0xd8, 0x75,
0x79, 0x2a, 0x5f, 0x29, 0xa5, 0x72, 0x3f, 0xb5, 0xff, 0x63, 0x04, 0x0b, 0x5b, 0x34, 0xbd, 0x27,
0x96, 0x04, 0x32, 0xdf, 0x89, 0xd4, 0x97, 0xc7, 0x2f, 0x14, 0x88, 0xae, 0x71, 0x44, 0x4b, 0xb8,
0x3c, 0x54, 0x12, 0xc0, 0xaf, 0x11, 0xbc, 0x22, 0x58, 0x4c, 0x48, 0xae, 0x8d, 0xb3, 0x94, 0x23,
0xbd, 0xc9, 0x71, 0x7d, 0x8a, 0xe3, 0x5a, 0x25, 0x13, 0xe1, 0xda, 0x10, 0x0d, 0xbd, 0xdf, 0x22,
0x78, 0x5d, 0xbd, 0x58, 0x8b, 0x26, 0xce, 0xc7, 0x8d, 0x5b, 0x49, 0x2f, 0x88, 0xdc, 0xe0, 0xf8,
0x0c, 0x7c, 0x6d, 0x12, 0x7c, 0x2d, 0xd1, 0xd6, 0xc1, 0xbf, 0x42, 0xf0, 0x1a, 0x6f, 0xa3, 0xa9,
0x8a, 0x87, 0x08, 0x79, 0x54, 0xd3, 0x6d, 0x02, 0x42, 0x16, 0x7b, 0x96, 0xbc, 0x10, 0xa8, 0x0d,
0xd1, 0xfe, 0x62, 0x0f, 0xa5, 0x57, 0xe5, 0x11, 0x20, 0xb2, 0xbb, 0x3a, 0x2e, 0x70, 0x2f, 0x7a,
0x64, 0x88, 0x72, 0x5b, 0x99, 0xac, 0xdc, 0xbe, 0x87, 0xa0, 0x26, 0x3a, 0x57, 0x25, 0xa7, 0xaa,
0xd2, 0xda, 0xd2, 0x4f, 0xe7, 0x56, 0xc9, 0xce, 0x0d, 0xf9, 0x2c, 0x37, 0xbb, 0x86, 0x5b, 0x65,
0x66, 0x03, 0xdf, 0x89, 0x5a, 0x8f, 0x45, 0x4b, 0xeb, 0x49, 0xab, 0xe3, 0xb7, 0xa3, 0xeb, 0x68,
0xf3, 0xed, 0xa7, 0x47, 0x8b, 0xe8, 0x1f, 0x47, 0x8b, 0xe8, 0x5f, 0x47, 0x8b, 0xe8, 0x1b, 0x9f,
0x9e, 0xe0, 0x4f, 0x06, 0x76, 0xc7, 0xa5, 0x5e, 0xac, 0x9a, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0xff,
0xff, 0x00, 0x68, 0x8b, 0x98, 0x5d, 0x21, 0x00, 0x00,
0x15, 0xa7, 0xc6, 0x63, 0xcf, 0xf8, 0x39, 0xd9, 0x24, 0xb5, 0x9b, 0xd0, 0xdb, 0x71, 0x9c, 0x51,
0xe5, 0xcb, 0x71, 0xe2, 0x9e, 0xd8, 0x04, 0x58, 0xbc, 0xa0, 0x10, 0x27, 0xc1, 0x31, 0x38, 0xc1,
0xb4, 0x13, 0x22, 0x21, 0x21, 0xd4, 0xdb, 0x5d, 0x1e, 0x37, 0x9e, 0xe9, 0x6e, 0xba, 0x7b, 0x26,
0x1a, 0xa2, 0x1c, 0x58, 0x24, 0xc4, 0x01, 0x81, 0x10, 0x1c, 0x58, 0xc4, 0xc7, 0x0a, 0xae, 0xdc,
0x80, 0x0b, 0x87, 0xbd, 0x20, 0x50, 0x8e, 0x08, 0xf6, 0x1c, 0x21, 0x8b, 0x3f, 0x80, 0x13, 0x67,
0x54, 0xd5, 0x55, 0xdd, 0xd5, 0x93, 0x9e, 0x9e, 0xc9, 0x7a, 0x10, 0xca, 0x6d, 0xea, 0x55, 0xf5,
0x7b, 0xbf, 0xf7, 0xea, 0x57, 0xef, 0x55, 0x3d, 0x0d, 0x9c, 0x8f, 0x68, 0xd8, 0xa3, 0x61, 0xd3,
0x0a, 0x82, 0xb6, 0x6b, 0x5b, 0xb1, 0xeb, 0x7b, 0xea, 0x6f, 0x23, 0x08, 0xfd, 0xd8, 0xc7, 0x73,
0x8a, 0x48, 0x7f, 0xa3, 0xe5, 0xb7, 0x7c, 0x2e, 0x6f, 0xb2, 0x5f, 0xc9, 0x12, 0x7d, 0xbe, 0xe5,
0xfb, 0xad, 0x36, 0x6d, 0x5a, 0x81, 0xdb, 0xb4, 0x3c, 0xcf, 0x8f, 0xf9, 0xe2, 0x48, 0xcc, 0x92,
0xfd, 0xb7, 0x22, 0xc3, 0xf5, 0xf9, 0xac, 0xed, 0x87, 0xb4, 0xd9, 0x5b, 0x69, 0xb6, 0xa8, 0x47,
0x43, 0x2b, 0xa6, 0x8e, 0x58, 0x73, 0x3d, 0x5b, 0xd3, 0xb1, 0xec, 0x3d, 0xd7, 0xa3, 0x61, 0xbf,
0x19, 0xec, 0xb7, 0x98, 0x20, 0x6a, 0x76, 0x68, 0x6c, 0x15, 0x7d, 0xb5, 0xd9, 0x72, 0xe3, 0xbd,
0xee, 0x3b, 0x86, 0xed, 0x77, 0x9a, 0x56, 0xc8, 0x81, 0x7d, 0x93, 0xff, 0x58, 0xb6, 0x9d, 0xec,
0x6b, 0xd5, 0xbd, 0xde, 0x8a, 0xd5, 0x0e, 0xf6, 0xac, 0x17, 0x55, 0xad, 0x97, 0xa9, 0x0a, 0x69,
0xe0, 0x8b, 0x58, 0xf1, 0x9f, 0x6e, 0xec, 0x87, 0x7d, 0xe5, 0x67, 0xa2, 0x83, 0xfc, 0x09, 0xc1,
0xf1, 0x9b, 0x99, 0xb1, 0xaf, 0x74, 0x69, 0xd8, 0xc7, 0x18, 0xaa, 0x9e, 0xd5, 0xa1, 0x1a, 0x6a,
0xa0, 0xc5, 0x59, 0x93, 0xff, 0xc6, 0x1a, 0xd4, 0x42, 0xba, 0x1b, 0xd2, 0x68, 0x4f, 0xab, 0x70,
0xb1, 0x1c, 0xe2, 0x8b, 0x50, 0x63, 0x96, 0xa9, 0x1d, 0x6b, 0x53, 0x8d, 0xa9, 0xc5, 0xd9, 0xf5,
0x23, 0x07, 0xcf, 0xcf, 0xd6, 0xb7, 0x13, 0x51, 0x64, 0xca, 0x49, 0x6c, 0xc0, 0xb1, 0x90, 0x46,
0x7e, 0x37, 0xb4, 0xe9, 0x57, 0x69, 0x18, 0xb9, 0xbe, 0xa7, 0x55, 0x99, 0xa6, 0xf5, 0xea, 0xb3,
0xe7, 0x67, 0x3f, 0x66, 0x0e, 0x4e, 0xe2, 0x06, 0xd4, 0x23, 0xda, 0xa6, 0x76, 0xec, 0x87, 0xda,
0xb4, 0xb2, 0x30, 0x95, 0x92, 0x0d, 0x38, 0x69, 0xd2, 0x9e, 0xcb, 0x56, 0xdf, 0xa3, 0xb1, 0xe5,
0x58, 0xb1, 0x35, 0xe8, 0x40, 0x25, 0x75, 0x40, 0x87, 0x7a, 0x28, 0x16, 0x6b, 0x15, 0x2e, 0x4f,
0xc7, 0x2c, 0x0a, 0x0b, 0x4a, 0x14, 0x4c, 0x81, 0xe4, 0x4e, 0x8f, 0x7a, 0x71, 0x34, 0x5c, 0xe5,
0x2a, 0x9c, 0x90, 0xa0, 0xef, 0x5b, 0x1d, 0x1a, 0x05, 0x96, 0x4d, 0x13, 0xdd, 0x02, 0xea, 0x8b,
0xd3, 0x78, 0x11, 0x8e, 0xa8, 0x42, 0x6d, 0x4a, 0x59, 0x9e, 0x9b, 0xc1, 0x17, 0x61, 0x4e, 0x8e,
0x1f, 0x6e, 0xde, 0xd6, 0xaa, 0xca, 0x42, 0x75, 0x82, 0x6c, 0x83, 0xa6, 0x60, 0xbf, 0x67, 0x79,
0xee, 0x2e, 0x8d, 0xe2, 0xe1, 0xa8, 0x1b, 0xb9, 0x40, 0x28, 0x71, 0x4d, 0xc3, 0x71, 0x12, 0x5e,
0xcf, 0x47, 0x23, 0xf0, 0xbd, 0x88, 0x92, 0x0f, 0x50, 0xce, 0xd2, 0xad, 0x90, 0x5a, 0x31, 0x35,
0xe9, 0xb7, 0xba, 0x34, 0x8a, 0xb1, 0x07, 0xea, 0xa1, 0xe3, 0x06, 0xe7, 0x56, 0xbf, 0x60, 0x64,
0x14, 0x35, 0x24, 0x45, 0xf9, 0x8f, 0x6f, 0xd8, 0x8e, 0x11, 0xec, 0xb7, 0x0c, 0xc6, 0x76, 0x43,
0x3d, 0xc0, 0x92, 0xed, 0x86, 0x62, 0x49, 0x7a, 0xad, 0xac, 0xc3, 0xa7, 0x60, 0xa6, 0x1b, 0x44,
0x34, 0x8c, 0xb9, 0x0f, 0x75, 0x53, 0x8c, 0xd8, 0x36, 0xf7, 0xac, 0xb6, 0xeb, 0x58, 0x31, 0x8b,
0x2d, 0x9b, 0x49, 0xc7, 0xe4, 0xfd, 0xbc, 0x03, 0x0f, 0x03, 0x47, 0x71, 0x60, 0xef, 0x7f, 0xe8,
0x40, 0x1e, 0xba, 0x0a, 0xb1, 0x32, 0x00, 0xf1, 0x6e, 0x0e, 0xe1, 0x6d, 0xda, 0xa6, 0x19, 0xc2,
0xa2, 0xcd, 0xd4, 0xa0, 0x66, 0x5b, 0x91, 0x6d, 0x39, 0x52, 0x95, 0x1c, 0x92, 0x67, 0x55, 0x38,
0xa5, 0xa8, 0xda, 0xe9, 0x7b, 0x76, 0x99, 0xa2, 0x91, 0xac, 0xc0, 0xf3, 0x30, 0xe3, 0x84, 0x7d,
0xb3, 0xeb, 0x25, 0x71, 0x15, 0xf3, 0x42, 0x86, 0x75, 0x98, 0x0e, 0xc2, 0xae, 0x47, 0xf9, 0x99,
0x96, 0x93, 0x89, 0x08, 0xdb, 0x50, 0x8f, 0x62, 0x96, 0xb9, 0x5a, 0x7d, 0x7e, 0x92, 0xe7, 0x56,
0x37, 0x0e, 0x11, 0x57, 0xe6, 0xc9, 0x8e, 0x50, 0x67, 0xa6, 0x8a, 0x71, 0x0c, 0xb3, 0xf2, 0x54,
0x44, 0x5a, 0xad, 0x31, 0xb5, 0x38, 0xb7, 0xba, 0x7d, 0x48, 0x2b, 0x5f, 0x0e, 0x58, 0xbe, 0x55,
0x12, 0x82, 0x70, 0x2b, 0x33, 0x84, 0xe7, 0x61, 0xb6, 0x23, 0x4e, 0x5c, 0xa4, 0xd5, 0x59, 0xfa,
0x33, 0x33, 0x01, 0x7e, 0x08, 0xd3, 0xae, 0xb7, 0xeb, 0x47, 0xda, 0x2c, 0xc7, 0x73, 0xe3, 0x10,
0x78, 0x36, 0xbd, 0x5d, 0xdf, 0x4c, 0xb4, 0x61, 0x0f, 0x8e, 0x86, 0x34, 0x0e, 0xfb, 0x32, 0x0a,
0x1a, 0xf0, 0xa0, 0xde, 0x3d, 0x84, 0x7a, 0x53, 0xd5, 0x67, 0xe6, 0xd5, 0x93, 0x3f, 0x20, 0x98,
0x7f, 0xe1, 0xdc, 0xec, 0x04, 0xb4, 0x94, 0x50, 0x0e, 0x54, 0xa3, 0x80, 0xda, 0x3c, 0x1f, 0xce,
0xad, 0x7e, 0x71, 0x32, 0x07, 0x89, 0x19, 0x15, 0x9b, 0xc0, 0xb5, 0x97, 0x1e, 0xf7, 0x0e, 0x7c,
0x5c, 0xf9, 0x74, 0xdb, 0x8a, 0xed, 0xbd, 0x32, 0xc0, 0x8c, 0xc1, 0x6c, 0x4d, 0x2e, 0x83, 0x27,
0x22, 0x4c, 0x60, 0x96, 0xff, 0x78, 0xd0, 0x0f, 0xf2, 0x29, 0x3b, 0x13, 0x93, 0xef, 0x21, 0xd0,
0xd5, 0x33, 0xef, 0xb7, 0xdb, 0xef, 0x58, 0xf6, 0x7e, 0xb9, 0xc9, 0x8a, 0xeb, 0x70, 0x7b, 0x53,
0xeb, 0xc0, 0xf4, 0x1d, 0x3c, 0x3f, 0x5b, 0xd9, 0xbc, 0x6d, 0x56, 0x5c, 0xe7, 0xa3, 0x1f, 0x37,
0xf2, 0xe1, 0x00, 0x10, 0x41, 0xd6, 0x32, 0x20, 0x04, 0x66, 0xbd, 0xc2, 0x0a, 0x96, 0x89, 0x5f,
0xa2, 0x72, 0x2d, 0x40, 0xad, 0x97, 0x56, 0xf8, 0x6c, 0x91, 0x14, 0x32, 0xf0, 0xad, 0xd0, 0xef,
0x06, 0xda, 0xb4, 0x1a, 0x69, 0x2e, 0xc2, 0x1a, 0x54, 0xf7, 0x5d, 0xcf, 0xd1, 0x66, 0x94, 0x29,
0x2e, 0x21, 0xef, 0x55, 0xe0, 0x6c, 0x81, 0x5b, 0x23, 0xf7, 0xf5, 0x15, 0xf0, 0x2d, 0xe3, 0x5e,
0x6d, 0x04, 0xf7, 0xea, 0xc5, 0xdc, 0xfb, 0x0f, 0x82, 0x46, 0x41, 0x6c, 0x46, 0xd7, 0x8f, 0x57,
0x24, 0x38, 0xbb, 0x7e, 0x68, 0x53, 0xad, 0x96, 0x72, 0x1d, 0x99, 0x89, 0x88, 0xfc, 0x1b, 0x81,
0x26, 0xbd, 0xbd, 0x69, 0x73, 0xdf, 0xbb, 0xde, 0xab, 0xee, 0xf0, 0x3c, 0xcc, 0x58, 0xdc, 0x97,
0x1c, 0x1d, 0x84, 0x8c, 0x7c, 0x1f, 0xc1, 0xe9, 0xbc, 0xcb, 0xd1, 0x96, 0x1b, 0xc5, 0xf2, 0x9a,
0x86, 0x5d, 0xa8, 0x25, 0x2b, 0x23, 0x0d, 0xf1, 0xb2, 0xb3, 0x79, 0xa8, 0xba, 0xa0, 0x1a, 0x92,
0xee, 0x09, 0xfd, 0xe4, 0x06, 0x9c, 0x2e, 0x4c, 0x34, 0x02, 0x49, 0x03, 0xea, 0xb2, 0x16, 0x26,
0x7b, 0x20, 0xef, 0x14, 0x52, 0x4a, 0xfe, 0x52, 0xc9, 0xe7, 0x68, 0xdf, 0xd9, 0xf2, 0x5b, 0x25,
0x37, 0xee, 0x71, 0x76, 0x4f, 0x83, 0x5a, 0xe0, 0x3b, 0xd9, 0xc6, 0x99, 0x72, 0xc8, 0xbe, 0xb6,
0x7d, 0x2f, 0xb6, 0xd8, 0x53, 0x2d, 0xb7, 0x5f, 0x99, 0x98, 0xed, 0x7d, 0xe4, 0x7a, 0x36, 0xdd,
0xa1, 0xb6, 0xef, 0x39, 0x11, 0xdf, 0xb8, 0x29, 0xb9, 0xf7, 0xea, 0x0c, 0xbe, 0x0b, 0xb3, 0x7c,
0xfc, 0xc0, 0xed, 0x50, 0x6d, 0x86, 0x57, 0xe0, 0x25, 0x23, 0x79, 0x13, 0x1a, 0xea, 0x9b, 0x30,
0x8b, 0x30, 0x7b, 0x13, 0x1a, 0xbd, 0x15, 0x83, 0x7d, 0x61, 0x66, 0x1f, 0x33, 0x5c, 0xb1, 0xe5,
0xb6, 0xb7, 0x5c, 0x8f, 0x5f, 0x5d, 0x32, 0x83, 0x99, 0x98, 0x71, 0x62, 0xd7, 0x6f, 0xb7, 0xfd,
0xc7, 0x3c, 0x05, 0xa4, 0xe5, 0x20, 0x91, 0x91, 0x6f, 0x43, 0x7d, 0xcb, 0x6f, 0xdd, 0xf1, 0xe2,
0xb0, 0xcf, 0x38, 0xc9, 0xdc, 0xa1, 0x5e, 0x3e, 0xe8, 0x52, 0x88, 0xef, 0xc3, 0x6c, 0xec, 0x76,
0xe8, 0x4e, 0x6c, 0x75, 0x02, 0x51, 0x9d, 0x5f, 0x02, 0x77, 0x8a, 0x4c, 0xaa, 0x20, 0x4d, 0x78,
0x33, 0xbd, 0x28, 0x3d, 0xa0, 0x61, 0xc7, 0xf5, 0xac, 0xd2, 0x9c, 0x43, 0x56, 0x72, 0xac, 0x61,
0x17, 0xad, 0x47, 0xae, 0xe7, 0xf8, 0x8f, 0x87, 0xef, 0x3b, 0xf9, 0x7b, 0xfe, 0x81, 0xa6, 0x7c,
0x93, 0x92, 0xed, 0x2e, 0x1c, 0x65, 0xb4, 0xec, 0x51, 0x31, 0x21, 0xc8, 0x4f, 0x72, 0xbc, 0x2e,
0xd4, 0x61, 0xe6, 0x3f, 0xc4, 0x5b, 0x70, 0xcc, 0x8a, 0x22, 0xb7, 0xe5, 0x51, 0x47, 0xea, 0xaa,
0x8c, 0xad, 0x6b, 0xf0, 0xd3, 0xe4, 0x86, 0xce, 0x57, 0x70, 0x3a, 0xf2, 0x1b, 0x3a, 0x1f, 0x92,
0xef, 0x22, 0x38, 0x59, 0xa8, 0x84, 0x85, 0x80, 0xa7, 0x06, 0x11, 0x02, 0x91, 0x05, 0xeb, 0x91,
0xbd, 0x47, 0x9d, 0x6e, 0x9b, 0xca, 0xf7, 0xab, 0x1c, 0xb3, 0x39, 0xa7, 0x9b, 0xec, 0x80, 0xe0,
0x7c, 0x3a, 0xc6, 0x0b, 0x00, 0x1d, 0xcb, 0xeb, 0x5a, 0x6d, 0x0e, 0xa1, 0xca, 0x21, 0x28, 0x12,
0x32, 0x0f, 0x7a, 0xd1, 0xf6, 0x89, 0x37, 0xdf, 0x87, 0x08, 0x5e, 0x93, 0xe7, 0x5a, 0xec, 0x8f,
0x01, 0xc7, 0x94, 0x30, 0xdc, 0x4f, 0xb7, 0x4a, 0x24, 0xe6, 0xc1, 0xc9, 0xc1, 0x33, 0x8b, 0x8a,
0xcf, 0x6c, 0xb2, 0xe7, 0x53, 0xca, 0x74, 0x72, 0xe2, 0x73, 0x19, 0x16, 0x95, 0x66, 0x58, 0x34,
0x3c, 0xc3, 0xa2, 0x81, 0xbb, 0x44, 0x1f, 0xb4, 0x7b, 0x96, 0x67, 0xb5, 0xa8, 0x93, 0x3a, 0x97,
0x12, 0xe9, 0xeb, 0x30, 0xed, 0xc6, 0xb4, 0x23, 0x09, 0xb4, 0x31, 0x81, 0xec, 0x79, 0xdb, 0xdd,
0xdd, 0x35, 0x13, 0xad, 0xab, 0xef, 0x2d, 0x00, 0x56, 0x77, 0x9d, 0x86, 0x3d, 0xd7, 0xa6, 0xf8,
0x47, 0x08, 0xaa, 0x2c, 0x8d, 0xe3, 0x33, 0xc3, 0x48, 0xc6, 0xa3, 0xaf, 0x4f, 0xe8, 0x22, 0xcd,
0x4c, 0x91, 0xf9, 0x77, 0xff, 0xf1, 0xaf, 0x9f, 0x54, 0x4e, 0xe1, 0x37, 0x78, 0x9f, 0xab, 0xb7,
0xa2, 0xb6, 0x9d, 0x22, 0xfc, 0x03, 0x04, 0x58, 0x14, 0x16, 0xa5, 0x1b, 0x82, 0xaf, 0x0c, 0xc3,
0x57, 0xd0, 0x35, 0xd1, 0xcf, 0x28, 0x89, 0xc5, 0xb0, 0xfd, 0x90, 0xb2, 0x34, 0xc2, 0x17, 0x70,
0x00, 0x4b, 0x1c, 0xc0, 0x79, 0x4c, 0x8a, 0x00, 0x34, 0x9f, 0x30, 0x02, 0x3c, 0x6d, 0xd2, 0xc4,
0xee, 0xaf, 0x11, 0x4c, 0x3f, 0xe2, 0x17, 0xa2, 0x11, 0x11, 0xda, 0x9e, 0x4c, 0x84, 0xb8, 0x2d,
0x0e, 0x95, 0x9c, 0xe3, 0x30, 0xcf, 0xe0, 0xd3, 0x12, 0x66, 0x14, 0x87, 0xd4, 0xea, 0xe4, 0xd0,
0x5e, 0x43, 0xf8, 0x37, 0x08, 0x66, 0x92, 0xa6, 0x08, 0xbe, 0x30, 0x0c, 0x62, 0xae, 0x69, 0xa2,
0x4f, 0xa8, 0xbd, 0x40, 0x2e, 0x73, 0x80, 0xe7, 0x48, 0xe1, 0x46, 0xae, 0xe5, 0x9a, 0x0f, 0x3f,
0x46, 0x30, 0xb5, 0x41, 0x47, 0xd2, 0x6c, 0x52, 0xc8, 0x5e, 0x08, 0x5d, 0xc1, 0x0e, 0xe3, 0xdf,
0x22, 0x78, 0x73, 0x83, 0xc6, 0xc5, 0x09, 0x1e, 0x2f, 0x8e, 0xce, 0xba, 0x82, 0x6d, 0x57, 0xc6,
0x58, 0x99, 0x66, 0xb6, 0x26, 0x47, 0x76, 0x19, 0x5f, 0x2a, 0xe3, 0x5e, 0xd4, 0xf7, 0xec, 0xc7,
0x02, 0xc7, 0x5f, 0x11, 0x1c, 0x1f, 0x6c, 0x37, 0xe2, 0x7c, 0x49, 0x28, 0xec, 0x46, 0xea, 0x5f,
0x3a, 0x54, 0x06, 0xc9, 0x6b, 0x24, 0x37, 0x39, 0xec, 0xb7, 0xf1, 0x67, 0xca, 0x60, 0xcb, 0x9e,
0x4d, 0xd4, 0x7c, 0x22, 0x7f, 0x3e, 0xe5, 0x1d, 0x69, 0x8e, 0xf9, 0x5d, 0x04, 0x47, 0x36, 0x68,
0x7c, 0x2f, 0x6d, 0x53, 0x0c, 0x65, 0x6b, 0xae, 0x99, 0xa8, 0xcf, 0x1b, 0x4a, 0xfb, 0x58, 0x4e,
0xa5, 0xf1, 0x5c, 0xe6, 0xc0, 0x2e, 0xe1, 0x0b, 0x65, 0xc0, 0xb2, 0xd6, 0xc8, 0x07, 0x08, 0x66,
0x92, 0x46, 0xc2, 0x70, 0xf3, 0xb9, 0x06, 0xdd, 0xc4, 0x28, 0x79, 0x87, 0x03, 0xbd, 0xa1, 0x5f,
0x2b, 0x06, 0xaa, 0x7e, 0x2f, 0x43, 0x66, 0x70, 0xf4, 0xf9, 0x83, 0xf4, 0x7b, 0x04, 0x90, 0x75,
0x42, 0xf0, 0xe5, 0x72, 0x27, 0x94, 0x6e, 0x89, 0x3e, 0xc1, 0x5e, 0x08, 0x31, 0xb8, 0x33, 0x8b,
0x7a, 0xa3, 0x94, 0xc5, 0x01, 0xb5, 0xd7, 0x92, 0x7e, 0xc9, 0x2f, 0x11, 0x4c, 0xf3, 0x17, 0x33,
0x3e, 0x3f, 0x0c, 0xb0, 0xfa, 0xa0, 0x9e, 0x58, 0xd0, 0x2f, 0x72, 0x9c, 0x8d, 0xd5, 0xb2, 0x3c,
0xb0, 0x86, 0x96, 0x70, 0x0f, 0x66, 0x92, 0x47, 0xeb, 0x70, 0x56, 0xe4, 0x1e, 0xb5, 0x7a, 0xa3,
0xa4, 0x1c, 0x25, 0xc4, 0x14, 0x29, 0x68, 0xa9, 0x34, 0x05, 0xbd, 0x8f, 0xa0, 0xca, 0xb2, 0x04,
0x3e, 0x57, 0x96, 0x43, 0x26, 0x1d, 0x95, 0x2b, 0x1c, 0xda, 0x05, 0xd2, 0x18, 0x95, 0x83, 0x58,
0x68, 0x7e, 0x86, 0xe0, 0xf8, 0xe0, 0xa5, 0x05, 0x9f, 0x1e, 0xc8, 0x3f, 0xea, 0x4d, 0x4d, 0xcf,
0x87, 0x70, 0xd8, 0x85, 0x87, 0x7c, 0x9e, 0xa3, 0x58, 0xc3, 0x6f, 0x8d, 0x3c, 0x10, 0xf7, 0xe5,
0x21, 0x66, 0x8a, 0x96, 0xb3, 0x2e, 0xe8, 0x1f, 0x11, 0x1c, 0x91, 0x7a, 0x1f, 0x84, 0x94, 0x96,
0xc3, 0x9a, 0x10, 0xff, 0x99, 0x21, 0xf2, 0x59, 0x8e, 0xfd, 0x53, 0xf8, 0xfa, 0x98, 0xd8, 0x25,
0xe6, 0xe5, 0x98, 0xc1, 0xfc, 0x33, 0x82, 0x13, 0x8f, 0x12, 0xba, 0xff, 0x3f, 0xc0, 0xdf, 0xe2,
0xe0, 0x3f, 0x87, 0xdf, 0x2e, 0xb9, 0x57, 0x8c, 0xf2, 0xe1, 0x1a, 0xc2, 0xbf, 0x43, 0x50, 0x97,
0xdd, 0x46, 0x7c, 0x69, 0xe8, 0x79, 0xc8, 0xf7, 0x23, 0x27, 0xc6, 0x61, 0x51, 0x47, 0xc9, 0xf9,
0xd2, 0x82, 0x24, 0x8c, 0x33, 0x1e, 0xff, 0x14, 0x01, 0x4e, 0x1f, 0x1a, 0xe9, 0xd3, 0x03, 0x5f,
0xcc, 0x99, 0x1a, 0xfa, 0xa2, 0xd4, 0x2f, 0x8d, 0x5c, 0x97, 0x2f, 0x48, 0x4b, 0xa5, 0x05, 0xc9,
0x4f, 0xed, 0xff, 0x10, 0xc1, 0xdc, 0x06, 0x4d, 0x6f, 0xbb, 0x25, 0x81, 0xcc, 0xf7, 0x53, 0xf5,
0xc5, 0xd1, 0x0b, 0x05, 0xa2, 0xab, 0x1c, 0xd1, 0x45, 0x5c, 0x1e, 0x2a, 0x09, 0xe0, 0x17, 0x08,
0x8e, 0x6e, 0xab, 0xe4, 0xc4, 0x57, 0x47, 0x59, 0xca, 0xa5, 0xee, 0xf1, 0x71, 0x7d, 0x82, 0xe3,
0x5a, 0x26, 0x63, 0xe1, 0x5a, 0x13, 0x6d, 0xc9, 0x5f, 0x21, 0x78, 0x5d, 0x7d, 0x1e, 0x88, 0x56,
0xd4, 0x47, 0x8d, 0x5b, 0x49, 0x47, 0x8b, 0x5c, 0xe7, 0xf8, 0x0c, 0x7c, 0x75, 0x1c, 0x7c, 0x4d,
0xd1, 0x9c, 0xc2, 0x3f, 0x47, 0x70, 0x82, 0x37, 0x03, 0x55, 0xc5, 0x03, 0x65, 0x65, 0x58, 0xeb,
0x70, 0x8c, 0xb2, 0x22, 0x32, 0x0f, 0x79, 0x29, 0x50, 0x6b, 0xa2, 0x89, 0xc7, 0x9e, 0x7b, 0xaf,
0xc9, 0x42, 0x26, 0x76, 0x77, 0x79, 0x54, 0xe0, 0x5e, 0xb6, 0xf0, 0x09, 0xba, 0x2d, 0x8d, 0x47,
0xb7, 0xef, 0x20, 0xa8, 0x89, 0xfe, 0x5b, 0xc9, 0xdd, 0x40, 0x69, 0xd0, 0xe9, 0x27, 0x73, 0xab,
0x64, 0xff, 0x89, 0x7c, 0x9a, 0x9b, 0x5d, 0xc1, 0xcd, 0x32, 0xb3, 0x81, 0xef, 0x44, 0xcd, 0x27,
0xa2, 0x31, 0xf7, 0xb4, 0xd9, 0xf6, 0x5b, 0xd1, 0x35, 0xb4, 0x7e, 0xeb, 0xd9, 0xc1, 0x02, 0xfa,
0xdb, 0xc1, 0x02, 0xfa, 0xe7, 0xc1, 0x02, 0xfa, 0xda, 0x27, 0xc7, 0xf8, 0xab, 0x84, 0xdd, 0x76,
0xa9, 0x17, 0xab, 0x26, 0xfe, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x67, 0x2b, 0xcb, 0xbc, 0x23, 0x22,
0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -2074,6 +2076,8 @@ type ApplicationServiceClient interface {
Sync(ctx context.Context, in *ApplicationSyncRequest, opts ...grpc.CallOption) (*v1alpha1.Application, error)
ManagedResources(ctx context.Context, in *ResourcesQuery, opts ...grpc.CallOption) (*ManagedResourcesResponse, error)
ResourceTree(ctx context.Context, in *ResourcesQuery, opts ...grpc.CallOption) (*v1alpha1.ApplicationTree, error)
// Watch returns stream of application resource tree
WatchResourceTree(ctx context.Context, in *ResourcesQuery, opts ...grpc.CallOption) (ApplicationService_WatchResourceTreeClient, error)
// Rollback syncs an application to its target state
Rollback(ctx context.Context, in *ApplicationRollbackRequest, opts ...grpc.CallOption) (*v1alpha1.Application, error)
// TerminateOperation terminates the currently running operation
@@ -2256,6 +2260,38 @@ func (c *applicationServiceClient) ResourceTree(ctx context.Context, in *Resourc
return out, nil
}
func (c *applicationServiceClient) WatchResourceTree(ctx context.Context, in *ResourcesQuery, opts ...grpc.CallOption) (ApplicationService_WatchResourceTreeClient, error) {
stream, err := c.cc.NewStream(ctx, &_ApplicationService_serviceDesc.Streams[1], "/application.ApplicationService/WatchResourceTree", opts...)
if err != nil {
return nil, err
}
x := &applicationServiceWatchResourceTreeClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type ApplicationService_WatchResourceTreeClient interface {
Recv() (*v1alpha1.ApplicationTree, error)
grpc.ClientStream
}
type applicationServiceWatchResourceTreeClient struct {
grpc.ClientStream
}
func (x *applicationServiceWatchResourceTreeClient) Recv() (*v1alpha1.ApplicationTree, error) {
m := new(v1alpha1.ApplicationTree)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
func (c *applicationServiceClient) Rollback(ctx context.Context, in *ApplicationRollbackRequest, opts ...grpc.CallOption) (*v1alpha1.Application, error) {
out := new(v1alpha1.Application)
err := c.cc.Invoke(ctx, "/application.ApplicationService/Rollback", in, out, opts...)
@@ -2320,7 +2356,7 @@ func (c *applicationServiceClient) DeleteResource(ctx context.Context, in *Appli
}
func (c *applicationServiceClient) PodLogs(ctx context.Context, in *ApplicationPodLogsQuery, opts ...grpc.CallOption) (ApplicationService_PodLogsClient, error) {
stream, err := c.cc.NewStream(ctx, &_ApplicationService_serviceDesc.Streams[1], "/application.ApplicationService/PodLogs", opts...)
stream, err := c.cc.NewStream(ctx, &_ApplicationService_serviceDesc.Streams[2], "/application.ApplicationService/PodLogs", opts...)
if err != nil {
return nil, err
}
@@ -2381,6 +2417,8 @@ type ApplicationServiceServer interface {
Sync(context.Context, *ApplicationSyncRequest) (*v1alpha1.Application, error)
ManagedResources(context.Context, *ResourcesQuery) (*ManagedResourcesResponse, error)
ResourceTree(context.Context, *ResourcesQuery) (*v1alpha1.ApplicationTree, error)
// Watch returns stream of application resource tree
WatchResourceTree(*ResourcesQuery, ApplicationService_WatchResourceTreeServer) error
// Rollback syncs an application to its target state
Rollback(context.Context, *ApplicationRollbackRequest) (*v1alpha1.Application, error)
// TerminateOperation terminates the currently running operation
@@ -2446,6 +2484,9 @@ func (*UnimplementedApplicationServiceServer) ManagedResources(ctx context.Conte
func (*UnimplementedApplicationServiceServer) ResourceTree(ctx context.Context, req *ResourcesQuery) (*v1alpha1.ApplicationTree, error) {
return nil, status.Errorf(codes.Unimplemented, "method ResourceTree not implemented")
}
func (*UnimplementedApplicationServiceServer) WatchResourceTree(req *ResourcesQuery, srv ApplicationService_WatchResourceTreeServer) error {
return status.Errorf(codes.Unimplemented, "method WatchResourceTree not implemented")
}
func (*UnimplementedApplicationServiceServer) Rollback(ctx context.Context, req *ApplicationRollbackRequest) (*v1alpha1.Application, error) {
return nil, status.Errorf(codes.Unimplemented, "method Rollback not implemented")
}
@@ -2748,6 +2789,27 @@ func _ApplicationService_ResourceTree_Handler(srv interface{}, ctx context.Conte
return interceptor(ctx, in, info, handler)
}
func _ApplicationService_WatchResourceTree_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(ResourcesQuery)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(ApplicationServiceServer).WatchResourceTree(m, &applicationServiceWatchResourceTreeServer{stream})
}
type ApplicationService_WatchResourceTreeServer interface {
Send(*v1alpha1.ApplicationTree) error
grpc.ServerStream
}
type applicationServiceWatchResourceTreeServer struct {
grpc.ServerStream
}
func (x *applicationServiceWatchResourceTreeServer) Send(m *v1alpha1.ApplicationTree) error {
return x.ServerStream.SendMsg(m)
}
func _ApplicationService_Rollback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ApplicationRollbackRequest)
if err := dec(in); err != nil {
@@ -2990,6 +3052,11 @@ var _ApplicationService_serviceDesc = grpc.ServiceDesc{
Handler: _ApplicationService_Watch_Handler,
ServerStreams: true,
},
{
StreamName: "WatchResourceTree",
Handler: _ApplicationService_WatchResourceTree_Handler,
ServerStreams: true,
},
{
StreamName: "PodLogs",
Handler: _ApplicationService_PodLogs_Handler,

View File

@@ -559,6 +559,52 @@ func request_ApplicationService_ResourceTree_0(ctx context.Context, marshaler ru
}
var (
filter_ApplicationService_WatchResourceTree_0 = &utilities.DoubleArray{Encoding: map[string]int{"applicationName": 0}, Base: []int{1, 1, 0}, Check: []int{0, 1, 2}}
)
func request_ApplicationService_WatchResourceTree_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (ApplicationService_WatchResourceTreeClient, runtime.ServerMetadata, error) {
var protoReq ResourcesQuery
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["applicationName"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "applicationName")
}
protoReq.ApplicationName, err = runtime.StringP(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "applicationName", err)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ApplicationService_WatchResourceTree_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
stream, err := client.WatchResourceTree(ctx, &protoReq)
if err != nil {
return nil, metadata, err
}
header, err := stream.Header()
if err != nil {
return nil, metadata, err
}
metadata.HeaderMD = header
return stream, metadata, nil
}
func request_ApplicationService_Rollback_0(ctx context.Context, marshaler runtime.Marshaler, client ApplicationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ApplicationRollbackRequest
var metadata runtime.ServerMetadata
@@ -1222,6 +1268,26 @@ func RegisterApplicationServiceHandlerClient(ctx context.Context, mux *runtime.S
})
mux.Handle("GET", pattern_ApplicationService_WatchResourceTree_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
rctx, err := runtime.AnnotateContext(ctx, mux, req)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_ApplicationService_WatchResourceTree_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_ApplicationService_WatchResourceTree_0(ctx, mux, outboundMarshaler, w, req, func() (proto.Message, error) { return resp.Recv() }, mux.GetForwardResponseOptions()...)
})
mux.Handle("POST", pattern_ApplicationService_Rollback_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
@@ -1416,6 +1482,8 @@ var (
pattern_ApplicationService_ResourceTree_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", "applicationName", "resource-tree"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_ApplicationService_WatchResourceTree_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3, 1, 0, 4, 1, 5, 4, 2, 5}, []string{"api", "v1", "stream", "applications", "applicationName", "resource-tree"}, "", runtime.AssumeColonVerbOpt(true)))
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"}, "", runtime.AssumeColonVerbOpt(true)))
pattern_ApplicationService_TerminateOperation_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", "operation"}, "", runtime.AssumeColonVerbOpt(true)))
@@ -1464,6 +1532,8 @@ var (
forward_ApplicationService_ResourceTree_0 = runtime.ForwardResponseMessage
forward_ApplicationService_WatchResourceTree_0 = runtime.ForwardResponseStream
forward_ApplicationService_Rollback_0 = runtime.ForwardResponseMessage
forward_ApplicationService_TerminateOperation_0 = runtime.ForwardResponseMessage

View File

@@ -11,6 +11,7 @@ import (
func init() {
forward_ApplicationService_PodLogs_0 = http.StreamForwarder
forward_ApplicationService_WatchResourceTree_0 = http.StreamForwarder
forward_ApplicationService_Watch_0 = http.NewStreamForwarder(func(message proto.Message) (string, error) {
event, ok := message.(*v1alpha1.ApplicationWatchEvent)
if !ok {

View File

@@ -0,0 +1,9 @@
package project
import (
"github.com/argoproj/pkg/grpc/http"
)
func init() {
forward_ProjectService_List_0 = http.UnaryForwarder
}

View File

@@ -283,6 +283,7 @@ message ApplicationStatus {
optional OperationState operationState = 7;
// ObservedAt indicates when the application state was updated without querying latest git state
// Deprecated: controller no longer updates ObservedAt field
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time observedAt = 8;
optional string sourceType = 9;

View File

@@ -1058,7 +1058,7 @@ func schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref common.Reference
},
"observedAt": {
SchemaProps: spec.SchemaProps{
Description: "ObservedAt indicates when the application state was updated without querying latest git state",
Description: "ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},

View File

@@ -425,6 +425,7 @@ type ApplicationStatus struct {
ReconciledAt *metav1.Time `json:"reconciledAt,omitempty" protobuf:"bytes,6,opt,name=reconciledAt"`
OperationState *OperationState `json:"operationState,omitempty" protobuf:"bytes,7,opt,name=operationState"`
// ObservedAt indicates when the application state was updated without querying latest git state
// Deprecated: controller no longer updates ObservedAt field
ObservedAt *metav1.Time `json:"observedAt,omitempty" protobuf:"bytes,8,opt,name=observedAt"`
SourceType ApplicationSourceType `json:"sourceType,omitempty" protobuf:"bytes,9,opt,name=sourceType"`
Summary ApplicationSummary `json:"summary,omitempty" protobuf:"bytes,10,opt,name=summary"`
@@ -2603,7 +2604,7 @@ func jwtTokensCombine(tokens1 []JWTToken, tokens2 []JWTToken) []JWTToken {
tokensMap[token.ID] = token
}
tokens := []JWTToken{}
var tokens []JWTToken
for _, v := range tokensMap {
tokens = append(tokens, v)
}

View File

@@ -1695,6 +1695,11 @@ func TestProjectNormalize(t *testing.T) {
assert.Nil(t, p.Spec.Roles)
assert.Nil(t, p.Status.JWTTokensByRole)
})
t.Run("HasRoles_NoTokens", func(t *testing.T) {
p := AppProject{Spec: AppProjectSpec{Roles: []ProjectRole{{Name: "test-role"}}}}
needNormalize := p.NormalizeJWTTokens()
assert.False(t, needNormalize)
})
t.Run("SpecRolesToken-StatusRolesTokenEmpty", func(t *testing.T) {
p := AppProject{Spec: AppProjectSpec{Roles: []ProjectRole{{Name: "test-role", JWTTokens: testTokens}}}}
needNormalize := p.NormalizeJWTTokens()

View File

@@ -572,14 +572,7 @@ func findManifests(appPath string, repoRoot string, env *v1alpha1.Env, directory
} else {
yamlObjs, err := kube.SplitYAML(out)
if err != nil {
if len(yamlObjs) > 0 {
// If we get here, we had a multiple objects in a single YAML file which had some
// valid k8s objects, but errors parsing others (within the same file). It's very
// likely the user messed up a portion of the YAML, so report on that.
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", f.Name(), err)
}
// Otherwise, it might be a unrelated YAML file which we will ignore
return nil
return status.Errorf(codes.FailedPrecondition, "Failed to unmarshal %q: %v", f.Name(), err)
}
objs = append(objs, yamlObjs...)
}

View File

@@ -16,6 +16,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/cli"
"github.com/argoproj/argo-cd/util/lua"
)
@@ -98,7 +99,7 @@ func TestLuaResourceActionsScript(t *testing.T) {
assert.NoError(t, err)
if diffResult.Modified {
t.Error("Output does not match input:")
err = diff.PrintDiff(test.Action, expectedObj, result)
err = cli.PrintDiff(test.Action, expectedObj, result)
assert.NoError(t, err)
}
})

View File

@@ -35,6 +35,7 @@ import (
"k8s.io/client-go/tools/cache"
"k8s.io/utils/pointer"
argocommon "github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apiclient/application"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -61,6 +62,7 @@ type Server struct {
kubeclientset kubernetes.Interface
appclientset appclientset.Interface
appLister applisters.ApplicationNamespaceLister
appInformer cache.SharedIndexInformer
appBroadcaster *broadcasterHandler
repoClientset apiclient.Clientset
kubectl kube.Kubectl
@@ -93,6 +95,7 @@ func NewServer(
ns: namespace,
appclientset: appclientset,
appLister: appLister,
appInformer: appInformer,
appBroadcaster: appBroadcaster,
kubeclientset: kubeclientset,
cache: cache,
@@ -132,6 +135,9 @@ func (s *Server) List(ctx context.Context, q *application.ApplicationQuery) (*ap
return newItems[i].Name < newItems[j].Name
})
appList := appv1.ApplicationList{
ListMeta: metav1.ListMeta{
ResourceVersion: s.appInformer.LastSyncResourceVersion(),
},
Items: newItems,
}
return &appList, nil
@@ -301,22 +307,49 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, appRBACName(*a)); err != nil {
return nil, err
}
if q.Refresh != nil {
refreshType := appv1.RefreshTypeNormal
if *q.Refresh == string(appv1.RefreshTypeHard) {
refreshType = appv1.RefreshTypeHard
}
appIf := s.appclientset.ArgoprojV1alpha1().Applications(s.ns)
_, err = argoutil.RefreshApp(appIf, *q.Name, refreshType)
if err != nil {
return nil, err
}
a, err = argoutil.WaitForRefresh(ctx, appIf, *q.Name, nil)
if err != nil {
return nil, err
if q.Refresh == nil {
return a, nil
}
refreshType := appv1.RefreshTypeNormal
if *q.Refresh == string(appv1.RefreshTypeHard) {
refreshType = appv1.RefreshTypeHard
}
appIf := s.appclientset.ArgoprojV1alpha1().Applications(s.ns)
// subscribe early with buffered channel to ensure we don't miss events
events := make(chan *appv1.ApplicationWatchEvent, 100)
unsubscribe := s.appBroadcaster.Subscribe(events, func(event *appv1.ApplicationWatchEvent) bool {
return event.Application.Name == q.GetName()
})
defer unsubscribe()
app, err := argoutil.RefreshApp(appIf, *q.Name, refreshType)
if err != nil {
return nil, err
}
minVersion := 0
if minVersion, err = strconv.Atoi(app.ResourceVersion); err != nil {
minVersion = 0
}
for {
select {
case <-ctx.Done():
return nil, fmt.Errorf("application refresh deadline exceeded")
case event := <-events:
if appVersion, err := strconv.Atoi(event.Application.ResourceVersion); err == nil && appVersion > minVersion {
annotations := event.Application.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string)
}
if _, ok := annotations[argocommon.AnnotationKeyRefresh]; !ok {
return &event.Application, nil
}
}
}
}
return a, nil
}
// ListResourceEvents returns a list of event resources
@@ -636,12 +669,15 @@ func (s *Server) Watch(q *application.ApplicationQuery, ws application.Applicati
}
events := make(chan *appv1.ApplicationWatchEvent)
apps, err := s.appLister.List(selector)
if err != nil {
return err
}
for i := range apps {
sendIfPermitted(*apps[i], watch.Added)
if q.ResourceVersion == "" {
// mimic watch API behavior: send ADDED events if no resource version provided
apps, err := s.appLister.List(selector)
if err != nil {
return err
}
for i := range apps {
sendIfPermitted(*apps[i], watch.Added)
}
}
unsubscribe := s.appBroadcaster.Subscribe(events)
defer unsubscribe()
@@ -901,6 +937,26 @@ func (s *Server) ResourceTree(ctx context.Context, q *application.ResourcesQuery
return s.getAppResources(ctx, a)
}
func (s *Server) WatchResourceTree(q *application.ResourcesQuery, ws application.ApplicationService_WatchResourceTreeServer) error {
a, err := s.appLister.Get(q.GetApplicationName())
if err != nil {
return err
}
if err := s.enf.EnforceErr(ws.Context().Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, appRBACName(*a)); err != nil {
return err
}
return s.cache.OnAppResourcesTreeChanged(ws.Context(), q.GetApplicationName(), func() error {
var tree appv1.ApplicationTree
err := s.cache.GetAppResourcesTree(q.GetApplicationName(), &tree)
if err != nil {
return err
}
return ws.Send(&tree)
})
}
func (s *Server) RevisionMetadata(ctx context.Context, q *application.RevisionMetadataQuery) (*v1alpha1.RevisionMetadata, error) {
a, err := s.appLister.Get(q.GetName())
if err != nil {

View File

@@ -294,6 +294,12 @@ service ApplicationService {
rpc ResourceTree(ResourcesQuery) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationTree) {
option (google.api.http).get = "/api/v1/applications/{applicationName}/resource-tree";
}
// Watch returns stream of application resource tree
rpc WatchResourceTree(ResourcesQuery) returns (stream github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationTree) {
option (google.api.http).get = "/api/v1/stream/applications/{applicationName}/resource-tree";
}
// Rollback syncs an application to its target state
rpc Rollback(ApplicationRollbackRequest) returns (github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Application) {
option (google.api.http) = {

View File

@@ -558,6 +558,7 @@ func TestServer_GetApplicationSyncWindowsState(t *testing.T) {
func TestGetCachedAppState(t *testing.T) {
testApp := newTestApp()
testApp.ObjectMeta.ResourceVersion = "1"
testApp.Spec.Project = "none"
appServer := newTestAppServer(testApp)
@@ -579,12 +580,15 @@ func TestGetCachedAppState(t *testing.T) {
fakeClientSet.WatchReactionChain = nil
fakeClientSet.AddReactor("patch", "applications", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
patched = true
watcher.Modify(testApp)
return true, nil, nil
updated := testApp.DeepCopy()
updated.ResourceVersion = "2"
appServer.appBroadcaster.OnUpdate(testApp, updated)
return true, testApp, nil
})
fakeClientSet.AddWatchReactor("applications", func(action kubetesting.Action) (handled bool, ret watch.Interface, err error) {
return true, watcher, nil
})
err := appServer.getCachedAppState(context.Background(), testApp, func() error {
res := cache.ErrCacheMiss
if retryCount == 1 {

View File

@@ -3,26 +3,49 @@ package application
import (
"sync"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/watch"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
)
type subscriber struct {
ch chan *appv1.ApplicationWatchEvent
filters []func(*appv1.ApplicationWatchEvent) bool
}
func (s *subscriber) matches(event *appv1.ApplicationWatchEvent) bool {
for i := range s.filters {
if !s.filters[i](event) {
return false
}
}
return true
}
type broadcasterHandler struct {
lock sync.Mutex
subscribers []chan *appv1.ApplicationWatchEvent
subscribers []*subscriber
}
func (b *broadcasterHandler) notify(event *appv1.ApplicationWatchEvent) {
subscribers := b.subscribers
for i := range subscribers {
subscribers[i] <- event
for _, s := range subscribers {
if s.matches(event) {
select {
case s.ch <- event:
default:
// drop event if cannot send right away
log.WithField("application", event.Application.Name).Warn("unable to send event notification")
}
}
}
}
func (b *broadcasterHandler) Subscribe(subscriber chan *appv1.ApplicationWatchEvent) func() {
func (b *broadcasterHandler) Subscribe(ch chan *appv1.ApplicationWatchEvent, filters ...func(event *appv1.ApplicationWatchEvent) bool) func() {
b.lock.Lock()
defer b.lock.Unlock()
subscriber := &subscriber{ch, filters}
b.subscribers = append(b.subscribers, subscriber)
return func() {
b.lock.Lock()

View File

@@ -15,7 +15,7 @@ func TestBroadcasterHandler_SubscribeUnsubscribe(t *testing.T) {
subscriber := make(chan *appv1.ApplicationWatchEvent)
unsubscribe := broadcaster.Subscribe(subscriber)
assert.ElementsMatch(t, broadcaster.subscribers, []chan *appv1.ApplicationWatchEvent{subscriber})
assert.Len(t, broadcaster.subscribers, 1)
unsubscribe()
assert.Empty(t, broadcaster.subscribers)
@@ -24,8 +24,8 @@ func TestBroadcasterHandler_SubscribeUnsubscribe(t *testing.T) {
func TestBroadcasterHandler_ReceiveEvents(t *testing.T) {
broadcaster := broadcasterHandler{}
subscriber1 := make(chan *appv1.ApplicationWatchEvent)
subscriber2 := make(chan *appv1.ApplicationWatchEvent)
subscriber1 := make(chan *appv1.ApplicationWatchEvent, 1000)
subscriber2 := make(chan *appv1.ApplicationWatchEvent, 1000)
_ = broadcaster.Subscribe(subscriber1)
_ = broadcaster.Subscribe(subscriber2)

View File

@@ -1,6 +1,7 @@
package cache
import (
"context"
"fmt"
"time"
@@ -57,6 +58,10 @@ func (c *Cache) GetAppResourcesTree(appName string, res *appv1.ApplicationTree)
return c.cache.GetAppResourcesTree(appName, res)
}
func (c *Cache) OnAppResourcesTreeChanged(ctx context.Context, appName string, callback func() error) error {
return c.cache.OnAppResourcesTreeChanged(ctx, appName, callback)
}
func (c *Cache) GetAppManagedResources(appName string, res *[]*appv1.ResourceDiff) error {
return c.cache.GetAppManagedResources(appName, res)
}

View File

@@ -412,7 +412,6 @@ func (s *Server) NormalizeProjs() error {
return status.Errorf(codes.Internal, "Error retrieving project list: %s", err.Error())
}
for _, proj := range projList.Items {
// if !apierr.IsConflict(err), retry 3 times
for i := 0; i < 3; i++ {
if proj.NormalizeJWTTokens() {
_, err := s.appclientset.ArgoprojV1alpha1().AppProjects(s.ns).Update(context.Background(), &proj, metav1.UpdateOptions{})
@@ -432,6 +431,8 @@ func (s *Server) NormalizeProjs() error {
if i == 2 {
return status.Errorf(codes.Internal, "Failed normalize project %s", proj.Name)
}
} else {
break
}
}
}

View File

@@ -22,6 +22,7 @@ import (
jwt "github.com/dgrijalva/jwt-go"
"github.com/go-redis/redis"
golang_proto "github.com/golang/protobuf/proto"
"github.com/gorilla/handlers"
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"
@@ -45,11 +46,6 @@ import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/cache"
cacheutil "github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/healthz"
"github.com/argoproj/argo-cd/util/swagger"
"github.com/argoproj/argo-cd/util/webhook"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apiclient"
accountpkg "github.com/argoproj/argo-cd/pkg/apiclient/account"
@@ -85,18 +81,22 @@ import (
"github.com/argoproj/argo-cd/server/version"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/assets"
cacheutil "github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/dex"
dexutil "github.com/argoproj/argo-cd/util/dex"
"github.com/argoproj/argo-cd/util/env"
grpc_util "github.com/argoproj/argo-cd/util/grpc"
"github.com/argoproj/argo-cd/util/healthz"
httputil "github.com/argoproj/argo-cd/util/http"
"github.com/argoproj/argo-cd/util/jwt/zjwt"
"github.com/argoproj/argo-cd/util/oidc"
"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"
"github.com/argoproj/argo-cd/util/swagger"
tlsutil "github.com/argoproj/argo-cd/util/tls"
"github.com/argoproj/argo-cd/util/webhook"
)
const maxConcurrentLoginRequestsCountEnv = "ARGOCD_MAX_CONCURRENT_LOGIN_REQUESTS_COUNT"
@@ -159,6 +159,7 @@ type ArgoCDServer struct {
type ArgoCDServerOpts struct {
DisableAuth bool
EnableGZip bool
Insecure bool
ListenPort int
MetricsPort int
@@ -520,7 +521,19 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
}
sessionService := session.NewServer(a.sessionMgr, a, a.policyEnforcer, loginRateLimiter)
projectLock := util.NewKeyLock()
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.appLister, a.appInformer, a.RepoClientset, a.Cache, kubectl, db, a.enf, projectLock, a.settingsMgr)
applicationService := application.NewServer(
a.Namespace,
a.KubeClientset,
a.AppClientset,
a.appLister,
a.appInformer,
a.RepoClientset,
a.Cache,
kubectl,
db,
a.enf,
projectLock,
a.settingsMgr)
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr, a.policyEnforcer)
settingsService := settings.NewServer(a.settingsMgr, a, a.DisableAuth)
accountService := account.NewServer(a.sessionMgr, a.settingsMgr, a.enf)
@@ -577,13 +590,23 @@ func withRootPath(handler http.Handler, a *ArgoCDServer) http.Handler {
mux.Handle("/"+root+"/", http.StripPrefix("/"+root, handler))
healthz.ServeHealthCheck(mux, func() error {
_, err := a.KubeClientset.(*kubernetes.Clientset).ServerVersion()
return err
return nil
})
return mux
}
func compressHandler(handler http.Handler) http.Handler {
compr := handlers.CompressHandler(handler)
return http.HandlerFunc(func(writer http.ResponseWriter, request *http.Request) {
if request.Header.Get("Accept") == "text/event-stream" {
handler.ServeHTTP(writer, request)
} else {
compr.ServeHTTP(writer, request)
}
})
}
// newHTTPServer returns the HTTP server to serve HTTP/HTTPS requests. This is implemented
// using grpc-gateway as a proxy to the gRPC server.
func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandler http.Handler) *http.Server {
@@ -629,7 +652,13 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
gwMuxOpts := runtime.WithMarshalerOption(runtime.MIMEWildcard, new(grpc_util.JSONMarshaler))
gwCookieOpts := runtime.WithForwardResponseOption(a.translateGrpcCookieHeader)
gwmux := runtime.NewServeMux(gwMuxOpts, gwCookieOpts)
mux.Handle("/api/", gwmux)
var handler http.Handler = gwmux
if a.EnableGZip {
handler = compressHandler(handler)
}
mux.Handle("/api/", handler)
mustRegisterGWHandler(versionpkg.RegisterVersionServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
mustRegisterGWHandler(clusterpkg.RegisterClusterServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
mustRegisterGWHandler(applicationpkg.RegisterApplicationServiceHandlerFromEndpoint, ctx, gwmux, endpoint, dOpts)
@@ -645,8 +674,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
// Swagger UI
swagger.ServeSwaggerUI(mux, assets.SwaggerJSON, "/swagger-ui", a.RootPath)
healthz.ServeHealthCheck(mux, func() error {
_, err := a.KubeClientset.(*kubernetes.Clientset).ServerVersion()
return err
return nil
})
// Dex reverse proxy and client app and OAuth2 login/callback

View File

@@ -1383,3 +1383,24 @@ func TestCreateDisableValidation(t *testing.T) {
AppSet("--path", "baddir3", "--validate=false")
}
func TestCreateFromPartialFile(t *testing.T) {
partialApp :=
`spec:
syncPolicy:
automated: {prune: true }`
path := "helm-values"
Given(t).
When().
// app should be auto-synced once created
CreateFromPartialFile(partialApp, "--path", path, "--helm-set", "foo=foo").
Then().
Expect(Success("")).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(NoConditions()).
And(func(app *Application) {
assert.Equal(t, path, app.Spec.Source.Path)
assert.Equal(t, []HelmParameter{{Name: "foo", Value: "foo"}}, app.Spec.Source.Helm.Parameters)
})
}

View File

@@ -58,7 +58,26 @@ func (a *Actions) AddSignedFile(fileName, fileContents string) *Actions {
return a
}
func (a *Actions) CreateFromFile(handler func(app *Application)) *Actions {
func (a *Actions) CreateFromPartialFile(data string, flags ...string) *Actions {
a.context.t.Helper()
tmpFile, err := ioutil.TempFile("", "")
errors.CheckError(err)
_, err = tmpFile.Write([]byte(data))
errors.CheckError(err)
args := append([]string{
"app", "create",
"-f", tmpFile.Name(),
"--name", a.context.name,
"--repo", fixture.RepoURL(a.context.repoURLType),
"--dest-server", a.context.destServer,
"--dest-namespace", fixture.DeploymentNamespace(),
}, flags...)
a.runCli(args...)
return a
}
func (a *Actions) CreateFromFile(handler func(app *Application), flags ...string) *Actions {
a.context.t.Helper()
app := &Application{
ObjectMeta: v1.ObjectMeta{
@@ -108,7 +127,12 @@ func (a *Actions) CreateFromFile(handler func(app *Application)) *Actions {
_, err = tmpFile.Write(data)
errors.CheckError(err)
a.runCli("app", "create", "-f", tmpFile.Name())
args := append([]string{
"app", "create",
"-f", tmpFile.Name(),
}, flags...)
a.runCli(args...)
return a
}

View File

@@ -56,7 +56,7 @@ const AutoSyncFormField = ReactFormField((props: {fieldApi: FieldApi; className:
value={automated ? auto : manual}
options={[manual, auto]}
onChange={opt => {
setValue(opt.value === auto ? {automated: {prune: false, selfHeal: false}} : null);
setValue(opt.value === auto ? {prune: false, selfHeal: false} : null);
}}
/>
{automated && (
@@ -120,7 +120,7 @@ export const ApplicationCreatePanel = (props: {
key='creation-deps'
load={() =>
Promise.all([
services.projects.list().then(projects => projects.map(proj => proj.metadata.name).sort()),
services.projects.list('items.metadata.name').then(projects => projects.map(proj => proj.metadata.name).sort()),
services.clusters.list().then(clusters => clusters.sort()),
services.repos.list()
]).then(([projects, clusters, reposInfo]) => ({projects, clusters, reposInfo}))

View File

@@ -38,7 +38,7 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{nam
apis: PropTypes.object
};
private refreshRequested = new BehaviorSubject(null);
private appChanged = new BehaviorSubject<appModels.Application>(null);
constructor(props: RouteComponentProps<{name: string}>) {
super(props);
@@ -459,7 +459,13 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{nam
</React.Fragment>
),
disabled: !!refreshing,
action: () => !refreshing && services.applications.get(app.metadata.name, 'normal')
action: () => {
if (!refreshing) {
services.applications.get(app.metadata.name, 'normal');
AppUtils.setAppRefreshing(app);
this.appChanged.next(app);
}
}
}
];
}
@@ -475,42 +481,43 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{nam
}
private loadAppInfo(name: string): Observable<{application: appModels.Application; tree: appModels.ApplicationTree}> {
return Observable.merge(
Observable.fromPromise(services.applications.get(name).then(app => ({app, watchEvent: false}))),
services.applications
.watch({name})
.map(watchEvent => {
if (watchEvent.type === 'DELETED') {
this.onAppDeleted();
}
return {app: watchEvent.application, watchEvent: true};
})
.repeat()
.retryWhen(errors => errors.delay(500)),
this.refreshRequested.filter(e => e !== null).flatMap(() => services.applications.get(name).then(app => ({app, watchEvent: true})))
).flatMap(appInfo => {
const app = appInfo.app;
const fallbackTree: appModels.ApplicationTree = {
nodes: app.status.resources.map(res => ({...res, parentRefs: [], info: [], resourceVersion: '', uid: ''})),
orphanedNodes: []
};
const treeSource = new Observable<{application: appModels.Application; tree: appModels.ApplicationTree}>(observer => {
services.applications
.resourceTree(app.metadata.name)
.then(tree => observer.next({application: app, tree}))
.catch(e => {
observer.next({application: app, tree: fallbackTree});
observer.error(e);
});
return Observable.fromPromise(services.applications.get(name))
.flatMap(app => {
const fallbackTree = {
nodes: app.status.resources.map(res => ({...res, parentRefs: [], info: [], resourceVersion: '', uid: ''})),
orphanedNodes: []
} as appModels.ApplicationTree;
return Observable.combineLatest(
Observable.merge(
Observable.from([app]),
this.appChanged.filter(item => !!item),
AppUtils.handlePageVisibility(() =>
services.applications
.watch({name})
.map(watchEvent => {
if (watchEvent.type === 'DELETED') {
this.onAppDeleted();
}
return watchEvent.application;
})
.repeat()
.retryWhen(errors => errors.delay(500))
)
),
Observable.merge(
Observable.from([fallbackTree]),
services.applications.resourceTree(name).catch(() => fallbackTree),
AppUtils.handlePageVisibility(() =>
services.applications
.watchResourceTree(name)
.repeat()
.retryWhen(errors => errors.delay(500))
)
)
);
})
.repeat()
.retryWhen(errors => errors.delay(1000));
if (appInfo.watchEvent) {
return treeSource;
} else {
return Observable.merge(Observable.from([{application: app, tree: fallbackTree}]), treeSource);
}
});
.filter(([application, tree]) => !!application && !!tree)
.map(([application, tree]) => ({application, tree}));
}
private onAppDeleted() {
@@ -523,8 +530,8 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{nam
latestApp.metadata.labels = app.metadata.labels;
latestApp.metadata.annotations = app.metadata.annotations;
latestApp.spec = app.spec;
await services.applications.update(latestApp);
this.refreshRequested.next({});
const updatedApp = await services.applications.update(latestApp);
this.appChanged.next(updatedApp);
}
private groupAppNodesByKey(application: appModels.Application, tree: appModels.ApplicationTree) {
@@ -593,7 +600,7 @@ Are you sure you want to disable auto-sync and rollback application '${this.prop
await services.applications.update(update);
}
await services.applications.rollback(this.props.match.params.name, revisionHistory.id);
this.refreshRequested.next({});
this.appChanged.next(await services.applications.get(this.props.match.params.name));
this.setRollbackPanelVisible(-1);
}
} catch (e) {
@@ -641,7 +648,7 @@ Are you sure you want to disable auto-sync and rollback application '${this.prop
submit: async (vals, _, close) => {
try {
await services.applications.deleteResource(this.props.match.params.name, resource, !!vals.force);
this.refreshRequested.next({});
this.appChanged.next(await services.applications.get(this.props.match.params.name));
close();
} catch (e) {
this.appContext.apis.notifications.show({

View File

@@ -2,7 +2,7 @@ import {AutocompleteField, DropDownMenu, FormField, FormSelect, HelpIcon, PopupA
import * as React from 'react';
import {FormApi, Text} from 'react-form';
import {Cluster, DataLoader, EditablePanel, EditablePanelItem, Expandable, MapInputField, Repo, Revision, RevisionHelpIcon} from '../../../shared/components';
import {Consumer} from '../../../shared/context';
import {Consumer, Context} from '../../../shared/context';
import * as models from '../../../shared/models';
import {services} from '../../../shared/services';
@@ -35,7 +35,7 @@ export const ApplicationSummary = (props: {app: models.Application; updateApp: (
title: 'PROJECT',
view: <a href={'/settings/projects/' + app.spec.project}>{app.spec.project}</a>,
edit: (formApi: FormApi) => (
<DataLoader load={() => services.projects.list().then(projs => projs.map(item => item.metadata.name))}>
<DataLoader load={() => services.projects.list('items.metadata.name').then(projs => projs.map(item => item.metadata.name))}>
{projects => <FormField formApi={formApi} field='spec.project' component={FormSelect} componentProps={{options: projects}} />}
</DataLoader>
)
@@ -369,8 +369,9 @@ export const ApplicationSummary = (props: {app: models.Application; updateApp: (
edit: null
});
const [badgeType, setBadgeType] = React.useState('URL');
const badgeURL = `${location.protocol}//${location.host}/api/badge?name=${props.app.metadata.name}&revision=true`;
const appURL = `${location.protocol}//${location.host}/applications/${props.app.metadata.name}`;
const context = React.useContext(Context);
const badgeURL = `${location.protocol}//${location.host}${context.baseHref}api/badge?name=${props.app.metadata.name}&revision=true`;
const appURL = `${location.protocol}//${location.host}${context.baseHref}applications/${props.app.metadata.name}`;
return (
<div className='application-summary'>

View File

@@ -146,7 +146,7 @@ export class ApplicationsFilter extends React.Component<ApplicationsFilterProps,
<p>Projects</p>
<ul>
<li>
<DataLoader load={() => services.projects.list()}>
<DataLoader load={() => services.projects.list('items.metadata.name')}>
{projects => {
const projAppCount = new Map<string, number>();
projects.forEach(proj => projAppCount.set(proj.metadata.name, 0));
@@ -168,9 +168,9 @@ export class ApplicationsFilter extends React.Component<ApplicationsFilterProps,
<li>
<TagsInput
placeholder='https://kubernetes.default.svc'
autocomplete={Array.from(new Set(applications.map(app => app.spec.destination.server).filter(item => !!item))).filter(
ns => pref.clustersFilter.indexOf(ns) === -1
)}
autocomplete={Array.from(
new Set(applications.map(app => app.spec.destination.server || app.spec.destination.name).filter(item => !!item))
).filter(ns => pref.clustersFilter.indexOf(ns) === -1)}
tags={pref.clustersFilter}
onChange={selected => onChange({...pref, clustersFilter: selected})}
/>

View File

@@ -21,6 +21,8 @@ import {ApplicationTiles} from './applications-tiles';
require('./applications-list.scss');
const EVENTS_BUFFER_TIMEOUT = 500;
const WATCH_RETRY_TIMEOUT = 500;
const APP_FIELDS = [
'metadata.name',
'metadata.annotations',
@@ -35,37 +37,44 @@ const APP_FIELDS = [
'status.operationState.operation.sync',
'status.summary'
];
const APP_LIST_FIELDS = APP_FIELDS.map(field => `items.${field}`);
const APP_LIST_FIELDS = ['metadata.resourceVersion', ...APP_FIELDS.map(field => `items.${field}`)];
const APP_WATCH_FIELDS = ['result.type', ...APP_FIELDS.map(field => `result.application.${field}`)];
function loadApplications(): Observable<models.Application[]> {
return Observable.fromPromise(services.applications.list([], {fields: APP_LIST_FIELDS})).flatMap(applications =>
Observable.merge(
return Observable.fromPromise(services.applications.list([], {fields: APP_LIST_FIELDS})).flatMap(applicationsList => {
const applications = applicationsList.items;
return Observable.merge(
Observable.from([applications]),
services.applications
.watch(null, {fields: APP_WATCH_FIELDS})
.map(appChange => {
const index = applications.findIndex(item => item.metadata.name === appChange.application.metadata.name);
switch (appChange.type) {
case 'DELETED':
if (index > -1) {
applications.splice(index, 1);
}
break;
default:
if (index > -1) {
applications[index] = appChange.application;
} else {
applications.unshift(appChange.application);
}
break;
}
return {applications, updated: true};
.watch({resourceVersion: applicationsList.metadata.resourceVersion}, {fields: APP_WATCH_FIELDS})
.repeat()
.retryWhen(errors => errors.delay(WATCH_RETRY_TIMEOUT))
// batch events to avoid constant re-rendering and improve UI performance
.bufferTime(EVENTS_BUFFER_TIMEOUT)
.map(appChanges => {
appChanges.forEach(appChange => {
const index = applications.findIndex(item => item.metadata.name === appChange.application.metadata.name);
switch (appChange.type) {
case 'DELETED':
if (index > -1) {
applications.splice(index, 1);
}
break;
default:
if (index > -1) {
applications[index] = appChange.application;
} else {
applications.unshift(appChange.application);
}
break;
}
});
return {applications, updated: appChanges.length > 0};
})
.filter(item => item.updated)
.map(item => item.applications)
)
);
);
});
}
const ViewPref = ({children}: {children: (pref: AppsListPreferences & {page: number; search: string}) => React.ReactNode}) => (
@@ -134,7 +143,7 @@ function filterApps(applications: models.Application[], pref: AppsListPreference
(pref.syncFilter.length === 0 || pref.syncFilter.includes(app.status.sync.status)) &&
(pref.healthFilter.length === 0 || pref.healthFilter.includes(app.status.health.status)) &&
(pref.namespacesFilter.length === 0 || pref.namespacesFilter.some(ns => minimatch(app.spec.destination.namespace, ns))) &&
(pref.clustersFilter.length === 0 || pref.clustersFilter.some(server => minimatch(app.spec.destination.server, server))) &&
(pref.clustersFilter.length === 0 || pref.clustersFilter.some(server => minimatch(app.spec.destination.server || app.spec.destination.name, server))) &&
(pref.labelsFilter.length === 0 || pref.labelsFilter.every(selector => LabelSelector.match(selector, app.metadata.labels)))
);
}
@@ -155,6 +164,21 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
const clusters = React.useMemo(() => services.clusters.list(), []);
const [isAppCreatePending, setAppCreatePending] = React.useState(false);
const loaderRef = React.useRef<DataLoader>();
function refreshApp(appName: string) {
// app refreshing might be done too quickly so that UI might miss it due to event batching
// add refreshing annotation in the UI to improve user experience
if (loaderRef.current) {
const applications = loaderRef.current.getData() as models.Application[];
const app = applications.find(item => item.metadata.name === appName);
if (app) {
AppUtils.setAppRefreshing(app);
loaderRef.current.setData(applications);
}
}
services.applications.get(appName, 'normal');
}
return (
<ClusterCtx.Provider value={clusters}>
<Consumer>
@@ -209,7 +233,8 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
<ViewPref>
{pref => (
<DataLoader
load={() => loadApplications()}
ref={loaderRef}
load={() => AppUtils.handlePageVisibility(() => loadApplications())}
loadingRenderer={() => (
<div className='argo-container'>
<MockupList height={100} marginTop={30} />
@@ -305,14 +330,14 @@ export const ApplicationsList = (props: RouteComponentProps<{}>) => {
<ApplicationTiles
applications={data}
syncApplication={appName => ctx.navigation.goto('.', {syncApp: appName})}
refreshApplication={appName => services.applications.get(appName, 'normal')}
refreshApplication={refreshApp}
deleteApplication={appName => AppUtils.deleteApplication(appName, ctx)}
/>
)) || (
<ApplicationsTable
applications={data}
syncApplication={appName => ctx.navigation.goto('.', {syncApp: appName})}
refreshApplication={appName => services.applications.get(appName, 'normal')}
refreshApplication={refreshApp}
deleteApplication={appName => AppUtils.deleteApplication(appName, ctx)}
/>
)

View File

@@ -1,6 +1,7 @@
import * as React from 'react';
import {Checkbox, NotificationType} from 'argo-ui';
import * as React from 'react';
import {Observable, Observer, Subscription} from 'rxjs';
import {COLORS, ErrorNotification, Revision} from '../../shared/components';
import {ContextApis} from '../../shared/context';
import * as appModels from '../../shared/models';
@@ -413,6 +414,15 @@ export function isAppRefreshing(app: appModels.Application) {
return !!(app.metadata.annotations && app.metadata.annotations[appModels.AnnotationRefreshKey]);
}
export function setAppRefreshing(app: appModels.Application) {
if (!app.metadata.annotations) {
app.metadata.annotations = {};
}
if (!app.metadata.annotations[appModels.AnnotationRefreshKey]) {
app.metadata.annotations[appModels.AnnotationRefreshKey] = 'refreshing';
}
}
export function refreshLinkAttrs(app: appModels.Application) {
return {disabled: isAppRefreshing(app)};
}
@@ -507,3 +517,42 @@ export const ApplicationSyncWindowStatusIcon = ({project, state}: {project: stri
</a>
);
};
/**
* Automatically stops and restarts the given observable when page visibility changes.
*/
export function handlePageVisibility<T>(src: () => Observable<T>): Observable<T> {
return new Observable<T>((observer: Observer<T>) => {
let subscription: Subscription;
const ensureUnsubscribed = () => {
if (subscription) {
subscription.unsubscribe();
subscription = null;
}
};
const start = () => {
ensureUnsubscribed();
subscription = src().subscribe((item: T) => observer.next(item), err => observer.error(err), () => observer.complete());
};
if (!document.hidden) {
start();
}
const visibilityChangeSubscription = Observable.fromEvent(document, 'visibilitychange')
// wait until user stop clicking back and forth to avoid restarting observable too often
.debounceTime(500)
.subscribe(() => {
if (document.hidden && subscription) {
ensureUnsubscribed();
} else if (!document.hidden && !subscription) {
start();
}
});
return () => {
visibilityChangeSubscription.unsubscribe();
ensureUnsubscribed();
};
});
}

View File

@@ -20,7 +20,7 @@ function generatePolicy(project: string, role: string, action?: string, object?:
const actions = ['get', 'create', 'update', 'delete', 'sync', 'override'];
export const ProjectRolePoliciesEdit = (props: ProjectRolePoliciesProps) => (
<DataLoader load={() => services.applications.list([props.projName], {fields: ['items.metadata.name']})}>
<DataLoader load={() => services.applications.list([props.projName], {fields: ['items.metadata.name']}).then(list => list.items)}>
{applications => (
<React.Fragment>
<h4>Policy Rules</h4>

View File

@@ -18,13 +18,14 @@ function optionsToSearch(options?: QueryOptions) {
}
export class ApplicationsService {
public list(projects: string[], options?: QueryOptions): Promise<models.Application[]> {
public list(projects: string[], options?: QueryOptions): Promise<models.ApplicationList> {
return requests
.get('/applications')
.query({project: projects, ...optionsToSearch(options)})
.then(res => res.body as models.ApplicationList)
.then(list => {
return (list.items || []).map(app => this.parseAppFields(app));
list.items = (list.items || []).map(app => this.parseAppFields(app));
return list;
});
}
@@ -54,6 +55,10 @@ export class ApplicationsService {
return requests.get(`/applications/${name}/resource-tree`).then(res => res.body as models.ApplicationTree);
}
public watchResourceTree(name: string): Observable<models.ApplicationTree> {
return requests.loadEventSource(`/stream/applications/${name}/resource-tree`).map(data => JSON.parse(data).result as models.ApplicationTree);
}
public managedResources(name: string, options: {id?: models.ResourceID; fields?: string[]} = {}): Promise<models.ResourceDiff[]> {
return requests
.get(`/applications/${name}/managed-resources`)
@@ -96,7 +101,7 @@ export class ApplicationsService {
return requests
.put(`/applications/${app.metadata.name}`)
.send(app)
.then(res => res.body as models.Application);
.then(res => this.parseAppFields(res.body));
}
public create(app: models.Application): Promise<models.Application> {
@@ -114,10 +119,15 @@ export class ApplicationsService {
.then(() => true);
}
public watch(query?: {name: string}, options?: QueryOptions): Observable<models.ApplicationWatchEvent> {
public watch(query?: {name?: string; resourceVersion?: string}, options?: QueryOptions): Observable<models.ApplicationWatchEvent> {
const search = new URLSearchParams();
if (query) {
search.set('name', query.name);
if (query.name) {
search.set('name', query.name);
}
if (query.resourceVersion) {
search.set('resourceVersion', query.resourceVersion);
}
}
if (options) {
const searchOptions = optionsToSearch(options);

View File

@@ -90,9 +90,10 @@ function paramsToProj(params: ProjectParams) {
}
export class ProjectsService {
public list(): Promise<models.Project[]> {
public list(...fields: string[]): Promise<models.Project[]> {
return requests
.get('/projects')
.query({fields: fields.join(',')})
.then(res => res.body as models.ProjectList)
.then(list => list.items || []);
}

View File

@@ -67,29 +67,26 @@ export default {
return initHandlers(agent.del(`${apiRoot()}${url}`));
},
loadEventSource(url: string, allowAutoRetry = false): Observable<string> {
loadEventSource(url: string): Observable<string> {
return Observable.create((observer: Observer<any>) => {
const eventSource = new EventSource(`${apiRoot()}${url}`);
let opened = false;
eventSource.onopen = msg => {
if (!opened) {
opened = true;
} else if (!allowAutoRetry) {
eventSource.close();
observer.complete();
}
};
let eventSource = new EventSource(`${apiRoot()}${url}`);
eventSource.onmessage = msg => observer.next(msg.data);
eventSource.onerror = e => () => {
if (e.eventPhase === ReadyState.CLOSED || eventSource.readyState === ReadyState.CONNECTING) {
observer.complete();
} else {
observer.error(e);
onError.next(e);
}
observer.error(e);
onError.next(e);
};
// EventSource does not provide easy way to get notification when connection closed.
// check readyState periodically instead.
const interval = setInterval(() => {
if (eventSource && eventSource.readyState === ReadyState.CLOSED) {
observer.complete();
}
}, 500);
return () => {
clearInterval(interval);
eventSource.close();
eventSource = null;
};
});
}

View File

@@ -14,10 +14,8 @@ import (
"google.golang.org/grpc/status"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime/schema"
"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"
@@ -91,38 +89,6 @@ func RefreshApp(appIf v1alpha1.ApplicationInterface, name string, refreshType ar
return nil, err
}
// WaitForRefresh watches an application until its comparison timestamp is after the refresh timestamp
// If refresh timestamp is not present, will use current timestamp at time of call
func WaitForRefresh(ctx context.Context, appIf v1alpha1.ApplicationInterface, name string, timeout *time.Duration) (*argoappv1.Application, error) {
var cancel context.CancelFunc
if timeout != nil {
ctx, cancel = context.WithTimeout(ctx, *timeout)
defer cancel()
}
ch := kube.WatchWithRetry(ctx, func() (i watch.Interface, e error) {
fieldSelector := fields.ParseSelectorOrDie(fmt.Sprintf("metadata.name=%s", name))
listOpts := metav1.ListOptions{FieldSelector: fieldSelector.String()}
return appIf.Watch(ctx, listOpts)
})
for next := range ch {
if next.Error != nil {
return nil, next.Error
}
app, ok := next.Object.(*argoappv1.Application)
if !ok {
return nil, fmt.Errorf("Application event object failed conversion: %v", next)
}
annotations := app.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string)
}
if _, ok := annotations[common.AnnotationKeyRefresh]; !ok {
return app, nil
}
}
return nil, fmt.Errorf("application refresh deadline exceeded")
}
func TestRepoWithKnownType(repo *argoappv1.Repository, isHelm bool) error {
repo = repo.DeepCopy()
if isHelm {

View File

@@ -4,9 +4,7 @@ import (
"context"
"fmt"
"path/filepath"
"strings"
"testing"
"time"
"github.com/argoproj/gitops-engine/pkg/utils/kube/kubetest"
"github.com/stretchr/testify/assert"
@@ -15,8 +13,6 @@ import (
"google.golang.org/grpc/status"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/watch"
testcore "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -65,33 +61,6 @@ func TestGetAppProjectWithNoProjDefined(t *testing.T) {
assert.Equal(t, proj.Name, projName)
}
func TestWaitForRefresh(t *testing.T) {
appClientset := appclientset.NewSimpleClientset()
// Verify timeout
appIf := appClientset.ArgoprojV1alpha1().Applications("default")
oneHundredMs := 100 * time.Millisecond
app, err := WaitForRefresh(context.Background(), appIf, "test-app", &oneHundredMs)
assert.NotNil(t, err)
assert.Nil(t, app)
assert.Contains(t, strings.ToLower(err.Error()), "deadline exceeded")
// Verify success
var testApp argoappv1.Application
testApp.Name = "test-app"
testApp.Namespace = "default"
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(context.Background(), appIf, "test-app", &oneHundredMs)
assert.Nil(t, err)
assert.NotNil(t, app)
}
func TestContainsSyncResource(t *testing.T) {
var (
blankUnstructured unstructured.Unstructured

View File

@@ -1,6 +1,7 @@
package appstate
import (
"context"
"fmt"
"time"
@@ -76,8 +77,16 @@ func (c *Cache) GetAppResourcesTree(appName string, res *appv1.ApplicationTree)
return err
}
func (c *Cache) OnAppResourcesTreeChanged(ctx context.Context, appName string, callback func() error) error {
return c.Cache.OnUpdated(ctx, appManagedResourcesKey(appName), callback)
}
func (c *Cache) SetAppResourcesTree(appName string, resourcesTree *appv1.ApplicationTree) error {
return c.SetItem(appResourcesTreeKey(appName), resourcesTree, c.appStateCacheExpiration, resourcesTree == nil)
err := c.SetItem(appResourcesTreeKey(appName), resourcesTree, c.appStateCacheExpiration, resourcesTree == nil)
if err != nil {
return err
}
return c.Cache.NotifyUpdated(appManagedResourcesKey(appName))
}
func (c *Cache) SetClusterInfo(server string, info *appv1.ClusterInfo) error {

9
util/cache/cache.go vendored
View File

@@ -1,6 +1,7 @@
package cache
import (
"context"
"fmt"
"math"
"os"
@@ -96,3 +97,11 @@ func (c *Cache) GetItem(key string, item interface{}) error {
key = fmt.Sprintf("%s|%s", key, common.CacheVersion)
return c.client.Get(key, item)
}
func (c *Cache) OnUpdated(ctx context.Context, key string, callback func() error) error {
return c.client.OnUpdated(ctx, fmt.Sprintf("%s|%s", key, common.CacheVersion), callback)
}
func (c *Cache) NotifyUpdated(key string) error {
return c.client.NotifyUpdated(fmt.Sprintf("%s|%s", key, common.CacheVersion))
}

View File

@@ -1,6 +1,7 @@
package cache
import (
"context"
"errors"
"time"
)
@@ -18,4 +19,6 @@ type CacheClient interface {
Set(item *Item) error
Get(key string, obj interface{}) error
Delete(key string) error
OnUpdated(ctx context.Context, key string, callback func() error) error
NotifyUpdated(key string) error
}

View File

@@ -2,6 +2,7 @@ package cache
import (
"bytes"
"context"
"encoding/gob"
"time"
@@ -45,3 +46,11 @@ func (i *InMemoryCache) Delete(key string) error {
func (i *InMemoryCache) Flush() {
i.memCache.Flush()
}
func (i *InMemoryCache) OnUpdated(ctx context.Context, key string, callback func() error) error {
return nil
}
func (i *InMemoryCache) NotifyUpdated(key string) error {
return nil
}

25
util/cache/redis.go vendored
View File

@@ -1,8 +1,10 @@
package cache
import (
"context"
"time"
ioutil "github.com/argoproj/gitops-engine/pkg/utils/io"
rediscache "github.com/go-redis/cache"
"github.com/go-redis/redis"
"github.com/vmihailenco/msgpack"
@@ -10,6 +12,7 @@ import (
func NewRedisCache(client *redis.Client, expiration time.Duration) CacheClient {
return &redisCache{
client: client,
expiration: expiration,
codec: &rediscache.Codec{
Redis: client,
@@ -25,6 +28,7 @@ func NewRedisCache(client *redis.Client, expiration time.Duration) CacheClient {
type redisCache struct {
expiration time.Duration
client *redis.Client
codec *rediscache.Codec
}
@@ -52,6 +56,27 @@ func (r *redisCache) Delete(key string) error {
return r.codec.Delete(key)
}
func (r *redisCache) OnUpdated(ctx context.Context, key string, callback func() error) error {
pubsub := r.client.Subscribe(key)
defer ioutil.Close(pubsub)
ch := pubsub.Channel()
for {
select {
case <-ctx.Done():
return nil
case <-ch:
if err := callback(); err != nil {
return err
}
}
}
}
func (r *redisCache) NotifyUpdated(key string) error {
return r.client.Publish(key, "").Err()
}
type MetricsRegistry interface {
IncRedisRequest(failed bool)
ObserveRedisRequestDuration(duration time.Duration)

View File

@@ -10,17 +10,21 @@ import (
"io/ioutil"
"os"
"os/exec"
"path"
"strconv"
"strings"
"github.com/argoproj/gitops-engine/pkg/utils/errors"
"github.com/argoproj/gitops-engine/pkg/utils/io"
"github.com/google/shlex"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/crypto/ssh/terminal"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/klog"
"k8s.io/kubectl/pkg/util/term"
"sigs.k8s.io/yaml"
"github.com/argoproj/argo-cd/common"
)
@@ -254,3 +258,50 @@ func InteractiveEdit(filePattern string, data []byte, save func(input []byte) er
errorComment = err.Error()
}
}
// PrintDiff prints a diff between two unstructured objects to stdout using an external diff utility
// Honors the diff utility set in the KUBECTL_EXTERNAL_DIFF environment variable
func PrintDiff(name string, live *unstructured.Unstructured, target *unstructured.Unstructured) error {
tempDir, err := ioutil.TempDir("", "argocd-diff")
if err != nil {
return err
}
targetFile := path.Join(tempDir, name)
targetData := []byte("")
if target != nil {
targetData, err = yaml.Marshal(target)
if err != nil {
return err
}
}
err = ioutil.WriteFile(targetFile, targetData, 0644)
if err != nil {
return err
}
liveFile := path.Join(tempDir, fmt.Sprintf("%s-live.yaml", name))
liveData := []byte("")
if live != nil {
liveData, err = yaml.Marshal(live)
if err != nil {
return err
}
}
err = ioutil.WriteFile(liveFile, liveData, 0644)
if err != nil {
return err
}
cmdBinary := "diff"
var args []string
if envDiff := os.Getenv("KUBECTL_EXTERNAL_DIFF"); envDiff != "" {
parts, err := shlex.Split(envDiff)
if err != nil {
return err
}
cmdBinary = parts[0]
args = parts[1:]
}
cmd := exec.Command(cmdBinary, append(args, liveFile, targetFile)...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
return cmd.Run()
}

View File

@@ -134,7 +134,7 @@ func replaceListSecrets(obj []interface{}, secretValues map[string]string) []int
// https://github.com/dexidp/dex/tree/master/Documentation/connectors
func needsRedirectURI(connectorType string) bool {
switch connectorType {
case "oidc", "saml", "microsoft", "linkedin", "gitlab", "github", "bitbucket-cloud":
case "oidc", "saml", "microsoft", "linkedin", "gitlab", "github", "bitbucket-cloud", "openshift":
return true
}
return false

View File

@@ -54,6 +54,9 @@ Expire-Date: 6m
%commit
`
// Canary marker for GNUPGHOME created by Argo CD
const canaryMarkerFilename = ".argocd-generated"
type PGPKeyID string
func isHexString(s string) bool {
@@ -162,6 +165,39 @@ func writeKeyToFile(keyData string) (string, error) {
return f.Name(), nil
}
// removeKeyRing removes an already initialized keyring from the file system
// This must only be called on container startup, when no gpg-agent is running
// yet, otherwise key generation will fail.
func removeKeyRing(path string) error {
_, err := os.Stat(filepath.Join(path, canaryMarkerFilename))
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("refusing to remove directory %s: it's not initialized by Argo CD", path)
} else {
return err
}
}
rd, err := os.Open(path)
if err != nil {
return err
}
defer rd.Close()
dns, err := rd.Readdirnames(-1)
if err != nil {
return err
}
for _, p := range dns {
if p == "." || p == ".." {
continue
}
err := os.RemoveAll(filepath.Join(path, p))
if err != nil {
return err
}
}
return nil
}
// IsGPGEnabled returns true if GPG feature is enabled
func IsGPGEnabled() bool {
if en := os.Getenv("ARGOCD_GPG_ENABLED"); strings.ToLower(en) == "false" || strings.ToLower(en) == "no" {
@@ -191,19 +227,23 @@ func InitializeGnuPG() error {
return fmt.Errorf("%s ('%s') does not point to a directory", common.EnvGnuPGHome, gnuPgHome)
}
// Check for sane permissions as well (GPG will issue a warning otherwise)
if st.Mode().Perm() != 0700 {
return fmt.Errorf("%s at '%s' has too wide permissions, must be 0700", common.EnvGnuPGHome, gnuPgHome)
}
_, err = os.Stat(path.Join(gnuPgHome, "trustdb.gpg"))
if err != nil {
if !os.IsNotExist(err) {
return err
}
} else {
// We can't initialize a second time
return fmt.Errorf("%s at %s already initialized, can't initialize again.", common.EnvGnuPGHome, gnuPgHome)
// This usually happens with emptyDir mount on container crash - we need to
// re-initialize key ring.
err = removeKeyRing(gnuPgHome)
if err != nil {
return fmt.Errorf("re-initializing keyring at %s failed: %v", gnuPgHome, err)
}
}
err = ioutil.WriteFile(filepath.Join(gnuPgHome, canaryMarkerFilename), []byte("canary"), 0644)
if err != nil {
return fmt.Errorf("could not create canary: %v", err)
}
f, err := ioutil.TempFile("", "gpg-key-recipe")
@@ -220,7 +260,7 @@ func InitializeGnuPG() error {
f.Close()
cmd := exec.Command("gpg", "--logger-fd", "1", "--batch", "--generate-key", f.Name())
cmd := exec.Command("gpg", "--no-permission-warning", "--logger-fd", "1", "--batch", "--generate-key", f.Name())
cmd.Env = getGPGEnviron()
_, err = executil.Run(cmd)
@@ -250,7 +290,7 @@ func ImportPGPKeysFromString(keyData string) ([]*appsv1.GnuPGPublicKey, error) {
func ImportPGPKeys(keyFile string) ([]*appsv1.GnuPGPublicKey, error) {
keys := make([]*appsv1.GnuPGPublicKey, 0)
cmd := exec.Command("gpg", "--logger-fd", "1", "--import", keyFile)
cmd := exec.Command("gpg", "--no-permission-warning", "--logger-fd", "1", "--import", keyFile)
cmd.Env = getGPGEnviron()
out, err := executil.Run(cmd)
@@ -364,7 +404,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error
f.Close()
// Load ownertrust from the file we have constructed and instruct gpg to update the trustdb
cmd := exec.Command("gpg", "--import-ownertrust", f.Name())
cmd := exec.Command("gpg", "--no-permission-warning", "--import-ownertrust", f.Name())
cmd.Env = getGPGEnviron()
_, err = executil.Run(cmd)
@@ -373,7 +413,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error
}
// Update the trustdb once we updated the ownertrust, to prevent gpg to do it once we validate a signature
cmd = exec.Command("gpg", "--update-trustdb")
cmd = exec.Command("gpg", "--no-permission-warning", "--update-trustdb")
cmd.Env = getGPGEnviron()
_, err = executil.Run(cmd)
if err != nil {
@@ -385,7 +425,7 @@ func SetPGPTrustLevel(pgpKeys []*appsv1.GnuPGPublicKey, trustLevel string) error
// DeletePGPKey deletes a key from our GnuPG key ring
func DeletePGPKey(keyID string) error {
args := append([]string{}, "--yes", "--batch", "--delete-keys", keyID)
args := append([]string{}, "--no-permission-warning", "--yes", "--batch", "--delete-keys", keyID)
cmd := exec.Command("gpg", args...)
cmd.Env = getGPGEnviron()
@@ -399,7 +439,7 @@ func DeletePGPKey(keyID string) error {
// IsSecretKey returns true if the keyID also has a private key in the keyring
func IsSecretKey(keyID string) (bool, error) {
args := append([]string{}, "--list-secret-keys", keyID)
args := append([]string{}, "--no-permission-warning", "--list-secret-keys", keyID)
cmd := exec.Command("gpg-wrapper.sh", args...)
cmd.Env = getGPGEnviron()
out, err := executil.Run(cmd)
@@ -416,7 +456,7 @@ func IsSecretKey(keyID string) (bool, error) {
func GetInstalledPGPKeys(kids []string) ([]*appsv1.GnuPGPublicKey, error) {
keys := make([]*appsv1.GnuPGPublicKey, 0)
args := append([]string{}, "--list-public-keys")
args := append([]string{}, "--no-permission-warning", "--list-public-keys")
// kids can contain an arbitrary list of key IDs we want to list. If empty, we list all keys.
if len(kids) > 0 {
args = append(args, kids...)
@@ -496,7 +536,7 @@ func GetInstalledPGPKeys(kids []string) ([]*appsv1.GnuPGPublicKey, error) {
// We need to get the final key for each imported key, so we run --export on each key
for _, key := range keys {
cmd := exec.Command("gpg", "-a", "--export", key.KeyID)
cmd := exec.Command("gpg", "--no-permission-warning", "-a", "--export", key.KeyID)
cmd.Env = getGPGEnviron()
out, err := executil.Run(cmd)
@@ -617,6 +657,12 @@ func SyncKeyRingFromDirectory(basePath string) ([]string, []string, error) {
// Collect configuration, i.e. files in basePath
err = filepath.Walk(basePath, func(path string, fi os.FileInfo, err error) error {
if err != nil {
return err
}
if fi == nil {
return nil
}
if IsShortKeyID(fi.Name()) {
configured[fi.Name()] = true
}

View File

@@ -5,10 +5,12 @@ import (
"io"
"io/ioutil"
"os"
"os/exec"
"path"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/test"
@@ -60,10 +62,20 @@ func Test_GPG_InitializeGnuPG(t *testing.T) {
assert.Len(t, keys, 1)
assert.Equal(t, keys[0].Trust, "ultimate")
// Second run should return error
// During unit-tests, we need to also kill gpg-agent so we can create a new key.
// In real world scenario -- i.e. container crash -- gpg-agent is not running yet.
cmd := exec.Command("gpgconf", "--kill", "gpg-agent")
cmd.Env = []string{fmt.Sprintf("GNUPGHOME=%s", p)}
err = cmd.Run()
require.NoError(t, err)
// Second run should not return error
err = InitializeGnuPG()
assert.Error(t, err)
assert.Contains(t, err.Error(), "already initialized")
require.NoError(t, err)
keys, err = GetInstalledPGPKeys(nil)
assert.NoError(t, err)
assert.Len(t, keys, 1)
assert.Equal(t, keys[0].Trust, "ultimate")
// GNUPGHOME is a file - we need to error out
f, err := ioutil.TempFile("", "gpg-test")
@@ -96,6 +108,8 @@ func Test_GPG_InitializeGnuPG(t *testing.T) {
}
// GNUPGHOME with too wide permissions
// We do not expect an error here, because of openshift's random UIDs that
// forced us to use an emptyDir mount (#4127)
p = initTempDir()
defer os.RemoveAll(p)
err = os.Chmod(p, 0777)
@@ -104,8 +118,7 @@ func Test_GPG_InitializeGnuPG(t *testing.T) {
}
os.Setenv(common.EnvGnuPGHome, p)
err = InitializeGnuPG()
assert.Error(t, err)
assert.NoError(t, err)
}
func Test_GPG_KeyManagement(t *testing.T) {