Compare commits

...

32 Commits

Author SHA1 Message Date
Alex Collins
75db0b6c8c Update manifests to v1.1.0-rc4 2019-07-03 14:07:53 -07:00
Alex Collins
0860b032ec Merged from master 2019-07-03 13:52:12 -07:00
Alexander Matyushentsev
ba267f627a Issue #1874 - validate app spec before verifying app permissions (#1875) 2019-07-03 13:10:23 -07:00
Alex Collins
3000146574 Redacts Helm username and password. Closes #1868 (#1871) 2019-07-03 13:02:48 -07:00
Alexander Matyushentsev
686ec75e0a Issue #1867 - Fix JS error on project role edit panel (#1869) 2019-07-03 10:38:46 -07:00
Alexander Matyushentsev
d08534f068 Upgrade argo-ui version to fix dropdown position calculation (#1847) 2019-07-01 10:48:11 -07:00
Alex Collins
7c0fd908a0 Update manifests to v1.1.0-rc3 2019-06-28 13:29:27 -07:00
Alex Collins
e530a4780e Removes logging that appears when using the CLI (#1842) 2019-06-28 13:19:37 -07:00
Alex Collins
8c76771a05 Adds file missing for tests 2019-06-28 13:06:53 -07:00
Alex Collins
65f430c395 Removes merge issue 2019-06-28 12:55:39 -07:00
Simon Behar
d409014da7 Added local path syncing (#1578) 2019-06-28 12:36:02 -07:00
Simon Behar
cfddf23275 Added local sync to docs (#1771) 2019-06-28 12:32:02 -07:00
Alexander Matyushentsev
5698d1b6b1 Issue #1820 - Make sure api server to repo server grpc calls have timeout (#1832) 2019-06-28 12:11:31 -07:00
Alex Collins
0e6895472b Adds a timeout to all external commands. Closes #1821 (#1823) 2019-06-28 12:07:32 -07:00
Jesse Suen
b7e0f91478 Running application actions should require override privileges not get (#1828) 2019-06-27 11:29:46 -07:00
Jesse Suen
78ab336c86 Parameterize Argo UI base image 2019-06-24 16:21:39 -07:00
Jesse Suen
a86e074b1f Switch to user root when building argo-cd base 2019-06-24 14:57:29 -07:00
Alex Collins
b742c66b14 update argo-ui URL from git:// to https:// 2019-06-24 14:15:18 -07:00
Alex Collins
e2756210d9 dep ensure 2019-06-21 16:08:54 -07:00
Alex Collins
97565c0895 Merged from master 2019-06-21 16:02:22 -07:00
Alex Collins
9a6f9ff824 Update manifests to v1.1.0-rc2 2019-06-21 16:00:06 -07:00
dthomson25
290cefaedd Use correct healthcheck for Rollout with empty steps list (#1776) 2019-06-21 15:04:19 -07:00
Jesse Suen
69e49d708f Move remarshaling to happen only during comparison, instead of manifest generation (#1788) 2019-06-21 15:01:07 -07:00
Jesse Suen
e27be81947 Server side rotation of cluster bearer tokens (#1744) 2019-06-21 13:41:14 -07:00
Alexander Matyushentsev
4febc66a64 Add health check to the controller deployment (#1785) 2019-06-21 11:02:43 -07:00
Alexander Matyushentsev
a984af76f1 Make status fields as optional fields (#1779) 2019-06-21 11:02:37 -07:00
Alexander Matyushentsev
be6a0fc21f Sync status button should be hidden if there is no sync operation (#1770) 2019-06-21 11:02:31 -07:00
Alexander Matyushentsev
122729e2a4 UI should allow editing repo URL (#1763) 2019-06-21 11:02:25 -07:00
Alex Collins
84635d4dbe Fixes a bug where cluster objs could leave app is running op state. C… (#1796) 2019-06-21 10:52:43 -07:00
Alex Collins
46550e009b Update manifests to v1.1.0-rc1 2019-06-14 11:16:08 -07:00
Alex Collins
683b9072b8 codegen 2019-06-14 11:15:09 -07:00
Alex Collins
33e66dcf5e Update manifests to v1.1.0-rc1 2019-06-14 11:13:23 -07:00
88 changed files with 2224 additions and 899 deletions

View File

@@ -309,6 +309,8 @@ jobs:
make test-e2e | tee /tmp/test-results/go-e2e.out
environment:
ARGOCD_OPTS: "--server localhost:8080 --plaintext"
ARGOCD_E2E_EXPECT_TIMEOUT: "30"
ARGOCD_E2E_K3S: "true"
- store_test_results:
path: /tmp/test-results
ui:

View File

@@ -96,6 +96,8 @@ RUN cd ${GOPATH}/src/dummy && \
####################################################################################################
FROM $BASE_IMAGE as argocd-base
USER root
RUN groupadd -g 999 argocd && \
useradd -r -u 999 -g argocd argocd && \
mkdir -p /home/argocd && \

7
Gopkg.lock generated
View File

@@ -70,14 +70,15 @@
[[projects]]
branch = "master"
digest = "1:e8ec0abbf32fdcc9f7eb14c0656c1d0fc2fc7ec8f60dff4b7ac080c50afd8e49"
digest = "1:c7b3f972d6de22ee4059a67d1df322699cd39793553e5dd265ce0e05e4b0eca5"
name = "github.com/argoproj/pkg"
packages = [
"exec",
"rand",
"time",
]
pruneopts = ""
revision = "88ab0e836a8e8c70bc297c5764669bd7da27afd1"
revision = "b94327e4ce8fabfc3819d4d3fdb01aab7c39bf87"
[[projects]]
digest = "1:d8a2bb36a048d1571bcc1aee208b61f39dc16c6c53823feffd37449dde162507"
@@ -1496,7 +1497,7 @@
version = "v0.1.0"
[[projects]]
digest = "1:aae856b28533bfdb39112514290f7722d00a55a99d2d0b897c6ee82e6feb87b3"
digest = "1:6fb17dac788a9f25fc454d8324180779687c46b60686c6e64136183c8134111e"
name = "k8s.io/kube-openapi"
packages = [
"cmd/openapi-gen",

View File

@@ -1 +1 @@
1.0.0
1.1.0-rc4

View File

@@ -15,6 +15,7 @@ p, role:admin, applications, create, */*, allow
p, role:admin, applications, update, */*, allow
p, role:admin, applications, delete, */*, allow
p, role:admin, applications, sync, */*, allow
p, role:admin, applications, override, */*, allow
p, role:admin, clusters, create, *, allow
p, role:admin, clusters, update, *, allow
p, role:admin, clusters, delete, *, allow
1 # Built-in policy which defines two roles: role:readonly and role:admin,
15 p, role:admin, applications, sync, */*, allow
16 p, role:admin, clusters, create, *, allow p, role:admin, applications, override, */*, allow
17 p, role:admin, clusters, update, *, allow p, role:admin, clusters, create, *, allow
18 p, role:admin, clusters, update, *, allow
19 p, role:admin, clusters, delete, *, allow
20 p, role:admin, repositories, create, *, allow
21 p, role:admin, repositories, update, *, allow

View File

@@ -868,6 +868,31 @@
}
}
},
"/api/v1/clusters/{server}/rotate-auth": {
"post": {
"tags": [
"ClusterService"
],
"summary": "RotateAuth returns a cluster by server address",
"operationId": "RotateAuth",
"parameters": [
{
"type": "string",
"name": "server",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "(empty)",
"schema": {
"$ref": "#/definitions/clusterClusterResponse"
}
}
}
}
},
"/api/v1/projects": {
"get": {
"tags": [
@@ -1471,6 +1496,12 @@
"type": "boolean",
"format": "boolean"
},
"manifests": {
"type": "array",
"items": {
"type": "string"
}
},
"name": {
"type": "string"
},
@@ -3320,6 +3351,13 @@
"format": "boolean",
"title": "DryRun will perform a `kubectl apply --dry-run` without actually performing the sync"
},
"manifests": {
"type": "array",
"title": "Manifests is an optional field that overrides sync source with a local directory for development",
"items": {
"type": "string"
}
},
"prune": {
"type": "boolean",
"format": "boolean",

View File

@@ -22,19 +22,20 @@ import (
// NewCommand returns a new instance of an argocd command
func NewCommand() *cobra.Command {
var (
insecure bool
listenPort int
metricsPort int
logLevel string
glogLevel int
clientConfig clientcmd.ClientConfig
staticAssetsDir string
baseHRef string
repoServerAddress string
dexServerAddress string
disableAuth bool
tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error)
cacheSrc func() (*cache.Cache, error)
insecure bool
listenPort int
metricsPort int
logLevel string
glogLevel int
clientConfig clientcmd.ClientConfig
repoServerTimeoutSeconds int
staticAssetsDir string
baseHRef string
repoServerAddress string
dexServerAddress string
disableAuth bool
tlsConfigCustomizerSrc func() (tls.ConfigCustomizer, error)
cacheSrc func() (*cache.Cache, error)
)
var command = &cobra.Command{
Use: cliName,
@@ -59,7 +60,7 @@ func NewCommand() *cobra.Command {
kubeclientset := kubernetes.NewForConfigOrDie(config)
appclientset := appclientset.NewForConfigOrDie(config)
repoclientset := reposerver.NewRepoServerClientset(repoServerAddress, 0)
repoclientset := reposerver.NewRepoServerClientset(repoServerAddress, repoServerTimeoutSeconds)
argoCDOpts := server.ArgoCDServerOpts{
Insecure: insecure,
@@ -103,6 +104,7 @@ func NewCommand() *cobra.Command {
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")
command.Flags().IntVar(&repoServerTimeoutSeconds, "repo-server-timeout-seconds", 60, "Repo server RPC call timeout seconds.")
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(command)
cacheSrc = cache.AddCacheFlagsToCmd(command)
return command

View File

@@ -612,6 +612,18 @@ func liveObjects(resources []*argoappv1.ResourceDiff) ([]*unstructured.Unstructu
}
func getLocalObjects(app *argoappv1.Application, local string, appLabelKey string) []*unstructured.Unstructured {
manifestStrings := getLocalObjectsString(app, local, appLabelKey)
objs := make([]*unstructured.Unstructured, len(manifestStrings))
for i := range manifestStrings {
obj := unstructured.Unstructured{}
err := json.Unmarshal([]byte(manifestStrings[i]), &obj)
errors.CheckError(err)
objs[i] = &obj
}
return objs
}
func getLocalObjectsString(app *argoappv1.Application, local string, appLabelKey string) []string {
res, err := repository.GenerateManifests(local, &repository.ManifestRequest{
ApplicationSource: &app.Spec.Source,
AppLabelKey: appLabelKey,
@@ -619,14 +631,8 @@ func getLocalObjects(app *argoappv1.Application, local string, appLabelKey strin
Namespace: app.Spec.Destination.Namespace,
})
errors.CheckError(err)
objs := make([]*unstructured.Unstructured, len(res.Manifests))
for i := range res.Manifests {
obj := unstructured.Unstructured{}
err = json.Unmarshal([]byte(res.Manifests[i]), &obj)
errors.CheckError(err)
objs[i] = &obj
}
return objs
return res.Manifests
}
type resourceInfoProvider struct {
@@ -1085,6 +1091,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
strategy string
force bool
async bool
local string
)
var command = &cobra.Command{
Use: "sync APPNAME",
@@ -1143,12 +1150,31 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
selectedResources := parseSelectedResources(resources)
var localObjsStrings []string
if local != "" {
app, err := appIf.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName})
if app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.Automated != nil {
log.Fatal("Cannot use local sync when Automatic Sync Policy is enabled")
}
errors.CheckError(err)
conn, settingsIf := acdClient.NewSettingsClientOrDie()
argoSettings, err := settingsIf.Get(context.Background(), &settingspkg.SettingsQuery{})
errors.CheckError(err)
util.Close(conn)
localObjsStrings = getLocalObjectsString(app, local, argoSettings.AppLabelKey)
}
syncReq := applicationpkg.ApplicationSyncRequest{
Name: &appName,
DryRun: dryRun,
Revision: revision,
Resources: selectedResources,
Prune: prune,
Manifests: localObjsStrings,
}
switch strategy {
case "apply":
@@ -1191,6 +1217,7 @@ func NewApplicationSyncCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
command.Flags().StringVar(&strategy, "strategy", "", "Sync strategy (one of: apply|hook)")
command.Flags().BoolVar(&force, "force", false, "Use a force apply")
command.Flags().BoolVar(&async, "async", false, "Do not wait for application to sync before continuing")
command.Flags().StringVar(&local, "local", "", "Path to a local directory. When this flag is present no git queries will be made")
return command
}

View File

@@ -22,6 +22,7 @@ import (
clusterpkg "github.com/argoproj/argo-cd/pkg/apiclient/cluster"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/clusterauth"
)
// NewClusterCommand returns a new instance of an `argocd cluster` command
@@ -39,6 +40,7 @@ func NewClusterCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clientc
command.AddCommand(NewClusterGetCommand(clientOpts))
command.AddCommand(NewClusterListCommand(clientOpts))
command.AddCommand(NewClusterRemoveCommand(clientOpts))
command.AddCommand(NewClusterRotateAuthCommand(clientOpts))
return command
}
@@ -86,7 +88,7 @@ func NewClusterAddCommand(clientOpts *argocdclient.ClientOptions, pathOpts *clie
// Install RBAC resources for managing the cluster
clientset, err := kubernetes.NewForConfig(conf)
errors.CheckError(err)
managerBearerToken, err = common.InstallClusterManagerRBAC(clientset, systemNamespace)
managerBearerToken, err = clusterauth.InstallClusterManagerRBAC(clientset, systemNamespace)
errors.CheckError(err)
}
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
@@ -178,7 +180,7 @@ func NewCluster(name string, conf *rest.Config, managerBearerToken string, awsAu
// NewClusterGetCommand returns a new instance of an `argocd cluster get` command
func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "get",
Use: "get CLUSTER",
Short: "Get cluster information",
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
@@ -202,7 +204,7 @@ func NewClusterGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command
// NewClusterRemoveCommand returns a new instance of an `argocd cluster list` command
func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "rm",
Use: "rm CLUSTER",
Short: "Remove cluster credentials",
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
@@ -217,7 +219,7 @@ func NewClusterRemoveCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comm
for _, clusterName := range args {
// TODO(jessesuen): find the right context and remove manager RBAC artifacts
// err := common.UninstallClusterManagerRBAC(clientset)
// err := clusterauth.UninstallClusterManagerRBAC(clientset)
// errors.CheckError(err)
_, err := clusterIf.Delete(context.Background(), &clusterpkg.ClusterQuery{Server: clusterName})
errors.CheckError(err)
@@ -247,3 +249,26 @@ func NewClusterListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Comman
}
return command
}
// NewClusterRotateAuthCommand returns a new instance of an `argocd cluster rotate-auth` command
func NewClusterRotateAuthCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var command = &cobra.Command{
Use: "rotate-auth CLUSTER",
Short: fmt.Sprintf("%s cluster rotate-auth CLUSTER", cliName),
Run: func(c *cobra.Command, args []string) {
if len(args) != 1 {
c.HelpFunc()(c, args)
os.Exit(1)
}
conn, clusterIf := argocdclient.NewClientOrDie(clientOpts).NewClusterClientOrDie()
defer util.Close(conn)
clusterQuery := clusterpkg.ClusterQuery{
Server: args[0],
}
_, err := clusterIf.RotateAuth(context.Background(), &clusterQuery)
errors.CheckError(err)
fmt.Printf("Cluster '%s' rotated auth\n", clusterQuery.Server)
},
}
return command
}

View File

@@ -113,7 +113,10 @@ func NewApplicationController(
appInformer, appLister := ctrl.newApplicationInformerAndLister()
projInformer := v1alpha1.NewAppProjectInformer(applicationClientset, namespace, appResyncPeriod, cache.Indexers{})
metricsAddr := fmt.Sprintf("0.0.0.0:%d", metricsPort)
ctrl.metricsServer = metrics.NewMetricsServer(metricsAddr, appLister)
ctrl.metricsServer = metrics.NewMetricsServer(metricsAddr, appLister, func() error {
_, err := kubeClientset.Discovery().ServerVersion()
return err
})
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settings, kubectlCmd, ctrl.metricsServer, ctrl.handleAppUpdated)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectlCmd, ctrl.settings, stateCache, projInformer, ctrl.metricsServer)
ctrl.appInformer = appInformer
@@ -494,6 +497,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
ctrl.setOperationState(app, state)
logCtx.Infof("Initialized new operation: %v", *app.Operation)
}
ctrl.appStateManager.SyncAppState(app, state)
if state.Phase == appv1.OperationRunning {
@@ -654,7 +658,12 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
return
}
compareResult, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, refreshType == appv1.RefreshTypeHard)
var localManifests []string
if opState := app.Status.OperationState; opState != nil {
localManifests = opState.Operation.Sync.Manifests
}
compareResult, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, refreshType == appv1.RefreshTypeHard, localManifests)
if err != nil {
conditions = append(conditions, appv1.ApplicationCondition{Type: appv1.ApplicationConditionComparisonError, Message: err.Error()})
} else {

View File

@@ -13,6 +13,7 @@ import (
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
applister "github.com/argoproj/argo-cd/pkg/client/listers/application/v1alpha1"
"github.com/argoproj/argo-cd/util/git"
"github.com/argoproj/argo-cd/util/healthz"
)
type MetricsServer struct {
@@ -59,12 +60,13 @@ var (
)
// NewMetricsServer returns a new prometheus server which collects application metrics
func NewMetricsServer(addr string, appLister applister.ApplicationLister) *MetricsServer {
func NewMetricsServer(addr string, appLister applister.ApplicationLister, healthCheck func() error) *MetricsServer {
mux := http.NewServeMux()
appRegistry := NewAppRegistry(appLister)
appRegistry.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{}))
appRegistry.MustRegister(prometheus.NewGoCollector())
mux.Handle(MetricsPath, promhttp.HandlerFor(appRegistry, promhttp.HandlerOpts{}))
healthz.ServeHealthCheck(mux, healthCheck)
syncCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{

View File

@@ -104,6 +104,10 @@ argocd_app_sync_status{name="my-app",namespace="argocd",project="default",sync_s
argocd_app_sync_status{name="my-app",namespace="argocd",project="default",sync_status="Unknown"} 0
`
var noOpHealthCheck = func() error {
return nil
}
func newFakeApp(fakeApp string) *argoappv1.Application {
var app argoappv1.Application
err := yaml.Unmarshal([]byte(fakeApp), &app)
@@ -133,7 +137,7 @@ func newFakeLister(fakeApp ...string) (context.CancelFunc, applister.Application
func testApp(t *testing.T, fakeApp string, expectedResponse string) {
cancel, appLister := newFakeLister(fakeApp)
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister)
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
req, err := http.NewRequest("GET", "/metrics", nil)
assert.NoError(t, err)
rr := httptest.NewRecorder()
@@ -176,7 +180,7 @@ argocd_app_sync_total{name="my-app",namespace="argocd",phase="Succeeded",project
func TestMetricsSyncCounter(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister)
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
fakeApp := newFakeApp(fakeApp)
metricsServ.IncSync(fakeApp, &argoappv1.OperationState{Phase: argoappv1.OperationRunning})
@@ -217,7 +221,7 @@ argocd_app_reconcile_count{name="my-app",namespace="argocd",project="important-p
func TestReconcileMetrics(t *testing.T) {
cancel, appLister := newFakeLister()
defer cancel()
metricsServ := NewMetricsServer("localhost:8082", appLister)
metricsServ := NewMetricsServer("localhost:8082", appLister, noOpHealthCheck)
fakeApp := newFakeApp(fakeApp)
metricsServ.IncReconcile(fakeApp, 5*time.Second)

View File

@@ -57,7 +57,7 @@ type ResourceInfoProvider interface {
// AppStateManager defines methods which allow to compare application spec and actual application state.
type AppStateManager interface {
CompareAppState(app *v1alpha1.Application, revision string, source v1alpha1.ApplicationSource, noCache bool) (*comparisonResult, error)
CompareAppState(app *v1alpha1.Application, revision string, source v1alpha1.ApplicationSource, noCache bool, localObjects []string) (*comparisonResult, error)
SyncAppState(app *v1alpha1.Application, state *v1alpha1.OperationState)
}
@@ -125,12 +125,18 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
return nil, nil, nil, err
}
targetObjs, hooks, nil := unmarshalManifests(manifestInfo.Manifests)
return targetObjs, hooks, manifestInfo, nil
}
func unmarshalManifests(manifests []string) ([]*unstructured.Unstructured, []*unstructured.Unstructured, error) {
targetObjs := make([]*unstructured.Unstructured, 0)
hooks := make([]*unstructured.Unstructured, 0)
for _, manifest := range manifestInfo.Manifests {
for _, manifest := range manifests {
obj, err := v1alpha1.UnmarshalToUnstructured(manifest)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
if resource.Ignore(obj) {
continue
@@ -141,7 +147,7 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
targetObjs = append(targetObjs, obj)
}
}
return targetObjs, hooks, manifestInfo, nil
return targetObjs, hooks, nil
}
func DeduplicateTargetObjects(
@@ -220,7 +226,7 @@ func dedupLiveResources(targetObjs []*unstructured.Unstructured, liveObjsByKey m
// CompareAppState compares application git state to the live app state, using the specified
// revision and supplied source. If revision or overrides are empty, then compares against
// revision and overrides in the app spec.
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision string, source v1alpha1.ApplicationSource, noCache bool) (*comparisonResult, error) {
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision string, source v1alpha1.ApplicationSource, noCache bool, localManifests []string) (*comparisonResult, error) {
diffNormalizer, err := argo.NewDiffNormalizer(app.Spec.IgnoreDifferences, m.settings.ResourceOverrides)
if err != nil {
return nil, err
@@ -231,12 +237,28 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision st
failedToLoadObjs := false
conditions := make([]v1alpha1.ApplicationCondition, 0)
appLabelKey := m.settings.GetAppInstanceLabelKey()
targetObjs, hooks, manifestInfo, err := m.getRepoObjs(app, source, appLabelKey, revision, noCache)
if err != nil {
targetObjs = make([]*unstructured.Unstructured, 0)
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error()})
failedToLoadObjs = true
var targetObjs []*unstructured.Unstructured
var hooks []*unstructured.Unstructured
var manifestInfo *repository.ManifestResponse
if len(localManifests) == 0 {
targetObjs, hooks, manifestInfo, err = m.getRepoObjs(app, source, appLabelKey, revision, noCache)
if err != nil {
targetObjs = make([]*unstructured.Unstructured, 0)
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error()})
failedToLoadObjs = true
}
} else {
targetObjs, hooks, err = unmarshalManifests(localManifests)
if err != nil {
targetObjs = make([]*unstructured.Unstructured, 0)
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error()})
failedToLoadObjs = true
}
manifestInfo = nil
}
targetObjs, dedupConditions, err := DeduplicateTargetObjects(app.Spec.Destination.Server, app.Spec.Destination.Namespace, targetObjs, m.liveStateCache)
if err != nil {
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error()})

View File

@@ -30,7 +30,7 @@ func TestCompareAppStateEmpty(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)
@@ -53,7 +53,7 @@ func TestCompareAppStateMissing(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
@@ -80,7 +80,7 @@ func TestCompareAppStateExtra(t *testing.T) {
},
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
@@ -107,7 +107,7 @@ func TestCompareAppStateHook(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)
@@ -134,7 +134,7 @@ func TestCompareAppStateCompareOptionIgnoreExtraneous(t *testing.T) {
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
@@ -163,7 +163,7 @@ func TestCompareAppStateExtraHook(t *testing.T) {
},
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)
@@ -200,7 +200,7 @@ func TestCompareAppStateDuplicatedNamespacedResources(t *testing.T) {
},
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Contains(t, compRes.conditions, argoappv1.ApplicationCondition{
@@ -251,7 +251,7 @@ func TestSetHealth(t *testing.T) {
},
})
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.Equal(t, compRes.healthStatus.Status, argoappv1.HealthStatusHealthy)
@@ -284,7 +284,7 @@ func TestSetHealthSelfReferencedApp(t *testing.T) {
},
})
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", app.Spec.Source, false, nil)
assert.NoError(t, err)
assert.Equal(t, compRes.healthStatus.Status, argoappv1.HealthStatusHealthy)

View File

@@ -92,7 +92,7 @@ func (m *appStateManager) SyncAppState(app *v1alpha1.Application, state *v1alpha
revision = syncOp.Revision
}
compareResult, err := m.CompareAppState(app, revision, source, false)
compareResult, err := m.CompareAppState(app, revision, source, false, syncOp.Manifests)
if err != nil {
state.Phase = v1alpha1.OperationError
state.Message = err.Error()
@@ -457,7 +457,8 @@ func (sc *syncContext) liveObj(obj *unstructured.Unstructured) *unstructured.Uns
for _, resource := range sc.compareResult.managedResources {
if resource.Group == obj.GroupVersionKind().Group &&
resource.Kind == obj.GetKind() &&
resource.Namespace == obj.GetNamespace() &&
// cluster scoped objects will not have a namespace, even if the user has defined it
(resource.Namespace == "" || resource.Namespace == obj.GetNamespace()) &&
resource.Name == obj.GetName() {
return resource.Live
}

View File

@@ -2,6 +2,7 @@ package controller
import (
"fmt"
"reflect"
"testing"
log "github.com/sirupsen/logrus"
@@ -526,3 +527,37 @@ func Test_syncContext_isSelectiveSync(t *testing.T) {
})
}
}
func Test_syncContext_liveObj(t *testing.T) {
type fields struct {
compareResult *comparisonResult
}
type args struct {
obj *unstructured.Unstructured
}
obj := test.NewPod()
obj.SetNamespace("my-ns")
found := test.NewPod()
tests := []struct {
name string
fields fields
args args
want *unstructured.Unstructured
}{
{"None", fields{compareResult: &comparisonResult{managedResources: []managedResource{}}}, args{obj: &unstructured.Unstructured{}}, nil},
{"Found", fields{compareResult: &comparisonResult{managedResources: []managedResource{{Group: obj.GroupVersionKind().Group, Kind: obj.GetKind(), Namespace: obj.GetNamespace(), Name: obj.GetName(), Live: found}}}}, args{obj: obj}, found},
{"EmptyNamespace", fields{compareResult: &comparisonResult{managedResources: []managedResource{{Group: obj.GroupVersionKind().Group, Kind: obj.GetKind(), Name: obj.GetName(), Live: found}}}}, args{obj: obj}, found},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
sc := &syncContext{
compareResult: tt.fields.compareResult,
}
if got := sc.liveObj(tt.args.obj); !reflect.DeepEqual(got, tt.want) {
t.Errorf("syncContext.liveObj() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -1,5 +1,7 @@
# Tools
## Production
Argo CD supports several different ways in which Kubernetes manifests can be defined:
* [Kustomize](kustomize.md) applications
@@ -7,3 +9,13 @@ Argo CD supports several different ways in which Kubernetes manifests can be def
* [Ksonnet](ksonnet.md) applications
* A directory of YAML/JSO/Jsonnet manifests
* Any [custom config management tool](config-management-plugins.md) configured as a config management plugin
## Development
Argo CD also supports uploading local manifests directly. Since this is an anti-pattern of the
GitOps paradigm, this should only be done for development purposes. A user with an `override` permission is required
to upload manifests locally (typically an admin). All of the different Kubernetes deployment tools above are supported.
To upload a local application:
```bash
$ argocd app sync APPNAME --local /path/to/dir/
```

View File

@@ -30,7 +30,14 @@ spec:
ports:
- containerPort: 8082
readinessProbe:
tcpSocket:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
livenessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10

View File

@@ -12,7 +12,7 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: latest
newTag: v1.1.0-rc4
- name: argoproj/argocd-ui
newName: argoproj/argocd-ui
newTag: latest
newTag: v1.1.0-rc4

View File

@@ -38,6 +38,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run` without
actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides sync
source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer tracked
in git
@@ -689,7 +695,6 @@ spec:
- revision
- deployedAt
- id
- source
type: object
type: array
observedAt: {}
@@ -712,6 +717,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run`
without actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides
sync source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer
tracked in git
@@ -1164,7 +1175,6 @@ spec:
type: object
required:
- revision
- source
type: object
required:
- operation

View File

@@ -17,7 +17,7 @@ patchesStrategicMerge:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: latest
newTag: v1.1.0-rc4
- name: argoproj/argocd-ui
newName: argoproj/argocd-ui
newTag: latest
newTag: v1.1.0-rc4

View File

@@ -39,6 +39,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run` without
actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides sync
source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer tracked
in git
@@ -690,7 +696,6 @@ spec:
- revision
- deployedAt
- id
- source
type: object
type: array
observedAt: {}
@@ -713,6 +718,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run`
without actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides
sync source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer
tracked in git
@@ -1165,7 +1176,6 @@ spec:
type: object
required:
- revision
- source
type: object
required:
- operation
@@ -2197,16 +2207,23 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
name: argocd-application-controller
ports:
- containerPort: 8082
readinessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
tcpSocket:
port: 8082
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
@@ -2244,7 +2261,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2299,7 +2316,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2361,7 +2378,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2388,7 +2405,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v1.1.0-rc4
imagePullPolicy: Always
name: ui
volumeMounts:

View File

@@ -39,6 +39,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run` without
actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides sync
source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer tracked
in git
@@ -690,7 +696,6 @@ spec:
- revision
- deployedAt
- id
- source
type: object
type: array
observedAt: {}
@@ -713,6 +718,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run`
without actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides
sync source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer
tracked in git
@@ -1165,7 +1176,6 @@ spec:
type: object
required:
- revision
- source
type: object
required:
- operation
@@ -2112,16 +2122,23 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
name: argocd-application-controller
ports:
- containerPort: 8082
readinessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
tcpSocket:
port: 8082
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
@@ -2159,7 +2176,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2214,7 +2231,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2276,7 +2293,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2303,7 +2320,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v1.1.0-rc4
imagePullPolicy: Always
name: ui
volumeMounts:

View File

@@ -39,6 +39,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run` without
actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides sync
source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer tracked
in git
@@ -690,7 +696,6 @@ spec:
- revision
- deployedAt
- id
- source
type: object
type: array
observedAt: {}
@@ -713,6 +718,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run`
without actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides
sync source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer
tracked in git
@@ -1165,7 +1176,6 @@ spec:
type: object
required:
- revision
- source
type: object
required:
- operation
@@ -1961,16 +1971,23 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
name: argocd-application-controller
ports:
- containerPort: 8082
readinessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
tcpSocket:
port: 8082
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
@@ -2008,7 +2025,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2071,7 +2088,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2110,7 +2127,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2137,7 +2154,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v1.1.0-rc4
imagePullPolicy: Always
name: ui
volumeMounts:

View File

@@ -39,6 +39,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run` without
actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides sync
source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer tracked
in git
@@ -690,7 +696,6 @@ spec:
- revision
- deployedAt
- id
- source
type: object
type: array
observedAt: {}
@@ -713,6 +718,12 @@ spec:
description: DryRun will perform a `kubectl apply --dry-run`
without actually performing the sync
type: boolean
manifests:
description: Manifests is an optional field that overrides
sync source with a local directory for development
items:
type: string
type: array
prune:
description: Prune deletes resources that are no longer
tracked in git
@@ -1165,7 +1176,6 @@ spec:
type: object
required:
- revision
- source
type: object
required:
- operation
@@ -1876,16 +1886,23 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
name: argocd-application-controller
ports:
- containerPort: 8082
readinessProbe:
httpGet:
path: /healthz
port: 8082
initialDelaySeconds: 5
periodSeconds: 10
tcpSocket:
port: 8082
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
@@ -1923,7 +1940,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -1986,7 +2003,7 @@ spec:
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2025,7 +2042,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v1.1.0-rc4
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2052,7 +2069,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v1.1.0-rc4
imagePullPolicy: Always
name: ui
volumeMounts:

View File

@@ -52,7 +52,7 @@ func (m *ApplicationQuery) Reset() { *m = ApplicationQuery{} }
func (m *ApplicationQuery) String() string { return proto.CompactTextString(m) }
func (*ApplicationQuery) ProtoMessage() {}
func (*ApplicationQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{0}
return fileDescriptor_application_0acf736a0f21a996, []int{0}
}
func (m *ApplicationQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -124,7 +124,7 @@ func (m *ApplicationResourceEventsQuery) Reset() { *m = ApplicationResou
func (m *ApplicationResourceEventsQuery) String() string { return proto.CompactTextString(m) }
func (*ApplicationResourceEventsQuery) ProtoMessage() {}
func (*ApplicationResourceEventsQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{1}
return fileDescriptor_application_0acf736a0f21a996, []int{1}
}
func (m *ApplicationResourceEventsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -194,7 +194,7 @@ func (m *ApplicationManifestQuery) Reset() { *m = ApplicationManifestQue
func (m *ApplicationManifestQuery) String() string { return proto.CompactTextString(m) }
func (*ApplicationManifestQuery) ProtoMessage() {}
func (*ApplicationManifestQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{2}
return fileDescriptor_application_0acf736a0f21a996, []int{2}
}
func (m *ApplicationManifestQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -247,7 +247,7 @@ func (m *ApplicationResponse) Reset() { *m = ApplicationResponse{} }
func (m *ApplicationResponse) String() string { return proto.CompactTextString(m) }
func (*ApplicationResponse) ProtoMessage() {}
func (*ApplicationResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{3}
return fileDescriptor_application_0acf736a0f21a996, []int{3}
}
func (m *ApplicationResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -288,7 +288,7 @@ func (m *ApplicationCreateRequest) Reset() { *m = ApplicationCreateReque
func (m *ApplicationCreateRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationCreateRequest) ProtoMessage() {}
func (*ApplicationCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{4}
return fileDescriptor_application_0acf736a0f21a996, []int{4}
}
func (m *ApplicationCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -342,7 +342,7 @@ func (m *ApplicationUpdateRequest) Reset() { *m = ApplicationUpdateReque
func (m *ApplicationUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationUpdateRequest) ProtoMessage() {}
func (*ApplicationUpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{5}
return fileDescriptor_application_0acf736a0f21a996, []int{5}
}
func (m *ApplicationUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -390,7 +390,7 @@ func (m *ApplicationDeleteRequest) Reset() { *m = ApplicationDeleteReque
func (m *ApplicationDeleteRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationDeleteRequest) ProtoMessage() {}
func (*ApplicationDeleteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{6}
return fileDescriptor_application_0acf736a0f21a996, []int{6}
}
func (m *ApplicationDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -441,6 +441,7 @@ type ApplicationSyncRequest struct {
Prune bool `protobuf:"varint,4,opt,name=prune" json:"prune"`
Strategy *v1alpha1.SyncStrategy `protobuf:"bytes,5,opt,name=strategy" json:"strategy,omitempty"`
Resources []v1alpha1.SyncOperationResource `protobuf:"bytes,7,rep,name=resources" json:"resources"`
Manifests []string `protobuf:"bytes,8,rep,name=manifests" json:"manifests,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -450,7 +451,7 @@ func (m *ApplicationSyncRequest) Reset() { *m = ApplicationSyncRequest{}
func (m *ApplicationSyncRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationSyncRequest) ProtoMessage() {}
func (*ApplicationSyncRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{7}
return fileDescriptor_application_0acf736a0f21a996, []int{7}
}
func (m *ApplicationSyncRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -521,6 +522,13 @@ func (m *ApplicationSyncRequest) GetResources() []v1alpha1.SyncOperationResource
return nil
}
func (m *ApplicationSyncRequest) GetManifests() []string {
if m != nil {
return m.Manifests
}
return nil
}
// ApplicationUpdateSpecRequest is a request to update application spec
type ApplicationUpdateSpecRequest struct {
Name *string `protobuf:"bytes,1,req,name=name" json:"name,omitempty"`
@@ -534,7 +542,7 @@ func (m *ApplicationUpdateSpecRequest) Reset() { *m = ApplicationUpdateS
func (m *ApplicationUpdateSpecRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationUpdateSpecRequest) ProtoMessage() {}
func (*ApplicationUpdateSpecRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{8}
return fileDescriptor_application_0acf736a0f21a996, []int{8}
}
func (m *ApplicationUpdateSpecRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -590,7 +598,7 @@ func (m *ApplicationPatchRequest) Reset() { *m = ApplicationPatchRequest
func (m *ApplicationPatchRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationPatchRequest) ProtoMessage() {}
func (*ApplicationPatchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{9}
return fileDescriptor_application_0acf736a0f21a996, []int{9}
}
func (m *ApplicationPatchRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -647,7 +655,7 @@ func (m *ApplicationRollbackRequest) Reset() { *m = ApplicationRollbackR
func (m *ApplicationRollbackRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationRollbackRequest) ProtoMessage() {}
func (*ApplicationRollbackRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{10}
return fileDescriptor_application_0acf736a0f21a996, []int{10}
}
func (m *ApplicationRollbackRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -720,7 +728,7 @@ func (m *ApplicationResourceRequest) Reset() { *m = ApplicationResourceR
func (m *ApplicationResourceRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationResourceRequest) ProtoMessage() {}
func (*ApplicationResourceRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{11}
return fileDescriptor_application_0acf736a0f21a996, []int{11}
}
func (m *ApplicationResourceRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -809,7 +817,7 @@ func (m *ApplicationResourcePatchRequest) Reset() { *m = ApplicationReso
func (m *ApplicationResourcePatchRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationResourcePatchRequest) ProtoMessage() {}
func (*ApplicationResourcePatchRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{12}
return fileDescriptor_application_0acf736a0f21a996, []int{12}
}
func (m *ApplicationResourcePatchRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -911,7 +919,7 @@ func (m *ApplicationResourceDeleteRequest) Reset() { *m = ApplicationRes
func (m *ApplicationResourceDeleteRequest) String() string { return proto.CompactTextString(m) }
func (*ApplicationResourceDeleteRequest) ProtoMessage() {}
func (*ApplicationResourceDeleteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{13}
return fileDescriptor_application_0acf736a0f21a996, []int{13}
}
func (m *ApplicationResourceDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1006,7 +1014,7 @@ func (m *ResourceActionRunRequest) Reset() { *m = ResourceActionRunReque
func (m *ResourceActionRunRequest) String() string { return proto.CompactTextString(m) }
func (*ResourceActionRunRequest) ProtoMessage() {}
func (*ResourceActionRunRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{14}
return fileDescriptor_application_0acf736a0f21a996, []int{14}
}
func (m *ResourceActionRunRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1095,7 +1103,7 @@ func (m *ResourceActionsListResponse) Reset() { *m = ResourceActionsList
func (m *ResourceActionsListResponse) String() string { return proto.CompactTextString(m) }
func (*ResourceActionsListResponse) ProtoMessage() {}
func (*ResourceActionsListResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{15}
return fileDescriptor_application_0acf736a0f21a996, []int{15}
}
func (m *ResourceActionsListResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1142,7 +1150,7 @@ func (m *ApplicationResourceResponse) Reset() { *m = ApplicationResource
func (m *ApplicationResourceResponse) String() string { return proto.CompactTextString(m) }
func (*ApplicationResourceResponse) ProtoMessage() {}
func (*ApplicationResourceResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{16}
return fileDescriptor_application_0acf736a0f21a996, []int{16}
}
func (m *ApplicationResourceResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1196,7 +1204,7 @@ func (m *ApplicationPodLogsQuery) Reset() { *m = ApplicationPodLogsQuery
func (m *ApplicationPodLogsQuery) String() string { return proto.CompactTextString(m) }
func (*ApplicationPodLogsQuery) ProtoMessage() {}
func (*ApplicationPodLogsQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{17}
return fileDescriptor_application_0acf736a0f21a996, []int{17}
}
func (m *ApplicationPodLogsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1293,7 +1301,7 @@ func (m *LogEntry) Reset() { *m = LogEntry{} }
func (m *LogEntry) String() string { return proto.CompactTextString(m) }
func (*LogEntry) ProtoMessage() {}
func (*LogEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{18}
return fileDescriptor_application_0acf736a0f21a996, []int{18}
}
func (m *LogEntry) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1347,7 +1355,7 @@ func (m *OperationTerminateRequest) Reset() { *m = OperationTerminateReq
func (m *OperationTerminateRequest) String() string { return proto.CompactTextString(m) }
func (*OperationTerminateRequest) ProtoMessage() {}
func (*OperationTerminateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{19}
return fileDescriptor_application_0acf736a0f21a996, []int{19}
}
func (m *OperationTerminateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1393,7 +1401,7 @@ func (m *OperationTerminateResponse) Reset() { *m = OperationTerminateRe
func (m *OperationTerminateResponse) String() string { return proto.CompactTextString(m) }
func (*OperationTerminateResponse) ProtoMessage() {}
func (*OperationTerminateResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{20}
return fileDescriptor_application_0acf736a0f21a996, []int{20}
}
func (m *OperationTerminateResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1433,7 +1441,7 @@ func (m *ResourcesQuery) Reset() { *m = ResourcesQuery{} }
func (m *ResourcesQuery) String() string { return proto.CompactTextString(m) }
func (*ResourcesQuery) ProtoMessage() {}
func (*ResourcesQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{21}
return fileDescriptor_application_0acf736a0f21a996, []int{21}
}
func (m *ResourcesQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1480,7 +1488,7 @@ func (m *ManagedResourcesResponse) Reset() { *m = ManagedResourcesRespon
func (m *ManagedResourcesResponse) String() string { return proto.CompactTextString(m) }
func (*ManagedResourcesResponse) ProtoMessage() {}
func (*ManagedResourcesResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_fe5e7332ebc1d7c2, []int{22}
return fileDescriptor_application_0acf736a0f21a996, []int{22}
}
func (m *ManagedResourcesResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -2686,6 +2694,21 @@ func (m *ApplicationSyncRequest) MarshalTo(dAtA []byte) (int, error) {
i += n
}
}
if len(m.Manifests) > 0 {
for _, s := range m.Manifests {
dAtA[i] = 0x42
i++
l = len(s)
for l >= 1<<7 {
dAtA[i] = uint8(uint64(l)&0x7f | 0x80)
l >>= 7
i++
}
dAtA[i] = uint8(l)
i++
i += copy(dAtA[i:], s)
}
}
if m.XXX_unrecognized != nil {
i += copy(dAtA[i:], m.XXX_unrecognized)
}
@@ -3441,6 +3464,12 @@ func (m *ApplicationSyncRequest) Size() (n int) {
n += 1 + l + sovApplication(uint64(l))
}
}
if len(m.Manifests) > 0 {
for _, s := range m.Manifests {
l = len(s)
n += 1 + l + sovApplication(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@@ -4741,6 +4770,35 @@ func (m *ApplicationSyncRequest) Unmarshal(dAtA []byte) error {
return err
}
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Manifests", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApplication
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthApplication
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Manifests = append(m.Manifests, string(dAtA[iNdEx:postIndex]))
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipApplication(dAtA[iNdEx:])
@@ -7264,122 +7322,123 @@ var (
)
func init() {
proto.RegisterFile("server/application/application.proto", fileDescriptor_application_fe5e7332ebc1d7c2)
proto.RegisterFile("server/application/application.proto", fileDescriptor_application_0acf736a0f21a996)
}
var fileDescriptor_application_fe5e7332ebc1d7c2 = []byte{
// 1797 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xcd, 0x6f, 0x1c, 0x49,
0x15, 0xa7, 0x66, 0xc6, 0x33, 0xe3, 0x67, 0xb3, 0x1f, 0xb5, 0xbb, 0xa1, 0xb7, 0xed, 0xd8, 0xa3,
0x8a, 0xe3, 0x38, 0xde, 0xb8, 0x3b, 0x36, 0x01, 0x56, 0x16, 0xd2, 0xee, 0x7a, 0x1d, 0xbc, 0x46,
0x5e, 0x63, 0xc6, 0x5e, 0x90, 0x90, 0x10, 0xea, 0x74, 0x97, 0xc7, 0x8d, 0x67, 0xba, 0x9b, 0xee,
0x9e, 0x41, 0x43, 0x94, 0x03, 0x11, 0x42, 0x1c, 0x10, 0x08, 0xc1, 0x21, 0x20, 0xbe, 0x94, 0x33,
0x37, 0xc4, 0x85, 0x03, 0x37, 0xa4, 0x1c, 0x91, 0xe0, 0x1c, 0x21, 0x93, 0x3f, 0x80, 0x13, 0x67,
0x54, 0xd5, 0x55, 0xdd, 0xd5, 0xf6, 0x4c, 0xcf, 0x38, 0x99, 0x3d, 0xe4, 0xd6, 0xf3, 0xaa, 0xfa,
0xbd, 0xdf, 0xfb, 0xa8, 0x57, 0xef, 0xd7, 0x03, 0x4b, 0x11, 0x0d, 0x7b, 0x34, 0x34, 0xad, 0x20,
0x68, 0xbb, 0xb6, 0x15, 0xbb, 0xbe, 0xa7, 0x3e, 0x1b, 0x41, 0xe8, 0xc7, 0x3e, 0x9e, 0x51, 0x44,
0xfa, 0x9b, 0x2d, 0xbf, 0xe5, 0x73, 0xb9, 0xc9, 0x9e, 0x92, 0x2d, 0xfa, 0x7c, 0xcb, 0xf7, 0x5b,
0x6d, 0x6a, 0x5a, 0x81, 0x6b, 0x5a, 0x9e, 0xe7, 0xc7, 0x7c, 0x73, 0x24, 0x56, 0xc9, 0xe9, 0xbb,
0x91, 0xe1, 0xfa, 0x7c, 0xd5, 0xf6, 0x43, 0x6a, 0xf6, 0xd6, 0xcd, 0x16, 0xf5, 0x68, 0x68, 0xc5,
0xd4, 0x11, 0x7b, 0xee, 0x64, 0x7b, 0x3a, 0x96, 0x7d, 0xe2, 0x7a, 0x34, 0xec, 0x9b, 0xc1, 0x69,
0x8b, 0x09, 0x22, 0xb3, 0x43, 0x63, 0x6b, 0xd0, 0x5b, 0xbb, 0x2d, 0x37, 0x3e, 0xe9, 0xde, 0x33,
0x6c, 0xbf, 0x63, 0x5a, 0x21, 0x07, 0xf6, 0x5d, 0xfe, 0xb0, 0x66, 0x3b, 0xd9, 0xdb, 0xaa, 0x7b,
0xbd, 0x75, 0xab, 0x1d, 0x9c, 0x58, 0x17, 0x55, 0x6d, 0x15, 0xa9, 0x0a, 0x69, 0xe0, 0x8b, 0x58,
0xf1, 0x47, 0x37, 0xf6, 0xc3, 0xbe, 0xf2, 0x98, 0xe8, 0x20, 0x8f, 0x10, 0xbc, 0xf6, 0x41, 0x66,
0xec, 0xeb, 0x5d, 0x1a, 0xf6, 0x31, 0x86, 0x8a, 0x67, 0x75, 0xa8, 0x86, 0x1a, 0x68, 0x65, 0xba,
0xc9, 0x9f, 0xb1, 0x06, 0xb5, 0x90, 0x1e, 0x87, 0x34, 0x3a, 0xd1, 0x4a, 0x5c, 0x2c, 0x7f, 0xe2,
0x65, 0xa8, 0x31, 0xcb, 0xd4, 0x8e, 0xb5, 0x72, 0xa3, 0xbc, 0x32, 0xbd, 0x35, 0x7b, 0xf6, 0x74,
0xb1, 0x7e, 0x90, 0x88, 0xa2, 0xa6, 0x5c, 0xc4, 0x06, 0xbc, 0x1a, 0xd2, 0xc8, 0xef, 0x86, 0x36,
0xfd, 0x06, 0x0d, 0x23, 0xd7, 0xf7, 0xb4, 0x0a, 0xd3, 0xb4, 0x55, 0x79, 0xf2, 0x74, 0xf1, 0x33,
0xcd, 0xf3, 0x8b, 0xe4, 0xaf, 0x08, 0x16, 0x14, 0x68, 0x4d, 0xb1, 0x7c, 0xb7, 0x47, 0xbd, 0x38,
0x3a, 0x0f, 0xb4, 0x94, 0x02, 0xdd, 0x80, 0xd7, 0xa5, 0xa6, 0x7d, 0xab, 0x43, 0xa3, 0xc0, 0xb2,
0xa9, 0x56, 0x62, 0x1b, 0x84, 0xa1, 0x8b, 0xcb, 0x78, 0x05, 0x66, 0x55, 0xa1, 0x56, 0x56, 0xb6,
0xe7, 0x56, 0xf0, 0x32, 0xcc, 0xc8, 0xdf, 0x9f, 0xec, 0x6e, 0x6b, 0x15, 0x65, 0xa3, 0xba, 0x40,
0x0e, 0x40, 0x53, 0xb0, 0x7f, 0x6c, 0x79, 0xee, 0x31, 0x8d, 0xe2, 0xe1, 0xa8, 0x1b, 0x50, 0x0f,
0x69, 0xcf, 0xe5, 0x51, 0x29, 0x29, 0x51, 0x49, 0xa5, 0xe4, 0x2d, 0x78, 0x23, 0x1f, 0x8d, 0xc0,
0xf7, 0x22, 0x4a, 0x1e, 0xa3, 0x9c, 0xa5, 0x0f, 0x43, 0x6a, 0xc5, 0xb4, 0x49, 0xbf, 0xd7, 0xa5,
0x51, 0x8c, 0x3d, 0x50, 0x4f, 0x02, 0x37, 0x38, 0xb3, 0xf1, 0x15, 0x23, 0xab, 0x1b, 0x43, 0xd6,
0x0d, 0x7f, 0xf8, 0x8e, 0xed, 0x18, 0xc1, 0x69, 0xcb, 0x60, 0x25, 0x68, 0xa8, 0xa7, 0x4a, 0x96,
0xa0, 0xa1, 0x58, 0x92, 0x5e, 0x2b, 0xfb, 0xf0, 0x15, 0xa8, 0x76, 0x83, 0x88, 0x86, 0x31, 0xf7,
0xa1, 0xde, 0x14, 0xbf, 0xc8, 0x8f, 0xf2, 0x20, 0x3f, 0x09, 0x1c, 0x05, 0xe4, 0xc9, 0xa7, 0x08,
0x32, 0x07, 0x8f, 0x7c, 0x94, 0x43, 0xb1, 0x4d, 0xdb, 0x34, 0x43, 0x31, 0x28, 0x29, 0x1a, 0xd4,
0x6c, 0x2b, 0xb2, 0x2d, 0x87, 0x0a, 0x7f, 0xe4, 0x4f, 0xf2, 0x9f, 0x12, 0x5c, 0x51, 0x54, 0x1d,
0xf6, 0x3d, 0xbb, 0x48, 0xd1, 0xc8, 0xec, 0xe2, 0x79, 0xa8, 0x3a, 0x61, 0xbf, 0xd9, 0xf5, 0xb4,
0x32, 0xb3, 0x24, 0xd6, 0x85, 0x0c, 0xeb, 0x30, 0x15, 0x84, 0x5d, 0x8f, 0xf2, 0x03, 0x23, 0x17,
0x13, 0x11, 0xb6, 0xa1, 0x1e, 0xc5, 0xac, 0x2d, 0xb4, 0xfa, 0xda, 0x54, 0x03, 0xad, 0xcc, 0x6c,
0xec, 0xbc, 0x40, 0xec, 0x98, 0x27, 0x87, 0x42, 0x5d, 0x33, 0x55, 0x8c, 0x63, 0x98, 0x96, 0xd5,
0x1d, 0x69, 0xb5, 0x46, 0x79, 0x65, 0x66, 0xe3, 0xe0, 0x05, 0xad, 0x7c, 0x2d, 0x60, 0xcd, 0x4c,
0x39, 0xd8, 0xc2, 0xad, 0xcc, 0x10, 0x6b, 0x4e, 0xf3, 0x17, 0xca, 0xe6, 0x30, 0xa0, 0x85, 0xb1,
0x76, 0xa0, 0x12, 0x05, 0xd4, 0xe6, 0x47, 0x7e, 0x66, 0xe3, 0xab, 0x93, 0xa9, 0x23, 0x66, 0x54,
0xe0, 0xe3, 0xda, 0xc9, 0x2e, 0x7c, 0x4e, 0x59, 0x3e, 0xb0, 0x62, 0xfb, 0xa4, 0x08, 0x14, 0x4b,
0x20, 0xdb, 0x93, 0x6b, 0x44, 0x89, 0x88, 0xfc, 0x18, 0x81, 0xae, 0x96, 0xac, 0xdf, 0x6e, 0xdf,
0xb3, 0xec, 0xd3, 0x62, 0x75, 0x25, 0xd7, 0xe1, 0xba, 0xca, 0x5b, 0xc0, 0x74, 0x9d, 0x3d, 0x5d,
0x2c, 0xed, 0x6e, 0x37, 0x4b, 0xae, 0xf3, 0xfc, 0x95, 0x44, 0xfe, 0x75, 0x0e, 0x88, 0xc8, 0x43,
0x11, 0x10, 0x02, 0xd3, 0xde, 0xc0, 0x26, 0x9b, 0x89, 0x2f, 0xd1, 0x5c, 0x17, 0xa0, 0xd6, 0x4b,
0x6f, 0x86, 0x6c, 0x93, 0x14, 0x32, 0xf0, 0xad, 0xd0, 0xef, 0x06, 0xda, 0x94, 0x1a, 0x45, 0x2e,
0xc2, 0x1a, 0x54, 0x4e, 0x5d, 0xcf, 0xd1, 0xaa, 0xca, 0x12, 0x97, 0x90, 0x5f, 0x97, 0x60, 0x71,
0x80, 0x5b, 0x23, 0x73, 0xf6, 0x12, 0xf8, 0x96, 0xd5, 0x55, 0xed, 0x42, 0x5d, 0x31, 0xfc, 0xfc,
0xe1, 0xa8, 0x1f, 0x50, 0xad, 0xae, 0xe2, 0x4f, 0xc5, 0xe4, 0x7f, 0x08, 0x1a, 0x03, 0x62, 0x33,
0xba, 0x35, 0xbe, 0x24, 0xc1, 0x39, 0xf6, 0x43, 0x9b, 0x6a, 0xb5, 0xb4, 0xd6, 0x51, 0x33, 0x11,
0x91, 0xff, 0x22, 0xd0, 0xa4, 0xb7, 0x1f, 0xd8, 0xdc, 0xf7, 0xae, 0xf7, 0xb2, 0x3b, 0x3c, 0x0f,
0x55, 0x8b, 0xfb, 0x92, 0x2b, 0x07, 0x21, 0x23, 0x3f, 0x41, 0x30, 0x97, 0x77, 0x39, 0xda, 0x73,
0xa3, 0x58, 0x4e, 0x12, 0xd8, 0x85, 0x5a, 0xb2, 0x33, 0xd2, 0x10, 0xef, 0xf0, 0xbb, 0x2f, 0xd0,
0x3b, 0xf3, 0x86, 0xa4, 0x7b, 0x42, 0x3f, 0x79, 0x0f, 0xe6, 0x06, 0x36, 0x1a, 0x81, 0xa4, 0x01,
0xf5, 0x8e, 0x98, 0x98, 0x92, 0x1c, 0xc8, 0xeb, 0x52, 0x4a, 0xc9, 0xdf, 0x4b, 0xf9, 0xfe, 0xeb,
0x3b, 0x7b, 0x7e, 0xab, 0x60, 0x28, 0x1c, 0x27, 0x7b, 0x1a, 0xd4, 0x02, 0xdf, 0xc9, 0x12, 0xd7,
0x94, 0x3f, 0xd9, 0xdb, 0xb6, 0xef, 0xc5, 0x16, 0x1b, 0xf1, 0x73, 0xf9, 0xca, 0xc4, 0x2c, 0xf7,
0x91, 0xeb, 0xd9, 0xf4, 0x90, 0xda, 0xbe, 0xe7, 0x44, 0x3c, 0x71, 0x65, 0x99, 0x7b, 0x75, 0x05,
0x7f, 0x04, 0xd3, 0xfc, 0xf7, 0x91, 0xdb, 0xa1, 0x5a, 0x95, 0xdf, 0xd8, 0xab, 0x46, 0xc2, 0x25,
0x0c, 0x95, 0x4b, 0x64, 0x11, 0x66, 0x5c, 0xc2, 0xe8, 0xad, 0x1b, 0xec, 0x8d, 0x66, 0xf6, 0x32,
0xc3, 0x15, 0x5b, 0x6e, 0x7b, 0xcf, 0xf5, 0xf8, 0xad, 0x9c, 0x19, 0xcc, 0xc4, 0xac, 0x26, 0x8e,
0xfd, 0x76, 0xdb, 0xff, 0x3e, 0x6f, 0x01, 0xe9, 0x75, 0x90, 0xc8, 0xc8, 0x0f, 0xa0, 0xbe, 0xe7,
0xb7, 0xee, 0x7a, 0x71, 0xd8, 0x67, 0x35, 0xc9, 0xdc, 0xa1, 0x5e, 0x3e, 0xe8, 0x52, 0x88, 0xf7,
0x61, 0x3a, 0x76, 0x3b, 0xf4, 0x30, 0xb6, 0x3a, 0x81, 0xb8, 0x5d, 0x2f, 0x81, 0x3b, 0x45, 0x26,
0x55, 0x10, 0x13, 0xde, 0x4e, 0x67, 0x80, 0x23, 0x1a, 0x76, 0x5c, 0xcf, 0x2a, 0xec, 0x39, 0x64,
0x1e, 0xf4, 0x41, 0x2f, 0x88, 0x41, 0xf8, 0x7d, 0x78, 0x45, 0x16, 0x92, 0x28, 0x04, 0x03, 0x5e,
0x55, 0x6a, 0x73, 0x3f, 0x55, 0x27, 0x3a, 0xc1, 0xf9, 0x45, 0xd2, 0x07, 0xed, 0x63, 0xcb, 0xb3,
0x5a, 0xd4, 0x49, 0x15, 0xa5, 0x25, 0xf9, 0x6d, 0x98, 0x72, 0x63, 0xda, 0x91, 0x47, 0x63, 0x67,
0x02, 0x47, 0x63, 0xdb, 0x3d, 0x3e, 0x6e, 0x26, 0x5a, 0x37, 0x9e, 0xbd, 0x0d, 0x58, 0x1d, 0x37,
0x68, 0xd8, 0x73, 0x6d, 0x8a, 0x7f, 0x8e, 0xa0, 0xc2, 0xce, 0x28, 0xbe, 0x9a, 0x53, 0x75, 0x9e,
0xb0, 0xe9, 0x13, 0x9a, 0x72, 0x98, 0x29, 0x32, 0xff, 0xf0, 0x9f, 0xcf, 0x7e, 0x59, 0xba, 0x82,
0xdf, 0xe4, 0xe4, 0xb7, 0xb7, 0xae, 0x72, 0xd1, 0x08, 0xff, 0x14, 0x01, 0x16, 0x5d, 0x43, 0x61,
0x63, 0xf8, 0x9d, 0x61, 0xf8, 0x06, 0xb0, 0x36, 0xfd, 0xaa, 0x52, 0x35, 0x06, 0x63, 0xd7, 0xac,
0x46, 0xf8, 0x06, 0x0e, 0x60, 0x95, 0x03, 0x58, 0xc2, 0x64, 0x10, 0x00, 0xf3, 0x3e, 0x2b, 0x85,
0x07, 0x26, 0x4d, 0xec, 0xfe, 0x01, 0xc1, 0xd4, 0x37, 0xf9, 0x6d, 0x37, 0x22, 0x42, 0x07, 0x93,
0x89, 0x10, 0xb7, 0xc5, 0xa1, 0x92, 0x6b, 0x1c, 0xe6, 0x55, 0x3c, 0x27, 0x61, 0x46, 0x71, 0x48,
0xad, 0x4e, 0x0e, 0xed, 0x6d, 0x84, 0x1f, 0x23, 0xa8, 0x26, 0xa4, 0x0c, 0x5f, 0x1f, 0x06, 0x31,
0x47, 0xda, 0xf4, 0x09, 0x51, 0x1f, 0x72, 0x93, 0x03, 0xbc, 0x46, 0x06, 0x26, 0x72, 0x33, 0xc7,
0xdb, 0x7e, 0x81, 0xa0, 0xbc, 0x43, 0x47, 0x96, 0xd9, 0xa4, 0x90, 0x5d, 0x08, 0xdd, 0x80, 0x0c,
0xe3, 0x87, 0x08, 0x66, 0x77, 0x68, 0x2c, 0xa9, 0x73, 0x34, 0x3c, 0x7c, 0x39, 0x76, 0xad, 0xcf,
0x1b, 0xca, 0x47, 0x0e, 0xb9, 0x94, 0x76, 0x89, 0x35, 0x6e, 0xfa, 0x06, 0xbe, 0x5e, 0x54, 0x5c,
0x9d, 0xd4, 0xe6, 0xdf, 0x10, 0x54, 0x13, 0xda, 0x31, 0xdc, 0x7c, 0x8e, 0xcd, 0x4e, 0x2c, 0x46,
0x77, 0x39, 0xd0, 0xf7, 0xf4, 0xdb, 0x83, 0x81, 0xaa, 0xef, 0xb3, 0x36, 0xeb, 0x58, 0xb1, 0x65,
0x70, 0xf4, 0xf9, 0xcc, 0xfe, 0x19, 0x01, 0x64, 0xbc, 0x09, 0xdf, 0x2c, 0x76, 0x42, 0xe1, 0x56,
0xfa, 0x04, 0x99, 0x13, 0x31, 0xb8, 0x33, 0x2b, 0x7a, 0xa3, 0x28, 0xea, 0x8c, 0x57, 0x6d, 0x72,
0x76, 0x85, 0x7f, 0x87, 0x60, 0x8a, 0xcf, 0xe7, 0x78, 0x69, 0x18, 0x60, 0x75, 0x7c, 0x9f, 0x58,
0xd0, 0x97, 0x39, 0xce, 0xc6, 0x46, 0x51, 0x61, 0x6e, 0xa2, 0x55, 0xdc, 0x83, 0x6a, 0x32, 0x22,
0x0f, 0xaf, 0x8a, 0xdc, 0x08, 0xad, 0x37, 0x0a, 0xfa, 0x63, 0x52, 0x98, 0xe2, 0x4c, 0xac, 0x16,
0x9e, 0x89, 0x3f, 0x22, 0xa8, 0x30, 0xee, 0x8c, 0xaf, 0x0d, 0xd3, 0xa7, 0x7c, 0x89, 0x98, 0x58,
0x54, 0xde, 0xe1, 0xd0, 0xae, 0x93, 0xe2, 0xec, 0xf5, 0x3d, 0x9b, 0x85, 0xe6, 0x11, 0x82, 0xd7,
0xce, 0xdf, 0xa2, 0x78, 0x2e, 0x67, 0x24, 0x7f, 0x4d, 0xeb, 0xf9, 0x10, 0x0e, 0xbb, 0x81, 0xc9,
0xfb, 0x1c, 0xc5, 0x26, 0x7e, 0x77, 0xe4, 0x81, 0xd8, 0x97, 0x87, 0x98, 0x29, 0x5a, 0x4b, 0x3f,
0x27, 0xe0, 0xbf, 0x20, 0x98, 0x95, 0x7a, 0x8f, 0x42, 0x4a, 0x8b, 0x61, 0x4d, 0xa8, 0xfe, 0x99,
0x21, 0xf2, 0x65, 0x8e, 0xfd, 0x8b, 0xf8, 0xce, 0x98, 0xd8, 0x25, 0xe6, 0xb5, 0x98, 0xc1, 0xfc,
0x13, 0x82, 0xba, 0xfc, 0x2a, 0x80, 0x6f, 0x0c, 0xad, 0xa4, 0xfc, 0x77, 0x83, 0x89, 0x65, 0xdf,
0xe4, 0xd8, 0x6f, 0x92, 0xa5, 0xa2, 0xec, 0x87, 0xc2, 0x38, 0xab, 0x80, 0x5f, 0x21, 0xc0, 0xe9,
0x78, 0x96, 0x0e, 0x6c, 0x78, 0x39, 0x67, 0x6a, 0xe8, 0xe4, 0xa7, 0xdf, 0x18, 0xb9, 0x2f, 0xdf,
0xca, 0x57, 0x0b, 0x5b, 0xb9, 0x9f, 0xda, 0xff, 0x19, 0x82, 0x99, 0x1d, 0x9a, 0x0e, 0x2e, 0x05,
0x81, 0xcc, 0x7f, 0xf7, 0xd0, 0x57, 0x46, 0x6f, 0x14, 0x88, 0x6e, 0x71, 0x44, 0xcb, 0xb8, 0x38,
0x54, 0x12, 0xc0, 0x6f, 0x11, 0x7c, 0x56, 0x74, 0x31, 0x21, 0xb9, 0x35, 0xca, 0x52, 0xae, 0xe9,
0x8d, 0x8f, 0xeb, 0xf3, 0x1c, 0xd7, 0x1a, 0x19, 0x0b, 0xd7, 0xa6, 0xf8, 0x7c, 0xf0, 0x7b, 0x04,
0x6f, 0xa8, 0x93, 0x9e, 0xa0, 0x8c, 0xcf, 0x1b, 0xb7, 0x02, 0xe6, 0x49, 0xee, 0x70, 0x7c, 0x06,
0xbe, 0x35, 0x0e, 0x3e, 0x53, 0x90, 0x48, 0xfc, 0x1b, 0x04, 0xaf, 0x73, 0xd2, 0xae, 0x2a, 0x3e,
0xd7, 0x90, 0x87, 0x51, 0xfc, 0x31, 0x1a, 0xb2, 0x38, 0xb3, 0xe4, 0x52, 0xa0, 0x36, 0x05, 0xd9,
0x66, 0x93, 0xfb, 0x2b, 0xf2, 0x0a, 0x10, 0xd9, 0x5d, 0x1b, 0x15, 0xb8, 0xcb, 0x5e, 0x19, 0xa2,
0xdc, 0x56, 0xc7, 0x2b, 0xb7, 0x1f, 0x22, 0xa8, 0x09, 0x9e, 0x5c, 0x70, 0xab, 0x2a, 0x44, 0x5a,
0x7f, 0x2b, 0xb7, 0x4b, 0xf2, 0x44, 0xf2, 0x25, 0x6e, 0x76, 0x1d, 0x9b, 0x45, 0x66, 0x03, 0xdf,
0x89, 0xcc, 0xfb, 0x82, 0x40, 0x3f, 0x30, 0xdb, 0x7e, 0x2b, 0xba, 0x8d, 0xb6, 0x3e, 0x7c, 0x72,
0xb6, 0x80, 0xfe, 0x71, 0xb6, 0x80, 0xfe, 0x7d, 0xb6, 0x80, 0xbe, 0xf5, 0x85, 0x31, 0xfe, 0x0a,
0xb3, 0xdb, 0x2e, 0xf5, 0x62, 0xd5, 0xc4, 0xff, 0x03, 0x00, 0x00, 0xff, 0xff, 0x99, 0x7a, 0xd8,
0x90, 0x03, 0x1c, 0x00, 0x00,
var fileDescriptor_application_0acf736a0f21a996 = []byte{
// 1809 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x59, 0xcd, 0x6f, 0x23, 0x49,
0x15, 0xa7, 0x6c, 0xc7, 0x76, 0x5e, 0xc2, 0x7e, 0xd4, 0xee, 0x0e, 0xbd, 0x1d, 0x4f, 0x62, 0xd5,
0x64, 0x32, 0x99, 0xec, 0xa4, 0x7b, 0x12, 0x06, 0x58, 0x45, 0x48, 0xbb, 0x9b, 0xcd, 0x90, 0x0d,
0xca, 0x86, 0xe0, 0x64, 0x41, 0x42, 0x42, 0xa8, 0xb7, 0xbb, 0xe2, 0x34, 0xb1, 0xbb, 0x9b, 0xee,
0xb6, 0x91, 0x59, 0xed, 0x61, 0x57, 0x08, 0x71, 0x40, 0x20, 0x04, 0x87, 0x01, 0xf1, 0xa5, 0x39,
0x73, 0x43, 0x5c, 0x38, 0x70, 0x43, 0x9a, 0x23, 0x12, 0x9c, 0x47, 0x28, 0x9a, 0x3f, 0x80, 0x13,
0x67, 0x54, 0xd5, 0x55, 0xdd, 0xd5, 0x89, 0xdd, 0x76, 0x66, 0xbc, 0x87, 0xb9, 0xb5, 0x5f, 0x55,
0xbf, 0xf7, 0x7b, 0x1f, 0xf5, 0xea, 0xfd, 0xda, 0xb0, 0x1c, 0xd1, 0xb0, 0x4f, 0x43, 0xd3, 0x0a,
0x82, 0x8e, 0x6b, 0x5b, 0xb1, 0xeb, 0x7b, 0xea, 0xb3, 0x11, 0x84, 0x7e, 0xec, 0xe3, 0x39, 0x45,
0xa4, 0xbf, 0xda, 0xf6, 0xdb, 0x3e, 0x97, 0x9b, 0xec, 0x29, 0xd9, 0xa2, 0x37, 0xda, 0xbe, 0xdf,
0xee, 0x50, 0xd3, 0x0a, 0x5c, 0xd3, 0xf2, 0x3c, 0x3f, 0xe6, 0x9b, 0x23, 0xb1, 0x4a, 0xce, 0xde,
0x8c, 0x0c, 0xd7, 0xe7, 0xab, 0xb6, 0x1f, 0x52, 0xb3, 0xbf, 0x61, 0xb6, 0xa9, 0x47, 0x43, 0x2b,
0xa6, 0x8e, 0xd8, 0x73, 0x2f, 0xdb, 0xd3, 0xb5, 0xec, 0x53, 0xd7, 0xa3, 0xe1, 0xc0, 0x0c, 0xce,
0xda, 0x4c, 0x10, 0x99, 0x5d, 0x1a, 0x5b, 0xc3, 0xde, 0xda, 0x6b, 0xbb, 0xf1, 0x69, 0xef, 0x43,
0xc3, 0xf6, 0xbb, 0xa6, 0x15, 0x72, 0x60, 0xdf, 0xe7, 0x0f, 0xeb, 0xb6, 0x93, 0xbd, 0xad, 0xba,
0xd7, 0xdf, 0xb0, 0x3a, 0xc1, 0xa9, 0x75, 0x59, 0xd5, 0x76, 0x91, 0xaa, 0x90, 0x06, 0xbe, 0x88,
0x15, 0x7f, 0x74, 0x63, 0x3f, 0x1c, 0x28, 0x8f, 0x89, 0x0e, 0xf2, 0x00, 0xc1, 0x4b, 0xef, 0x64,
0xc6, 0xbe, 0xd9, 0xa3, 0xe1, 0x00, 0x63, 0xa8, 0x78, 0x56, 0x97, 0x6a, 0xa8, 0x89, 0x56, 0x67,
0x5b, 0xfc, 0x19, 0x6b, 0x50, 0x0b, 0xe9, 0x49, 0x48, 0xa3, 0x53, 0xad, 0xc4, 0xc5, 0xf2, 0x27,
0x5e, 0x81, 0x1a, 0xb3, 0x4c, 0xed, 0x58, 0x2b, 0x37, 0xcb, 0xab, 0xb3, 0xdb, 0xf3, 0xe7, 0x8f,
0x97, 0xea, 0x87, 0x89, 0x28, 0x6a, 0xc9, 0x45, 0x6c, 0xc0, 0x8b, 0x21, 0x8d, 0xfc, 0x5e, 0x68,
0xd3, 0x6f, 0xd1, 0x30, 0x72, 0x7d, 0x4f, 0xab, 0x30, 0x4d, 0xdb, 0x95, 0x47, 0x8f, 0x97, 0x3e,
0xd7, 0xba, 0xb8, 0x48, 0xfe, 0x86, 0x60, 0x51, 0x81, 0xd6, 0x12, 0xcb, 0xf7, 0xfb, 0xd4, 0x8b,
0xa3, 0x8b, 0x40, 0x4b, 0x29, 0xd0, 0x4d, 0x78, 0x59, 0x6a, 0x3a, 0xb0, 0xba, 0x34, 0x0a, 0x2c,
0x9b, 0x6a, 0x25, 0xb6, 0x41, 0x18, 0xba, 0xbc, 0x8c, 0x57, 0x61, 0x5e, 0x15, 0x6a, 0x65, 0x65,
0x7b, 0x6e, 0x05, 0xaf, 0xc0, 0x9c, 0xfc, 0xfd, 0xc1, 0xde, 0x8e, 0x56, 0x51, 0x36, 0xaa, 0x0b,
0xe4, 0x10, 0x34, 0x05, 0xfb, 0xfb, 0x96, 0xe7, 0x9e, 0xd0, 0x28, 0x1e, 0x8d, 0xba, 0x09, 0xf5,
0x90, 0xf6, 0x5d, 0x1e, 0x95, 0x92, 0x12, 0x95, 0x54, 0x4a, 0x5e, 0x83, 0x57, 0xf2, 0xd1, 0x08,
0x7c, 0x2f, 0xa2, 0xe4, 0x21, 0xca, 0x59, 0x7a, 0x37, 0xa4, 0x56, 0x4c, 0x5b, 0xf4, 0x07, 0x3d,
0x1a, 0xc5, 0xd8, 0x03, 0xf5, 0x24, 0x70, 0x83, 0x73, 0x9b, 0x5f, 0x33, 0xb2, 0xba, 0x31, 0x64,
0xdd, 0xf0, 0x87, 0xef, 0xd9, 0x8e, 0x11, 0x9c, 0xb5, 0x0d, 0x56, 0x82, 0x86, 0x7a, 0xaa, 0x64,
0x09, 0x1a, 0x8a, 0x25, 0xe9, 0xb5, 0xb2, 0x0f, 0x5f, 0x83, 0x6a, 0x2f, 0x88, 0x68, 0x18, 0x73,
0x1f, 0xea, 0x2d, 0xf1, 0x8b, 0xfc, 0x38, 0x0f, 0xf2, 0x83, 0xc0, 0x51, 0x40, 0x9e, 0x7e, 0x86,
0x20, 0x73, 0xf0, 0xc8, 0x7b, 0x39, 0x14, 0x3b, 0xb4, 0x43, 0x33, 0x14, 0xc3, 0x92, 0xa2, 0x41,
0xcd, 0xb6, 0x22, 0xdb, 0x72, 0xa8, 0xf0, 0x47, 0xfe, 0x24, 0x9f, 0x94, 0xe1, 0x9a, 0xa2, 0xea,
0x68, 0xe0, 0xd9, 0x45, 0x8a, 0xc6, 0x66, 0x17, 0x37, 0xa0, 0xea, 0x84, 0x83, 0x56, 0xcf, 0xd3,
0xca, 0xcc, 0x92, 0x58, 0x17, 0x32, 0xac, 0xc3, 0x4c, 0x10, 0xf6, 0x3c, 0xca, 0x0f, 0x8c, 0x5c,
0x4c, 0x44, 0xd8, 0x86, 0x7a, 0x14, 0xb3, 0xb6, 0xd0, 0x1e, 0x68, 0x33, 0x4d, 0xb4, 0x3a, 0xb7,
0xb9, 0xfb, 0x0c, 0xb1, 0x63, 0x9e, 0x1c, 0x09, 0x75, 0xad, 0x54, 0x31, 0x8e, 0x61, 0x56, 0x56,
0x77, 0xa4, 0xd5, 0x9a, 0xe5, 0xd5, 0xb9, 0xcd, 0xc3, 0x67, 0xb4, 0xf2, 0x8d, 0x80, 0x35, 0x33,
0xe5, 0x60, 0x0b, 0xb7, 0x32, 0x43, 0xb8, 0x01, 0xb3, 0x5d, 0x71, 0x72, 0x22, 0xad, 0xce, 0x7a,
0x4b, 0x2b, 0x13, 0xb0, 0xd6, 0xd5, 0xb8, 0x54, 0x54, 0x47, 0x01, 0x2d, 0xcc, 0x84, 0x03, 0x95,
0x28, 0xa0, 0x36, 0x6f, 0x08, 0x73, 0x9b, 0x5f, 0x9f, 0x4e, 0x95, 0x31, 0xa3, 0x02, 0x3d, 0xd7,
0x4e, 0xf6, 0xe0, 0x0b, 0xca, 0xf2, 0xa1, 0x15, 0xdb, 0xa7, 0x45, 0xa0, 0x58, 0x7a, 0xd9, 0x9e,
0x5c, 0x9b, 0x4a, 0x44, 0xe4, 0x27, 0x08, 0x74, 0xb5, 0xa0, 0xfd, 0x4e, 0xe7, 0x43, 0xcb, 0x3e,
0x2b, 0x56, 0x57, 0x72, 0x1d, 0xae, 0xab, 0xbc, 0x0d, 0x4c, 0xd7, 0xf9, 0xe3, 0xa5, 0xd2, 0xde,
0x4e, 0xab, 0xe4, 0x3a, 0x4f, 0x5f, 0x67, 0xe4, 0xdf, 0x17, 0x80, 0x88, 0x2c, 0x15, 0x01, 0x21,
0x30, 0xeb, 0x0d, 0x6d, 0xc1, 0x99, 0xf8, 0x0a, 0xad, 0x77, 0x11, 0x6a, 0xfd, 0xf4, 0xde, 0xc8,
0x36, 0x49, 0x21, 0x03, 0xdf, 0x0e, 0xfd, 0x5e, 0xa0, 0xcd, 0xa8, 0x51, 0xe4, 0x22, 0xac, 0x41,
0xe5, 0xcc, 0xf5, 0x1c, 0xad, 0xaa, 0x2c, 0x71, 0x09, 0xf9, 0x4d, 0x09, 0x96, 0x86, 0xb8, 0x35,
0x36, 0x67, 0xcf, 0x81, 0x6f, 0x59, 0x5d, 0xd5, 0x2e, 0xd5, 0x15, 0xc3, 0xcf, 0x1f, 0x8e, 0x07,
0x01, 0xd5, 0xea, 0x2a, 0xfe, 0x54, 0x4c, 0xfe, 0x87, 0xa0, 0x39, 0x24, 0x36, 0xe3, 0x1b, 0xe7,
0x73, 0x12, 0x9c, 0x13, 0x3f, 0xb4, 0xa9, 0x56, 0x4b, 0x6b, 0x1d, 0xb5, 0x12, 0x11, 0xf9, 0x2f,
0x02, 0x4d, 0x7a, 0xfb, 0x8e, 0xcd, 0x7d, 0xef, 0x79, 0xcf, 0xbb, 0xc3, 0x0d, 0xa8, 0x5a, 0xdc,
0x97, 0x5c, 0x39, 0x08, 0x19, 0xf9, 0x29, 0x82, 0x85, 0xbc, 0xcb, 0xd1, 0xbe, 0x1b, 0xc5, 0x72,
0xce, 0xc0, 0x2e, 0xd4, 0x92, 0x9d, 0x91, 0x86, 0x78, 0xff, 0xdf, 0x7b, 0x86, 0xde, 0x99, 0x37,
0x24, 0xdd, 0x13, 0xfa, 0xc9, 0x5b, 0xb0, 0x30, 0xb4, 0xd1, 0x08, 0x24, 0x4d, 0xa8, 0xcb, 0x4b,
0x20, 0xc9, 0x81, 0xbc, 0x4c, 0xa5, 0x94, 0xfc, 0xa3, 0x94, 0xef, 0xbf, 0xbe, 0xb3, 0xef, 0xb7,
0x0b, 0x46, 0xc6, 0x49, 0xb2, 0xa7, 0x41, 0x2d, 0xf0, 0x9d, 0x2c, 0x71, 0x2d, 0xf9, 0x93, 0xbd,
0x6d, 0xfb, 0x5e, 0x6c, 0x31, 0x02, 0x90, 0xcb, 0x57, 0x26, 0x66, 0xb9, 0x8f, 0x5c, 0xcf, 0xa6,
0x47, 0xd4, 0xf6, 0x3d, 0x27, 0xe2, 0x89, 0x2b, 0xcb, 0xdc, 0xab, 0x2b, 0xf8, 0x3d, 0x98, 0xe5,
0xbf, 0x8f, 0xdd, 0x2e, 0xd5, 0xaa, 0xfc, 0x3e, 0x5f, 0x33, 0x12, 0xa6, 0x61, 0xa8, 0x4c, 0x23,
0x8b, 0x30, 0x63, 0x1a, 0x46, 0x7f, 0xc3, 0x60, 0x6f, 0xb4, 0xb2, 0x97, 0x19, 0xae, 0xd8, 0x72,
0x3b, 0xfb, 0xae, 0xc7, 0xef, 0xec, 0xcc, 0x60, 0x26, 0x66, 0x35, 0x71, 0xe2, 0x77, 0x3a, 0xfe,
0x0f, 0x79, 0x0b, 0x48, 0xaf, 0x83, 0x44, 0x46, 0x7e, 0x04, 0xf5, 0x7d, 0xbf, 0x7d, 0xdf, 0x8b,
0xc3, 0x01, 0xab, 0x49, 0xe6, 0x0e, 0xf5, 0xf2, 0x41, 0x97, 0x42, 0x7c, 0x00, 0xb3, 0xb1, 0xdb,
0xa5, 0x47, 0xb1, 0xd5, 0x0d, 0xc4, 0xed, 0x7a, 0x05, 0xdc, 0x29, 0x32, 0xa9, 0x82, 0x98, 0xf0,
0x7a, 0x3a, 0x21, 0x1c, 0xd3, 0xb0, 0xeb, 0x7a, 0x56, 0x61, 0xcf, 0x21, 0x0d, 0xd0, 0x87, 0xbd,
0x20, 0xc6, 0xe4, 0xb7, 0xe1, 0x05, 0x59, 0x48, 0xa2, 0x10, 0x0c, 0x78, 0x51, 0xa9, 0xcd, 0x83,
0x54, 0x9d, 0xe8, 0x04, 0x17, 0x17, 0xc9, 0x00, 0xb4, 0xf7, 0x2d, 0xcf, 0x6a, 0x53, 0x27, 0x55,
0x94, 0x96, 0xe4, 0x77, 0x61, 0xc6, 0x8d, 0x69, 0x57, 0x1e, 0x8d, 0xdd, 0x29, 0x1c, 0x8d, 0x1d,
0xf7, 0xe4, 0xa4, 0x95, 0x68, 0xdd, 0x7c, 0xf2, 0x3a, 0x60, 0x75, 0xdc, 0xa0, 0x61, 0xdf, 0xb5,
0x29, 0xfe, 0x05, 0x82, 0x0a, 0x3b, 0xa3, 0xf8, 0x7a, 0x4e, 0xd5, 0x45, 0x3a, 0xa7, 0x4f, 0x69,
0xca, 0x61, 0xa6, 0x48, 0xe3, 0xd3, 0x7f, 0x3d, 0xf9, 0x55, 0xe9, 0x1a, 0x7e, 0x95, 0x53, 0xe3,
0xfe, 0x86, 0xca, 0x54, 0x23, 0xfc, 0x33, 0x04, 0x58, 0x74, 0x0d, 0x85, 0xab, 0xe1, 0x37, 0x46,
0xe1, 0x1b, 0xc2, 0xe9, 0xf4, 0xeb, 0x4a, 0xd5, 0x18, 0x8c, 0x7b, 0xb3, 0x1a, 0xe1, 0x1b, 0x38,
0x80, 0x35, 0x0e, 0x60, 0x19, 0x93, 0x61, 0x00, 0xcc, 0x8f, 0x58, 0x29, 0x7c, 0x6c, 0xd2, 0xc4,
0xee, 0x1f, 0x11, 0xcc, 0x7c, 0x9b, 0xdf, 0x76, 0x63, 0x22, 0x74, 0x38, 0x9d, 0x08, 0x71, 0x5b,
0x1c, 0x2a, 0xb9, 0xc1, 0x61, 0x5e, 0xc7, 0x0b, 0x12, 0x66, 0x14, 0x87, 0xd4, 0xea, 0xe6, 0xd0,
0xde, 0x45, 0xf8, 0x21, 0x82, 0x6a, 0x42, 0xd9, 0xf0, 0xcd, 0x51, 0x10, 0x73, 0x94, 0x4e, 0x9f,
0x12, 0x31, 0x22, 0xb7, 0x39, 0xc0, 0x1b, 0x64, 0x68, 0x22, 0xb7, 0x72, 0xac, 0xee, 0x97, 0x08,
0xca, 0xbb, 0x74, 0x6c, 0x99, 0x4d, 0x0b, 0xd9, 0xa5, 0xd0, 0x0d, 0xc9, 0x30, 0xfe, 0x14, 0xc1,
0xfc, 0x2e, 0x8d, 0x25, 0xb1, 0x8e, 0x46, 0x87, 0x2f, 0xc7, 0xbd, 0xf5, 0x86, 0xa1, 0x7c, 0x02,
0x91, 0x4b, 0x69, 0x97, 0x58, 0xe7, 0xa6, 0x6f, 0xe1, 0x9b, 0x45, 0xc5, 0x95, 0x32, 0x10, 0xfc,
0x77, 0x04, 0xd5, 0x84, 0x76, 0x8c, 0x36, 0x9f, 0xe3, 0xba, 0x53, 0x8b, 0xd1, 0x7d, 0x0e, 0xf4,
0x2d, 0xfd, 0xee, 0x70, 0xa0, 0xea, 0xfb, 0xac, 0xcd, 0x3a, 0x56, 0x6c, 0x19, 0x1c, 0x7d, 0x3e,
0xb3, 0x7f, 0x41, 0x00, 0x19, 0x6f, 0xc2, 0xb7, 0x8b, 0x9d, 0x50, 0xb8, 0x95, 0x3e, 0x45, 0xe6,
0x44, 0x0c, 0xee, 0xcc, 0xaa, 0xde, 0x2c, 0x8a, 0x3a, 0xe3, 0x55, 0x5b, 0x9c, 0x5d, 0xe1, 0xdf,
0x23, 0x98, 0xe1, 0xf3, 0x39, 0x5e, 0x1e, 0x05, 0x58, 0x1d, 0xdf, 0xa7, 0x16, 0xf4, 0x15, 0x8e,
0xb3, 0xb9, 0x59, 0x54, 0x98, 0x5b, 0x68, 0x0d, 0xf7, 0xa1, 0x9a, 0x8c, 0xc8, 0xa3, 0xab, 0x22,
0x37, 0x42, 0xeb, 0xcd, 0x82, 0xfe, 0x98, 0x14, 0xa6, 0x38, 0x13, 0x6b, 0x85, 0x67, 0xe2, 0x4f,
0x08, 0x2a, 0x8c, 0x59, 0xe3, 0x1b, 0xa3, 0xf4, 0x29, 0xdf, 0x29, 0xa6, 0x16, 0x95, 0x37, 0x38,
0xb4, 0x9b, 0xa4, 0x38, 0x7b, 0x03, 0xcf, 0x66, 0xa1, 0x79, 0x80, 0xe0, 0xa5, 0x8b, 0xb7, 0x28,
0x5e, 0xc8, 0x19, 0xc9, 0x5f, 0xd3, 0x7a, 0x3e, 0x84, 0xa3, 0x6e, 0x60, 0xf2, 0x36, 0x47, 0xb1,
0x85, 0xdf, 0x1c, 0x7b, 0x20, 0x0e, 0xe4, 0x21, 0x66, 0x8a, 0xd6, 0xb3, 0x8f, 0x0d, 0x7f, 0x45,
0x30, 0x2f, 0xf5, 0x1e, 0x87, 0x94, 0x16, 0xc3, 0x9a, 0x52, 0xfd, 0x33, 0x43, 0xe4, 0xab, 0x1c,
0xfb, 0x97, 0xf1, 0xbd, 0x09, 0xb1, 0x4b, 0xcc, 0xeb, 0x31, 0x83, 0xf9, 0x67, 0x04, 0x75, 0xf9,
0x55, 0x00, 0xdf, 0x1a, 0x59, 0x49, 0xf9, 0xef, 0x06, 0x53, 0xcb, 0xbe, 0xc9, 0xb1, 0xdf, 0x26,
0xcb, 0x45, 0xd9, 0x0f, 0x85, 0x71, 0x56, 0x01, 0xbf, 0x46, 0x80, 0xd3, 0xf1, 0x2c, 0x1d, 0xd8,
0xf0, 0x4a, 0xce, 0xd4, 0xc8, 0xc9, 0x4f, 0xbf, 0x35, 0x76, 0x5f, 0xbe, 0x95, 0xaf, 0x15, 0xb6,
0x72, 0x3f, 0xb5, 0xff, 0x73, 0x04, 0x73, 0xbb, 0x34, 0x1d, 0x5c, 0x0a, 0x02, 0x99, 0xff, 0xee,
0xa1, 0xaf, 0x8e, 0xdf, 0x28, 0x10, 0xdd, 0xe1, 0x88, 0x56, 0x70, 0x71, 0xa8, 0x24, 0x80, 0xdf,
0x21, 0xf8, 0xbc, 0xe8, 0x62, 0x42, 0x72, 0x67, 0x9c, 0xa5, 0x5c, 0xd3, 0x9b, 0x1c, 0xd7, 0x17,
0x39, 0xae, 0x75, 0x32, 0x11, 0xae, 0x2d, 0xf1, 0xf9, 0xe0, 0x0f, 0x08, 0x5e, 0x51, 0x27, 0x3d,
0x41, 0x19, 0x9f, 0x36, 0x6e, 0x05, 0xcc, 0x93, 0xdc, 0xe3, 0xf8, 0x0c, 0x7c, 0x67, 0x12, 0x7c,
0xa6, 0x20, 0x91, 0xf8, 0xb7, 0x08, 0x5e, 0xe6, 0xa4, 0x5d, 0x55, 0x7c, 0xa1, 0x21, 0x8f, 0xa2,
0xf8, 0x13, 0x34, 0x64, 0x71, 0x66, 0xc9, 0x95, 0x40, 0x6d, 0x09, 0xb2, 0xcd, 0x26, 0xf7, 0x17,
0xe4, 0x15, 0x20, 0xb2, 0xbb, 0x3e, 0x2e, 0x70, 0x57, 0xbd, 0x32, 0x44, 0xb9, 0xad, 0x4d, 0x56,
0x6e, 0x9f, 0x20, 0xa8, 0x09, 0x9e, 0x5c, 0x70, 0xab, 0x2a, 0x44, 0x5a, 0x7f, 0x2d, 0xb7, 0x4b,
0xf2, 0x44, 0xf2, 0x15, 0x6e, 0x76, 0x03, 0x9b, 0x45, 0x66, 0x03, 0xdf, 0x89, 0xcc, 0x8f, 0x04,
0x81, 0xfe, 0xd8, 0xec, 0xf8, 0xed, 0xe8, 0x2e, 0xda, 0x7e, 0xf7, 0xd1, 0xf9, 0x22, 0xfa, 0xe7,
0xf9, 0x22, 0xfa, 0xcf, 0xf9, 0x22, 0xfa, 0xce, 0x97, 0x26, 0xf8, 0xa3, 0xcc, 0xee, 0xb8, 0xd4,
0x8b, 0x55, 0x13, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0xbd, 0x68, 0x78, 0xac, 0x21, 0x1c, 0x00,
0x00,
}

View File

@@ -45,7 +45,7 @@ func (m *ClusterQuery) Reset() { *m = ClusterQuery{} }
func (m *ClusterQuery) String() string { return proto.CompactTextString(m) }
func (*ClusterQuery) ProtoMessage() {}
func (*ClusterQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_cluster_63d48da351ddefcc, []int{0}
return fileDescriptor_cluster_66eaae81439ad97b, []int{0}
}
func (m *ClusterQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -91,7 +91,7 @@ func (m *ClusterResponse) Reset() { *m = ClusterResponse{} }
func (m *ClusterResponse) String() string { return proto.CompactTextString(m) }
func (*ClusterResponse) ProtoMessage() {}
func (*ClusterResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_cluster_63d48da351ddefcc, []int{1}
return fileDescriptor_cluster_66eaae81439ad97b, []int{1}
}
func (m *ClusterResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -132,7 +132,7 @@ func (m *ClusterCreateRequest) Reset() { *m = ClusterCreateRequest{} }
func (m *ClusterCreateRequest) String() string { return proto.CompactTextString(m) }
func (*ClusterCreateRequest) ProtoMessage() {}
func (*ClusterCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cluster_63d48da351ddefcc, []int{2}
return fileDescriptor_cluster_66eaae81439ad97b, []int{2}
}
func (m *ClusterCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -186,7 +186,7 @@ func (m *ClusterUpdateRequest) Reset() { *m = ClusterUpdateRequest{} }
func (m *ClusterUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*ClusterUpdateRequest) ProtoMessage() {}
func (*ClusterUpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cluster_63d48da351ddefcc, []int{3}
return fileDescriptor_cluster_66eaae81439ad97b, []int{3}
}
func (m *ClusterUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -250,6 +250,8 @@ type ClusterServiceClient interface {
Update(ctx context.Context, in *ClusterUpdateRequest, opts ...grpc.CallOption) (*v1alpha1.Cluster, error)
// Delete deletes a cluster
Delete(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*ClusterResponse, error)
// RotateAuth returns a cluster by server address
RotateAuth(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*ClusterResponse, error)
}
type clusterServiceClient struct {
@@ -305,6 +307,15 @@ func (c *clusterServiceClient) Delete(ctx context.Context, in *ClusterQuery, opt
return out, nil
}
func (c *clusterServiceClient) RotateAuth(ctx context.Context, in *ClusterQuery, opts ...grpc.CallOption) (*ClusterResponse, error) {
out := new(ClusterResponse)
err := c.cc.Invoke(ctx, "/cluster.ClusterService/RotateAuth", in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// Server API for ClusterService service
type ClusterServiceServer interface {
@@ -318,6 +329,8 @@ type ClusterServiceServer interface {
Update(context.Context, *ClusterUpdateRequest) (*v1alpha1.Cluster, error)
// Delete deletes a cluster
Delete(context.Context, *ClusterQuery) (*ClusterResponse, error)
// RotateAuth returns a cluster by server address
RotateAuth(context.Context, *ClusterQuery) (*ClusterResponse, error)
}
func RegisterClusterServiceServer(s *grpc.Server, srv ClusterServiceServer) {
@@ -414,6 +427,24 @@ func _ClusterService_Delete_Handler(srv interface{}, ctx context.Context, dec fu
return interceptor(ctx, in, info, handler)
}
func _ClusterService_RotateAuth_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ClusterQuery)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ClusterServiceServer).RotateAuth(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: "/cluster.ClusterService/RotateAuth",
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ClusterServiceServer).RotateAuth(ctx, req.(*ClusterQuery))
}
return interceptor(ctx, in, info, handler)
}
var _ClusterService_serviceDesc = grpc.ServiceDesc{
ServiceName: "cluster.ClusterService",
HandlerType: (*ClusterServiceServer)(nil),
@@ -438,6 +469,10 @@ var _ClusterService_serviceDesc = grpc.ServiceDesc{
MethodName: "Delete",
Handler: _ClusterService_Delete_Handler,
},
{
MethodName: "RotateAuth",
Handler: _ClusterService_RotateAuth_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "server/cluster/cluster.proto",
@@ -1061,39 +1096,41 @@ var (
)
func init() {
proto.RegisterFile("server/cluster/cluster.proto", fileDescriptor_cluster_63d48da351ddefcc)
proto.RegisterFile("server/cluster/cluster.proto", fileDescriptor_cluster_66eaae81439ad97b)
}
var fileDescriptor_cluster_63d48da351ddefcc = []byte{
// 475 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x4f, 0x8b, 0x13, 0x31,
0x18, 0xc6, 0xc9, 0xaa, 0xa3, 0x46, 0xf1, 0x4f, 0x58, 0xa5, 0x8e, 0x6b, 0xd9, 0x9d, 0x83, 0x2c,
0xa2, 0x09, 0xad, 0x17, 0xf1, 0x22, 0xec, 0x8a, 0x22, 0x78, 0xb1, 0xe2, 0x45, 0x16, 0x24, 0x3b,
0x7d, 0xc9, 0xc6, 0x8e, 0x93, 0x98, 0x64, 0x06, 0x44, 0x44, 0xd0, 0xab, 0x78, 0xf1, 0x03, 0x78,
0xf5, 0xa3, 0x78, 0x14, 0xfc, 0x02, 0x52, 0xfc, 0x20, 0x32, 0x99, 0xa4, 0xdd, 0xed, 0x50, 0x10,
0x2c, 0x9e, 0x9a, 0xbc, 0x49, 0x9f, 0xf7, 0x97, 0x27, 0xcf, 0x04, 0x6f, 0x58, 0x30, 0x35, 0x18,
0x96, 0x17, 0x95, 0x75, 0xf3, 0x5f, 0xaa, 0x8d, 0x72, 0x8a, 0x9c, 0x0c, 0xd3, 0x74, 0x5d, 0x28,
0xa1, 0x7c, 0x8d, 0x35, 0xa3, 0x76, 0x39, 0xdd, 0x10, 0x4a, 0x89, 0x02, 0x18, 0xd7, 0x92, 0xf1,
0xb2, 0x54, 0x8e, 0x3b, 0xa9, 0x4a, 0x1b, 0x56, 0xb3, 0xc9, 0x1d, 0x4b, 0xa5, 0xf2, 0xab, 0xb9,
0x32, 0xc0, 0xea, 0x01, 0x13, 0x50, 0x82, 0xe1, 0x0e, 0xc6, 0x61, 0xcf, 0x23, 0x21, 0xdd, 0x41,
0xb5, 0x4f, 0x73, 0xf5, 0x8a, 0x71, 0xe3, 0x5b, 0xbc, 0xf4, 0x83, 0x5b, 0xf9, 0x98, 0xe9, 0x89,
0x68, 0xfe, 0x6c, 0x19, 0xd7, 0xba, 0x90, 0xb9, 0x17, 0x67, 0xf5, 0x80, 0x17, 0xfa, 0x80, 0x77,
0xa4, 0xb2, 0xeb, 0xf8, 0xec, 0x6e, 0x4b, 0xfb, 0xa4, 0x02, 0xf3, 0x86, 0x5c, 0xc6, 0x49, 0x7b,
0xb6, 0x1e, 0xda, 0x44, 0xdb, 0xa7, 0x47, 0x61, 0x96, 0x5d, 0xc4, 0xe7, 0xc3, 0xbe, 0x11, 0x58,
0xad, 0x4a, 0x0b, 0xd9, 0x27, 0x84, 0xd7, 0x43, 0x6d, 0xd7, 0x00, 0x77, 0x30, 0x82, 0xd7, 0x15,
0x58, 0x47, 0xf6, 0x70, 0x74, 0xc0, 0x8b, 0x9c, 0x19, 0xee, 0xd0, 0x39, 0x30, 0x8d, 0xc0, 0x7e,
0xf0, 0x22, 0x1f, 0x53, 0x3d, 0x11, 0xb4, 0x01, 0xa6, 0x87, 0x80, 0x69, 0x04, 0xa6, 0xb1, 0x6b,
0x94, 0x6c, 0x08, 0x2b, 0x6d, 0xc1, 0xb8, 0xde, 0xda, 0x26, 0xda, 0x3e, 0x35, 0x0a, 0xb3, 0xcc,
0xcd, 0x68, 0x9e, 0xe9, 0xf1, 0xff, 0xa2, 0x19, 0x7e, 0x3b, 0x81, 0xcf, 0x85, 0xe2, 0x53, 0x30,
0xb5, 0xcc, 0x81, 0xbc, 0xc7, 0xc7, 0x1f, 0x4b, 0xeb, 0xc8, 0x25, 0x1a, 0x63, 0x71, 0xd8, 0xe1,
0xf4, 0xc1, 0xbf, 0xb7, 0x6f, 0xe4, 0xb3, 0xde, 0x87, 0x9f, 0xbf, 0xbf, 0xac, 0x11, 0x72, 0xc1,
0x47, 0xa5, 0x1e, 0xc4, 0x10, 0x5a, 0xf2, 0x19, 0xe1, 0xa4, 0xbd, 0x11, 0x72, 0x6d, 0x91, 0xe1,
0xc8, 0x4d, 0xa5, 0x2b, 0xb0, 0x22, 0xdb, 0xf2, 0x1c, 0x57, 0xb3, 0x0e, 0xc7, 0xdd, 0xd9, 0x95,
0x7d, 0x44, 0xf8, 0xd8, 0x43, 0x58, 0xea, 0xc8, 0x0a, 0x29, 0xc8, 0x95, 0x45, 0x0a, 0xf6, 0xb6,
0x4d, 0xf0, 0x3b, 0xf2, 0x15, 0xe1, 0xa4, 0x8d, 0x46, 0xd7, 0x96, 0x23, 0x91, 0x59, 0x09, 0xd0,
0xd0, 0x03, 0xdd, 0x4c, 0xb7, 0xba, 0x40, 0xb1, 0x77, 0x00, 0x9b, 0xfb, 0xb4, 0x87, 0x93, 0xfb,
0x50, 0x80, 0x83, 0x65, 0x4e, 0xf5, 0x16, 0xcb, 0xb3, 0x8f, 0x31, 0x9c, 0xff, 0xc6, 0xf2, 0xf3,
0xef, 0xdc, 0xfb, 0x3e, 0xed, 0xa3, 0x1f, 0xd3, 0x3e, 0xfa, 0x35, 0xed, 0xa3, 0xe7, 0x83, 0xbf,
0x78, 0x43, 0xf2, 0x42, 0x42, 0xe9, 0xa2, 0xd4, 0x7e, 0xe2, 0x9f, 0x8c, 0xdb, 0x7f, 0x02, 0x00,
0x00, 0xff, 0xff, 0x9f, 0x92, 0x8b, 0xe2, 0xfe, 0x04, 0x00, 0x00,
var fileDescriptor_cluster_66eaae81439ad97b = []byte{
// 502 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x94, 0x4f, 0x8b, 0x13, 0x3f,
0x18, 0xc7, 0xc9, 0xfe, 0x7e, 0x8c, 0x1a, 0xc5, 0x3f, 0x61, 0x95, 0x3a, 0xae, 0x65, 0x37, 0xa0,
0x2e, 0x62, 0x13, 0x5a, 0x2f, 0xe2, 0x45, 0xdc, 0x15, 0x45, 0xf0, 0xe2, 0x88, 0x17, 0x59, 0x90,
0xec, 0xf4, 0x61, 0x3a, 0x76, 0x9c, 0xc4, 0x24, 0x33, 0x20, 0x22, 0x82, 0x5e, 0xc5, 0x8b, 0xe0,
0xd5, 0xb7, 0xe3, 0x51, 0xf0, 0x0d, 0x48, 0xf1, 0x85, 0xc8, 0x64, 0x92, 0x76, 0xb7, 0xa5, 0xa2,
0x58, 0x3c, 0x35, 0x79, 0x92, 0x7e, 0xbf, 0x9f, 0x7c, 0xf3, 0x4c, 0xf0, 0x86, 0x01, 0x5d, 0x83,
0xe6, 0x69, 0x51, 0x19, 0x3b, 0xfb, 0x65, 0x4a, 0x4b, 0x2b, 0xc9, 0x11, 0x3f, 0x8d, 0xd7, 0x33,
0x99, 0x49, 0x57, 0xe3, 0xcd, 0xa8, 0x5d, 0x8e, 0x37, 0x32, 0x29, 0xb3, 0x02, 0xb8, 0x50, 0x39,
0x17, 0x65, 0x29, 0xad, 0xb0, 0xb9, 0x2c, 0x8d, 0x5f, 0xa5, 0xe3, 0x1b, 0x86, 0xe5, 0xd2, 0xad,
0xa6, 0x52, 0x03, 0xaf, 0xfb, 0x3c, 0x83, 0x12, 0xb4, 0xb0, 0x30, 0xf4, 0x7b, 0xee, 0x67, 0xb9,
0x1d, 0x55, 0xfb, 0x2c, 0x95, 0xcf, 0xb9, 0xd0, 0xce, 0xe2, 0x99, 0x1b, 0xf4, 0xd2, 0x21, 0x57,
0xe3, 0xac, 0xf9, 0xb3, 0xe1, 0x42, 0xa9, 0x22, 0x4f, 0x9d, 0x38, 0xaf, 0xfb, 0xa2, 0x50, 0x23,
0xb1, 0x20, 0x45, 0x2f, 0xe3, 0x13, 0xbb, 0x2d, 0xed, 0xc3, 0x0a, 0xf4, 0x4b, 0x72, 0x0e, 0x47,
0xed, 0xd9, 0x3a, 0x68, 0x13, 0x6d, 0x1f, 0x4b, 0xfc, 0x8c, 0x9e, 0xc1, 0xa7, 0xfc, 0xbe, 0x04,
0x8c, 0x92, 0xa5, 0x01, 0xfa, 0x1e, 0xe1, 0x75, 0x5f, 0xdb, 0xd5, 0x20, 0x2c, 0x24, 0xf0, 0xa2,
0x02, 0x63, 0xc9, 0x1e, 0x0e, 0x09, 0x38, 0x91, 0xe3, 0x83, 0x1d, 0x36, 0x03, 0x66, 0x01, 0xd8,
0x0d, 0x9e, 0xa6, 0x43, 0xa6, 0xc6, 0x19, 0x6b, 0x80, 0xd9, 0x01, 0x60, 0x16, 0x80, 0x59, 0x70,
0x0d, 0x92, 0x0d, 0x61, 0xa5, 0x0c, 0x68, 0xdb, 0x59, 0xdb, 0x44, 0xdb, 0x47, 0x13, 0x3f, 0xa3,
0x76, 0x4a, 0xf3, 0x58, 0x0d, 0xff, 0x15, 0xcd, 0xe0, 0x53, 0x84, 0x4f, 0xfa, 0xe2, 0x23, 0xd0,
0x75, 0x9e, 0x02, 0x79, 0x83, 0xff, 0x7f, 0x90, 0x1b, 0x4b, 0xce, 0xb2, 0xd0, 0x16, 0x07, 0x13,
0x8e, 0xef, 0xfe, 0xbd, 0x7d, 0x23, 0x4f, 0x3b, 0x6f, 0xbf, 0xfd, 0xf8, 0xb8, 0x46, 0xc8, 0x69,
0xd7, 0x2a, 0x75, 0x3f, 0x34, 0xa1, 0x21, 0x1f, 0x10, 0x8e, 0xda, 0x1b, 0x21, 0x17, 0xe7, 0x19,
0x0e, 0xdd, 0x54, 0xbc, 0x82, 0x28, 0xe8, 0x96, 0xe3, 0xb8, 0x40, 0x17, 0x38, 0x6e, 0x4e, 0xaf,
0xec, 0x1d, 0xc2, 0xff, 0xdd, 0x83, 0xa5, 0x89, 0xac, 0x90, 0x82, 0x9c, 0x9f, 0xa7, 0xe0, 0xaf,
0xda, 0x0e, 0x7e, 0x4d, 0x3e, 0x23, 0x1c, 0xb5, 0xad, 0xb1, 0x18, 0xcb, 0xa1, 0x96, 0x59, 0x09,
0xd0, 0xc0, 0x01, 0x5d, 0x8b, 0xb7, 0x16, 0x81, 0x82, 0xb7, 0x07, 0x9b, 0xe5, 0xb4, 0x87, 0xa3,
0x3b, 0x50, 0x80, 0x85, 0x65, 0x49, 0x75, 0xe6, 0xcb, 0xd3, 0x8f, 0xd1, 0x9f, 0xff, 0xea, 0x2f,
0xce, 0x5f, 0x60, 0x9c, 0x34, 0x8f, 0x0d, 0xdc, 0xae, 0xec, 0xe8, 0xcf, 0x1d, 0x7a, 0xce, 0xe1,
0x0a, 0xbd, 0xb4, 0xd4, 0x81, 0x6b, 0x27, 0xdf, 0x13, 0x95, 0x1d, 0xed, 0xdc, 0xfa, 0x32, 0xe9,
0xa2, 0xaf, 0x93, 0x2e, 0xfa, 0x3e, 0xe9, 0xa2, 0x27, 0xfd, 0xdf, 0x78, 0xb1, 0xd2, 0x22, 0x87,
0xd2, 0x06, 0xd9, 0xfd, 0xc8, 0x3d, 0x50, 0xd7, 0x7f, 0x06, 0x00, 0x00, 0xff, 0xff, 0x4e, 0xde,
0x52, 0x19, 0x6c, 0x05, 0x00, 0x00,
}

View File

@@ -151,6 +151,33 @@ func request_ClusterService_Delete_0(ctx context.Context, marshaler runtime.Mars
}
func request_ClusterService_RotateAuth_0(ctx context.Context, marshaler runtime.Marshaler, client ClusterServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var protoReq ClusterQuery
var metadata runtime.ServerMetadata
var (
val string
ok bool
err error
_ = err
)
val, ok = pathParams["server"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "server")
}
protoReq.Server, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "server", err)
}
msg, err := client.RotateAuth(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
// RegisterClusterServiceHandlerFromEndpoint is same as RegisterClusterServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterClusterServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
@@ -334,6 +361,35 @@ func RegisterClusterServiceHandlerClient(ctx context.Context, mux *runtime.Serve
})
mux.Handle("POST", pattern_ClusterService_RotateAuth_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
if cn, ok := w.(http.CloseNotifier); ok {
go func(done <-chan struct{}, closed <-chan bool) {
select {
case <-done:
case <-closed:
cancel()
}
}(ctx.Done(), cn.CloseNotify())
}
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_ClusterService_RotateAuth_0(rctx, inboundMarshaler, client, req, pathParams)
ctx = runtime.NewServerMetadataContext(ctx, md)
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
forward_ClusterService_RotateAuth_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
@@ -347,6 +403,8 @@ var (
pattern_ClusterService_Update_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "cluster.server"}, ""))
pattern_ClusterService_Delete_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"api", "v1", "clusters", "server"}, ""))
pattern_ClusterService_RotateAuth_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 1, 5, 3, 2, 4}, []string{"api", "v1", "clusters", "server", "rotate-auth"}, ""))
)
var (
@@ -359,4 +417,6 @@ var (
forward_ClusterService_Update_0 = runtime.ForwardResponseMessage
forward_ClusterService_Delete_0 = runtime.ForwardResponseMessage
forward_ClusterService_RotateAuth_0 = runtime.ForwardResponseMessage
)

File diff suppressed because it is too large Load Diff

View File

@@ -682,6 +682,9 @@ message SyncOperation {
// Source overrides the source definition set in the application.
// This is typically set in a Rollback operation and nil during a Sync operation
optional ApplicationSource source = 7;
// Manifests is an optional field that overrides sync source with a local directory for development
repeated string manifests = 8;
}
// SyncOperationResource contains resources to sync.

View File

@@ -326,7 +326,7 @@ func schema_pkg_apis_application_v1alpha1_Application(ref common.ReferenceCallba
},
},
},
Required: []string{"metadata", "spec", "status"},
Required: []string{"metadata", "spec"},
},
},
Dependencies: []string{
@@ -2442,7 +2442,7 @@ func schema_pkg_apis_application_v1alpha1_RevisionHistory(ref common.ReferenceCa
},
},
},
Required: []string{"revision", "deployedAt", "id", "source"},
Required: []string{"revision", "deployedAt", "id"},
},
},
Dependencies: []string{
@@ -2503,6 +2503,20 @@ func schema_pkg_apis_application_v1alpha1_SyncOperation(ref common.ReferenceCall
Ref: ref("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1.ApplicationSource"),
},
},
"manifests": {
SchemaProps: spec.SchemaProps{
Description: "Manifests is an optional field that overrides sync source with a local directory for development",
Type: []string{"array"},
Items: &spec.SchemaOrArray{
Schema: &spec.Schema{
SchemaProps: spec.SchemaProps{
Type: []string{"string"},
Format: "",
},
},
},
},
},
},
},
},
@@ -2577,7 +2591,7 @@ func schema_pkg_apis_application_v1alpha1_SyncOperationResult(ref common.Referen
},
},
},
Required: []string{"revision", "source"},
Required: []string{"revision"},
},
},
Dependencies: []string{

View File

@@ -30,7 +30,7 @@ type Application struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata" protobuf:"bytes,1,opt,name=metadata"`
Spec ApplicationSpec `json:"spec" protobuf:"bytes,2,opt,name=spec"`
Status ApplicationStatus `json:"status" protobuf:"bytes,3,opt,name=status"`
Status ApplicationStatus `json:"status,omitempty" protobuf:"bytes,3,opt,name=status"`
Operation *Operation `json:"operation,omitempty" protobuf:"bytes,4,opt,name=operation"`
}
@@ -269,6 +269,8 @@ type SyncOperation struct {
// Source overrides the source definition set in the application.
// This is typically set in a Rollback operation and nil during a Sync operation
Source *ApplicationSource `json:"source,omitempty" protobuf:"bytes,7,opt,name=source"`
// Manifests is an optional field that overrides sync source with a local directory for development
Manifests []string `json:"manifests,omitempty" protobuf:"bytes,8,opt,name=manifests"`
}
func (o *SyncOperation) IsApplyStrategy() bool {
@@ -394,7 +396,7 @@ type SyncOperationResult struct {
// Revision holds the git commit SHA of the sync
Revision string `json:"revision" protobuf:"bytes,2,opt,name=revision"`
// Source records the application source information of the sync, used for comparing auto-sync
Source ApplicationSource `json:"source" protobuf:"bytes,3,opt,name=source"`
Source ApplicationSource `json:"source,omitempty" protobuf:"bytes,3,opt,name=source"`
}
type ResultCode string
@@ -476,7 +478,7 @@ type RevisionHistory struct {
Revision string `json:"revision" protobuf:"bytes,2,opt,name=revision"`
DeployedAt metav1.Time `json:"deployedAt" protobuf:"bytes,4,opt,name=deployedAt"`
ID int64 `json:"id" protobuf:"bytes,5,opt,name=id"`
Source ApplicationSource `json:"source" protobuf:"bytes,6,opt,name=source"`
Source ApplicationSource `json:"source,omitempty" protobuf:"bytes,6,opt,name=source"`
}
// ApplicationWatchEvent contains information about application change.

View File

@@ -1327,6 +1327,11 @@ func (in *SyncOperation) DeepCopyInto(out *SyncOperation) {
*out = new(ApplicationSource)
(*in).DeepCopyInto(*out)
}
if in.Manifests != nil {
in, out := &in.Manifests, &out.Manifests
*out = make([]string, len(*in))
copy(*out, *in)
}
return
}

View File

@@ -26,6 +26,7 @@ import (
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/config"
"github.com/argoproj/argo-cd/util/git"
"github.com/argoproj/argo-cd/util/helm"
"github.com/argoproj/argo-cd/util/ksonnet"
@@ -509,7 +510,7 @@ func runCommand(command v1alpha1.Command, path string, env []string) (string, er
cmd := exec.Command(command.Command[0], append(command.Command[1:], command.Args...)...)
cmd.Env = env
cmd.Dir = path
return argoexec.RunCommandExt(cmd)
return argoexec.RunCommandExt(cmd, config.CmdOpts())
}
func runConfigManagementPlugin(appPath string, q *ManifestRequest, creds git.Creds, plugins []*v1alpha1.ConfigManagementPlugin) ([]*unstructured.Unstructured, error) {

View File

@@ -99,7 +99,7 @@ func TestGenerateHelmChartWithDependencies(t *testing.T) {
helmHome, err := ioutil.TempDir("", "")
assert.NoError(t, err)
os.Setenv("HELM_HOME", helmHome)
_, err = exec.RunCommand("helm", "init", "--client-only", "--skip-refresh")
_, err = exec.RunCommand("helm", exec.CmdOpts{}, "init", "--client-only", "--skip-refresh")
assert.NoError(t, err)
defer func() {
_ = os.RemoveAll(helmHome)

View File

@@ -99,7 +99,7 @@ if obj.status ~= nil then
end
if obj.spec.strategy.canary ~= nil then
currentRSIsStable = obj.status.canary.stableRS == obj.status.currentPodHash
if obj.spec.strategy.canary.steps ~= nil then
if obj.spec.strategy.canary.steps ~= nil and table.getn(obj.spec.strategy.canary.steps) > 0 then
stepCount = table.getn(obj.spec.strategy.canary.steps)
if obj.status.currentStepIndex ~= nil then
currentStepIndex = obj.status.currentStepIndex

View File

@@ -56,4 +56,8 @@ tests:
- healthStatus:
status: Healthy
message: The rollout has completed canary deployment
inputPath: testdata/canary/healthy_noSteps.yaml
inputPath: testdata/canary/healthy_noSteps.yaml
- healthStatus:
status: Healthy
message: The rollout has completed canary deployment
inputPath: testdata/canary/healthy_emptyStepsList.yaml

View File

@@ -0,0 +1,67 @@
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: >
{"apiVersion":"argoproj.io/v1alpha1","kind":"Rollout","metadata":{"annotations":{},"labels":{"app.kubernetes.io/instance":"guestbook-canary","ksonnet.io/component":"guestbook-ui"},"name":"guestbook-canary","namespace":"default"},"spec":{"minReadySeconds":10,"replicas":5,"selector":{"matchLabels":{"app":"guestbook-canary"}},"strategy":{"canary":{"maxSurge":1,"maxUnavailable":0,"steps":[{"setWeight":20},{"pause":{"duration":30}},{"setWeight":40},{"pause":{}}]}},"template":{"metadata":{"labels":{"app":"guestbook-canary"}},"spec":{"containers":[{"image":"gcr.io/heptio-images/ks-guestbook-demo:0.1","name":"guestbook-canary","ports":[{"containerPort":80}]}]}}}}
rollout.argoproj.io/revision: '2'
clusterName: ''
creationTimestamp: '2019-05-01T21:55:30Z'
generation: 1
labels:
app.kubernetes.io/instance: guestbook-canary
ksonnet.io/component: guestbook-ui
name: guestbook-canary
namespace: default
resourceVersion: '956205'
selfLink: /apis/argoproj.io/v1alpha1/namespaces/default/rollouts/guestbook-canary
uid: d6105ccd-6c5b-11e9-b8d7-025000000001
spec:
minReadySeconds: 10
replicas: 5
selector:
matchLabels:
app: guestbook-canary
strategy:
canary:
maxSurge: 1
maxUnavailable: 0
steps: []
template:
metadata:
creationTimestamp: null
labels:
app: guestbook-canary
spec:
containers:
- image: 'gcr.io/heptio-images/ks-guestbook-demo:0.2'
name: guestbook-canary
ports:
- containerPort: 80
resources: {}
status:
HPAReplicas: 5
availableReplicas: 5
blueGreen: {}
canary:
stableRS: 567dd56d89
conditions:
- lastTransitionTime: '2019-05-01T22:00:16Z'
lastUpdateTime: '2019-05-01T22:00:16Z'
message: Rollout has minimum availability
reason: AvailableReason
status: 'True'
type: Available
- lastTransitionTime: '2019-05-01T21:55:30Z'
lastUpdateTime: '2019-05-01T22:00:16Z'
message: ReplicaSet "guestbook-canary-567dd56d89" has successfully progressed.
reason: NewReplicaSetAvailable
status: 'True'
type: Progressing
currentPodHash: 567dd56d89
currentStepHash: 6c9545789c
observedGeneration: 6886f85bff
readyReplicas: 5
replicas: 5
selector: app=guestbook-canary
updatedReplicas: 5

View File

@@ -353,7 +353,7 @@ func (s *Server) Patch(ctx context.Context, q *application.ApplicationPatchReque
return nil, err
}
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionUpdate, appRBACName(*app)); err != nil {
if err = s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionOverride, appRBACName(*app)); err != nil {
return nil, err
}
@@ -533,14 +533,6 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica
return err
}
}
conditions, err := argo.ValidatePermissions(ctx, &app.Spec, proj, s.db)
if err != nil {
return err
}
if len(conditions) > 0 {
return status.Errorf(codes.InvalidArgument, "application spec is invalid: %s", argo.FormatAppConditions(conditions))
}
conditions, appSourceType, err := argo.ValidateRepo(ctx, &app.Spec, s.repoClientset, s.db)
if err != nil {
return err
@@ -548,6 +540,15 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica
if len(conditions) > 0 {
return status.Errorf(codes.InvalidArgument, "application spec is invalid: %s", argo.FormatAppConditions(conditions))
}
conditions, err = argo.ValidatePermissions(ctx, &app.Spec, proj, s.db)
if err != nil {
return err
}
if len(conditions) > 0 {
return status.Errorf(codes.InvalidArgument, "application spec is invalid: %s", argo.FormatAppConditions(conditions))
}
app.Spec = *argo.NormalizeApplicationSpec(&app.Spec, appSourceType)
return nil
}
@@ -822,6 +823,14 @@ func (s *Server) Sync(ctx context.Context, syncReq *application.ApplicationSyncR
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionSync, appRBACName(*a)); err != nil {
return nil, err
}
if syncReq.Manifests != nil {
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionOverride, appRBACName(*a)); err != nil {
return nil, err
}
if a.Spec.SyncPolicy != nil {
return nil, status.Error(codes.FailedPrecondition, "Cannot use local sync when Automatic Sync Policy is enabled")
}
}
if a.DeletionTimestamp != nil {
return nil, status.Errorf(codes.FailedPrecondition, "application is deleting")
}
@@ -843,6 +852,7 @@ func (s *Server) Sync(ctx context.Context, syncReq *application.ApplicationSyncR
DryRun: syncReq.DryRun,
SyncStrategy: syncReq.Strategy,
Resources: syncReq.Resources,
Manifests: syncReq.Manifests,
},
}
a, err = argo.SetAppOperation(appIf, *syncReq.Name, &op)
@@ -1029,7 +1039,7 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
Version: q.Version,
Group: q.Group,
}
res, config, _, err := s.getAppResource(ctx, rbacpolicy.ActionGet, resourceRequest)
res, config, _, err := s.getAppResource(ctx, rbacpolicy.ActionOverride, resourceRequest)
if err != nil {
return nil, err
}

View File

@@ -60,6 +60,7 @@ message ApplicationSyncRequest {
optional bool prune = 4 [(gogoproto.nullable) = false];
optional github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.SyncStrategy strategy = 5;
repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.SyncOperationResource resources = 7 [(gogoproto.nullable) = false];
repeated string manifests = 8;
}
// ApplicationUpdateSpecRequest is a request to update application spec

View File

@@ -17,6 +17,7 @@ import (
"github.com/argoproj/argo-cd/server/rbacpolicy"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cache"
"github.com/argoproj/argo-cd/util/clusterauth"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/rbac"
@@ -174,6 +175,55 @@ func (s *Server) Delete(ctx context.Context, q *cluster.ClusterQuery) (*cluster.
return &cluster.ClusterResponse{}, err
}
// RotateAuth rotates the bearer token used for a cluster
func (s *Server) RotateAuth(ctx context.Context, q *cluster.ClusterQuery) (*cluster.ClusterResponse, error) {
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, q.Server); err != nil {
return nil, err
}
logCtx := log.WithField("cluster", q.Server)
logCtx.Info("Rotating auth")
clust, err := s.db.GetCluster(ctx, q.Server)
if err != nil {
return nil, err
}
restCfg := clust.RESTConfig()
if restCfg.BearerToken == "" {
return nil, status.Errorf(codes.InvalidArgument, "Cluster '%s' does not use bearer token authentication", q.Server)
}
claims, err := clusterauth.ParseServiceAccountToken(restCfg.BearerToken)
if err != nil {
return nil, err
}
kubeclientset, err := kubernetes.NewForConfig(restCfg)
if err != nil {
return nil, err
}
newSecret, err := clusterauth.GenerateNewClusterManagerSecret(kubeclientset, claims)
if err != nil {
return nil, err
}
// we are using token auth, make sure we don't store client-cert information
clust.Config.KeyData = nil
clust.Config.CertData = nil
clust.Config.BearerToken = string(newSecret.Data["token"])
// Test the token we just created before persisting it
err = kube.TestConfig(clust.RESTConfig())
if err != nil {
return nil, err
}
_, err = s.db.UpdateCluster(ctx, clust)
if err != nil {
return nil, err
}
err = clusterauth.RotateServiceAccountSecrets(kubeclientset, claims, newSecret)
if err != nil {
return nil, err
}
logCtx.Infof("Rotated auth (old: %s, new: %s)", claims.SecretName, newSecret.Name)
return &cluster.ClusterResponse{}, nil
}
func redact(clust *appv1.Cluster) *appv1.Cluster {
if clust == nil {
return nil

View File

@@ -62,4 +62,9 @@ service ClusterService {
option (google.api.http).delete = "/api/v1/clusters/{server}";
}
// RotateAuth returns a cluster by server address
rpc RotateAuth(ClusterQuery) returns (ClusterResponse) {
option (google.api.http).post = "/api/v1/clusters/{server}/rotate-auth";
}
}

View File

@@ -19,11 +19,12 @@ const (
ResourceApplications = "applications"
ResourceRepositories = "repositories"
ActionGet = "get"
ActionCreate = "create"
ActionUpdate = "update"
ActionDelete = "delete"
ActionSync = "sync"
ActionGet = "get"
ActionCreate = "create"
ActionUpdate = "update"
ActionDelete = "delete"
ActionSync = "sync"
ActionOverride = "override"
)
var (

View File

@@ -3,6 +3,7 @@ package e2e
import (
"context"
"fmt"
"os"
"path"
"strings"
"testing"
@@ -27,7 +28,8 @@ import (
)
const (
guestbookPath = "guestbook"
guestbookPath = "guestbook"
guestbookPathLocal = "./testdata/guestbook_local"
)
func TestAppCreation(t *testing.T) {
@@ -282,7 +284,8 @@ func TestResourceDiffing(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
And(func(app *Application) {
diffOutput, _ := fixture.RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
diffOutput, err := fixture.RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
assert.Error(t, err)
assert.Contains(t, diffOutput, fmt.Sprintf("===== apps/Deployment %s/guestbook-ui ======", fixture.DeploymentNamespace()))
}).
Given().
@@ -344,7 +347,9 @@ func TestKsonnetApp(t *testing.T) {
Given(t).
Path("ksonnet").
Env("prod").
// Null out dest server to verify that destination is inferred from ksonnet app
Parameter("guestbook-ui=image=gcr.io/heptio-images/ks-guestbook-demo:0.1").
DestServer("").
When().
Create().
Sync().
@@ -433,8 +438,61 @@ func TestSyncResourceByLabel(t *testing.T) {
}).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, _ := fixture.RunCli("app", "sync", app.Name, "--label", "this-label=does-not-exist")
assert.Contains(t, res, "level=fatal")
_, err := fixture.RunCli("app", "sync", app.Name, "--label", "this-label=does-not-exist")
assert.Error(t, err)
assert.Contains(t, err.Error(), "level=fatal")
})
}
func TestLocalManifestSync(t *testing.T) {
Given(t).
Path(guestbookPath).
When().
Create().
Sync().
Then().
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 80")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.2")
}).
Given().
LocalPath(guestbookPathLocal).
When().
Sync().
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 81")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.3")
}).
Given().
LocalPath("").
When().
Sync().
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 80")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.2")
})
}
func TestNoLocalSyncWithAutosyncEnabled(t *testing.T) {
Given(t).
Path(guestbookPath).
When().
Create().
Sync().
Then().
And(func(app *Application) {
_, err := fixture.RunCli("app", "set", app.Name, "--sync-policy", "automated")
assert.NoError(t, err)
_, err = fixture.RunCli("app", "sync", app.Name, "--local", guestbookPathLocal)
assert.Error(t, err)
})
}
@@ -458,14 +516,14 @@ func TestPermissions(t *testing.T) {
assert.NoError(t, err)
// make sure app cannot be created without permissions in project
output, err := fixture.RunCli("app", "create", appName, "--repo", fixture.RepoURL(),
_, err = fixture.RunCli("app", "create", appName, "--repo", fixture.RepoURL(),
"--path", guestbookPath, "--project", "test", "--dest-server", common.KubernetesInternalAPIServerAddr, "--dest-namespace", fixture.DeploymentNamespace())
assert.Error(t, err)
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'test'", fixture.RepoURL())
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'test'", common.KubernetesInternalAPIServerAddr, fixture.DeploymentNamespace())
assert.Contains(t, output, sourceError)
assert.Contains(t, output, destinationError)
assert.Contains(t, err.Error(), sourceError)
assert.Contains(t, err.Error(), destinationError)
proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Get("test", metav1.GetOptions{})
assert.NoError(t, err)
@@ -532,6 +590,33 @@ func TestSyncOptionPruneFalse(t *testing.T) {
Expect(ResourceSyncStatusIs("Pod", "pod-1", SyncStatusCodeOutOfSync))
}
// make sure that if we have an invalid manifest, we can add it if we disable validation, we get a server error rather than a client error
func TestSyncOptionValidateFalse(t *testing.T) {
// k3s does not validate at all, so this test does not work
if os.Getenv("ARGOCD_E2E_K3S") == "true" {
t.SkipNow()
}
Given(t).
Path("crd-validation").
When().
Create().
Then().
Expect(Success("")).
When().
Sync().
Then().
// client error
Expect(Error("error validating data", "")).
When().
PatchFile("deployment.yaml", `[{"op": "add", "path": "/metadata/annotations", "value": {"argocd.argoproj.io/sync-options": "Validate=false"}}]`).
Sync().
Then().
// server error
Expect(Error("Error from server", ""))
}
// make sure that, if we have a resource that needs pruning, but we're ignoring it, the app is in-sync
func TestCompareOptionIgnoreExtraneous(t *testing.T) {
Given(t).

View File

@@ -0,0 +1,21 @@
package e2e
import (
"testing"
. "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
. "github.com/argoproj/argo-cd/test/e2e/fixture/app"
)
// ensure that cluster scoped objects, like a cluster role, as a hok, can be successfully deployed
func TestClusterRoleBinding(t *testing.T) {
Given(t).
Path("cluster-role").
When().
Create().
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(HealthIs(HealthStatusHealthy)).
Expect(SyncStatusIs(SyncStatusCodeSynced))
}

View File

@@ -75,6 +75,10 @@ func (a *Actions) Sync() *Actions {
args = append(args, "--resource", a.context.resource)
}
if a.context.localPath != "" {
args = append(args, "--local", a.context.localPath)
}
a.runCli(args...)
return a
}

View File

@@ -22,6 +22,7 @@ type Context struct {
prune bool
configManagementPlugin string
async bool
localPath string
}
func Given(t *testing.T) *Context {
@@ -103,3 +104,8 @@ func (c *Context) Async(async bool) *Context {
c.async = async
return c
}
func (c *Context) LocalPath(localPath string) *Context {
c.localPath = localPath
return c
}

View File

@@ -187,9 +187,9 @@ func Success(message string) Expectation {
}
// asserts that the last command was an error with substring match
func Error(message string) Expectation {
func Error(message, err string) Expectation {
return func(c *Consequences) (state, string) {
if c.actions.lastError != nil && strings.Contains(c.actions.lastOutput, message) {
if c.actions.lastError != nil && strings.Contains(c.actions.lastOutput, message) && strings.Contains(c.actions.lastError.Error(), err) {
return succeeded, fmt.Sprintf("found error with message '%s'", c.actions.lastOutput)
}
return failed, fmt.Sprintf("expected error with message '%s', got error '%v' message '%s'", message, c.actions.lastError, c.actions.lastOutput)

View File

@@ -3,36 +3,21 @@ package fixture
import (
"os"
"os/exec"
"strings"
"time"
argoexec "github.com/argoproj/pkg/exec"
log "github.com/sirupsen/logrus"
)
func init() {
// ensure we log all shell execs
log.SetLevel(log.DebugLevel)
}
func Run(workDir, name string, args ...string) (string, error) {
start := time.Now()
log.WithFields(log.Fields{"name": name, "args": args, "workDir": workDir}).Info("running command")
cmd := exec.Command(name, args...)
cmd.Env = os.Environ()
cmd.Dir = workDir
outBytes, err := cmd.Output()
output := string(outBytes)
if err != nil {
exErr, ok := err.(*exec.ExitError)
if ok {
output = output + string(exErr.Stderr)
}
}
for i, line := range strings.Split(output, "\n") {
log.Infof("%d: %s", i, line)
}
log.WithFields(log.Fields{"err": err, "duration": time.Since(start)}).Info("ran command")
return output, err
return argoexec.RunCommandExt(cmd, argoexec.CmdOpts{})
}

View File

@@ -81,7 +81,7 @@ func TestSyncStatusOptionIgnore(t *testing.T) {
When().
Sync().
Then().
Expect(Error("1 resources require pruning")).
Expect(Error("", "1 resources require pruning")).
Expect(OperationPhaseIs(OperationSucceeded)).
// this is a key check - we expect the app to be healthy because, even though we have a resources that needs
// pruning, because it is annotated with IgnoreExtraneous it should not contribute to the sync status

View File

@@ -123,12 +123,12 @@ func TestAddProjectDestination(t *testing.T) {
t.Fatalf("Unable to add project destination %v", err)
}
output, err := fixture.RunCli("proj", "add-destination", projectName,
_, err = fixture.RunCli("proj", "add-destination", projectName,
"https://192.168.99.100:8443",
"test1",
)
assert.Error(t, err)
assert.True(t, strings.Contains(output, "already defined"))
assert.True(t, strings.Contains(err.Error(), "already defined"))
proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Get(projectName, metav1.GetOptions{})
assert.NoError(t, err)
@@ -167,12 +167,12 @@ func TestRemoveProjectDestination(t *testing.T) {
t.Fatalf("Unable to remove project destination %v", err)
}
output, err := fixture.RunCli("proj", "remove-destination", projectName,
_, err = fixture.RunCli("proj", "remove-destination", projectName,
"https://192.168.99.100:8443",
"test1",
)
assert.NotNil(t, err)
assert.True(t, strings.Contains(output, "does not exist"))
assert.Error(t, err)
assert.Contains(t, err.Error(), "does not exist")
proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Get(projectName, metav1.GetOptions{})
if err != nil {

View File

@@ -21,5 +21,5 @@ func TestPruningRequired(t *testing.T) {
DeleteFile("pod-2.yaml").
Sync().
Then().
Expect(Error("1 resources require pruning"))
Expect(Error("", "1 resources require pruning"))
}

View File

@@ -18,7 +18,7 @@ func TestCannotAddAppFromPrivateRepoWithoutCfg(t *testing.T) {
When().
Create().
Then().
Expect(Error("repository not accessible: authentication required"))
Expect(Error("", "repository not accessible: authentication required"))
}
// make sure you can create an app from a private repo, if the repo is set-up in the CM

View File

@@ -0,0 +1,41 @@
package e2e
import (
"os"
"testing"
. "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
. "github.com/argoproj/argo-cd/test/e2e/fixture/app"
)
// TestSyncOptionsValidateFalse verifies we can disable validation during kubectl apply, using the
// 'argocd.argoproj.io/sync-options: Validate=false' sync option
func TestSyncOptionsValidateFalse(t *testing.T) {
Given(t).
Path("sync-options-validate-false").
When().
Create().
Sync().
Then().
Expect(OperationPhaseIs(OperationSucceeded))
// NOTE: it is a bug that we do not detect this as OutOfSync. This is because we
// are dropping fields as part of remarshalling. See: https://github.com/argoproj/argo-cd/issues/1787
// Expect(SyncStatusIs(SyncStatusCodeOutOfSync))
}
// TestSyncOptionsValidateTrue verifies when 'argocd.argoproj.io/sync-options: Validate=false' is
// not present, then validation is performed and we fail during the apply
func TestSyncOptionsValidateTrue(t *testing.T) {
// k3s does not validate at all, so this test does not work
if os.Getenv("ARGOCD_E2E_K3S") == "true" {
t.SkipNow()
}
Given(t).
Path("sync-options-validate-false").
When().
Create().
PatchFile("invalid-cm.yaml", `[{"op": "remove", "path": "/metadata/annotations"}]`).
Sync().
Then().
Expect(OperationPhaseIs(OperationFailed))
}

View File

@@ -0,0 +1,15 @@
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
namespace: cert-manager
name: my-cluster-role-binding
annotations:
argocd.argoproj.io/hook: PreSync
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: default
namespace: default

12
test/e2e/testdata/cluster-role/pod.yaml vendored Normal file
View File

@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: main
image: alpine:latest
imagePullPolicy: IfNotPresent
command:
- "true"
restartPolicy: Never

View File

@@ -0,0 +1,22 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: "80"
imagePullPolicy: IfNotPresent

View File

@@ -0,0 +1,20 @@
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: guestbook-ui
spec:
replicas: 0
revisionHistoryLimit: 3
selector:
matchLabels:
app: guestbook-ui
template:
metadata:
labels:
app: guestbook-ui
spec:
containers:
- image: gcr.io/heptio-images/ks-guestbook-demo:0.3
name: guestbook-ui
ports:
- containerPort: 81

View File

@@ -0,0 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: guestbook-ui
spec:
ports:
- port: 81
targetPort: 81
selector:
app: guestbook-ui

View File

@@ -0,0 +1,6 @@
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ./guestbook-ui-deployment.yaml
- ./guestbook-ui-svc.yaml

View File

@@ -0,0 +1,8 @@
# This configmap fails when running `kubectl apply`, but succeeds when running `kubectl apply --validate=false`
apiVersion: v1
kind: ConfigMap
metadata:
name: invalid-cm
annotations:
argocd.argoproj.io/sync-options: Validate=false
invalidKey: this-fails

View File

@@ -0,0 +1,20 @@
package revision_metadata
import (
"fmt"
"strings"
argoexec "github.com/argoproj/pkg/exec"
"github.com/argoproj/argo-cd/errors"
)
var Author string
func init() {
userName, err := argoexec.RunCommand("git", argoexec.CmdOpts{}, "config", "--get", "user.name")
errors.CheckError(err)
userEmail, err := argoexec.RunCommand("git", argoexec.CmdOpts{}, "config", "--get", "user.email")
errors.CheckError(err)
Author = fmt.Sprintf("%s <%s>", strings.TrimSpace(userName), strings.TrimSpace(userEmail))
}

View File

@@ -14,7 +14,7 @@ import (
// TestBuildManifests makes sure we are consistent in naming, and all kustomization.yamls are buildable
func TestBuildManifests(t *testing.T) {
out, err := argoexec.RunCommand("kustomize", "version")
out, err := argoexec.RunCommand("kustomize", argoexec.CmdOpts{}, "version")
assert.NoError(t, err)
assert.True(t, Contains(out, "KustomizeVersion:2") || Contains(out, "KustomizeVersion:v2"), "kustomize should be version 2")
@@ -35,7 +35,7 @@ func TestBuildManifests(t *testing.T) {
return nil
}
dirName := filepath.Dir(path)
_, err = argoexec.RunCommand("kustomize", "build", dirName)
_, err = argoexec.RunCommand("kustomize", argoexec.CmdOpts{}, "build", dirName)
return err
})
assert.NoError(t, err)

View File

@@ -1,3 +1,5 @@
ARG UI_BASE_IMAGE=alpine:3.7
FROM node:11.15.0 as build
WORKDIR /src
@@ -11,6 +13,9 @@ ARG ARGO_VERSION=latest
ENV ARGO_VERSION=$ARGO_VERSION
RUN NODE_ENV='production' yarn build
FROM alpine:3.7
####################################################################################################
# Final UI Image
####################################################################################################
FROM $UI_BASE_IMAGE
COPY --from=build ./src/dist/app /app

View File

@@ -27,7 +27,7 @@
"@types/react-router": "^4.0.27",
"@types/react-router-dom": "^4.2.3",
"@types/superagent": "^3.5.7",
"argo-ui": "git://github.com/argoproj/argo-ui.git",
"argo-ui": "https://github.com/argoproj/argo-ui.git",
"awesome-typescript-loader": "^5.2.1",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.3",

View File

@@ -246,7 +246,7 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{ na
services.repos.appDetails(src.repoURL, src.path, src.targetRevision, src.details)
.catch(() => ({ type: 'Directory' as appModels.AppSourceType, path: application.spec.source.path }))}>
{(details: appModels.RepoAppDetails) => <ApplicationParameters
save={(app) => services.applications.updateSpec(app.metadata.name, app.spec)} application={application} details={details} />}
save={(app) => this.updateApp(app)} application={application} details={details} />}
</DataLoader>
),
}, {
@@ -301,11 +301,11 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{ na
iconClassName: 'fa fa-sync',
title: <span className='show-for-medium'>Sync</span>,
action: () => this.showDeploy('all'),
}, {
}, ...(application.status.operationState && [{
iconClassName: 'fa fa-info-circle',
title: <span className='show-for-medium'>Sync Status</span>,
action: () => this.setOperationStatusVisible(true),
}, {
action: () => this.setOperationStatusVisible(true),
}] || []), {
iconClassName: 'fa fa-history',
title: <span className='show-for-medium'>History and rollback</span>,
action: () => this.setRollbackPanelVisible(0),
@@ -370,15 +370,8 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{ na
}
private async updateApp(app: appModels.Application) {
try {
await services.applications.updateSpec(app.metadata.name, app.spec);
this.refreshRequested.next({});
} catch (e) {
this.appContext.apis.notifications.show({
content: <ErrorNotification title='Unable to update application' e={e}/>,
type: NotificationType.Error,
});
}
await services.applications.updateSpec(app.metadata.name, app.spec);
this.refreshRequested.next({});
}
private groupAppNodesByKey(application: appModels.Application, tree: appModels.ApplicationTree) {

View File

@@ -126,7 +126,7 @@ export const ApplicationOperationState: React.StatelessComponent<Props> = ({appl
</div>
<div className='columns small-1'>
<utils.ResourceResultIcon
resource={resource}/> {resource.status || resource.hookPhase}
resource={resource}/> {resource.hookType ? resource.hookPhase : resource.status}
</div>
<div className='columns small-1'>
{resource.hookType}

View File

@@ -62,6 +62,7 @@ export const ApplicationSummary = (props: {
<i className='fa fa-external-link'/> {app.spec.source.repoURL}
</a>
),
edit: (formApi: FormApi) => <FormField formApi={formApi} field='spec.source.repoURL' component={Text}/>,
},
{
title: 'TARGET REVISION',

View File

@@ -171,7 +171,7 @@ export const ResourceResultIcon = ({resource}: { resource: appModels.ResourceRes
let color = COLORS.sync_result.unknown;
let icon = 'fa-question-circle';
if (resource.status) {
if (!resource.hookType && resource.status) {
switch (resource.status) {
case appModels.ResultCodes.Synced:
color = COLORS.sync_result.synced;
@@ -195,7 +195,7 @@ export const ResourceResultIcon = ({resource}: { resource: appModels.ResourceRes
}
return <i title={title} className={'fa ' + icon} style={{ color }} />;
}
if (resource.hookPhase) {
if (resource.hookType && resource.hookPhase) {
let className = '';
switch (resource.hookPhase) {
case appModels.OperationPhases.Running:

View File

@@ -133,12 +133,6 @@ export interface ApplicationSource {
*/
path: string;
/**
* DEPRECATED.
* Overridden component parameters.
*/
componentParameterOverrides?: ComponentParameter[];
helm?: ApplicationSourceHelm;
kustomize?: ApplicationSourceKustomize;

View File

@@ -1,3 +1,4 @@
import * as deepMerge from 'deepmerge';
import { Observable } from 'rxjs';
import * as models from '../models';
@@ -49,7 +50,6 @@ export class ApplicationsService {
}
public updateSpec(appName: string, spec: models.ApplicationSpec): Promise<models.ApplicationSpec> {
spec.source.componentParameterOverrides = null;
return requests.put(`/applications/${appName}/spec`).send(spec).then((res) => res.body as models.ApplicationSpec);
}
@@ -167,16 +167,18 @@ export class ApplicationsService {
}
private parseAppFields(data: any): models.Application {
const app = data as models.Application;
app.kind = app.kind || 'Application';
if (app.spec) {
app.spec.project = app.spec.project || 'default';
delete app.spec.source.componentParameterOverrides;
}
if (app.status) {
app.status.resources = app.status.resources || [];
app.status.summary = app.status.summary || {};
}
return app;
data = deepMerge({
apiVersion: 'argoproj.io/v1alpha1',
kind: 'Application',
spec: {
project: 'default',
},
status: {
resources: [],
summary: {},
},
}, data);
return data as models.Application;
}
}

View File

@@ -826,9 +826,9 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.6"
"argo-ui@git://github.com/argoproj/argo-ui.git":
"argo-ui@https://github.com/argoproj/argo-ui.git":
version "1.0.0"
resolved "git://github.com/argoproj/argo-ui.git#20bf3cbe3db2c60f5882bd95c153c538e39a0b7b"
resolved "https://github.com/argoproj/argo-ui.git#e972a2060e5b2b59348e7db07ddf4787c9287bf2"
dependencies:
"@fortawesome/fontawesome-free" "^5.8.1"
"@tippy.js/react" "^2.1.2"
@@ -856,7 +856,9 @@ are-we-there-yet@~1.1.2:
rxjs "^5.5.6"
superagent "^3.8.2"
superagent-promise "^1.1.0"
ts-loader "^6.0.4"
typescript "^2.8.3"
webpack-cli "^3.3.5"
winston "^3.1.0"
ws "^4.0.0"
xterm "2.4.0"
@@ -1591,6 +1593,11 @@ big.js@^3.1.3:
version "3.2.0"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-3.2.0.tgz#a5fc298b81b9e0dca2e458824784b65c52ba588e"
big.js@^5.2.2:
version "5.2.2"
resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328"
integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==
binary-extensions@^1.0.0:
version "1.11.0"
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
@@ -1688,6 +1695,13 @@ braces@^2.3.0, braces@^2.3.1:
split-string "^3.0.2"
to-regex "^3.0.1"
braces@^3.0.1:
version "3.0.2"
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
dependencies:
fill-range "^7.0.1"
brorand@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f"
@@ -1921,6 +1935,15 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
chalk@2.4.2, chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.0:
version "1.1.3"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98"
@@ -1931,15 +1954,6 @@ chalk@^1.1.1, chalk@^1.1.3, chalk@~1.1.0:
strip-ansi "^3.0.0"
supports-color "^2.0.0"
chalk@^2.0.0, chalk@^2.0.1, chalk@^2.1.0, chalk@^2.4.2:
version "2.4.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424"
integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==
dependencies:
ansi-styles "^3.2.1"
escape-string-regexp "^1.0.5"
supports-color "^5.3.0"
chalk@^2.3.0, chalk@^2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e"
@@ -2048,6 +2062,15 @@ cliui@^4.0.0:
strip-ansi "^4.0.0"
wrap-ansi "^2.0.0"
cliui@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5"
integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==
dependencies:
string-width "^3.1.0"
strip-ansi "^5.2.0"
wrap-ansi "^5.1.0"
clone-deep@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/clone-deep/-/clone-deep-2.0.2.tgz#00db3a1e173656730d1188c3d6aced6d7ea97713"
@@ -2340,6 +2363,17 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4:
safe-buffer "^5.0.1"
sha.js "^2.4.8"
cross-spawn@6.0.5, cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^3.0.0:
version "3.0.1"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-3.0.1.tgz#1256037ecb9f0c5f79e3d6ef135e30770184b982"
@@ -2356,17 +2390,6 @@ cross-spawn@^5.0.1:
shebang-command "^1.2.0"
which "^1.2.9"
cross-spawn@^6.0.0, cross-spawn@^6.0.5:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==
dependencies:
nice-try "^1.0.4"
path-key "^2.0.1"
semver "^5.5.0"
shebang-command "^1.2.0"
which "^1.2.9"
cryptiles@2.x.x:
version "2.0.5"
resolved "https://registry.yarnpkg.com/cryptiles/-/cryptiles-2.0.5.tgz#3bdfecdc608147c1c67202fa291e7dca59eaa3b8"
@@ -2794,6 +2817,11 @@ elliptic@^6.0.0:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.0"
emoji-regex@^7.0.1:
version "7.0.3"
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==
emojis-list@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389"
@@ -2815,7 +2843,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0:
dependencies:
once "^1.4.0"
enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
enhanced-resolve@4.1.0, enhanced-resolve@^4.0.0, enhanced-resolve@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.0.tgz#41c7e0bfdfe74ac1ffe1e57ad6a5c6c9f3742a7f"
integrity sha512-F/7vkyTtyc/llOIn8oWclcB25KdRaiPBpZYDgJHgh/UHtpgT2p2eldQgtQnLtUvfMKPKxbRaQM/hHkvLHt1Vng==
@@ -3198,6 +3226,13 @@ fill-range@^4.0.0:
repeat-string "^1.6.1"
to-regex-range "^2.1.0"
fill-range@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
dependencies:
to-regex-range "^5.0.1"
finalhandler@1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105"
@@ -3247,6 +3282,16 @@ find-up@^3.0.0:
dependencies:
locate-path "^3.0.0"
findup-sync@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-3.0.0.tgz#17b108f9ee512dfb7a5c7f3c8b27ea9e1a9c08d1"
integrity sha512-YbffarhcicEhOrm4CtrwdKBdCuz576RLdhJDsIfvNtxUuhdRet1qZcsMjqbePtAseKdAnDyM/IyXbu7PRPRLYg==
dependencies:
detect-file "^1.0.0"
is-glob "^4.0.0"
micromatch "^3.0.4"
resolve-dir "^1.0.1"
findup-sync@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/findup-sync/-/findup-sync-2.0.0.tgz#9326b1488c22d1a6088650a86901b2d9a90a2cbc"
@@ -3429,6 +3474,11 @@ get-caller-file@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.2.tgz#f702e63127e7e231c160a80c1554acb70d5047e5"
get-caller-file@^2.0.1:
version "2.0.5"
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-stdin@^4.0.1:
version "4.0.1"
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-4.0.1.tgz#b968c6b0a04384324902e8bf1a5df32579a450fe"
@@ -3505,6 +3555,13 @@ glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
global-modules@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780"
integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==
dependencies:
global-prefix "^3.0.0"
global-modules@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-1.0.0.tgz#6d770f0eb523ac78164d72b5e71a8877265cc3ea"
@@ -3525,6 +3582,15 @@ global-prefix@^1.0.1:
is-windows "^1.0.1"
which "^1.2.14"
global-prefix@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97"
integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==
dependencies:
ini "^1.3.5"
kind-of "^6.0.2"
which "^1.3.1"
global@^4.3.0:
version "4.3.2"
resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
@@ -3943,7 +4009,7 @@ ignore@^3.3.5:
version "3.3.10"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043"
import-local@^2.0.0:
import-local@2.0.0, import-local@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d"
integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==
@@ -3988,7 +4054,7 @@ inherits@2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1"
ini@^1.3.4, ini@~1.3.0:
ini@^1.3.4, ini@^1.3.5, ini@~1.3.0:
version "1.3.5"
resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927"
@@ -4000,7 +4066,7 @@ internal-ip@^4.2.0:
default-gateway "^4.0.1"
ipaddr.js "^1.9.0"
interpret@^1.1.0:
interpret@1.2.0, interpret@^1.1.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296"
integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw==
@@ -4189,6 +4255,11 @@ is-number@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-4.0.0.tgz#0026e37f5454d73e356dfe6564699867c6a7f0ff"
is-number@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b"
integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==
is-odd@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/is-odd/-/is-odd-2.0.0.tgz#7646624671fd7ea558ccd9a2795182f2958f1b24"
@@ -4881,6 +4952,13 @@ json5@^0.5.0, json5@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821"
json5@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe"
integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==
dependencies:
minimist "^1.2.0"
jsondiffpatch@^0.3.5:
version "0.3.10"
resolved "https://registry.yarnpkg.com/jsondiffpatch/-/jsondiffpatch-0.3.10.tgz#79b132ea4e50b370fd9f5b150625462a05fedcd2"
@@ -5018,6 +5096,15 @@ loader-runner@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.3.0.tgz#f482aea82d543e07921700d5a46ef26fdac6b8a2"
loader-utils@1.2.3:
version "1.2.3"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7"
integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA==
dependencies:
big.js "^5.2.2"
emojis-list "^2.0.0"
json5 "^1.0.1"
loader-utils@^0.2.16, loader-utils@~0.2.2:
version "0.2.17"
resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-0.2.17.tgz#f86e6374d43205a6e6c60e9196f17c0299bfb348"
@@ -5298,6 +5385,14 @@ micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4, micromatch@^3.1.8, mic
snapdragon "^0.8.1"
to-regex "^3.0.2"
micromatch@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259"
integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q==
dependencies:
braces "^3.0.1"
picomatch "^2.0.5"
miller-rabin@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d"
@@ -5915,7 +6010,7 @@ os-locale@^2.0.0:
lcid "^1.0.0"
mem "^1.1.0"
os-locale@^3.0.0:
os-locale@^3.0.0, os-locale@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a"
integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==
@@ -6145,6 +6240,11 @@ performance-now@^2.1.0:
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
picomatch@^2.0.5:
version "2.0.7"
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.0.7.tgz#514169d8c7cd0bdbeecc8a2609e34a7163de69f6"
integrity sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==
pify@^2.0.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
@@ -7591,6 +7691,15 @@ string-width@^1.0.1, string-width@^1.0.2:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^4.0.0"
string-width@^3.0.0, string-width@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961"
integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==
dependencies:
emoji-regex "^7.0.1"
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
string_decoder@^1.0.0, string_decoder@~1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8"
@@ -7624,7 +7733,7 @@ strip-ansi@^4.0.0:
dependencies:
ansi-regex "^3.0.0"
strip-ansi@^5.0.0:
strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae"
integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==
@@ -7689,6 +7798,13 @@ superagent@^3.8.2:
qs "^6.5.1"
readable-stream "^2.3.5"
supports-color@6.1.0, supports-color@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
dependencies:
has-flag "^3.0.0"
supports-color@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7"
@@ -7706,13 +7822,6 @@ supports-color@^5.5.0:
dependencies:
has-flag "^3.0.0"
supports-color@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3"
integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==
dependencies:
has-flag "^3.0.0"
symbol-observable@1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4"
@@ -7854,6 +7963,13 @@ to-regex-range@^2.1.0:
is-number "^3.0.0"
repeat-string "^1.6.1"
to-regex-range@^5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4"
integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==
dependencies:
is-number "^7.0.0"
to-regex@^3.0.1, to-regex@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce"
@@ -7934,6 +8050,17 @@ ts-jest@^24.0.2:
semver "^5.5"
yargs-parser "10.x"
ts-loader@^6.0.4:
version "6.0.4"
resolved "https://registry.yarnpkg.com/ts-loader/-/ts-loader-6.0.4.tgz#bc331ad91a887a60632d94c9f79448666f2c4b63"
integrity sha512-p2zJYe7OtwR+49kv4gs7v4dMrfYD1IPpOtqiSPCbe8oR+4zEBtdHwzM7A7M91F+suReqgzZrlClk4LRSSp882g==
dependencies:
chalk "^2.3.0"
enhanced-resolve "^4.0.0"
loader-utils "^1.0.2"
micromatch "^4.0.0"
semver "^6.0.0"
ts-node@^4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-4.1.0.tgz#36d9529c7b90bb993306c408cd07f7743de20712"
@@ -8209,6 +8336,11 @@ uuid@^3.0.0, uuid@^3.0.1, uuid@^3.1.0:
version "3.2.1"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14"
v8-compile-cache@2.0.3:
version "2.0.3"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.3.tgz#00f7494d2ae2b688cfe2899df6ed2c54bef91dbe"
integrity sha512-CNmdbwQMBjwr9Gsmohvm0pbL954tJrNzf6gWL3K+QMQf00PF7ERGrEiLgjuU3mKreLC2MeGhUsNV9ybTbLgd3w==
v8-compile-cache@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.0.2.tgz#a428b28bb26790734c4fc8bc9fa106fccebf6a6c"
@@ -8331,6 +8463,23 @@ webpack-cli@^3.2.3:
v8-compile-cache "^2.0.2"
yargs "^12.0.4"
webpack-cli@^3.3.5:
version "3.3.5"
resolved "https://registry.yarnpkg.com/webpack-cli/-/webpack-cli-3.3.5.tgz#f4d1238a66a2843d9cebf189835ea22142e72767"
integrity sha512-w0j/s42c5UhchwTmV/45MLQnTVwRoaUTu9fM5LuyOd/8lFoCNCELDogFoecx5NzRUndO0yD/gF2b02XKMnmAWQ==
dependencies:
chalk "2.4.2"
cross-spawn "6.0.5"
enhanced-resolve "4.1.0"
findup-sync "3.0.0"
global-modules "2.0.0"
import-local "2.0.0"
interpret "1.2.0"
loader-utils "1.2.3"
supports-color "6.1.0"
v8-compile-cache "2.0.3"
yargs "13.2.4"
webpack-dev-middleware@^3.5.1:
version "3.6.0"
resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.6.0.tgz#71f1b04e52ff8d442757af2be3a658237d53a3e5"
@@ -8486,7 +8635,7 @@ which-module@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a"
which@1, which@^1.2.14, which@^1.2.9, which@^1.3.0:
which@1, which@^1.2.14, which@^1.2.9, which@^1.3.0, which@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a"
dependencies:
@@ -8557,6 +8706,15 @@ wrap-ansi@^2.0.0:
string-width "^1.0.1"
strip-ansi "^3.0.1"
wrap-ansi@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09"
integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==
dependencies:
ansi-styles "^3.2.0"
string-width "^3.0.0"
strip-ansi "^5.0.0"
wrappy@1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
@@ -8667,6 +8825,14 @@ yargs-parser@^11.1.1:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^13.1.0:
version "13.1.1"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-13.1.1.tgz#d26058532aa06d365fe091f6a1fc06b2f7e5eca0"
integrity sha512-oVAVsHz6uFrg3XQheFII8ESO2ssAf9luWuAd6Wexsu4F3OtIW0o8IribPXYrD4WC24LWtPrJlGy87y5udK+dxQ==
dependencies:
camelcase "^5.0.0"
decamelize "^1.2.0"
yargs-parser@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-5.0.0.tgz#275ecf0d7ffe05c77e64e7c86e4cd94bf0e1228a"
@@ -8698,6 +8864,23 @@ yargs@12.0.2:
y18n "^3.2.1 || ^4.0.0"
yargs-parser "^10.1.0"
yargs@13.2.4:
version "13.2.4"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83"
integrity sha512-HG/DWAJa1PAnHT9JAhNa8AbAv3FPaiLzioSjCcmuXXhP8MlpHO5vwls4g4j6n30Z74GVQj8Xa62dWVx1QCGklg==
dependencies:
cliui "^5.0.0"
find-up "^3.0.0"
get-caller-file "^2.0.1"
os-locale "^3.1.0"
require-directory "^2.1.1"
require-main-filename "^2.0.0"
set-blocking "^2.0.0"
string-width "^3.0.0"
which-module "^2.0.0"
y18n "^4.0.0"
yargs-parser "^13.1.0"
yargs@^11.0.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-11.1.0.tgz#90b869934ed6e871115ea2ff58b03f4724ed2d77"

View File

@@ -1,11 +1,13 @@
package common
package clusterauth
import (
"fmt"
"strings"
"time"
jwt "github.com/dgrijalva/jwt-go"
log "github.com/sirupsen/logrus"
apiv1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -39,7 +41,7 @@ func CreateServiceAccount(
serviceAccountName string,
namespace string,
) error {
serviceAccount := apiv1.ServiceAccount{
serviceAccount := corev1.ServiceAccount{
TypeMeta: metav1.TypeMeta{
APIVersion: "v1",
Kind: "ServiceAccount",
@@ -153,7 +155,7 @@ func InstallClusterManagerRBAC(clientset kubernetes.Interface, ns string) (strin
return "", err
}
var serviceAccount *apiv1.ServiceAccount
var serviceAccount *corev1.ServiceAccount
var secretName string
err = wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) {
serviceAccount, err = clientset.CoreV1().ServiceAccounts(ns).Get(ArgoCDManagerServiceAccount, metav1.GetOptions{})
@@ -215,3 +217,106 @@ func UninstallRBAC(clientset kubernetes.Interface, namespace, bindingName, roleN
}
return nil
}
type ServiceAccountClaims struct {
Sub string `json:"sub"`
Iss string `json:"iss"`
Namespace string `json:"kubernetes.io/serviceaccount/namespace"`
SecretName string `json:"kubernetes.io/serviceaccount/secret.name"`
ServiceAccountName string `json:"kubernetes.io/serviceaccount/service-account.name"`
ServiceAccountUID string `json:"kubernetes.io/serviceaccount/service-account.uid"`
}
// Valid satisfies the jwt.Claims interface to enable JWT parsing
func (sac *ServiceAccountClaims) Valid() error {
return nil
}
// ParseServiceAccountToken parses a Kubernetes service account token
func ParseServiceAccountToken(token string) (*ServiceAccountClaims, error) {
parser := &jwt.Parser{
SkipClaimsValidation: true,
}
var claims ServiceAccountClaims
_, _, err := parser.ParseUnverified(token, &claims)
if err != nil {
return nil, fmt.Errorf("Failed to parse service account token: %s", err)
}
return &claims, nil
}
// GenerateNewClusterManagerSecret creates a new secret derived with same metadata as existing one
// and waits until the secret is populated with a bearer token
func GenerateNewClusterManagerSecret(clientset kubernetes.Interface, claims *ServiceAccountClaims) (*corev1.Secret, error) {
secretsClient := clientset.CoreV1().Secrets(claims.Namespace)
existingSecret, err := secretsClient.Get(claims.SecretName, metav1.GetOptions{})
if err != nil {
return nil, err
}
var newSecret corev1.Secret
secretNameSplit := strings.Split(claims.SecretName, "-")
if len(secretNameSplit) > 0 {
secretNameSplit = secretNameSplit[:len(secretNameSplit)-1]
}
newSecret.Type = corev1.SecretTypeServiceAccountToken
newSecret.GenerateName = strings.Join(secretNameSplit, "-") + "-"
newSecret.Annotations = existingSecret.Annotations
// We will create an empty secret and let kubernetes populate the data
newSecret.Data = nil
created, err := secretsClient.Create(&newSecret)
if err != nil {
return nil, err
}
err = wait.Poll(500*time.Millisecond, 30*time.Second, func() (bool, error) {
created, err = secretsClient.Get(created.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
if len(created.Data) == 0 {
return false, nil
}
return true, nil
})
if err != nil {
return nil, fmt.Errorf("Timed out waiting for secret to generate new token")
}
return created, nil
}
// RotateServiceAccountSecrets rotates the entries in the service accounts secrets list
func RotateServiceAccountSecrets(clientset kubernetes.Interface, claims *ServiceAccountClaims, newSecret *corev1.Secret) error {
// 1. update service account secrets list with new secret name while also removing the old name
saClient := clientset.CoreV1().ServiceAccounts(claims.Namespace)
sa, err := saClient.Get(claims.ServiceAccountName, metav1.GetOptions{})
if err != nil {
return err
}
var newSecretsList []corev1.ObjectReference
alreadyPresent := false
for _, objRef := range sa.Secrets {
if objRef.Name == claims.SecretName {
continue
}
if objRef.Name == newSecret.Name {
alreadyPresent = true
}
newSecretsList = append(newSecretsList, objRef)
}
if !alreadyPresent {
sa.Secrets = append(newSecretsList, corev1.ObjectReference{Name: newSecret.Name})
}
_, err = saClient.Update(sa)
if err != nil {
return err
}
// 2. delete existing secret object
secretsClient := clientset.CoreV1().Secrets(claims.Namespace)
err = secretsClient.Delete(claims.SecretName, &metav1.DeleteOptions{})
if !apierr.IsNotFound(err) {
return err
}
return nil
}

View File

@@ -0,0 +1,102 @@
package clusterauth
import (
"io/ioutil"
"testing"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes/fake"
kubetesting "k8s.io/client-go/testing"
"github.com/argoproj/argo-cd/errors"
)
const (
testToken = "eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJhcmdvY2QtbWFuYWdlci10b2tlbi10ajc5ciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJhcmdvY2QtbWFuYWdlciIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjkxZGQzN2NmLThkOTItMTFlOS1hMDkxLWQ2NWYyYWU3ZmE4ZCIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTphcmdvY2QtbWFuYWdlciJ9.ytZjt2pDV8-A7DBMR06zQ3wt9cuVEfq262TQw7sdra-KRpDpMPnziMhc8bkwvgW-LGhTWUh5iu1y-1QhEx6mtbCt7vQArlBRxfvM5ys6ClFkplzq5c2TtZ7EzGSD0Up7tdxuG9dvR6TGXYdfFcG779yCdZo2H48sz5OSJfdEriduMEY1iL5suZd3ebOoVi1fGflmqFEkZX6SvxkoArl5mtNP6TvZ1eTcn64xh4ws152hxio42E-eSnl_CET4tpB5vgP5BVlSKW2xB7w2GJxqdETA5LJRI_OilY77dTOp8cMr_Ck3EOeda3zHfh4Okflg8rZFEeAuJYahQNeAILLkcA"
)
var (
testClaims = ServiceAccountClaims{
Sub: "system:serviceaccount:kube-system:argocd-manager",
Iss: "kubernetes/serviceaccount",
Namespace: "kube-system",
SecretName: "argocd-manager-token-tj79r",
ServiceAccountName: "argocd-manager",
ServiceAccountUID: "91dd37cf-8d92-11e9-a091-d65f2ae7fa8d",
}
)
func newServiceAccount() *corev1.ServiceAccount {
saBytes, err := ioutil.ReadFile("./testdata/argocd-manager-sa.yaml")
errors.CheckError(err)
var sa corev1.ServiceAccount
err = yaml.Unmarshal(saBytes, &sa)
errors.CheckError(err)
return &sa
}
func newServiceAccountSecret() *corev1.Secret {
secretBytes, err := ioutil.ReadFile("./testdata/argocd-manager-sa-token.yaml")
errors.CheckError(err)
var secret corev1.Secret
err = yaml.Unmarshal(secretBytes, &secret)
errors.CheckError(err)
return &secret
}
func TestParseServiceAccountToken(t *testing.T) {
claims, err := ParseServiceAccountToken(testToken)
assert.NoError(t, err)
assert.Equal(t, testClaims, *claims)
}
func TestGenerateNewClusterManagerSecret(t *testing.T) {
kubeclientset := fake.NewSimpleClientset(newServiceAccountSecret())
kubeclientset.ReactionChain = nil
generatedSecret := newServiceAccountSecret()
generatedSecret.Name = "argocd-manager-token-abc123"
generatedSecret.Data = map[string][]byte{
"token": []byte("fake-token"),
}
kubeclientset.AddReactor("*", "secrets", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
return true, generatedSecret, nil
})
created, err := GenerateNewClusterManagerSecret(kubeclientset, &testClaims)
assert.NoError(t, err)
assert.Equal(t, "argocd-manager-token-abc123", created.Name)
assert.Equal(t, "fake-token", string(created.Data["token"]))
}
func TestRotateServiceAccountSecrets(t *testing.T) {
generatedSecret := newServiceAccountSecret()
generatedSecret.Name = "argocd-manager-token-abc123"
generatedSecret.Data = map[string][]byte{
"token": []byte("fake-token"),
}
kubeclientset := fake.NewSimpleClientset(newServiceAccount(), newServiceAccountSecret(), generatedSecret)
err := RotateServiceAccountSecrets(kubeclientset, &testClaims, generatedSecret)
assert.NoError(t, err)
// Verify service account references new secret and old secret is deleted
saClient := kubeclientset.CoreV1().ServiceAccounts(testClaims.Namespace)
sa, err := saClient.Get(testClaims.ServiceAccountName, metav1.GetOptions{})
assert.NoError(t, err)
assert.Equal(t, sa.Secrets, []corev1.ObjectReference{
{
Name: "argocd-manager-token-abc123",
},
})
secretsClient := kubeclientset.CoreV1().Secrets(testClaims.Namespace)
_, err = secretsClient.Get(testClaims.SecretName, metav1.GetOptions{})
assert.True(t, apierr.IsNotFound(err))
}

View File

@@ -0,0 +1,18 @@
apiVersion: v1
data:
ca.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM1ekNDQWMrZ0F3SUJBZ0lCQVRBTkJna3Foa2lHOXcwQkFRc0ZBREFWTVJNd0VRWURWUVFERXdwdGFXNXAKYTNWaVpVTkJNQjRYRFRFNE1USXdOakF4TXpnME1Gb1hEVEk0TVRJd05EQXhNemcwTUZvd0ZURVRNQkVHQTFVRQpBeE1LYldsdWFXdDFZbVZEUVRDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRGdnRVBBRENDQVFvQ2dnRUJBS2RICkxWSGkwSnh4M1dYVkpueVdJck15djJZUThPWll5YzJpSHBSSVZ4eHlGdENnTVJqVEo1T3IxcTVoUG9XeGhrb1YKeFduUThWWFBGdlpNNUtTcS9Ocis5UGJ2WHlrdFdBaDZaYkVrM2s3S29taXorQk9CSjhMdkh6OHNicDRMQ2VnZwpHLzZ4aGRNWlNUL1VhNlFYbjhTQzBoRFBTSE4vdVpDb1dxWHlqdE5sdnJCeU81di9LZ3dXWjkvcGFnbmtmck1sCk5Qemh5Q2taK0pHSTR5THBtc3VBMnBYMTQrRXdhY2N1OGZmWUhOYitkMnJnZWltSTFmNytPaGRHRUtlTG5lamEKQm90NTZodnpYRWNoTjRJNS9nOU1CbXZOenhabndPbmVrUllOVDQvTHlwaUJEZU5UR1JlZWhybHlzaUVBcldJQgpPb3U0ZFBYbE5RblVmYTBPVVprQ0F3RUFBYU5DTUVBd0RnWURWUjBQQVFIL0JBUURBZ0trTUIwR0ExVWRKUVFXCk1CUUdDQ3NHQVFVRkJ3TUNCZ2dyQmdFRkJRY0RBVEFQQmdOVkhSTUJBZjhFQlRBREFRSC9NQTBHQ1NxR1NJYjMKRFFFQkN3VUFBNElCQVFBTldRcUE1Q2UrR1N4WVVmNTg4bm91ZzNhZVJZZnBLZXIvSnlvazM4TzFKeFlLK2IydApxWGtIdFU0VmpRWFdGNEp6RG9sMlo1bDRSYzRVUWl5QlVUQk1ieS8vY2NGUnVYcER5R3ROQTNnU1hURG9YMjkzCk5SUUlPZndDTlFDUEJjbEpCN3d5YzRqZlZLWWxheXpkOGRuN0V6LzhNNmJXYUlIRWwxcEd0L21XZXZMZXoxUjQKdEhzbXA2RlY5d1lIckFaQyttaFMzOUVFc1lBRjBBdlVtUkFseU5GN1J4ZVdzRG14ZVVDUG9iQnd2Z0ppeGdJWQpqakZiWEk1ang1cEVlSnZnTVcvQmFMRHNpQlVWVnMvZnYzRGdjZkwzMm0zR1hiUHVzRHN0OGs1ZmYvWjV1UkdVCkJaVGtFeUxuUG9vM1pVRDhXZmI5T2x1MXhNSklnYlY5d3NuYwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
namespace: a3ViZS1zeXN0ZW0=
token: ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWkNJNklpSjkuZXlKcGMzTWlPaUpyZFdKbGNtNWxkR1Z6TDNObGNuWnBZMlZoWTJOdmRXNTBJaXdpYTNWaVpYSnVaWFJsY3k1cGJ5OXpaWEoyYVdObFlXTmpiM1Z1ZEM5dVlXMWxjM0JoWTJVaU9pSnJkV0psTFhONWMzUmxiU0lzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVmpjbVYwTG01aGJXVWlPaUpoY21kdlkyUXRiV0Z1WVdkbGNpMTBiMnRsYmkxMGFqYzVjaUlzSW10MVltVnlibVYwWlhNdWFXOHZjMlZ5ZG1salpXRmpZMjkxYm5RdmMyVnlkbWxqWlMxaFkyTnZkVzUwTG01aGJXVWlPaUpoY21kdlkyUXRiV0Z1WVdkbGNpSXNJbXQxWW1WeWJtVjBaWE11YVc4dmMyVnlkbWxqWldGalkyOTFiblF2YzJWeWRtbGpaUzFoWTJOdmRXNTBMblZwWkNJNklqa3haR1F6TjJObUxUaGtPVEl0TVRGbE9TMWhNRGt4TFdRMk5XWXlZV1UzWm1FNFpDSXNJbk4xWWlJNkluTjVjM1JsYlRwelpYSjJhV05sWVdOamIzVnVkRHByZFdKbExYTjVjM1JsYlRwaGNtZHZZMlF0YldGdVlXZGxjaUo5Lnl0Wmp0MnBEVjgtQTdEQk1SMDZ6UTN3dDljdVZFZnEyNjJUUXc3c2RyYS1LUnBEcE1QbnppTWhjOGJrd3ZnVy1MR2hUV1VoNWl1MXktMVFoRXg2bXRiQ3Q3dlFBcmxCUnhmdk01eXM2Q2xGa3BsenE1YzJUdFo3RXpHU0QwVXA3dGR4dUc5ZHZSNlRHWFlkZkZjRzc3OXlDZFpvMkg0OHN6NU9TSmZkRXJpZHVNRVkxaUw1c3VaZDNlYk9vVmkxZkdmbG1xRkVrWlg2U3Z4a29Bcmw1bXROUDZUdloxZVRjbjY0eGg0d3MxNTJoeGlvNDJFLWVTbmxfQ0VUNHRwQjV2Z1A1QlZsU0tXMnhCN3cyR0p4cWRFVEE1TEpSSV9PaWxZNzdkVE9wOGNNcl9DazNFT2VkYTN6SGZoNE9rZmxnOHJaRkVlQXVKWWFoUU5lQUlMTGtjQQ==
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: argocd-manager
kubernetes.io/service-account.uid: 91dd37cf-8d92-11e9-a091-d65f2ae7fa8d
creationTimestamp: "2019-06-13T04:30:24Z"
generateName: argocd-manager-token-
name: argocd-manager-token-tj79r
namespace: kube-system
resourceVersion: "133010"
selfLink: /api/v1/namespaces/kube-system/secrets/argocd-manager-token-tj79r
uid: f657d67e-8d93-11e9-a091-d65f2ae7fa8d
type: kubernetes.io/service-account-token

View File

@@ -0,0 +1,11 @@
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2019-06-13T04:20:26Z"
name: argocd-manager
namespace: kube-system
resourceVersion: "133015"
selfLink: /api/v1/namespaces/kube-system/serviceaccounts/argocd-manager
uid: 91dd37cf-8d92-11e9-a091-d65f2ae7fa8d
secrets:
- name: argocd-manager-token-tj79r

26
util/config/exec.go Normal file
View File

@@ -0,0 +1,26 @@
package config
import (
"os"
"time"
"github.com/argoproj/pkg/exec"
)
var timeout time.Duration
func init() {
initTimeout()
}
func initTimeout() {
var err error
timeout, err = time.ParseDuration(os.Getenv("ARGOCD_EXEC_TIMEOUT"))
if err != nil {
timeout = 90 * time.Second
}
}
func CmdOpts() exec.CmdOpts {
return exec.CmdOpts{Timeout: timeout}
}

34
util/config/exec_test.go Normal file
View File

@@ -0,0 +1,34 @@
package config
import (
"os"
"testing"
"time"
"github.com/argoproj/pkg/exec"
"github.com/stretchr/testify/assert"
)
func Test_timeout(t *testing.T) {
defer func() { _ = os.Unsetenv("ARGOCD_EXEC_TIMEOUT") }()
tests := []struct {
name string
text string
want time.Duration
}{
{"Default", "", 90 * time.Second},
{"OneSecond", "1s", 1 * time.Second},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
_ = os.Setenv("ARGOCD_EXEC_TIMEOUT", tt.text)
initTimeout()
assert.Equal(t, tt.want, timeout)
})
}
}
func TestCmdOpts(t *testing.T) {
initTimeout()
assert.Equal(t, exec.CmdOpts{Timeout: 90 * time.Second}, CmdOpts())
}

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
"reflect"
log "github.com/sirupsen/logrus"
"github.com/yudai/gojsondiff"
@@ -36,11 +37,11 @@ type Normalizer interface {
// "kubectl.kubernetes.io/last-applied-configuration", then perform a three way diff.
func Diff(config, live *unstructured.Unstructured, normalizer Normalizer) *DiffResult {
if config != nil {
config = stripTypeInformation(config)
config = remarshal(config)
Normalize(config, normalizer)
}
if live != nil {
live = stripTypeInformation(live)
live = remarshal(live)
Normalize(live, normalizer)
}
orig := GetLastAppliedConfigAnnotation(live)
@@ -439,3 +440,39 @@ func toString(val interface{}) string {
}
return fmt.Sprintf("%s", val)
}
// remarshal checks resource kind and version and re-marshal using corresponding struct custom marshaller.
// This ensures that expected resource state is formatter same as actual resource state in kubernetes
// and allows to find differences between actual and target states more accurately.
// Remarshalling also strips any type information (e.g. float64 vs. int) from the unstructured
// object. This is important for diffing since it will cause godiff to report a false difference.
func remarshal(obj *unstructured.Unstructured) *unstructured.Unstructured {
obj = stripTypeInformation(obj)
data, err := json.Marshal(obj)
if err != nil {
panic(err)
}
gvk := obj.GroupVersionKind()
item, err := scheme.Scheme.New(obj.GroupVersionKind())
if err != nil {
// this is common. the scheme is not registered
log.Debugf("Could not create new object of type %s: %v", gvk, err)
return obj
}
// This will drop any omitempty fields, perform resource conversion etc...
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = json.Unmarshal(data, &unmarshalledObj)
if err != nil {
// User may have specified an invalid spec in git. Return original object
log.Warnf("Could not unmarshal to object of type %s: %v", gvk, err)
return obj
}
unstrBody, err := runtime.DefaultUnstructuredConverter.ToUnstructured(unmarshalledObj)
if err != nil {
log.Warnf("Could not unmarshal to object of type %s: %v", gvk, err)
return obj
}
// remove all default values specified by custom formatter (e.g. creationTimestamp)
unstrBody = jsonutil.RemoveMapFields(obj.Object, unstrBody)
return &unstructured.Unstructured{Object: unstrBody}
}

View File

@@ -587,3 +587,48 @@ func TestHideSecretDataLastAppliedConfig(t *testing.T) {
assert.Equal(t, map[string]interface{}{"key1": replacement3}, secretData(lastAppliedSecret))
}
func TestRemarshal(t *testing.T) {
manifest := []byte(`
apiVersion: v1
kind: ServiceAccount
imagePullSecrets: []
metadata:
name: my-sa
`)
var un unstructured.Unstructured
err := yaml.Unmarshal(manifest, &un)
assert.NoError(t, err)
newUn := remarshal(&un)
_, ok := newUn.Object["imagePullSecrets"]
assert.False(t, ok)
metadata := newUn.Object["metadata"].(map[string]interface{})
_, ok = metadata["creationTimestamp"]
assert.False(t, ok)
}
func TestRemarshalResources(t *testing.T) {
manifest := []byte(`
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: nginx:1.7.9
name: nginx
resources:
requests:
cpu: 0.2
`)
un := unstructured.Unstructured{}
err := yaml.Unmarshal(manifest, &un)
assert.NoError(t, err)
requestsBefore := un.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
log.Println(requestsBefore)
newUn := remarshal(&un)
requestsAfter := newUn.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
log.Println(requestsAfter)
assert.Equal(t, float64(0.2), requestsBefore["cpu"])
assert.Equal(t, "200m", requestsAfter["cpu"])
}

View File

@@ -6,6 +6,7 @@ import (
"os/exec"
"strings"
argoexec "github.com/argoproj/pkg/exec"
log "github.com/sirupsen/logrus"
"golang.org/x/crypto/ssh"
"gopkg.in/src-d/go-git.v4"
@@ -15,6 +16,8 @@ import (
"gopkg.in/src-d/go-git.v4/plumbing/transport/http"
ssh2 "gopkg.in/src-d/go-git.v4/plumbing/transport/ssh"
"gopkg.in/src-d/go-git.v4/storage/memory"
argoconfig "github.com/argoproj/argo-cd/util/config"
)
// Client is a generic git client interface
@@ -101,7 +104,7 @@ func (m *nativeGitClient) Init() error {
return err
}
log.Infof("Initializing %s to %s", m.repoURL, m.root)
_, err = exec.Command("rm", "-rf", m.root).Output()
_, err = argoexec.RunCommand("rm", argoconfig.CmdOpts(), "-rf", m.root)
if err != nil {
return fmt.Errorf("unable to clean repo at %s: %v", m.root, err)
}
@@ -261,18 +264,5 @@ func (m *nativeGitClient) runCmdOutput(cmd *exec.Cmd) (string, error) {
cmd.Env = append(cmd.Env, "HOME=/dev/null")
cmd.Env = append(cmd.Env, "GIT_CONFIG_NOSYSTEM=true")
cmd.Env = append(cmd.Env, "GIT_CONFIG_NOGLOBAL=true")
out, err := cmd.Output()
if len(out) > 0 {
log.Debug(string(out))
}
if err != nil {
exErr, ok := err.(*exec.ExitError)
if ok {
errOutput := strings.Split(string(exErr.Stderr), "\n")[0]
log.Debug(errOutput)
return string(out), fmt.Errorf("'%s' failed: %v", strings.Join(cmd.Args, " "), errOutput)
}
return string(out), fmt.Errorf("'%s' failed: %v", strings.Join(cmd.Args, " "), err)
}
return string(out), nil
return argoexec.RunCommandExt(cmd, argoconfig.CmdOpts())
}

View File

@@ -11,6 +11,7 @@ import (
"sort"
"strings"
argoexec "github.com/argoproj/pkg/exec"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -211,12 +212,10 @@ func (h *helm) GetParameters(valuesFiles []string) ([]*argoappv1.HelmParameter,
}
func (h *helm) helmCmd(args ...string) (string, error) {
return h.helmCmdExt(args, func(s string) string {
return s
})
return h.helmCmdExt(args, argoexec.Unredacted)
}
func (h *helm) helmCmdExt(args []string, logFormat func(string) string) (string, error) {
func (h *helm) helmCmdExt(args []string, redactor func(string) string) (string, error) {
cleanHelmParameters(args)
cmd := exec.Command("helm", args...)
cmd.Env = os.Environ()
@@ -224,21 +223,11 @@ func (h *helm) helmCmdExt(args []string, logFormat func(string) string) (string,
if h.home != "" {
cmd.Env = append(cmd.Env, fmt.Sprintf("HELM_HOME=%s", h.home))
}
cmdStr := logFormat(strings.Join(cmd.Args, " "))
log.Info(cmdStr)
outBytes, err := cmd.Output()
if err != nil {
exErr, ok := err.(*exec.ExitError)
if !ok {
return "", err
}
errOutput := string(exErr.Stderr)
log.Errorf("`%s` failed: %s", cmdStr, errOutput)
return "", fmt.Errorf(strings.TrimSpace(errOutput))
}
out := string(outBytes)
log.Debug(out)
return out, nil
return argoexec.RunCommandExt(cmd, argoexec.CmdOpts{
Timeout: config.CmdOpts().Timeout,
Redactor: redactor,
})
}
func flatVals(input map[string]interface{}, output map[string]string, prefixes ...string) {

View File

@@ -9,11 +9,12 @@ import (
"path/filepath"
"strings"
argoexec "github.com/argoproj/pkg/exec"
"github.com/ghodss/yaml"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/config"
"github.com/argoproj/argo-cd/util/kube"
)
@@ -98,21 +99,7 @@ func (k *ksonnetApp) ksCmd(args ...string) (string, error) {
cmd := exec.Command("ks", args...)
cmd.Dir = k.Root()
cmdStr := strings.Join(cmd.Args, " ")
log.Debug(cmdStr)
outBytes, err := cmd.Output()
if err != nil {
exErr, ok := err.(*exec.ExitError)
if !ok {
return "", err
}
errOutput := string(exErr.Stderr)
log.Errorf("`%s` failed: %s", cmdStr, errOutput)
return "", fmt.Errorf(strings.TrimSpace(errOutput))
}
out := string(outBytes)
log.Debug(out)
return out, nil
return argoexec.RunCommandExt(cmd, config.CmdOpts())
}
func (k *ksonnetApp) Root() string {

View File

@@ -8,7 +8,7 @@ import (
"os/exec"
"strings"
"github.com/pkg/errors"
argoexec "github.com/argoproj/pkg/exec"
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -20,6 +20,7 @@ import (
"k8s.io/client-go/rest"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/config"
"github.com/argoproj/argo-cd/util/diff"
)
@@ -244,7 +245,6 @@ func runKubectl(kubeconfigPath string, namespace string, args []string, manifest
cmdArgs = append(cmdArgs, "--dry-run")
}
cmd := exec.Command("kubectl", cmdArgs...)
log.Info(cmd.Args)
if log.IsLevelEnabled(log.DebugLevel) {
var obj unstructured.Unstructured
err := json.Unmarshal(manifestBytes, &obj)
@@ -262,15 +262,11 @@ func runKubectl(kubeconfigPath string, namespace string, args []string, manifest
log.Debug(string(redactedBytes))
}
cmd.Stdin = bytes.NewReader(manifestBytes)
out, err := cmd.Output()
out, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
if exErr, ok := err.(*exec.ExitError); ok {
errMsg := cleanKubectlOutput(string(exErr.Stderr))
return "", errors.New(errMsg)
}
return "", err
return "", fmt.Errorf(cleanKubectlOutput(err.Error()))
}
return strings.TrimSpace(string(out)), nil
return out, nil
}
// ConvertToVersion converts an unstructured object into the specified group/version
@@ -296,18 +292,14 @@ func (k KubectlCmd) ConvertToVersion(obj *unstructured.Unstructured, group strin
outputVersion := fmt.Sprintf("%s/%s", group, version)
cmd := exec.Command("kubectl", "convert", "--output-version", outputVersion, "-o", "json", "--local=true", "-f", f.Name())
cmd.Stdin = bytes.NewReader(manifestBytes)
out, err := cmd.Output()
out, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
if exErr, ok := err.(*exec.ExitError); ok {
errMsg := cleanKubectlOutput(string(exErr.Stderr))
return nil, errors.New(errMsg)
}
return nil, fmt.Errorf("failed to convert %s/%s to %s/%s", obj.GetKind(), obj.GetName(), group, version)
return nil, fmt.Errorf(cleanKubectlOutput(err.Error()))
}
// NOTE: when kubectl convert runs against stdin (i.e. kubectl convert -f -), the output is
// a unstructured list instead of an unstructured object
var convertedObj unstructured.Unstructured
err = json.Unmarshal(out, &convertedObj)
err = json.Unmarshal([]byte(out), &convertedObj)
if err != nil {
return nil, err
}

View File

@@ -3,9 +3,7 @@ package kube
import (
"context"
"encoding/json"
"fmt"
"reflect"
"regexp"
"strings"
"time"
@@ -27,10 +25,8 @@ import (
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
"k8s.io/kubernetes/pkg/kubectl/scheme"
"github.com/argoproj/argo-cd/common"
jsonutil "github.com/argoproj/argo-cd/util/json"
)
const (
@@ -369,44 +365,11 @@ func SplitYAML(out string) ([]*unstructured.Unstructured, error) {
}
continue
}
remObj, err := Remarshal(&obj)
if err != nil {
log.Debugf("Failed to remarshal oject: %v", err)
} else {
obj = *remObj
}
objs = append(objs, &obj)
}
return objs, firstErr
}
// Remarshal checks resource kind and version and re-marshal using corresponding struct custom marshaller.
// This ensures that expected resource state is formatter same as actual resource state in kubernetes
// and allows to find differences between actual and target states more accurately.
func Remarshal(obj *unstructured.Unstructured) (*unstructured.Unstructured, error) {
data, err := json.Marshal(obj)
if err != nil {
return nil, err
}
item, err := scheme.Scheme.New(obj.GroupVersionKind())
if err != nil {
return nil, err
}
// This will drop any omitempty fields, perform resource conversion etc...
unmarshalledObj := reflect.New(reflect.TypeOf(item).Elem()).Interface()
err = json.Unmarshal(data, &unmarshalledObj)
if err != nil {
return nil, err
}
unstrBody, err := runtime.DefaultUnstructuredConverter.ToUnstructured(unmarshalledObj)
if err != nil {
return nil, err
}
// remove all default values specified by custom formatter (e.g. creationTimestamp)
unstrBody = jsonutil.RemoveMapFields(obj.Object, unstrBody)
return &unstructured.Unstructured{Object: unstrBody}, nil
}
// WatchWithRetry returns channel of watch events or errors of failed to call watch API.
func WatchWithRetry(ctx context.Context, getWatch func() (watch.Interface, error)) chan struct {
*watch.Event

View File

@@ -202,53 +202,6 @@ func TestCleanKubectlOutput(t *testing.T) {
assert.Equal(t, cleanKubectlOutput(testString), `error validating data: ValidationError(Deployment.spec): missing required field "selector" in io.k8s.api.apps.v1beta2.DeploymentSpec`)
}
func TestRemarshal(t *testing.T) {
manifest := []byte(`
apiVersion: v1
kind: ServiceAccount
imagePullSecrets: []
metadata:
name: my-sa
`)
var un unstructured.Unstructured
err := yaml.Unmarshal(manifest, &un)
assert.NoError(t, err)
newUn, err := Remarshal(&un)
assert.NoError(t, err)
_, ok := newUn.Object["imagePullSecrets"]
assert.False(t, ok)
metadata := newUn.Object["metadata"].(map[string]interface{})
_, ok = metadata["creationTimestamp"]
assert.False(t, ok)
}
func TestRemarshalResources(t *testing.T) {
manifest := []byte(`
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- image: nginx:1.7.9
name: nginx
resources:
requests:
cpu: 0.2
`)
un := unstructured.Unstructured{}
err := yaml.Unmarshal(manifest, &un)
assert.NoError(t, err)
requestsBefore := un.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
log.Println(requestsBefore)
newUn, err := Remarshal(&un)
assert.NoError(t, err)
requestsAfter := newUn.Object["spec"].(map[string]interface{})["containers"].([]interface{})[0].(map[string]interface{})["resources"].(map[string]interface{})["requests"].(map[string]interface{})
log.Println(requestsAfter)
assert.Equal(t, float64(0.2), requestsBefore["cpu"])
assert.Equal(t, "200m", requestsAfter["cpu"])
}
func TestInClusterKubeConfig(t *testing.T) {
restConfig := &rest.Config{}
kubeConfig := NewKubeConfig(restConfig, "")

View File

@@ -16,6 +16,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/config"
"github.com/argoproj/argo-cd/util/git"
"github.com/argoproj/argo-cd/util/kube"
)
@@ -69,7 +70,7 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize) ([]*unstruc
if opts.NamePrefix != "" {
cmd := exec.Command(commandName, "edit", "set", "nameprefix", opts.NamePrefix)
cmd.Dir = k.path
_, err := argoexec.RunCommandExt(cmd)
_, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
return nil, nil, nil, err
}
@@ -82,7 +83,7 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize) ([]*unstruc
for _, override := range opts.ImageTags {
cmd := exec.Command(commandName, "edit", "set", "imagetag", fmt.Sprintf("%s:%s", override.Name, override.Value))
cmd.Dir = k.path
_, err := argoexec.RunCommandExt(cmd)
_, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
return nil, nil, nil, err
}
@@ -100,7 +101,7 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize) ([]*unstruc
args = append(args, opts.Images...)
cmd := exec.Command(commandName, args...)
cmd.Dir = k.path
_, err := argoexec.RunCommandExt(cmd)
_, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
return nil, nil, nil, err
}
@@ -120,7 +121,7 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize) ([]*unstruc
args = append(args, arg)
cmd := exec.Command(commandName, args...)
cmd.Dir = k.path
_, err := argoexec.RunCommandExt(cmd)
_, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
return nil, nil, nil, err
}
@@ -135,7 +136,7 @@ func (k *kustomize) Build(opts *v1alpha1.ApplicationSourceKustomize) ([]*unstruc
}
defer func() { _ = closer.Close() }()
cmd.Env = append(cmd.Env, environ...)
out, err := argoexec.RunCommandExt(cmd)
out, err := argoexec.RunCommandExt(cmd, config.CmdOpts())
if err != nil {
return nil, nil, nil, err
}

View File

@@ -25,7 +25,7 @@ func testDataDir() (string, error) {
if err != nil {
return "", err
}
_, err = exec.RunCommand("cp", "-r", "./testdata/"+kustomization1, filepath.Join(res, "testdata"))
_, err = exec.RunCommand("cp", exec.CmdOpts{}, "-r", "./testdata/"+kustomization1, filepath.Join(res, "testdata"))
if err != nil {
return "", err
}