Compare commits

...

27 Commits

Author SHA1 Message Date
Alexander Matyushentsev
7c2b92f70c Update manifests to v0.11.0-rc3 2019-01-03 15:37:27 -08:00
Jesse Suen
b451c4fe53 Update versions for kubectl (v1.13.1), helm (v2.12.1), ksonnet (v0.13.1) (#973) 2019-01-03 15:24:25 -08:00
Alexander Matyushentsev
de26eac63f Reduce timeout for checking cluster health (#972) 2019-01-03 15:22:34 -08:00
Alexander Matyushentsev
71194d7fac Update sample commands in project management doc (#971) 2019-01-03 15:22:27 -08:00
Jesse Suen
ff2de56543 Update manifests to v0.11.0-rc2 2018-12-27 16:18:08 -08:00
Alexander Matyushentsev
c8ad7ccf39 Use --refresh --hard-refresh flags in 'app get' 'app diff' commands (#963) 2018-12-27 16:09:42 -08:00
Alexander Matyushentsev
58b77718f8 Issue #916 - Use 'diff' to render actual vs target state difference (#962) 2018-12-27 11:29:57 -08:00
Jesse Suen
5fff89bd12 Show sync policy in app list view (#961) 2018-12-27 11:29:50 -08:00
Jesse Suen
c2975bd258 Handle diff corner case where Role/ClusterRole rules are null (#960) 2018-12-27 11:29:43 -08:00
Alexander Matyushentsev
99daa3e315 Load repo/cluster status in parallel to improve /repos /clusters API performance (#958) 2018-12-27 11:29:36 -08:00
Alexander Matyushentsev
d21c8d09fa Issue #956 - Slow comparison if cluster is down (#957) 2018-12-27 11:29:30 -08:00
Jesse Suen
75dc868ecf Make injected application instance label configurable from default (#944)
* Make injected application instance label configurable from default
Stop removing ksonnet.io/component label, unless using legacy label

* Fix applying of resources when namespace is empty
2018-12-27 11:29:24 -08:00
Zvi Cahana
43064ac126 Prefix controller resource names with 'argocd-' (#917)
* Prefix controller resource names with 'argocd-'

* Regenerate installation manifests

* Rename some additional application-controller occurrences

* Rename [cluster]role[binding] resources

* Regenerate installation manifests
2018-12-27 11:29:17 -08:00
Alexander Matyushentsev
21902828ee Issue #950 - Application controller don't refresh app after destination update (#951) 2018-12-27 11:29:09 -08:00
lbrictson
d250155672 Update aws-iam-authenticator to new version, fix url (#948) 2018-12-27 11:29:03 -08:00
Alexander Matyushentsev
a8221c33ab Correctly drop cluster cache after CRD creation/deletion (#947) 2018-12-27 11:28:53 -08:00
Jesse Suen
f463589348 Diff library handles case where live object has null secret data (#945) 2018-12-27 11:28:46 -08:00
Alexander Matyushentsev
3a6dadd803 Issue #939 - Fix nil dereference error in Diff function (#940) 2018-12-27 11:28:39 -08:00
Alexander Matyushentsev
d265404e23 Issue 914 - Allow invalidating application related cache (#931) 2018-12-27 11:28:33 -08:00
Alexander Matyushentsev
09d8a8ee42 Issue 906 - Support setting different base href in UI (#930) 2018-12-27 11:28:27 -08:00
Alexander Matyushentsev
dbac3d4905 Issue #912 - Make ResourceNode 'tags' into a more generic 'info' struct (#926)
* Issue #912 - Make ResourceNode 'tags' into a more generic 'info' struct
2018-12-27 11:28:21 -08:00
Alexander Matyushentsev
ec0e64975e Issue #927 - Add missing handlings for deprecated extensions group kinds (#928) 2018-12-27 11:28:14 -08:00
Alexander Matyushentsev
6802e1ed35 Issue #922 - Fix nil derefrence error in 'argocd app diff' command (#925) 2018-12-27 11:28:07 -08:00
Alexander Matyushentsev
d09f8f974e Issue #910 - Reconstruct tree structure on the flight to avoid inconsistent state (#921) 2018-12-27 11:28:00 -08:00
Alexander Matyushentsev
7a6951dfe2 Issue #915 - Local 'argocd app diff' fails (#920) 2018-12-27 11:27:52 -08:00
Jesse Suen
476e351d12 Fix issue preventing kustomize apps being multi-namespaced (#913) 2018-12-10 09:42:53 -08:00
Alexander Matyushentsev
e0bc94dcf6 Update manifests to v0.11.0-rc1 2018-12-07 17:07:31 -08:00
83 changed files with 2414 additions and 1237 deletions

View File

@@ -1,2 +1,6 @@
ignore:
- "**/*.pb.go"
- "**/*.pb.go"
- "**/*_test.go"
- "pkg/apis/.*"
- "pkg/client/.*"
- "test/.*"

View File

@@ -29,33 +29,34 @@ RUN wget https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-lin
chmod +x /usr/local/bin/dep
# Install gometalinter
RUN curl -sLo- https://github.com/alecthomas/gometalinter/releases/download/v2.0.5/gometalinter-2.0.5-linux-amd64.tar.gz | \
ENV GOMETALINTER_VERSION=2.0.12
RUN curl -sLo- https://github.com/alecthomas/gometalinter/releases/download/v${GOMETALINTER_VERSION}/gometalinter-${GOMETALINTER_VERSION}-linux-amd64.tar.gz | \
tar -xzC "$GOPATH/bin" --exclude COPYING --exclude README.md --strip-components 1 -f- && \
ln -s $GOPATH/bin/gometalinter $GOPATH/bin/gometalinter.v2
# Install packr
ENV PACKR_VERSION=1.13.2
ENV PACKR_VERSION=1.21.9
RUN wget https://github.com/gobuffalo/packr/releases/download/v${PACKR_VERSION}/packr_${PACKR_VERSION}_linux_amd64.tar.gz && \
tar -vxf packr*.tar.gz -C /tmp/ && \
mv /tmp/packr /usr/local/bin/packr
# Install kubectl
RUN curl -L -o /usr/local/bin/kubectl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl && \
# NOTE: keep the version synced with https://storage.googleapis.com/kubernetes-release/release/stable.txt
ENV KUBECTL_VERSION=1.13.1
RUN curl -L -o /usr/local/bin/kubectl -LO https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl && \
chmod +x /usr/local/bin/kubectl
# Install ksonnet
# NOTE: we frequently switch between tip of master ksonnet vs. official builds. Comment/uncomment
# the corresponding section to switch between the two options:
# Option 1: build ksonnet ourselves
#RUN go get -v -u github.com/ksonnet/ksonnet && mv ${GOPATH}/bin/ksonnet /usr/local/bin/ks
# Option 2: use official tagged ksonnet release
ENV KSONNET_VERSION=0.13.0
ENV KSONNET_VERSION=0.13.1
RUN wget https://github.com/ksonnet/ksonnet/releases/download/v${KSONNET_VERSION}/ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
tar -C /tmp/ -xf ks_${KSONNET_VERSION}_linux_amd64.tar.gz && \
mv /tmp/ks_${KSONNET_VERSION}_linux_amd64/ks /usr/local/bin/ks
# NOTE: we occasionally switch between tip of master ksonnet vs. official builds. Run the following
# to use tip instead of official release:
#RUN go get -v -u github.com/ksonnet/ksonnet && mv ${GOPATH}/bin/ksonnet /usr/local/bin/ks
# Install helm
ENV HELM_VERSION=2.11.0
ENV HELM_VERSION=2.12.1
RUN wget https://storage.googleapis.com/kubernetes-helm/helm-v${HELM_VERSION}-linux-amd64.tar.gz && \
tar -C /tmp/ -xf helm-v${HELM_VERSION}-linux-amd64.tar.gz && \
mv /tmp/linux-amd64/helm /usr/local/bin/helm
@@ -65,8 +66,9 @@ ENV KUSTOMIZE_VERSION=1.0.11
RUN curl -L -o /usr/local/bin/kustomize https://github.com/kubernetes-sigs/kustomize/releases/download/v${KUSTOMIZE_VERSION}/kustomize_${KUSTOMIZE_VERSION}_linux_amd64 && \
chmod +x /usr/local/bin/kustomize
ENV AWS_IAM_AUTHENTICATOR_VERSION=0.3.0
RUN curl -L -o /usr/local/bin/aws-iam-authenticator https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/v${AWS_IAM_AUTHENTICATOR_VERSION}/heptio-authenticator-aws_${AWS_IAM_AUTHENTICATOR_VERSION}_linux_amd64 && \
# Install AWS IAM Authenticator
ENV AWS_IAM_AUTHENTICATOR_VERSION=0.4.0-alpha.1
RUN curl -L -o /usr/local/bin/aws-iam-authenticator https://github.com/kubernetes-sigs/aws-iam-authenticator/releases/download/${AWS_IAM_AUTHENTICATOR_VERSION}/aws-iam-authenticator_${AWS_IAM_AUTHENTICATOR_VERSION}_linux_amd64 && \
chmod +x /usr/local/bin/aws-iam-authenticator

9
Gopkg.lock generated
View File

@@ -381,6 +381,14 @@
pruneopts = ""
revision = "24818f796faf91cd76ec7bddd72458fbced7a6c1"
[[projects]]
branch = "master"
digest = "1:d0899ec7c2f61fd5e4ccba7dbefe72e366a3ecce23ecdb982c768fa1d38812fb"
name = "github.com/google/shlex"
packages = ["."]
pruneopts = ""
revision = "c34317bd91bf98fab745d77b03933cf8769299fe"
[[projects]]
digest = "1:2a131706ff80636629ab6373f2944569b8252ecc018cda8040931b05d32e3c16"
name = "github.com/googleapis/gnostic"
@@ -1412,6 +1420,7 @@
"github.com/golang/protobuf/protoc-gen-go",
"github.com/golang/protobuf/ptypes/empty",
"github.com/google/go-jsonnet",
"github.com/google/shlex",
"github.com/grpc-ecosystem/go-grpc-middleware",
"github.com/grpc-ecosystem/go-grpc-middleware/auth",
"github.com/grpc-ecosystem/go-grpc-middleware/logging",

View File

@@ -1,3 +1,4 @@
[![slack](https://img.shields.io/badge/slack-argoproj-brightgreen.svg?logo=slack)](https://argoproj.github.io/community/join-slack)
[![codecov](https://codecov.io/gh/argoproj/argo-cd/branch/master/graph/badge.svg)](https://codecov.io/gh/argoproj/argo-cd)
# Argo CD - Declarative Continuous Delivery for Kubernetes

View File

@@ -1 +1 @@
0.11.0
0.11.0-rc3

View File

@@ -27,6 +27,7 @@ func NewCommand() *cobra.Command {
glogLevel int
clientConfig clientcmd.ClientConfig
staticAssetsDir string
baseHRef string
repoServerAddress string
appControllerServerAddress string
dexServerAddress string
@@ -59,6 +60,7 @@ func NewCommand() *cobra.Command {
Insecure: insecure,
Namespace: namespace,
StaticAssetsDir: staticAssetsDir,
BaseHRef: baseHRef,
KubeClientset: kubeclientset,
AppClientset: appclientset,
RepoClientset: repoclientset,
@@ -85,6 +87,7 @@ func NewCommand() *cobra.Command {
clientConfig = cli.AddKubectlFlagsToCmd(command)
command.Flags().BoolVar(&insecure, "insecure", false, "Run server without TLS")
command.Flags().StringVar(&staticAssetsDir, "staticassets", "", "Static assets directory path")
command.Flags().StringVar(&baseHRef, "basehref", "/", "Value for base href in index.html. Used if Argo CD is running behind reverse proxy under subpath different from /")
command.Flags().StringVar(&logLevel, "loglevel", "info", "Set the logging level. One of: debug|info|warn|error")
command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level")
command.Flags().StringVar(&repoServerAddress, "repo-server", common.DefaultRepoServerAddr, "Repo server address")

View File

@@ -5,8 +5,11 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path"
"reflect"
"strconv"
"strings"
@@ -14,14 +17,16 @@ import (
"time"
"github.com/ghodss/yaml"
"github.com/google/shlex"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/yudai/gojsondiff/formatter"
"golang.org/x/crypto/ssh/terminal"
"github.com/yudai/gojsondiff"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/controller/services"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/pkg/apiclient"
@@ -124,13 +129,28 @@ func NewApplicationCreateCommand(clientOpts *argocdclient.ClientOptions) *cobra.
return command
}
func getRefreshType(refresh bool, hardRefresh bool) *string {
if hardRefresh {
refreshType := string(argoappv1.RefreshTypeHard)
return &refreshType
}
if refresh {
refreshType := string(argoappv1.RefreshTypeNormal)
return &refreshType
}
return nil
}
// NewApplicationGetCommand returns a new instance of an `argocd app get` command
func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
refresh bool
hardRefresh bool
output string
showParams bool
showOperation bool
refresh bool
)
var command = &cobra.Command{
Use: "get APPNAME",
@@ -144,7 +164,7 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
conn, appIf := acdClient.NewApplicationClientOrDie()
defer util.Close(conn)
appName := args[0]
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: refresh})
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)})
errors.CheckError(err)
switch output {
case "yaml":
@@ -188,6 +208,7 @@ func NewApplicationGetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
command.Flags().BoolVar(&showOperation, "show-operation", false, "Show application operation")
command.Flags().BoolVar(&showParams, "show-params", false, "Show application parameters and overrides")
command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache")
return command
}
@@ -592,9 +613,7 @@ func getLocalObjects(app *argoappv1.Application, local string, env string, value
log.Fatal("--env option invalid when performing local diff on Kustomize application")
}
k := kustomize.NewKustomizeApp(local)
opts := kustomize.KustomizeBuildOpts{
Namespace: app.Namespace,
}
opts := kustomize.KustomizeBuildOpts{}
if app.Spec.Source.Kustomize != nil {
opts.NamePrefix = app.Spec.Source.Kustomize.NamePrefix
}
@@ -613,17 +632,47 @@ func getLocalObjects(app *argoappv1.Application, local string, env string, value
return localObjs
}
func groupLocalObjs(localObs []*unstructured.Unstructured, liveObjs []*unstructured.Unstructured, appNamespace string) map[kube.ResourceKey]*unstructured.Unstructured {
namespacedByGk := make(map[schema.GroupKind]bool)
for i := range liveObjs {
if liveObjs[i] != nil {
key := kube.GetResourceKey(liveObjs[i])
namespacedByGk[schema.GroupKind{Group: key.Group, Kind: key.Kind}] = key.Namespace != ""
}
}
objByKey := make(map[kube.ResourceKey]*unstructured.Unstructured)
for i := range localObs {
obj := localObs[i]
gk := obj.GroupVersionKind().GroupKind()
// Infer if obj is namespaced or not from corresponding live objects list. If corresponding live object has namespace then target object is also namespaced.
// If live object is missing then it does not matter if target is namespaced or not.
namespace := obj.GetNamespace()
if namespacedByGk[gk] {
namespace = ""
} else {
if namespace == "" {
namespace = appNamespace
}
}
objByKey[kube.NewResourceKey(gk.Group, gk.Kind, namespace, obj.GetName())] = obj
}
return objByKey
}
// NewApplicationDiffCommand returns a new instance of an `argocd app diff` command
func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
refresh bool
local string
env string
values []string
refresh bool
hardRefresh bool
local string
env string
values []string
)
shortDesc := "Perform a diff against the target and live state."
var command = &cobra.Command{
Use: "diff APPNAME",
Short: "Perform a diff against the target and live state",
Short: shortDesc,
Long: shortDesc + "\nUses 'diff' to render the difference. KUBECTL_EXTERNAL_DIFF environment variable can be used to select your own diff tool.",
Run: func(c *cobra.Command, args []string) {
if len(args) == 0 {
c.HelpFunc()(c, args)
@@ -633,59 +682,147 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
conn, appIf := argocdclient.NewClientOrDie(clientOpts).NewApplicationClientOrDie()
defer util.Close(conn)
appName := args[0]
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: refresh})
app, err := appIf.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: getRefreshType(refresh, hardRefresh)})
errors.CheckError(err)
resources, err := appIf.ManagedResources(context.Background(), &services.ResourcesQuery{ApplicationName: appName})
errors.CheckError(err)
liveObjs, err := liveObjects(resources.Items)
errors.CheckError(err)
targetObjs, err := targetObjects(resources.Items)
errors.CheckError(err)
localObjs := []*unstructured.Unstructured{}
items := make([]struct {
key kube.ResourceKey
live *unstructured.Unstructured
target *unstructured.Unstructured
}, 0)
if local != "" {
localObjs = getLocalObjects(app, local, env, values)
if len(resources.Items) != len(localObjs) {
log.Fatal("Local comparison doesn't have the same number of resources as the live resource")
localObjs := groupLocalObjs(getLocalObjects(app, local, env, values), liveObjs, app.Spec.Destination.Namespace)
for _, res := range resources.Items {
var live = &unstructured.Unstructured{}
err := json.Unmarshal([]byte(res.LiveState), &live)
errors.CheckError(err)
key := kube.NewResourceKey(res.Group, res.Kind, res.Namespace, res.Name)
if local, ok := localObjs[key]; ok || live != nil {
if local != nil {
// TODO(jessesuen): expose the configured app label key in settings and
// use configured label instead of default
err = kube.SetAppInstanceLabel(local, common.LabelKeyAppInstance, appName)
errors.CheckError(err)
}
items = append(items, struct {
key kube.ResourceKey
live *unstructured.Unstructured
target *unstructured.Unstructured
}{
live: live,
target: local,
key: key,
})
delete(localObjs, key)
}
}
for key, local := range localObjs {
items = append(items, struct {
key kube.ResourceKey
live *unstructured.Unstructured
target *unstructured.Unstructured
}{
live: nil,
target: local,
key: key,
})
}
} else {
for i := range resources.Items {
res := resources.Items[i]
var live = &unstructured.Unstructured{}
err := json.Unmarshal([]byte(res.LiveState), &live)
errors.CheckError(err)
var target = &unstructured.Unstructured{}
err = json.Unmarshal([]byte(res.TargetState), &target)
errors.CheckError(err)
items = append(items, struct {
key kube.ResourceKey
live *unstructured.Unstructured
target *unstructured.Unstructured
}{
live: live,
target: target,
key: kube.NewResourceKey(res.Group, res.Kind, res.Namespace, res.Name),
})
}
} else if env != "" || len(values) > 0 {
log.Fatal("--env option invalid when performing git diff")
}
for i := range resources.Items {
item := resources.Items[i]
// Diff is already available in ManagedResource Diff field but we have to recalculate diff again due to https://github.com/yudai/gojsondiff/issues/31
diffRes := diff.Diff(targetObjs[i], liveObjs[i])
fmt.Printf("===== %s %s ======\n", item.Kind, item.Name)
if local != "" {
liveObj, err := item.LiveObject()
errors.CheckError(err)
err = kube.SetAppInstanceLabel(localObjs[i], appName)
errors.CheckError(err)
diffRes = diff.Diff(localObjs[i], liveObj)
}
if diffRes.Modified {
formatOpts := formatter.AsciiFormatterConfig{
Coloring: terminal.IsTerminal(int(os.Stdout.Fd())),
for i := range items {
item := items[i]
// Diff is already available in ResourceDiff Diff field but we have to recalculate diff again due to https://github.com/yudai/gojsondiff/issues/31
diffRes := diff.Diff(item.target, item.live)
fmt.Printf("===== %s/%s %s/%s ======\n", item.key.Group, item.key.Kind, item.key.Namespace, item.key.Name)
if diffRes.Modified || item.target == nil || item.live == nil {
var live *unstructured.Unstructured
var target *unstructured.Unstructured
if item.target != nil && item.live != nil {
target = item.live
live = item.live.DeepCopy()
gojsondiff.New().ApplyPatch(live.Object, diffRes.Diff)
} else {
live = item.live
target = item.target
}
liveObj := liveObjs[i]
if liveObj == nil {
liveObj = &unstructured.Unstructured{Object: make(map[string]interface{})}
}
out, err := diffRes.ASCIIFormat(liveObj, formatOpts)
errors.CheckError(err)
fmt.Println(out)
printDiff(item.key.Name, live, target)
}
}
},
}
command.Flags().BoolVar(&refresh, "refresh", false, "Refresh application data when retrieving")
command.Flags().BoolVar(&hardRefresh, "hard-refresh", false, "Refresh application data as well as target manifests cache")
command.Flags().StringVar(&local, "local", "", "Compare live app to a local ksonnet app")
command.Flags().StringVar(&env, "env", "", "Compare live app to a specific environment")
command.Flags().StringArrayVar(&values, "values", []string{}, "Helm values file(s) in the helm directory to use")
return command
}
func printDiff(name string, live *unstructured.Unstructured, target *unstructured.Unstructured) {
tempDir, err := ioutil.TempDir("", "argocd-diff")
errors.CheckError(err)
targetFile := path.Join(tempDir, fmt.Sprintf("%s", name))
targetData := []byte("")
if target != nil {
targetData, err = yaml.Marshal(target)
errors.CheckError(err)
}
err = ioutil.WriteFile(targetFile, targetData, 0644)
errors.CheckError(err)
liveFile := path.Join(tempDir, fmt.Sprintf("%s-live.yaml", name))
liveData := []byte("")
if live != nil {
liveData, err = yaml.Marshal(live)
errors.CheckError(err)
}
err = ioutil.WriteFile(liveFile, liveData, 0644)
errors.CheckError(err)
cmdBinary := "diff"
var args []string
if envDiff := os.Getenv("KUBECTL_EXTERNAL_DIFF"); envDiff != "" {
parts, err := shlex.Split(envDiff)
errors.CheckError(err)
cmdBinary = parts[0]
args = parts[1:]
}
cmd := exec.Command(cmdBinary, append(args, liveFile, targetFile)...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
_ = cmd.Run()
}
// NewApplicationDeleteCommand returns a new instance of an `argocd app delete` command
func NewApplicationDeleteCommand(clientOpts *argocdclient.ClientOptions) *cobra.Command {
var (
@@ -732,12 +869,12 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
errors.CheckError(err)
w := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
var fmtStr string
headers := []interface{}{"NAME", "CLUSTER", "NAMESPACE", "PROJECT", "STATUS", "HEALTH", "CONDITIONS"}
headers := []interface{}{"NAME", "CLUSTER", "NAMESPACE", "PROJECT", "STATUS", "HEALTH", "SYNCPOLICY", "CONDITIONS"}
if output == "wide" {
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
headers = append(headers, "REPO", "PATH", "TARGET")
} else {
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
fmtStr = "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n"
}
fmt.Fprintf(w, fmtStr, headers...)
for _, app := range apps.Items {
@@ -748,6 +885,7 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
app.Spec.GetProject(),
app.Status.Sync.Status,
app.Status.Health.Status,
formatSyncPolicy(app),
formatConditionsSummary(app),
}
if output == "wide" {
@@ -762,6 +900,17 @@ func NewApplicationListCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
return command
}
func formatSyncPolicy(app argoappv1.Application) string {
if app.Spec.SyncPolicy == nil || app.Spec.SyncPolicy.Automated == nil {
return "<none>"
}
policy := "Auto"
if app.Spec.SyncPolicy.Automated.Prune {
policy = policy + "-Prune"
}
return policy
}
func formatConditionsSummary(app argoappv1.Application) string {
typeToCnt := make(map[string]int)
for i := range app.Status.Conditions {
@@ -1074,7 +1223,8 @@ func waitOnApplicationStatus(acdClient apiclient.Client, appName string, timeout
var err error
if refresh {
conn, appClient := acdClient.NewApplicationClientOrDie()
app, err = appClient.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: true})
refreshType := string(argoappv1.RefreshTypeNormal)
app, err = appClient.Get(context.Background(), &application.ApplicationQuery{Name: &appName, Refresh: &refreshType})
errors.CheckError(err)
_ = conn.Close()
}

View File

@@ -3,7 +3,7 @@ package common
// Default service addresses and URLS of Argo CD internal services
const (
// DefaultAppControllerServerAddr is the gRPC address of the Argo CD app controller server
DefaultAppControllerServerAddr = "application-controller:8083"
DefaultAppControllerServerAddr = "argocd-application-controller:8083"
// DefaultRepoServerAddr is the gRPC address of the Argo CD repo server
DefaultRepoServerAddr = "argocd-repo-server:8081"
// DefaultDexServerAddr is the HTTP address of the Dex OIDC server, which we run a reverse proxy against
@@ -67,16 +67,9 @@ const (
AnnotationKeyHook = "argocd.argoproj.io/hook"
// AnnotationKeyHookDeletePolicy is the policy of deleting a hook
AnnotationKeyHookDeletePolicy = "argocd.argoproj.io/hook-delete-policy"
// AnnotationKeyRefresh is the annotation key in the application which is updated with an
// arbitrary value (i.e. timestamp) on a git event, to force the controller to wake up and
// re-evaluate the application
// AnnotationKeyRefresh is the annotation key which indicates that app needs to be refreshed. Removed by application controller after app is refreshed.
// Might take values 'normal'/'hard'. Value 'hard' means manifest cache and target cluster state cache should be invalidated before refresh.
AnnotationKeyRefresh = "argocd.argoproj.io/refresh"
// AnnotationKeyConnectionStatus contains connection state status
AnnotationKeyConnectionStatus = "argocd.argoproj.io/connection-status"
// AnnotationKeyConnectionMessage contains additional information about connection status
AnnotationKeyConnectionMessage = "argocd.argoproj.io/connection-message"
// AnnotationConnectionModifiedAt contains timestamp when connection state had been modified
AnnotationConnectionModifiedAt = "argocd.argoproj.io/connection-modified-at"
// AnnotationKeyManagedBy is annotation name which indicates that k8s resource is managed by an application.
AnnotationKeyManagedBy = "managed-by"
// AnnotationValueManagedByArgoCD is a 'managed-by' annotation value for resources managed by Argo CD
@@ -95,6 +88,4 @@ const (
EnvVarSSODebug = "ARGOCD_SSO_DEBUG"
// EnvVarRBACDebug is an environment variable to enable additional RBAC debugging in the API server
EnvVarRBACDebug = "ARGOCD_RBAC_DEBUG"
// EnvVarLegacyLabels is an environment variable to use the legacy 'applications.argoproj.io/app-name' label instead of 'app.kubernetes.io/instance'
EnvVarLegacyLabels = "ARGOCD_LEGACY_LABELS"
)

View File

@@ -31,6 +31,7 @@ import (
"k8s.io/client-go/util/workqueue"
"k8s.io/kubernetes/pkg/apis/core"
"github.com/argoproj/argo-cd/common"
statecache "github.com/argoproj/argo-cd/controller/cache"
"github.com/argoproj/argo-cd/controller/services"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
@@ -53,23 +54,25 @@ const (
// ApplicationController is the controller for application resources.
type ApplicationController struct {
namespace string
kubeClientset kubernetes.Interface
kubectl kube.Kubectl
applicationClientset appclientset.Interface
auditLogger *argo.AuditLogger
appRefreshQueue workqueue.RateLimitingInterface
appOperationQueue workqueue.RateLimitingInterface
appInformer cache.SharedIndexInformer
appStateManager AppStateManager
stateCache statecache.LiveStateCache
statusRefreshTimeout time.Duration
repoClientset reposerver.Clientset
db db.ArgoDB
forceRefreshApps map[string]bool
forceRefreshAppsMutex *sync.Mutex
managedResources map[string][]managedResource
managedResourcesMutex *sync.Mutex
namespace string
kubeClientset kubernetes.Interface
kubectl kube.Kubectl
applicationClientset appclientset.Interface
auditLogger *argo.AuditLogger
appRefreshQueue workqueue.RateLimitingInterface
appOperationQueue workqueue.RateLimitingInterface
appInformer cache.SharedIndexInformer
appStateManager AppStateManager
stateCache statecache.LiveStateCache
statusRefreshTimeout time.Duration
repoClientset reposerver.Clientset
db db.ArgoDB
settings *settings_util.ArgoCDSettings
settingsMgr *settings_util.SettingsManager
refreshRequestedApps map[string]bool
refreshRequestedAppsMutex *sync.Mutex
managedResources map[string][]managedResource
managedResourcesMutex *sync.Mutex
}
type ApplicationControllerConfig struct {
@@ -89,27 +92,29 @@ func NewApplicationController(
db := db.NewDB(namespace, settingsMgr, kubeClientset)
kubectlCmd := kube.KubectlCmd{}
ctrl := ApplicationController{
namespace: namespace,
kubeClientset: kubeClientset,
kubectl: kubectlCmd,
applicationClientset: applicationClientset,
repoClientset: repoClientset,
appRefreshQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
appOperationQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
db: db,
statusRefreshTimeout: appResyncPeriod,
forceRefreshApps: make(map[string]bool),
forceRefreshAppsMutex: &sync.Mutex{},
auditLogger: argo.NewAuditLogger(namespace, kubeClientset, "application-controller"),
managedResources: make(map[string][]managedResource),
managedResourcesMutex: &sync.Mutex{},
namespace: namespace,
kubeClientset: kubeClientset,
kubectl: kubectlCmd,
applicationClientset: applicationClientset,
repoClientset: repoClientset,
appRefreshQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
appOperationQueue: workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter()),
db: db,
statusRefreshTimeout: appResyncPeriod,
refreshRequestedApps: make(map[string]bool),
refreshRequestedAppsMutex: &sync.Mutex{},
auditLogger: argo.NewAuditLogger(namespace, kubeClientset, "argocd-application-controller"),
managedResources: make(map[string][]managedResource),
managedResourcesMutex: &sync.Mutex{},
settingsMgr: settingsMgr,
settings: &settings_util.ArgoCDSettings{},
}
appInformer := ctrl.newApplicationInformer()
stateCache := statecache.NewLiveStateCache(db, appInformer, kubectlCmd, func(appName string) {
ctrl.forceAppRefresh(appName)
stateCache := statecache.NewLiveStateCache(db, appInformer, ctrl.settings, kubectlCmd, func(appName string) {
ctrl.requestAppRefresh(appName)
ctrl.appRefreshQueue.Add(fmt.Sprintf("%s/%s", ctrl.namespace, appName))
})
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectlCmd, stateCache)
appStateManager := NewAppStateManager(db, applicationClientset, repoClientset, namespace, kubectlCmd, ctrl.settings, stateCache)
ctrl.appInformer = appInformer
ctrl.appStateManager = appStateManager
ctrl.stateCache = stateCache
@@ -251,7 +256,7 @@ func hideSecretData(target *unstructured.Unstructured, live *unstructured.Unstru
if obj == nil {
continue
}
diff.EncodeSecretStringData(obj)
diff.NormalizeSecret(obj)
if data, found, err := unstructured.NestedMap(obj.Object, "data"); found && err == nil {
for k := range data {
keys[k] = true
@@ -313,6 +318,7 @@ func (ctrl *ApplicationController) Run(ctx context.Context, statusProcessors int
defer ctrl.appRefreshQueue.ShutDown()
go ctrl.appInformer.Run(ctx.Done())
go ctrl.watchSettings(ctx)
if !cache.WaitForCacheSync(ctx.Done(), ctrl.appInformer.HasSynced) {
log.Error("Timed out waiting for caches to sync")
@@ -342,7 +348,7 @@ func (ctrl *ApplicationController) CreateGRPC(tlsConfCustomizer tlsutil.ConfigCu
// generate TLS cert
hosts := []string{
"localhost",
"application-controller",
"argocd-application-controller",
}
cert, err := tlsutil.GenerateX509KeyPair(tlsutil.CertOptions{
Hosts: hosts,
@@ -374,18 +380,18 @@ func (ctrl *ApplicationController) CreateGRPC(tlsConfCustomizer tlsutil.ConfigCu
return server, nil
}
func (ctrl *ApplicationController) forceAppRefresh(appName string) {
ctrl.forceRefreshAppsMutex.Lock()
defer ctrl.forceRefreshAppsMutex.Unlock()
ctrl.forceRefreshApps[appName] = true
func (ctrl *ApplicationController) requestAppRefresh(appName string) {
ctrl.refreshRequestedAppsMutex.Lock()
defer ctrl.refreshRequestedAppsMutex.Unlock()
ctrl.refreshRequestedApps[appName] = true
}
func (ctrl *ApplicationController) isRefreshForced(appName string) bool {
ctrl.forceRefreshAppsMutex.Lock()
defer ctrl.forceRefreshAppsMutex.Unlock()
_, ok := ctrl.forceRefreshApps[appName]
func (ctrl *ApplicationController) isRefreshRequested(appName string) bool {
ctrl.refreshRequestedAppsMutex.Lock()
defer ctrl.refreshRequestedAppsMutex.Unlock()
_, ok := ctrl.refreshRequestedApps[appName]
if ok {
delete(ctrl.forceRefreshApps, appName)
delete(ctrl.refreshRequestedApps, appName)
}
return ok
}
@@ -572,7 +578,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
if state.Phase.Completed() {
// if we just completed an operation, force a refresh so that UI will report up-to-date
// sync/health information
ctrl.forceAppRefresh(app.ObjectMeta.Name)
ctrl.requestAppRefresh(app.ObjectMeta.Name)
}
}
@@ -662,7 +668,9 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
log.Warnf("Key '%s' in index is not an application", appKey)
return
}
if !ctrl.needRefreshAppStatus(origApp, ctrl.statusRefreshTimeout) {
needRefresh, refreshType := ctrl.needRefreshAppStatus(origApp, ctrl.statusRefreshTimeout)
if !needRefresh {
return
}
// NOTE: normalization returns a copy
@@ -677,7 +685,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
return
}
compareResult, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compareResult, err := ctrl.appStateManager.CompareAppState(app, "", nil, refreshType == appv1.RefreshTypeHard)
if err != nil {
conditions = append(conditions, appv1.ApplicationCondition{Type: appv1.ApplicationConditionComparisonError, Message: err.Error()})
} else {
@@ -701,24 +709,30 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
// needRefreshAppStatus answers if application status needs to be refreshed.
// Returns true if application never been compared, has changed or comparison result has expired.
func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout time.Duration) bool {
func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application, statusRefreshTimeout time.Duration) (bool, appv1.RefreshType) {
logCtx := log.WithFields(log.Fields{"application": app.Name})
var reason string
refreshType := appv1.RefreshTypeNormal
expired := app.Status.ObservedAt.Add(statusRefreshTimeout).Before(time.Now().UTC())
if ctrl.isRefreshForced(app.Name) {
reason = "force refresh"
if requestedType, ok := app.IsRefreshRequested(); ok {
refreshType = requestedType
reason = fmt.Sprintf("refresh requested (%s)", refreshType)
} else if ctrl.isRefreshRequested(app.Name) {
reason = fmt.Sprintf("refresh requested (%s)", refreshType)
} else if app.Status.Sync.Status == appv1.SyncStatusCodeUnknown && expired {
reason = "comparison status unknown"
} else if !app.Spec.Source.Equals(app.Status.Sync.ComparedTo) {
} else if !app.Spec.Source.Equals(app.Status.Sync.ComparedTo.Source) {
reason = "spec.source differs"
} else if !app.Spec.Destination.Equals(app.Status.Sync.ComparedTo.Destination) {
reason = "spec.source differs"
} else if expired {
reason = fmt.Sprintf("comparison expired. observedAt: %v, expiry: %v", app.Status.ObservedAt, statusRefreshTimeout)
}
if reason != "" {
logCtx.Infof("Refreshing app status (%s)", reason)
return true
return true, refreshType
}
return false
return false, refreshType
}
func (ctrl *ApplicationController) refreshAppConditions(app *appv1.Application) ([]appv1.ApplicationCondition, bool) {
@@ -808,7 +822,17 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
message := fmt.Sprintf("Updated health status: %s -> %s", orig.Status.Health.Status, newStatus.Health.Status)
ctrl.auditLogger.LogAppEvent(orig, argo.EventInfo{Reason: argo.EventReasonResourceUpdated, Type: v1.EventTypeNormal}, message)
}
patch, modified, err := diff.CreateTwoWayMergePatch(&appv1.Application{Status: orig.Status}, &appv1.Application{Status: *newStatus}, appv1.Application{})
var newAnnotations map[string]string
if orig.GetAnnotations() != nil {
newAnnotations = make(map[string]string)
for k, v := range orig.GetAnnotations() {
newAnnotations[k] = v
}
delete(newAnnotations, common.AnnotationKeyRefresh)
}
patch, modified, err := diff.CreateTwoWayMergePatch(
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: orig.GetAnnotations()}, Status: orig.Status},
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus}, appv1.Application{})
if err != nil {
logCtx.Errorf("Error constructing app status patch: %v", err)
return
@@ -919,7 +943,7 @@ func (ctrl *ApplicationController) newApplicationInformer() cache.SharedIndexInf
if oldOK && newOK {
if toggledAutomatedSync(oldApp, newApp) {
log.WithField("application", newApp.Name).Info("Enabled automated sync")
ctrl.forceAppRefresh(newApp.Name)
ctrl.requestAppRefresh(newApp.Name)
}
}
ctrl.appRefreshQueue.Add(key)
@@ -955,3 +979,27 @@ func toggledAutomatedSync(old *appv1.Application, new *appv1.Application) bool {
// nothing changed
return false
}
func (ctrl *ApplicationController) watchSettings(ctx context.Context) {
ctrl.settingsMgr.StartNotifier(context.Background(), ctrl.settings)
updateCh := make(chan struct{}, 1)
ctrl.settingsMgr.Subscribe(updateCh)
prevAppLabelKey := ctrl.settings.GetAppInstanceLabelKey()
done := false
for !done {
select {
case <-updateCh:
newAppLabelKey := ctrl.settings.GetAppInstanceLabelKey()
if prevAppLabelKey != newAppLabelKey {
log.Infof("label key changed: %s -> %s", prevAppLabelKey, newAppLabelKey)
ctrl.stateCache.Invalidate()
prevAppLabelKey = newAppLabelKey
}
case <-ctx.Done():
done = true
}
}
log.Info("shutting down settings watch")
ctrl.settingsMgr.Unsubscribe(updateCh)
close(updateCh)
}

View File

@@ -7,22 +7,17 @@ import (
"time"
log "github.com/sirupsen/logrus"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/discovery"
"k8s.io/client-go/tools/cache"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/db"
"github.com/argoproj/argo-cd/util/kube"
)
const (
watchResourcesRetryTimeout = 10 * time.Second
"github.com/argoproj/argo-cd/util/settings"
)
type LiveStateCache interface {
@@ -35,6 +30,8 @@ type LiveStateCache interface {
Run(ctx context.Context)
// Deletes specified resource from cluster.
Delete(server string, obj *unstructured.Unstructured) error
// Invalidate invalidates the entire cluster state cache
Invalidate()
}
func GetTargetObjKey(a *appv1.Application, un *unstructured.Unstructured, isNamespaced bool) kube.ResourceKey {
@@ -48,7 +45,7 @@ func GetTargetObjKey(a *appv1.Application, un *unstructured.Unstructured, isName
return key
}
func NewLiveStateCache(db db.ArgoDB, appInformer cache.SharedIndexInformer, kubectl kube.Kubectl, onAppUpdated func(appName string)) LiveStateCache {
func NewLiveStateCache(db db.ArgoDB, appInformer cache.SharedIndexInformer, settings *settings.ArgoCDSettings, kubectl kube.Kubectl, onAppUpdated func(appName string)) LiveStateCache {
return &liveStateCache{
appInformer: appInformer,
db: db,
@@ -56,6 +53,7 @@ func NewLiveStateCache(db db.ArgoDB, appInformer cache.SharedIndexInformer, kube
lock: &sync.Mutex{},
onAppUpdated: onAppUpdated,
kubectl: kubectl,
settings: settings,
}
}
@@ -66,10 +64,11 @@ type liveStateCache struct {
appInformer cache.SharedIndexInformer
onAppUpdated func(appName string)
kubectl kube.Kubectl
settings *settings.ArgoCDSettings
}
func (c *liveStateCache) processEvent(event watch.EventType, obj *unstructured.Unstructured, url string) error {
info, err := c.getCluster(url)
info, err := c.getSyncedCluster(url)
if err != nil {
return err
}
@@ -85,54 +84,58 @@ func (c *liveStateCache) removeCluster(server string) {
func (c *liveStateCache) getCluster(server string) (*clusterInfo, error) {
c.lock.Lock()
defer c.lock.Unlock()
info, ok := c.clusters[server]
if !ok {
cluster, err := c.db.GetCluster(context.Background(), server)
if err != nil {
return nil, err
}
info = &clusterInfo{
apis: make(map[schema.GroupVersionKind]v1.APIResource),
lock: &sync.Mutex{},
nodes: make(map[kube.ResourceKey]*node),
nsIndex: make(map[string]map[kube.ResourceKey]*node),
onAppUpdated: c.onAppUpdated,
kubectl: c.kubectl,
cluster: cluster,
syncTime: nil,
syncLock: &sync.Mutex{},
log: log.WithField("server", cluster.Server),
settings: c.settings,
}
c.clusters[cluster.Server] = info
disco, err := discovery.NewDiscoveryClientForConfig(cluster.RESTConfig())
if err != nil {
return nil, err
}
resources, err := disco.ServerResources()
if err != nil {
return nil, err
}
for _, r := range resources {
gv, err := schema.ParseGroupVersion(r.GroupVersion)
if err != nil {
gv = schema.GroupVersion{}
}
for i := range r.APIResources {
info.apis[gv.WithKind(r.APIResources[i].Kind)] = r.APIResources[i]
}
}
}
c.lock.Unlock()
err := info.ensureSynced()
return info, nil
}
func (c *liveStateCache) getSyncedCluster(server string) (*clusterInfo, error) {
info, err := c.getCluster(server)
if err != nil {
return nil, err
}
err = info.ensureSynced()
if err != nil {
return nil, err
}
return info, nil
}
func (c *liveStateCache) Invalidate() {
log.Info("invalidating live state cache")
c.lock.Lock()
defer c.lock.Unlock()
for _, clust := range c.clusters {
clust.lock.Lock()
clust.invalidate()
clust.lock.Unlock()
}
log.Info("live state cache invalidated")
}
func (c *liveStateCache) Delete(server string, obj *unstructured.Unstructured) error {
clusterInfo, err := c.getCluster(server)
clusterInfo, err := c.getSyncedCluster(server)
if err != nil {
return err
}
@@ -140,7 +143,7 @@ func (c *liveStateCache) Delete(server string, obj *unstructured.Unstructured) e
}
func (c *liveStateCache) IsNamespaced(server string, gvk schema.GroupVersionKind) (bool, error) {
clusterInfo, err := c.getCluster(server)
clusterInfo, err := c.getSyncedCluster(server)
if err != nil {
return false, err
}
@@ -148,7 +151,7 @@ func (c *liveStateCache) IsNamespaced(server string, gvk schema.GroupVersionKind
}
func (c *liveStateCache) GetChildren(server string, obj *unstructured.Unstructured) ([]appv1.ResourceNode, error) {
clusterInfo, err := c.getCluster(server)
clusterInfo, err := c.getSyncedCluster(server)
if err != nil {
return nil, err
}
@@ -156,7 +159,7 @@ func (c *liveStateCache) GetChildren(server string, obj *unstructured.Unstructur
}
func (c *liveStateCache) GetManagedLiveObjs(a *appv1.Application, targetObjs []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error) {
clusterInfo, err := c.getCluster(a.Spec.Destination.Server)
clusterInfo, err := c.getSyncedCluster(a.Spec.Destination.Server)
if err != nil {
return nil, err
}
@@ -220,11 +223,24 @@ func (c *liveStateCache) Run(ctx context.Context) {
}
}
c.appInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{AddFunc: onAppModified, DeleteFunc: onAppModified})
c.appInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: onAppModified,
UpdateFunc: func(oldObj, newObj interface{}) {
oldApp, oldOk := oldObj.(*appv1.Application)
newApp, newOk := newObj.(*appv1.Application)
if oldOk && newOk {
if oldApp.Spec.Destination.Server != newApp.Spec.Destination.Server {
onAppModified(oldObj)
onAppModified(newApp)
}
}
},
DeleteFunc: onAppModified,
})
return c.db.WatchClusters(ctx, clusterEventCallback)
}, "watch clusters", ctx, watchResourcesRetryTimeout)
}, "watch clusters", ctx, clusterRetryTimeout)
<-ctx.Done()
}
@@ -239,6 +255,8 @@ func (c *liveStateCache) watchClusterResources(ctx context.Context, item appv1.C
}()
config := item.RESTConfig()
watchStartTime := time.Now()
ctx, cancel := context.WithCancel(ctx)
defer cancel()
ch, err := c.kubectl.WatchResources(ctx, config, "")
if err != nil {
@@ -249,8 +267,10 @@ func (c *liveStateCache) watchClusterResources(ctx context.Context, item appv1.C
if kube.IsCRD(eventObj) {
// restart if new CRD has been created after watch started
if event.Type == watch.Added && watchStartTime.Before(eventObj.GetCreationTimestamp().Time) {
c.removeCluster(item.Server)
return fmt.Errorf("Restarting the watch because a new CRD was added.")
} else if event.Type == watch.Deleted {
c.removeCluster(item.Server)
return fmt.Errorf("Restarting the watch because a CRD was deleted.")
}
}
@@ -260,5 +280,5 @@ func (c *liveStateCache) watchClusterResources(ctx context.Context, item appv1.C
}
}
return fmt.Errorf("resource updates channel has closed")
}, fmt.Sprintf("watch app resources on %s", item.Server), ctx, watchResourcesRetryTimeout)
}, fmt.Sprintf("watch app resources on %s", item.Server), ctx, clusterRetryTimeout)
}

View File

@@ -1,39 +1,46 @@
package cache
import (
"fmt"
"runtime/debug"
"sync"
"time"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/kube"
log "github.com/sirupsen/logrus"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/settings"
)
const (
clusterSyncTimeout = 1 * time.Hour
clusterSyncTimeout = 1 * time.Hour
clusterRetryTimeout = 10 * time.Second
)
type clusterInfo struct {
apis map[schema.GroupVersionKind]metav1.APIResource
nodes map[kube.ResourceKey]*node
nsIndex map[string]map[kube.ResourceKey]*node
lock *sync.Mutex
onAppUpdated func(appName string)
kubectl kube.Kubectl
cluster *appv1.Cluster
syncLock *sync.Mutex
syncTime *time.Time
syncError error
log *log.Entry
settings *settings.ArgoCDSettings
}
func createObjInfo(un *unstructured.Unstructured) *node {
func createObjInfo(un *unstructured.Unstructured, appInstanceLabel string) *node {
ownerRefs := un.GetOwnerReferences()
// Special case for endpoint. Remove after https://github.com/kubernetes/kubernetes/issues/28483 is fixed
if un.GroupVersionKind().Group == "" && un.GetKind() == kube.EndpointsKind && len(un.GetOwnerReferences()) == 0 {
@@ -52,11 +59,9 @@ func createObjInfo(un *unstructured.Unstructured) *node {
Namespace: un.GetNamespace(),
},
ownerRefs: ownerRefs,
parents: make(map[kube.ResourceKey]*node),
children: make(map[kube.ResourceKey]*node),
tags: getTags(un),
info: getNodeInfo(un),
}
appName := kube.GetAppInstanceLabel(un)
appName := kube.GetAppInstanceLabel(un, appInstanceLabel)
if len(ownerRefs) == 0 && appName != "" {
info.appName = appName
info.resource = un
@@ -64,20 +69,65 @@ func createObjInfo(un *unstructured.Unstructured) *node {
return info
}
func (c *clusterInfo) synced() bool {
return c.syncTime != nil && time.Now().Before(c.syncTime.Add(clusterSyncTimeout))
func (c *clusterInfo) setNode(n *node) {
key := n.resourceKey()
c.nodes[key] = n
ns, ok := c.nsIndex[key.Namespace]
if !ok {
ns = make(map[kube.ResourceKey]*node)
c.nsIndex[key.Namespace] = ns
}
ns[key] = n
}
func (c *clusterInfo) ensureSynced() error {
if c.synced() {
return nil
func (c *clusterInfo) removeNode(key kube.ResourceKey) {
delete(c.nodes, key)
if ns, ok := c.nsIndex[key.Namespace]; ok {
delete(ns, key)
if len(ns) == 0 {
delete(c.nsIndex, key.Namespace)
}
}
c.syncLock.Lock()
defer c.syncLock.Unlock()
if c.synced() {
return nil
}
func (c *clusterInfo) invalidate() {
c.syncTime = nil
}
func (c *clusterInfo) synced() bool {
if c.syncTime == nil {
return false
}
if c.syncError != nil {
return time.Now().Before(c.syncTime.Add(clusterRetryTimeout))
}
return time.Now().Before(c.syncTime.Add(clusterSyncTimeout))
}
func (c *clusterInfo) sync() (err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("Recovered from panic: %+v\n%s", r, debug.Stack())
}
}()
c.log.Info("Start syncing cluster")
clusterResources, err := c.kubectl.GetAPIResources(c.cluster.RESTConfig())
if err != nil {
return err
}
c.apis = make(map[schema.GroupVersionKind]metav1.APIResource)
for _, r := range clusterResources {
gv, err := schema.ParseGroupVersion(r.GroupVersion)
if err != nil {
gv = schema.GroupVersion{}
}
for i := range r.APIResources {
c.apis[gv.WithKind(r.APIResources[i].Kind)] = r.APIResources[i]
}
}
c.nodes = make(map[kube.ResourceKey]*node)
resources, err := c.kubectl.GetResources(c.cluster.RESTConfig(), "")
if err != nil {
@@ -85,32 +135,42 @@ func (c *clusterInfo) ensureSynced() error {
return err
}
appLabelKey := c.settings.GetAppInstanceLabelKey()
for i := range resources {
c.nodes[kube.GetResourceKey(resources[i])] = createObjInfo(resources[i])
c.setNode(createObjInfo(resources[i], appLabelKey))
}
nodes := make(map[kube.ResourceKey]*node)
for k, v := range c.nodes {
nodes[k] = v
}
for _, obj := range c.nodes {
if len(obj.ownerRefs) == 0 {
obj.fillChildren(nodes)
}
}
resyncTime := time.Now()
c.syncTime = &resyncTime
c.log.Info("Cluster successfully synced")
return nil
}
func (c *clusterInfo) ensureSynced() error {
if c.synced() {
return c.syncError
}
c.syncLock.Lock()
defer c.syncLock.Unlock()
if c.synced() {
return c.syncError
}
err := c.sync()
syncTime := time.Now()
c.syncTime = &syncTime
c.syncError = err
return c.syncError
}
func (c *clusterInfo) getChildren(obj *unstructured.Unstructured) []appv1.ResourceNode {
c.lock.Lock()
defer c.lock.Unlock()
children := make([]appv1.ResourceNode, 0)
if objInfo, ok := c.nodes[kube.GetResourceKey(obj)]; ok {
for _, child := range objInfo.children {
children = append(children, child.childResourceNodes())
nsNodes := c.nsIndex[obj.GetNamespace()]
for _, child := range nsNodes {
if objInfo.isParentOf(child) {
children = append(children, child.childResourceNodes(nsNodes))
}
}
}
return children
@@ -129,7 +189,7 @@ func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*uns
managedObjs := make(map[kube.ResourceKey]*unstructured.Unstructured)
for key, o := range c.nodes {
if o.appName == a.Name && o.resource != nil && len(o.parents) == 0 {
if o.appName == a.Name && o.resource != nil && len(o.ownerRefs) == 0 {
managedObjs[key] = o.resource
}
}
@@ -174,14 +234,6 @@ func (c *clusterInfo) getManagedLiveObjs(a *appv1.Application, targetObjs []*uns
return managedObjs, nil
}
func ownerRefGV(ownerRef metav1.OwnerReference) schema.GroupVersion {
gv, err := schema.ParseGroupVersion(ownerRef.APIVersion)
if err != nil {
gv = schema.GroupVersion{}
}
return gv
}
func (c *clusterInfo) delete(obj *unstructured.Unstructured) error {
err := c.kubectl.DeleteResource(c.cluster.RESTConfig(), obj.GroupVersionKind(), obj.GetName(), obj.GetNamespace(), false)
err = c.handleError(obj.GroupVersionKind(), obj.GetNamespace(), obj.GetName(), err)
@@ -208,62 +260,36 @@ func (c *clusterInfo) handleError(gvk schema.GroupVersionKind, namespace string,
func (c *clusterInfo) processEvent(event watch.EventType, un *unstructured.Unstructured) error {
c.lock.Lock()
defer c.lock.Unlock()
obj, exists := c.nodes[kube.GetResourceKey(un)]
if exists && event == watch.Deleted {
for i := range obj.parents {
delete(obj.parents[i].children, obj.resourceKey())
}
for i := range obj.children {
delete(obj.children[i].parents, obj.resourceKey())
}
delete(c.nodes, kube.GetResourceKey(un))
if obj.appName != "" {
c.onAppUpdated(obj.appName)
}
} else if !exists && event != watch.Deleted {
newObj := createObjInfo(un)
c.nodes[newObj.resourceKey()] = newObj
if len(newObj.ownerRefs) > 0 {
sameNamespace := make(map[kube.ResourceKey]*node)
for k := range c.nodes {
if c.nodes[k].ref.Namespace == un.GetNamespace() {
sameNamespace[k] = c.nodes[k]
}
}
for _, ownerRef := range newObj.ownerRefs {
if owner, ok := sameNamespace[kube.NewResourceKey(ownerRefGV(ownerRef).Group, ownerRef.Kind, un.GetNamespace(), ownerRef.Name)]; ok {
owner.fillChildren(sameNamespace)
}
key := kube.GetResourceKey(un)
existingNode, exists := c.nodes[key]
if event == watch.Deleted {
if exists {
c.removeNode(key)
if existingNode.appName != "" {
c.onAppUpdated(existingNode.appName)
}
}
if newObj.appName != "" {
c.onAppUpdated(newObj.appName)
}
} else if exists {
obj.resourceVersion = un.GetResourceVersion()
toNotify := make([]string, 0)
if obj.appName != "" {
toNotify = append(toNotify, obj.appName)
} else if event != watch.Deleted {
nodes := make([]*node, 0)
if exists {
nodes = append(nodes, existingNode)
}
newObj := createObjInfo(un, c.settings.GetAppInstanceLabelKey())
c.setNode(newObj)
nodes = append(nodes, newObj)
if len(obj.ownerRefs) == 0 {
newAppName := kube.GetAppInstanceLabel(un)
if newAppName != obj.appName {
obj.setAppName(newAppName)
if newAppName != "" {
toNotify = append(toNotify, newAppName)
toNotify := make(map[string]bool)
for i := range nodes {
n := nodes[i]
if ns, ok := c.nsIndex[n.ref.Namespace]; ok {
app := n.getApp(ns)
if app != "" {
toNotify[app] = true
}
}
}
if len(obj.parents) == 0 && obj.appName != "" {
obj.resource = un
} else {
obj.resource = nil
}
obj.tags = getTags(un)
for _, name := range toNotify {
for name := range toNotify {
c.onAppUpdated(name)
}
}

View File

@@ -6,20 +6,19 @@ import (
"sync"
"testing"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/kube/kubetest"
"github.com/argoproj/argo-cd/util/settings"
log "github.com/sirupsen/logrus"
)
@@ -81,11 +80,13 @@ func newCluster(resources ...*unstructured.Unstructured) *clusterInfo {
kubectl: kubetest.MockKubectlCmd{
Resources: resources,
},
nsIndex: make(map[string]map[kube.ResourceKey]*node),
cluster: &appv1.Cluster{},
syncTime: nil,
syncLock: &sync.Mutex{},
apis: make(map[schema.GroupVersionKind]v1.APIResource),
apis: make(map[schema.GroupVersionKind]metav1.APIResource),
log: log.WithField("cluster", "test"),
settings: &settings.ArgoCDSettings{},
}
}
@@ -101,7 +102,7 @@ func TestGetChildren(t *testing.T) {
Name: "helm-guestbook-pod",
Group: "",
Version: "v1",
Tags: []string{"0/0"},
Info: []appv1.InfoItem{{Name: "Containers", Value: "0/0"}},
Children: make([]appv1.ResourceNode, 0),
ResourceVersion: "123",
}}, rsChildren)
@@ -115,7 +116,7 @@ func TestGetChildren(t *testing.T) {
Version: "v1beta1",
ResourceVersion: "123",
Children: rsChildren,
Tags: []string{},
Info: []appv1.InfoItem{},
}}, deployChildren)
}
@@ -133,7 +134,7 @@ metadata:
app: helm-guestbook`)
managedObjs, err := cluster.getManagedLiveObjs(&appv1.Application{
ObjectMeta: v1.ObjectMeta{Name: "helm-guestbook"},
ObjectMeta: metav1.ObjectMeta{Name: "helm-guestbook"},
Spec: appv1.ApplicationSpec{
Destination: appv1.ApplicationDestination{
Namespace: "default",
@@ -188,7 +189,7 @@ func TestProcessNewChildEvent(t *testing.T) {
Name: "helm-guestbook-pod",
Group: "",
Version: "v1",
Tags: []string{"0/0"},
Info: []appv1.InfoItem{{Name: "Containers", Value: "0/0"}},
Children: make([]appv1.ResourceNode, 0),
ResourceVersion: "123",
}, {
@@ -197,7 +198,7 @@ func TestProcessNewChildEvent(t *testing.T) {
Name: "helm-guestbook-pod2",
Group: "",
Version: "v1",
Tags: []string{"0/0"},
Info: []appv1.InfoItem{{Name: "Containers", Value: "0/0"}},
Children: make([]appv1.ResourceNode, 0),
ResourceVersion: "123",
}}, rsChildren)
@@ -205,8 +206,8 @@ func TestProcessNewChildEvent(t *testing.T) {
func TestUpdateResourceTags(t *testing.T) {
pod := &corev1.Pod{
TypeMeta: v1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
ObjectMeta: v1.ObjectMeta{Name: "testPod", Namespace: "default"},
TypeMeta: metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{Name: "testPod", Namespace: "default"},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "test",
@@ -222,7 +223,7 @@ func TestUpdateResourceTags(t *testing.T) {
podNode := cluster.nodes[kube.GetResourceKey(mustToUnstructured(pod))]
assert.NotNil(t, podNode)
assert.Equal(t, []string{"0/1"}, podNode.tags)
assert.Equal(t, []appv1.InfoItem{{Name: "Containers", Value: "0/1"}}, podNode.info)
pod.Status = corev1.PodStatus{
ContainerStatuses: []corev1.ContainerStatus{{
@@ -239,7 +240,7 @@ func TestUpdateResourceTags(t *testing.T) {
podNode = cluster.nodes[kube.GetResourceKey(mustToUnstructured(pod))]
assert.NotNil(t, podNode)
assert.Equal(t, []string{"ExitCode:-1", "0/1"}, podNode.tags)
assert.Equal(t, []appv1.InfoItem{{Name: "Status Reason", Value: "ExitCode:-1"}, {Name: "Containers", Value: "0/1"}}, podNode.info)
}
func TestUpdateAppResource(t *testing.T) {
@@ -257,28 +258,3 @@ func TestUpdateAppResource(t *testing.T) {
assert.Equal(t, []string{"helm-guestbook"}, updatesReceived)
}
func TestUpdateRootAppResource(t *testing.T) {
updatesReceived := make([]string, 0)
cluster := newCluster(testPod, testRS, testDeploy)
cluster.onAppUpdated = func(appName string) {
updatesReceived = append(updatesReceived, appName)
}
err := cluster.ensureSynced()
assert.Nil(t, err)
for k := range cluster.nodes {
assert.Equal(t, "helm-guestbook", cluster.nodes[k].appName)
}
updatedDeploy := testDeploy.DeepCopy()
updatedDeploy.SetLabels(map[string]string{common.LabelKeyAppInstance: "helm-guestbook2"})
err = cluster.processEvent(watch.Modified, updatedDeploy)
assert.Nil(t, err)
assert.Equal(t, []string{"helm-guestbook", "helm-guestbook2"}, updatesReceived)
for k := range cluster.nodes {
assert.Equal(t, "helm-guestbook2", cluster.nodes[k].appName)
}
}

View File

@@ -3,6 +3,8 @@ package cache
import (
"fmt"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/kube"
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
@@ -10,20 +12,20 @@ import (
k8snode "k8s.io/kubernetes/pkg/util/node"
)
func getTags(un *unstructured.Unstructured) []string {
func getNodeInfo(un *unstructured.Unstructured) []v1alpha1.InfoItem {
gvk := un.GroupVersionKind()
if gvk.Kind == kube.PodKind && gvk.Group == "" {
return getPodTags(un)
return getPodInfo(un)
}
return []string{}
return []v1alpha1.InfoItem{}
}
func getPodTags(un *unstructured.Unstructured) []string {
func getPodInfo(un *unstructured.Unstructured) []v1alpha1.InfoItem {
pod := v1.Pod{}
err := runtime.DefaultUnstructuredConverter.FromUnstructured(un.Object, &pod)
if err != nil {
return []string{}
return []v1alpha1.InfoItem{}
}
restarts := 0
totalContainers := len(pod.Spec.Containers)
@@ -97,9 +99,9 @@ func getPodTags(un *unstructured.Unstructured) []string {
reason = "Terminating"
}
tags := make([]string, 0)
info := make([]v1alpha1.InfoItem, 0)
if reason != "" {
tags = append(tags, reason)
info = append(info, v1alpha1.InfoItem{Name: "Status Reason", Value: reason})
}
return append(tags, fmt.Sprintf("%d/%d", readyContainers, totalContainers))
return append(info, v1alpha1.InfoItem{Name: "Containers", Value: fmt.Sprintf("%d/%d", readyContainers, totalContainers)})
}

View File

@@ -74,6 +74,11 @@ func (_m *LiveStateCache) GetManagedLiveObjs(a *v1alpha1.Application, targetObjs
return r0, r1
}
// Invalidate provides a mock function with given fields:
func (_m *LiveStateCache) Invalidate() {
_m.Called()
}
// IsNamespaced provides a mock function with given fields: server, gvk
func (_m *LiveStateCache) IsNamespaced(server string, gvk schema.GroupVersionKind) (bool, error) {
ret := _m.Called(server, gvk)

View File

@@ -13,9 +13,7 @@ type node struct {
resourceVersion string
ref v1.ObjectReference
ownerRefs []metav1.OwnerReference
children map[kube.ResourceKey]*node
parents map[kube.ResourceKey]*node
tags []string
info []appv1.InfoItem
appName string
resource *unstructured.Unstructured
}
@@ -25,9 +23,6 @@ func (n *node) resourceKey() kube.ResourceKey {
}
func (n *node) isParentOf(child *node) bool {
if n.ref.Namespace != child.ref.Namespace {
return false
}
ownerGvk := n.ref.GroupVersionKind()
for _, ownerRef := range child.ownerRefs {
if kube.NewResourceKey(ownerGvk.Group, ownerRef.Kind, n.ref.Namespace, ownerRef.Name) == n.resourceKey() {
@@ -38,29 +33,36 @@ func (n *node) isParentOf(child *node) bool {
return false
}
func (n *node) setAppName(appName string) {
n.appName = appName
for i := range n.children {
n.children[i].setAppName(appName)
func ownerRefGV(ownerRef metav1.OwnerReference) schema.GroupVersion {
gv, err := schema.ParseGroupVersion(ownerRef.APIVersion)
if err != nil {
gv = schema.GroupVersion{}
}
return gv
}
func (n *node) fillChildren(nodes map[kube.ResourceKey]*node) {
for k, child := range nodes {
if n.isParentOf(child) {
delete(nodes, k)
child.appName = n.appName
child.parents[n.resourceKey()] = n
n.children[child.resourceKey()] = child
child.fillChildren(nodes)
func (n *node) getApp(ns map[kube.ResourceKey]*node) string {
if n.appName != "" {
return n.appName
}
for _, ownerRef := range n.ownerRefs {
gv := ownerRefGV(ownerRef)
if parent, ok := ns[kube.NewResourceKey(gv.Group, ownerRef.Kind, n.ref.Namespace, ownerRef.Name)]; ok {
app := parent.getApp(ns)
if app != "" {
return app
}
}
}
return ""
}
func (n *node) childResourceNodes() appv1.ResourceNode {
func (n *node) childResourceNodes(ns map[kube.ResourceKey]*node) appv1.ResourceNode {
children := make([]appv1.ResourceNode, 0)
for i := range n.children {
children = append(children, n.children[i].childResourceNodes())
for key := range ns {
if n.isParentOf(ns[key]) {
children = append(children, ns[key].childResourceNodes(ns))
}
}
gv, err := schema.ParseGroupVersion(n.ref.APIVersion)
if err != nil {
@@ -72,7 +74,7 @@ func (n *node) childResourceNodes() appv1.ResourceNode {
Version: gv.Version,
Kind: n.ref.Kind,
Namespace: n.ref.Namespace,
Tags: n.tags,
Info: n.info,
Children: children,
ResourceVersion: n.resourceVersion,
}

View File

@@ -35,7 +35,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_9e06f70e07dd0483, []int{0}
return fileDescriptor_application_22f1e591d294b941, []int{0}
}
func (m *ResourcesQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -82,7 +82,7 @@ func (m *ResourceTreeResponse) Reset() { *m = ResourceTreeResponse{} }
func (m *ResourceTreeResponse) String() string { return proto.CompactTextString(m) }
func (*ResourceTreeResponse) ProtoMessage() {}
func (*ResourceTreeResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_application_9e06f70e07dd0483, []int{1}
return fileDescriptor_application_22f1e591d294b941, []int{1}
}
func (m *ResourceTreeResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -129,7 +129,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_9e06f70e07dd0483, []int{2}
return fileDescriptor_application_22f1e591d294b941, []int{2}
}
func (m *ManagedResourcesResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -784,10 +784,10 @@ var (
)
func init() {
proto.RegisterFile("controller/services/application.proto", fileDescriptor_application_9e06f70e07dd0483)
proto.RegisterFile("controller/services/application.proto", fileDescriptor_application_22f1e591d294b941)
}
var fileDescriptor_application_9e06f70e07dd0483 = []byte{
var fileDescriptor_application_22f1e591d294b941 = []byte{
// 337 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xb4, 0x53, 0xcd, 0x4a, 0x33, 0x31,
0x14, 0x6d, 0xbe, 0x0f, 0x05, 0xa3, 0xa8, 0x04, 0x17, 0xa5, 0x8b, 0x52, 0x06, 0x84, 0x6e, 0x4c,

View File

@@ -24,6 +24,7 @@ import (
"github.com/argoproj/argo-cd/util/health"
hookutil "github.com/argoproj/argo-cd/util/hook"
kubeutil "github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/settings"
)
type managedResource struct {
@@ -48,7 +49,7 @@ func GetLiveObjs(res []managedResource) []*unstructured.Unstructured {
// AppStateManager defines methods which allow to compare application spec and actual application state.
type AppStateManager interface {
CompareAppState(app *v1alpha1.Application, revision string, overrides []v1alpha1.ComponentParameter) (*comparisonResult, error)
CompareAppState(app *v1alpha1.Application, revision string, overrides []v1alpha1.ComponentParameter, noCache bool) (*comparisonResult, error)
SyncAppState(app *v1alpha1.Application, state *v1alpha1.OperationState)
}
@@ -65,6 +66,7 @@ type comparisonResult struct {
// appStateManager allows to compare applications to git
type appStateManager struct {
db db.ArgoDB
settings *settings.ArgoCDSettings
appclientset appclientset.Interface
kubectl kubeutil.Kubectl
repoClientset reposerver.Clientset
@@ -72,7 +74,7 @@ type appStateManager struct {
namespace string
}
func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, revision string, overrides []v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*unstructured.Unstructured, *repository.ManifestResponse, error) {
func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, appLabelKey, revision string, overrides []v1alpha1.ComponentParameter, noCache bool) ([]*unstructured.Unstructured, []*unstructured.Unstructured, *repository.ManifestResponse, error) {
helmRepos, err := m.db.ListHelmRepos(context.Background())
if err != nil {
return nil, nil, nil, err
@@ -110,8 +112,10 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, revision string
Repo: repo,
HelmRepos: helmRepos,
Revision: revision,
NoCache: noCache,
ComponentParameterOverrides: mfReqOverrides,
AppLabel: app.Name,
AppLabelKey: appLabelKey,
AppLabelValue: app.Name,
Namespace: app.Spec.Destination.Namespace,
ApplicationSource: &app.Spec.Source,
})
@@ -138,11 +142,12 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, revision string
// CompareAppState compares application git state to the live app state, using the specified
// revision and supplied overrides. 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, overrides []v1alpha1.ComponentParameter) (*comparisonResult, error) {
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision string, overrides []v1alpha1.ComponentParameter, noCache bool) (*comparisonResult, error) {
observedAt := metav1.Now()
failedToLoadObjs := false
conditions := make([]v1alpha1.ApplicationCondition, 0)
targetObjs, hooks, manifestInfo, err := m.getRepoObjs(app, revision, overrides)
appLabelKey := m.settings.GetAppInstanceLabelKey()
targetObjs, hooks, manifestInfo, err := m.getRepoObjs(app, appLabelKey, revision, overrides, noCache)
if err != nil {
targetObjs = make([]*unstructured.Unstructured, 0)
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error()})
@@ -158,7 +163,7 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision st
for _, liveObj := range liveObjByKey {
if liveObj != nil {
appInstanceName := kubeutil.GetAppInstanceLabel(liveObj)
appInstanceName := kubeutil.GetAppInstanceLabel(liveObj, appLabelKey)
if appInstanceName != "" && appInstanceName != app.Name {
conditions = append(conditions, v1alpha1.ApplicationCondition{
Type: v1alpha1.ApplicationConditionSharedResourceWarning,
@@ -253,8 +258,11 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision st
syncCode = v1alpha1.SyncStatusCodeUnknown
}
syncStatus := v1alpha1.SyncStatus{
ComparedTo: app.Spec.Source,
Status: syncCode,
ComparedTo: appv1.ComparedTo{
Source: app.Spec.Source,
Destination: app.Spec.Destination,
},
Status: syncCode,
}
if manifestInfo != nil {
syncStatus.Revision = manifestInfo.Revision
@@ -322,6 +330,7 @@ func NewAppStateManager(
repoClientset reposerver.Clientset,
namespace string,
kubectl kubeutil.Kubectl,
settings *settings.ArgoCDSettings,
liveStateCache statecache.LiveStateCache,
) AppStateManager {
return &appStateManager{
@@ -331,5 +340,6 @@ func NewAppStateManager(
kubectl: kubectl,
repoClientset: repoClientset,
namespace: namespace,
settings: settings,
}
}

View File

@@ -28,7 +28,7 @@ func TestCompareAppStateEmpty(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil, false)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)
@@ -51,7 +51,7 @@ func TestCompareAppStateMissing(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil, false)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
@@ -78,7 +78,7 @@ func TestCompareAppStateExtra(t *testing.T) {
},
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil, false)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
@@ -105,7 +105,7 @@ func TestCompareAppStateHook(t *testing.T) {
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil, false)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)
@@ -133,7 +133,7 @@ func TestCompareAppStateExtraHook(t *testing.T) {
},
}
ctrl := newFakeController(&data)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil)
compRes, err := ctrl.appStateManager.CompareAppState(app, "", nil, false)
assert.NoError(t, err)
assert.NotNil(t, compRes)
assert.Equal(t, argoappv1.SyncStatusCodeSynced, compRes.syncStatus.Status)

View File

@@ -75,7 +75,7 @@ func (m *appStateManager) SyncAppState(app *appv1.Application, state *appv1.Oper
revision = syncOp.Revision
}
compareResult, err := m.CompareAppState(app, revision, overrides)
compareResult, err := m.CompareAppState(app, revision, overrides, false)
if err != nil {
state.Phase = appv1.OperationError
state.Message = err.Error()
@@ -247,11 +247,12 @@ func (sc *syncContext) generateSyncTasks() ([]syncTask, bool) {
var targetObj *unstructured.Unstructured
if resourceState.Target != nil {
targetObj = resourceState.Target.DeepCopy()
if targetObj.GetNamespace() == "" {
targetObj.SetNamespace(sc.namespace)
}
gvk := targetObj.GroupVersionKind()
serverRes, err := kube.ServerResourceForGroupVersionKind(sc.disco, gvk)
if err == nil && targetObj.GetNamespace() == "" && serverRes.Namespaced {
targetObj.SetNamespace(sc.namespace)
}
if err != nil {
// Special case for custom resources: if custom resource definition is not supported by the cluster by defined in application then
// skip verification using `kubectl apply --dry-run` and since CRD should be created during app synchronization.
@@ -267,6 +268,7 @@ func (sc *syncContext) generateSyncTasks() ([]syncTask, bool) {
Message: err.Error(),
Status: appv1.ResultCodeSyncFailed,
})
successful = false
}
} else {
if !sc.proj.IsResourcePermitted(metav1.GroupKind{Group: gvk.Group, Kind: gvk.Kind}, serverRes.Namespaced) {

View File

@@ -124,3 +124,53 @@ happen at the ingress controller.
Neither ALBs and Classic ELB in HTTP mode, do not have full support for HTTP2/gRPC which is the
protocol used by the `argocd` CLI. Thus, when using an AWS load balancer, either Classic ELB in
passthrough mode is needed, or NLBs.
## UI base path
If Argo CD UI is available under non-root path (e.g. `/argo-cd` instead of `/`) then UI path should be configured in API server.
To configure UI path add `--basehref` flag into `argocd-server` deployment command:
```yaml
spec:
template:
spec:
name: argocd-server
containers:
- command:
- /argocd-server
- --staticassets
- /shared/app
- --repo-server
- argocd-repo-server:8081
- --base-href
- /argo-cd
```
NOTE: flag `--basehref` only changes UI base URL. API server keep using `/` path so you need to add URL rewrite rule to proxy config.
Example nginx.conf with URL rewrite:
```
worker_processes 1;
events { worker_connections 1024; }
http {
sendfile on;
server {
listen 443;
location /argo-cd {
rewrite /argo-cd/(.*) /$1 break;
proxy_pass https://localhost:8080;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
```

View File

@@ -42,24 +42,24 @@ argocd proj create myproject -d https://kubernetes.default.svc,mynamespace -s ht
Permitted source git repositories are managed using commands:
```bash
argocd project add-source <PROJECT> <REPO>
argocd project remove-source <PROJECT> <REPO>
argocd proj add-source <PROJECT> <REPO>
argocd proj remove-source <PROJECT> <REPO>
```
Permitted destination clusters and namespaces are managed with the commands:
```
argocd project add-destination <PROJECT> <CLUSTER>,<NAMESPACE>
argocd project remove-destination <PROJECT> <CLUSTER>,<NAMESPACE>
argocd proj add-destination <PROJECT> <CLUSTER>,<NAMESPACE>
argocd proj remove-destination <PROJECT> <CLUSTER>,<NAMESPACE>
```
Permitted destination K8s resource kinds are managed with the commands. Note that namespaced-scoped
resources are restricted via a blacklist, whereas cluster-scoped resources are restricted via
whitelist.
```
argocd project allow-cluster-resource <PROJECT> <GROUP> <KIND>
argocd project allow-namespace-resource <PROJECT> <GROUP> <KIND>
argocd project deny-cluster-resource <PROJECT> <GROUP> <KIND>
argocd project deny-namespace-resource <PROJECT> <GROUP> <KIND>
argocd proj allow-cluster-resource <PROJECT> <GROUP> <KIND>
argocd proj allow-namespace-resource <PROJECT> <GROUP> <KIND>
argocd proj deny-cluster-resource <PROJECT> <GROUP> <KIND>
argocd proj deny-namespace-resource <PROJECT> <GROUP> <KIND>
```
### Assign application to a project

View File

@@ -1,15 +1,15 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-controller
name: argocd-application-controller
spec:
selector:
matchLabels:
app: application-controller
app: argocd-application-controller
template:
metadata:
labels:
app: application-controller
app: argocd-application-controller
spec:
containers:
- command:
@@ -20,7 +20,7 @@ spec:
- "10"
image: argoproj/argocd:latest
imagePullPolicy: Always
name: application-controller
name: argocd-application-controller
ports:
- containerPort: 8083
readinessProbe:
@@ -28,4 +28,4 @@ spec:
port: 8083
initialDelaySeconds: 5
periodSeconds: 10
serviceAccountName: application-controller
serviceAccountName: argocd-application-controller

View File

@@ -1,15 +1,17 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: application-controller-role
name: argocd-application-controller
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- argoproj.io
resources:
@@ -23,14 +25,6 @@ rules:
- update
- patch
- delete
- apiGroups:
- ""
resources:
- configmaps
resourceNames:
- argocd-cm
verbs:
- get
- apiGroups:
- ""
resources:

View File

@@ -1,11 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: application-controller-role-binding
name: argocd-application-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: application-controller-role
name: argocd-application-controller
subjects:
- kind: ServiceAccount
name: application-controller
name: argocd-application-controller

View File

@@ -1,4 +1,4 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: application-controller
name: argocd-application-controller

View File

@@ -1,10 +1,10 @@
apiVersion: v1
kind: Service
metadata:
name: application-controller
name: argocd-application-controller
spec:
ports:
- port: 8083
targetPort: 8083
selector:
app: application-controller
app: argocd-application-controller

View File

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

View File

@@ -1,11 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argocd-server-role-binding
name: argocd-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-server-role
name: argocd-server
subjects:
- kind: ServiceAccount
name: argocd-server

View File

@@ -1,7 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dex-server-role
name: dex-server
rules:
- apiGroups:
- ""

View File

@@ -1,11 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dex-server-role-binding
name: dex-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dex-server-role
name: dex-server
subjects:
- kind: ServiceAccount
name: dex-server

View File

@@ -2,11 +2,11 @@ resources:
- argocd-cm.yaml
- argocd-secret.yaml
- argocd-rbac-cm.yaml
- application-controller-sa.yaml
- application-controller-role.yaml
- application-controller-rolebinding.yaml
- application-controller-deployment.yaml
- application-controller-service.yaml
- argocd-application-controller-sa.yaml
- argocd-application-controller-role.yaml
- argocd-application-controller-rolebinding.yaml
- argocd-application-controller-deployment.yaml
- argocd-application-controller-service.yaml
- argocd-server-sa.yaml
- argocd-server-role.yaml
- argocd-server-rolebinding.yaml
@@ -23,6 +23,6 @@ resources:
imageTags:
- name: argoproj/argocd
newTag: latest
newTag: v0.11.0-rc3
- name: argoproj/argocd-ui
newTag: latest
newTag: v0.11.0-rc3

View File

@@ -1,7 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: application-controller-clusterrole
name: argocd-application-controller
rules:
- apiGroups:
- '*'

View File

@@ -1,12 +1,12 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: application-controller-clusterrolebinding
name: argocd-application-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: application-controller-clusterrole
name: argocd-application-controller
subjects:
- kind: ServiceAccount
name: application-controller
name: argocd-application-controller
namespace: argocd

View File

@@ -1,7 +1,7 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-server-clusterrole
name: argocd-server
rules:
- apiGroups:
- '*'

View File

@@ -1,11 +1,11 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-server-clusterrolebinding
name: argocd-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-server-clusterrole
name: argocd-server
subjects:
- kind: ServiceAccount
name: argocd-server

View File

@@ -2,7 +2,7 @@ bases:
- ../namespace-install
resources:
- application-controller-clusterrole.yaml
- application-controller-clusterrolebinding.yaml
- argocd-application-controller-clusterrole.yaml
- argocd-application-controller-clusterrolebinding.yaml
- argocd-server-clusterrole.yaml
- argocd-server-clusterrolebinding.yaml

View File

@@ -31,7 +31,7 @@ spec:
apiVersion: v1
kind: ServiceAccount
metadata:
name: application-controller
name: argocd-application-controller
---
apiVersion: v1
kind: ServiceAccount
@@ -46,15 +46,17 @@ metadata:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: application-controller-role
name: argocd-application-controller
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- argoproj.io
resources:
@@ -68,14 +70,6 @@ rules:
- update
- patch
- delete
- apiGroups:
- ""
resourceNames:
- argocd-cm
resources:
- configmaps
verbs:
- get
- apiGroups:
- ""
resources:
@@ -87,7 +81,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: argocd-server-role
name: argocd-server
rules:
- apiGroups:
- ""
@@ -126,7 +120,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dex-server-role
name: dex-server
rules:
- apiGroups:
- ""
@@ -141,7 +135,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: application-controller-clusterrole
name: argocd-application-controller
rules:
- apiGroups:
- '*'
@@ -157,7 +151,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: argocd-server-clusterrole
name: argocd-server
rules:
- apiGroups:
- '*'
@@ -165,6 +159,7 @@ rules:
- '*'
verbs:
- delete
- get
- apiGroups:
- ""
resources:
@@ -182,23 +177,23 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: application-controller-role-binding
name: argocd-application-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: application-controller-role
name: argocd-application-controller
subjects:
- kind: ServiceAccount
name: application-controller
name: argocd-application-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argocd-server-role-binding
name: argocd-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-server-role
name: argocd-server
subjects:
- kind: ServiceAccount
name: argocd-server
@@ -206,11 +201,11 @@ subjects:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dex-server-role-binding
name: dex-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dex-server-role
name: dex-server
subjects:
- kind: ServiceAccount
name: dex-server
@@ -218,24 +213,24 @@ subjects:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: application-controller-clusterrolebinding
name: argocd-application-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: application-controller-clusterrole
name: argocd-application-controller
subjects:
- kind: ServiceAccount
name: application-controller
name: argocd-application-controller
namespace: argocd
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: argocd-server-clusterrolebinding
name: argocd-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: argocd-server-clusterrole
name: argocd-server
subjects:
- kind: ServiceAccount
name: argocd-server
@@ -260,13 +255,13 @@ type: Opaque
apiVersion: v1
kind: Service
metadata:
name: application-controller
name: argocd-application-controller
spec:
ports:
- port: 8083
targetPort: 8083
selector:
app: application-controller
app: argocd-application-controller
---
apiVersion: v1
kind: Service
@@ -331,15 +326,15 @@ spec:
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-controller
name: argocd-application-controller
spec:
selector:
matchLabels:
app: application-controller
app: argocd-application-controller
template:
metadata:
labels:
app: application-controller
app: argocd-application-controller
spec:
containers:
- command:
@@ -348,9 +343,9 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: application-controller
name: argocd-application-controller
ports:
- containerPort: 8083
readinessProbe:
@@ -358,7 +353,7 @@ spec:
periodSeconds: 10
tcpSocket:
port: 8083
serviceAccountName: application-controller
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
kind: Deployment
@@ -377,7 +372,7 @@ spec:
containers:
- command:
- argocd-repo-server
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -406,7 +401,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: argocd-server
ports:
@@ -426,7 +421,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v0.11.0-rc3
imagePullPolicy: Always
name: ui
volumeMounts:
@@ -468,7 +463,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: copyutil
volumeMounts:

View File

@@ -31,7 +31,7 @@ spec:
apiVersion: v1
kind: ServiceAccount
metadata:
name: application-controller
name: argocd-application-controller
---
apiVersion: v1
kind: ServiceAccount
@@ -46,15 +46,17 @@ metadata:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: application-controller-role
name: argocd-application-controller
rules:
- apiGroups:
- ""
resources:
- secrets
- configmaps
verbs:
- get
- list
- watch
- apiGroups:
- argoproj.io
resources:
@@ -68,14 +70,6 @@ rules:
- update
- patch
- delete
- apiGroups:
- ""
resourceNames:
- argocd-cm
resources:
- configmaps
verbs:
- get
- apiGroups:
- ""
resources:
@@ -87,7 +81,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: argocd-server-role
name: argocd-server
rules:
- apiGroups:
- ""
@@ -126,7 +120,7 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: dex-server-role
name: dex-server
rules:
- apiGroups:
- ""
@@ -141,23 +135,23 @@ rules:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: application-controller-role-binding
name: argocd-application-controller
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: application-controller-role
name: argocd-application-controller
subjects:
- kind: ServiceAccount
name: application-controller
name: argocd-application-controller
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: argocd-server-role-binding
name: argocd-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: argocd-server-role
name: argocd-server
subjects:
- kind: ServiceAccount
name: argocd-server
@@ -165,11 +159,11 @@ subjects:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: dex-server-role-binding
name: dex-server
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dex-server-role
name: dex-server
subjects:
- kind: ServiceAccount
name: dex-server
@@ -193,13 +187,13 @@ type: Opaque
apiVersion: v1
kind: Service
metadata:
name: application-controller
name: argocd-application-controller
spec:
ports:
- port: 8083
targetPort: 8083
selector:
app: application-controller
app: argocd-application-controller
---
apiVersion: v1
kind: Service
@@ -264,15 +258,15 @@ spec:
apiVersion: apps/v1
kind: Deployment
metadata:
name: application-controller
name: argocd-application-controller
spec:
selector:
matchLabels:
app: application-controller
app: argocd-application-controller
template:
metadata:
labels:
app: application-controller
app: argocd-application-controller
spec:
containers:
- command:
@@ -281,9 +275,9 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: application-controller
name: argocd-application-controller
ports:
- containerPort: 8083
readinessProbe:
@@ -291,7 +285,7 @@ spec:
periodSeconds: 10
tcpSocket:
port: 8083
serviceAccountName: application-controller
serviceAccountName: argocd-application-controller
---
apiVersion: apps/v1
kind: Deployment
@@ -310,7 +304,7 @@ spec:
containers:
- command:
- argocd-repo-server
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: argocd-repo-server
ports:
@@ -339,7 +333,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: argocd-server
ports:
@@ -359,7 +353,7 @@ spec:
- -r
- /app
- /shared
image: argoproj/argocd-ui:latest
image: argoproj/argocd-ui:v0.11.0-rc3
imagePullPolicy: Always
name: ui
volumeMounts:
@@ -401,7 +395,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:latest
image: argoproj/argocd:v0.11.0-rc3
imagePullPolicy: Always
name: copyutil
volumeMounts:

File diff suppressed because it is too large Load Diff

View File

@@ -242,6 +242,13 @@ message ClusterList {
repeated Cluster items = 2;
}
// ComparedTo contains application source and target which was used for resources comparison
message ComparedTo {
optional ApplicationSource source = 1;
optional ApplicationDestination destination = 2;
}
// ComponentParameter contains information about component parameter value
message ComponentParameter {
optional string component = 1;
@@ -282,6 +289,15 @@ message HelmRepository {
optional string password = 7;
}
// InfoItem contains human readable information about object
message InfoItem {
// Name is a human readable title for this piece of information.
optional string name = 1;
// Value is human readable content.
optional string value = 2;
}
// JWTToken holds the issuedAt and expiresAt values of a token
message JWTToken {
optional int64 iat = 1;
@@ -391,7 +407,7 @@ message ResourceNode {
optional string name = 5;
repeated string tags = 6;
repeated InfoItem info = 6;
repeated ResourceNode children = 7;
@@ -507,7 +523,7 @@ message SyncPolicyAutomated {
message SyncStatus {
optional string status = 1;
optional ApplicationSource comparedTo = 2;
optional ComparedTo comparedTo = 2;
optional string revision = 3;
}

View File

@@ -76,6 +76,13 @@ const (
ApplicationSourceTypeDirectory ApplicationSourceType = "Directory"
)
type RefreshType string
const (
RefreshTypeNormal RefreshType = "normal"
RefreshTypeHard RefreshType = "hard"
)
// ApplicationSourceHelm holds helm specific options
type ApplicationSourceHelm struct {
// ValuesFiles is a list of Helm value files to use when generating a template
@@ -375,11 +382,17 @@ type ApplicationCondition struct {
Message string `json:"message" protobuf:"bytes,2,opt,name=message"`
}
// ComparedTo contains application source and target which was used for resources comparison
type ComparedTo struct {
Source ApplicationSource `json:"source" protobuf:"bytes,1,opt,name=source"`
Destination ApplicationDestination `json:"destination" protobuf:"bytes,2,opt,name=destination"`
}
// SyncStatus is a comparison result of application spec and deployed application.
type SyncStatus struct {
Status SyncStatusCode `json:"status" protobuf:"bytes,1,opt,name=status,casttype=SyncStatusCode"`
ComparedTo ApplicationSource `json:"comparedTo" protobuf:"bytes,2,opt,name=comparedTo"`
Revision string `json:"revision" protobuf:"bytes,3,opt,name=revision"`
Status SyncStatusCode `json:"status" protobuf:"bytes,1,opt,name=status,casttype=SyncStatusCode"`
ComparedTo ComparedTo `json:"comparedTo" protobuf:"bytes,2,opt,name=comparedTo"`
Revision string `json:"revision" protobuf:"bytes,3,opt,name=revision"`
}
type HealthStatus struct {
@@ -397,6 +410,14 @@ const (
HealthStatusMissing HealthStatusCode = "Missing"
)
// InfoItem contains human readable information about object
type InfoItem struct {
// Name is a human readable title for this piece of information.
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`
// Value is human readable content.
Value string `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
}
// ResourceNode contains information about live resource and its children
type ResourceNode struct {
Group string `json:"group,omitempty" protobuf:"bytes,1,opt,name=group"`
@@ -404,7 +425,7 @@ type ResourceNode struct {
Kind string `json:"kind,omitempty" protobuf:"bytes,3,opt,name=kind"`
Namespace string `json:"namespace,omitempty" protobuf:"bytes,4,opt,name=namespace"`
Name string `json:"name,omitempty" protobuf:"bytes,5,opt,name=name"`
Tags []string `json:"tags,omitempty" protobuf:"bytes,6,opt,name=tags"`
Info []InfoItem `json:"info,omitempty" protobuf:"bytes,6,opt,name=info"`
Children []ResourceNode `json:"children,omitempty" protobuf:"bytes,7,opt,name=children"`
ResourceVersion string `json:"resourceVersion,omitempty" protobuf:"bytes,8,opt,name=resourceVersion"`
}
@@ -649,6 +670,25 @@ func (app *Application) CascadedDeletion() bool {
return app.getFinalizerIndex(common.ResourcesFinalizerName) > -1
}
func (app *Application) IsRefreshRequested() (RefreshType, bool) {
refreshType := RefreshTypeNormal
annotations := app.GetAnnotations()
if annotations == nil {
return refreshType, false
}
typeStr, ok := annotations[common.AnnotationKeyRefresh]
if !ok {
return refreshType, false
}
if typeStr == string(RefreshTypeHard) {
refreshType = RefreshTypeHard
}
return refreshType, true
}
// SetCascadedDeletion sets or remove resources finalizer
func (app *Application) SetCascadedDeletion(prune bool) {
index := app.getFinalizerIndex(common.ResourcesFinalizerName)
@@ -684,6 +724,11 @@ func (source ApplicationSource) Equals(other ApplicationSource) bool {
return reflect.DeepEqual(source, other)
}
// Equals compares two instances of ApplicationDestination and return true if instances are equal.
func (source ApplicationDestination) Equals(other ApplicationDestination) bool {
return reflect.DeepEqual(source, other)
}
// GetProject returns the application's project. This is preferred over spec.Project which may be empty
func (spec ApplicationSpec) GetProject() string {
if spec.Project == "" {

View File

@@ -493,6 +493,24 @@ func (in *ClusterList) DeepCopy() *ClusterList {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ComparedTo) DeepCopyInto(out *ComparedTo) {
*out = *in
in.Source.DeepCopyInto(&out.Source)
out.Destination = in.Destination
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ComparedTo.
func (in *ComparedTo) DeepCopy() *ComparedTo {
if in == nil {
return nil
}
out := new(ComparedTo)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ComponentParameter) DeepCopyInto(out *ComponentParameter) {
*out = *in
@@ -581,6 +599,22 @@ func (in *HelmRepository) DeepCopy() *HelmRepository {
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InfoItem) DeepCopyInto(out *InfoItem) {
*out = *in
return
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InfoItem.
func (in *InfoItem) DeepCopy() *InfoItem {
if in == nil {
return nil
}
out := new(InfoItem)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *JWTToken) DeepCopyInto(out *JWTToken) {
*out = *in
@@ -749,9 +783,9 @@ func (in *ResourceDiff) DeepCopy() *ResourceDiff {
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *ResourceNode) DeepCopyInto(out *ResourceNode) {
*out = *in
if in.Tags != nil {
in, out := &in.Tags, &out.Tags
*out = make([]string, len(*in))
if in.Info != nil {
in, out := &in.Info, &out.Info
*out = make([]InfoItem, len(*in))
copy(*out, *in)
}
if in.Children != nil {

View File

@@ -18,6 +18,7 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
"github.com/argoproj/argo-cd/util/cache"
@@ -134,15 +135,17 @@ func (s *Service) GenerateManifest(c context.Context, q *ManifestRequest) (*Mani
}
cacheKey := manifestCacheKey(commitSHA, q)
var res ManifestResponse
err = s.cache.Get(cacheKey, &res)
if err == nil {
log.Infof("manifest cache hit: %s", cacheKey)
return &res, nil
}
if err != cache.ErrCacheMiss {
log.Warnf("manifest cache error %s: %v", cacheKey, err)
} else {
log.Infof("manifest cache miss: %s", cacheKey)
if !q.NoCache {
err = s.cache.Get(cacheKey, &res)
if err == nil {
log.Infof("manifest cache hit: %s", cacheKey)
return &res, nil
}
if err != cache.ErrCacheMiss {
log.Warnf("manifest cache error %s: %v", cacheKey, err)
} else {
log.Infof("manifest cache miss: %s", cacheKey)
}
}
s.repoLock.Lock(gitClient.Root())
@@ -183,9 +186,7 @@ func helmOpts(q *ManifestRequest) helm.HelmTemplateOpts {
}
func kustomizeOpts(q *ManifestRequest) kustomize.KustomizeBuildOpts {
opts := kustomize.KustomizeBuildOpts{
Namespace: q.Namespace,
}
opts := kustomize.KustomizeBuildOpts{}
if q.ApplicationSource.Kustomize != nil {
opts.NamePrefix = q.ApplicationSource.Kustomize.NamePrefix
}
@@ -203,7 +204,7 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
switch appSourceType {
case v1alpha1.ApplicationSourceTypeKsonnet:
env := v1alpha1.KsonnetEnv(q.ApplicationSource)
targetObjs, params, dest, err = ksShow(appPath, env, q.ComponentParameterOverrides)
targetObjs, params, dest, err = ksShow(q.AppLabelKey, appPath, env, q.ComponentParameterOverrides)
case v1alpha1.ApplicationSourceTypeHelm:
h := helm.NewHelmApp(appPath, q.HelmRepos)
err := h.Init()
@@ -211,7 +212,7 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
return nil, err
}
opts := helmOpts(q)
targetObjs, err = h.Template(q.AppLabel, opts, q.ComponentParameterOverrides)
targetObjs, err = h.Template(q.AppLabelValue, opts, q.ComponentParameterOverrides)
if err != nil {
if !helm.IsMissingDependencyErr(err) {
return nil, err
@@ -220,7 +221,7 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
if err != nil {
return nil, err
}
targetObjs, err = h.Template(q.AppLabel, opts, q.ComponentParameterOverrides)
targetObjs, err = h.Template(q.AppLabelValue, opts, q.ComponentParameterOverrides)
if err != nil {
return nil, err
}
@@ -261,8 +262,8 @@ func generateManifests(appPath string, q *ManifestRequest) (*ManifestResponse, e
}
for _, target := range targets {
if q.AppLabel != "" && !kube.IsCRD(target) {
err = kube.SetAppInstanceLabel(target, q.AppLabel)
if q.AppLabelKey != "" && q.AppLabelValue != "" && !kube.IsCRD(target) {
err = kube.SetAppInstanceLabel(target, q.AppLabelKey, q.AppLabelValue)
if err != nil {
return nil, err
}
@@ -330,7 +331,7 @@ func manifestCacheKey(commitSHA string, q *ManifestRequest) string {
appSrcStr, _ := json.Marshal(appSrc)
pStr, _ := json.Marshal(q.ComponentParameterOverrides)
fnva := hash.FNVa(string(appSrcStr) + string(pStr))
return fmt.Sprintf("mfst|%s|%s|%s|%d", q.AppLabel, commitSHA, q.Namespace, fnva)
return fmt.Sprintf("mfst|%s|%s|%s|%s|%d", q.AppLabelKey, q.AppLabelValue, commitSHA, q.Namespace, fnva)
}
func listDirCacheKey(commitSHA string, q *ListDirRequest) string {
@@ -342,7 +343,7 @@ func getFileCacheKey(commitSHA string, q *GetFileRequest) string {
}
// ksShow runs `ks show` in an app directory after setting any component parameter overrides
func ksShow(appPath, envName string, overrides []*v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*v1alpha1.ComponentParameter, *v1alpha1.ApplicationDestination, error) {
func ksShow(appLabelKey, appPath, envName string, overrides []*v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*v1alpha1.ComponentParameter, *v1alpha1.ApplicationDestination, error) {
ksApp, err := ksonnet.NewKsonnetApp(appPath)
if err != nil {
return nil, nil, nil, status.Errorf(codes.FailedPrecondition, "unable to load application from %s: %v", appPath, err)
@@ -364,6 +365,12 @@ func ksShow(appPath, envName string, overrides []*v1alpha1.ComponentParameter) (
return nil, nil, nil, status.Errorf(codes.InvalidArgument, err.Error())
}
targetObjs, err := ksApp.Show(envName)
if err == nil && appLabelKey == common.LabelKeyLegacyApplicationName {
// Address https://github.com/ksonnet/ksonnet/issues/707
for _, d := range targetObjs {
kube.UnsetLabel(d, "ksonnet.io/component")
}
}
if err != nil {
return nil, nil, nil, err
}

View File

@@ -31,7 +31,9 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
type ManifestRequest struct {
Repo *v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo" json:"repo,omitempty"`
Revision string `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
AppLabel string `protobuf:"bytes,5,opt,name=appLabel,proto3" json:"appLabel,omitempty"`
NoCache bool `protobuf:"varint,3,opt,name=noCache,proto3" json:"noCache,omitempty"`
AppLabelKey string `protobuf:"bytes,4,opt,name=appLabelKey,proto3" json:"appLabelKey,omitempty"`
AppLabelValue string `protobuf:"bytes,5,opt,name=appLabelValue,proto3" json:"appLabelValue,omitempty"`
ComponentParameterOverrides []*v1alpha1.ComponentParameter `protobuf:"bytes,6,rep,name=componentParameterOverrides" json:"componentParameterOverrides,omitempty"`
Namespace string `protobuf:"bytes,8,opt,name=namespace,proto3" json:"namespace,omitempty"`
ApplicationSource *v1alpha1.ApplicationSource `protobuf:"bytes,10,opt,name=applicationSource" json:"applicationSource,omitempty"`
@@ -45,7 +47,7 @@ func (m *ManifestRequest) Reset() { *m = ManifestRequest{} }
func (m *ManifestRequest) String() string { return proto.CompactTextString(m) }
func (*ManifestRequest) ProtoMessage() {}
func (*ManifestRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{0}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{0}
}
func (m *ManifestRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -88,9 +90,23 @@ func (m *ManifestRequest) GetRevision() string {
return ""
}
func (m *ManifestRequest) GetAppLabel() string {
func (m *ManifestRequest) GetNoCache() bool {
if m != nil {
return m.AppLabel
return m.NoCache
}
return false
}
func (m *ManifestRequest) GetAppLabelKey() string {
if m != nil {
return m.AppLabelKey
}
return ""
}
func (m *ManifestRequest) GetAppLabelValue() string {
if m != nil {
return m.AppLabelValue
}
return ""
}
@@ -138,7 +154,7 @@ func (m *ManifestResponse) Reset() { *m = ManifestResponse{} }
func (m *ManifestResponse) String() string { return proto.CompactTextString(m) }
func (*ManifestResponse) ProtoMessage() {}
func (*ManifestResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{1}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{1}
}
func (m *ManifestResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -216,7 +232,7 @@ func (m *ListDirRequest) Reset() { *m = ListDirRequest{} }
func (m *ListDirRequest) String() string { return proto.CompactTextString(m) }
func (*ListDirRequest) ProtoMessage() {}
func (*ListDirRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{2}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{2}
}
func (m *ListDirRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -278,7 +294,7 @@ func (m *FileList) Reset() { *m = FileList{} }
func (m *FileList) String() string { return proto.CompactTextString(m) }
func (*FileList) ProtoMessage() {}
func (*FileList) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{3}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{3}
}
func (m *FileList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -328,7 +344,7 @@ func (m *GetFileRequest) Reset() { *m = GetFileRequest{} }
func (m *GetFileRequest) String() string { return proto.CompactTextString(m) }
func (*GetFileRequest) ProtoMessage() {}
func (*GetFileRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{4}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{4}
}
func (m *GetFileRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -390,7 +406,7 @@ func (m *GetFileResponse) Reset() { *m = GetFileResponse{} }
func (m *GetFileResponse) String() string { return proto.CompactTextString(m) }
func (*GetFileResponse) ProtoMessage() {}
func (*GetFileResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_47857c07b7787e09, []int{5}
return fileDescriptor_repository_d96dec39a34a8c7f, []int{5}
}
func (m *GetFileResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -610,11 +626,27 @@ func (m *ManifestRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintRepository(dAtA, i, uint64(len(m.Revision)))
i += copy(dAtA[i:], m.Revision)
}
if len(m.AppLabel) > 0 {
if m.NoCache {
dAtA[i] = 0x18
i++
if m.NoCache {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
if len(m.AppLabelKey) > 0 {
dAtA[i] = 0x22
i++
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppLabelKey)))
i += copy(dAtA[i:], m.AppLabelKey)
}
if len(m.AppLabelValue) > 0 {
dAtA[i] = 0x2a
i++
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppLabel)))
i += copy(dAtA[i:], m.AppLabel)
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppLabelValue)))
i += copy(dAtA[i:], m.AppLabelValue)
}
if len(m.ComponentParameterOverrides) > 0 {
for _, msg := range m.ComponentParameterOverrides {
@@ -897,7 +929,14 @@ func (m *ManifestRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
l = len(m.AppLabel)
if m.NoCache {
n += 2
}
l = len(m.AppLabelKey)
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
l = len(m.AppLabelValue)
if l > 0 {
n += 1 + l + sovRepository(uint64(l))
}
@@ -1134,9 +1173,29 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
}
m.Revision = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
case 3:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field NoCache", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.NoCache = bool(v != 0)
case 4:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AppLabel", wireType)
return fmt.Errorf("proto: wrong wireType = %d for field AppLabelKey", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
@@ -1161,7 +1220,36 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AppLabel = string(dAtA[iNdEx:postIndex])
m.AppLabelKey = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field AppLabelValue", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowRepository
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthRepository
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.AppLabelValue = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 6:
if wireType != 2 {
@@ -2059,47 +2147,49 @@ var (
)
func init() {
proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptor_repository_47857c07b7787e09)
proto.RegisterFile("reposerver/repository/repository.proto", fileDescriptor_repository_d96dec39a34a8c7f)
}
var fileDescriptor_repository_47857c07b7787e09 = []byte{
// 602 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0xcf, 0x6e, 0xd3, 0x4e,
0x10, 0xae, 0xdb, 0x34, 0x6d, 0x36, 0x3f, 0xfd, 0xda, 0xae, 0x22, 0x64, 0x39, 0x51, 0x14, 0x59,
0x02, 0xe5, 0x82, 0xad, 0x84, 0x0b, 0x17, 0x84, 0x80, 0x42, 0xa9, 0x94, 0xaa, 0xc8, 0x3d, 0xc1,
0x05, 0x6d, 0x9c, 0xc1, 0x59, 0x62, 0x7b, 0x97, 0xdd, 0x8d, 0x25, 0x78, 0x09, 0x1e, 0x80, 0x27,
0xe1, 0x0d, 0x38, 0xf2, 0x08, 0x28, 0xb7, 0xbe, 0x05, 0xf2, 0xda, 0x8e, 0x9d, 0x3f, 0xea, 0x25,
0x42, 0x70, 0x9b, 0x9d, 0x59, 0x7f, 0xdf, 0xe7, 0x6f, 0xc6, 0x63, 0xf4, 0x40, 0x00, 0x67, 0x12,
0x44, 0x02, 0xc2, 0xd5, 0x21, 0x55, 0x4c, 0x7c, 0xae, 0x84, 0x0e, 0x17, 0x4c, 0x31, 0x8c, 0xca,
0x8c, 0xd5, 0x0a, 0x58, 0xc0, 0x74, 0xda, 0x4d, 0xa3, 0xec, 0x86, 0xd5, 0x09, 0x18, 0x0b, 0x42,
0x70, 0x09, 0xa7, 0x2e, 0x89, 0x63, 0xa6, 0x88, 0xa2, 0x2c, 0x96, 0x79, 0xd5, 0x9e, 0x3d, 0x96,
0x0e, 0x65, 0xba, 0xea, 0x33, 0x01, 0x6e, 0x32, 0x70, 0x03, 0x88, 0x41, 0x10, 0x05, 0x93, 0xfc,
0xce, 0x65, 0x40, 0xd5, 0x74, 0x3e, 0x76, 0x7c, 0x16, 0xb9, 0x44, 0x68, 0x8a, 0x8f, 0x3a, 0x78,
0xe8, 0x4f, 0x5c, 0x3e, 0x0b, 0xd2, 0x87, 0xa5, 0x4b, 0x38, 0x0f, 0xa9, 0xaf, 0xc1, 0xdd, 0x64,
0x40, 0x42, 0x3e, 0x25, 0x1b, 0x50, 0xf6, 0xf7, 0x1a, 0x3a, 0xb9, 0x22, 0x31, 0xfd, 0x00, 0x52,
0x79, 0xf0, 0x69, 0x0e, 0x52, 0xe1, 0xb7, 0xa8, 0x96, 0xbe, 0x84, 0x69, 0xf4, 0x8c, 0x7e, 0x73,
0xf8, 0xd2, 0x29, 0xd9, 0x9c, 0x82, 0x4d, 0x07, 0xef, 0xfd, 0x89, 0xc3, 0x67, 0x81, 0x93, 0xb2,
0x39, 0x15, 0x36, 0xa7, 0x60, 0x73, 0xbc, 0xa5, 0x17, 0x9e, 0x86, 0xc4, 0x16, 0x3a, 0x16, 0x90,
0x50, 0x49, 0x59, 0x6c, 0xee, 0xf7, 0x8c, 0x7e, 0xc3, 0x5b, 0x9e, 0xd3, 0x1a, 0xe1, 0x7c, 0x44,
0xc6, 0x10, 0x9a, 0x87, 0x59, 0xad, 0x38, 0xe3, 0xaf, 0x06, 0x6a, 0xfb, 0x2c, 0xe2, 0x2c, 0x86,
0x58, 0xbd, 0x21, 0x82, 0x44, 0xa0, 0x40, 0x5c, 0x27, 0x20, 0x04, 0x9d, 0x80, 0x34, 0xeb, 0xbd,
0x83, 0x7e, 0x73, 0x78, 0xb5, 0x83, 0xd4, 0x17, 0x1b, 0xe8, 0xde, 0x5d, 0x8c, 0xb8, 0x83, 0x1a,
0x31, 0x89, 0x40, 0x72, 0xe2, 0x83, 0x79, 0xac, 0xe5, 0x96, 0x09, 0xfc, 0x05, 0x9d, 0x55, 0x58,
0x6e, 0xd8, 0x5c, 0xf8, 0x60, 0x22, 0xed, 0xe7, 0x68, 0x07, 0x91, 0xcf, 0xd6, 0x31, 0xbd, 0x4d,
0x1a, 0x1c, 0xa0, 0xc6, 0x14, 0xc2, 0x48, 0x7b, 0x6f, 0x36, 0xb5, 0x31, 0x97, 0x3b, 0x70, 0xbe,
0x2e, 0xb0, 0xb2, 0x3e, 0x96, 0xd8, 0xf6, 0xad, 0x81, 0x4e, 0xcb, 0xd9, 0x91, 0x9c, 0xc5, 0x12,
0x52, 0x5f, 0xa2, 0x3c, 0x27, 0x4d, 0xa3, 0x77, 0x90, 0xfa, 0xb2, 0x4c, 0xac, 0xba, 0xb6, 0xbf,
0xee, 0xda, 0x3d, 0x54, 0xcf, 0xbe, 0x30, 0xf3, 0x40, 0x97, 0xf2, 0xd3, 0xca, 0xd4, 0xd4, 0xd6,
0xa6, 0x06, 0x50, 0x9d, 0xa7, 0xdd, 0x91, 0xe6, 0xe1, 0x9f, 0x98, 0x81, 0x1c, 0xdc, 0xfe, 0x66,
0xa0, 0xff, 0x47, 0x54, 0xaa, 0x73, 0x2a, 0xfe, 0xf2, 0x67, 0x82, 0x51, 0x8d, 0x13, 0x35, 0xcd,
0x2d, 0xd2, 0xb1, 0xdd, 0x43, 0xc7, 0xaf, 0x68, 0x08, 0xa9, 0x40, 0xdc, 0x42, 0x87, 0x54, 0x41,
0x54, 0x98, 0x9f, 0x1d, 0xb4, 0xfe, 0x0b, 0x50, 0xe9, 0xad, 0x7f, 0x50, 0xff, 0x7d, 0x74, 0xb2,
0x14, 0x97, 0xcf, 0x11, 0x46, 0xb5, 0x09, 0x51, 0x44, 0xab, 0xfb, 0xcf, 0xd3, 0xf1, 0xf0, 0xd6,
0x40, 0x67, 0x25, 0xd7, 0x0d, 0x88, 0x84, 0xfa, 0x80, 0xaf, 0xd1, 0xe9, 0x45, 0xbe, 0xd5, 0x8a,
0x69, 0xc4, 0x6d, 0xa7, 0xb2, 0x98, 0xd7, 0xf6, 0x9b, 0xd5, 0xd9, 0x5e, 0xcc, 0x88, 0xed, 0x3d,
0xfc, 0x04, 0x1d, 0xe5, 0xad, 0xc6, 0x56, 0xf5, 0xea, 0x6a, 0xff, 0xad, 0x56, 0xb5, 0x56, 0xd8,
0x6f, 0xef, 0xe1, 0x73, 0x74, 0x94, 0xbf, 0xcc, 0xea, 0xe3, 0xab, 0xf6, 0x5b, 0xed, 0xad, 0xb5,
0x42, 0xc4, 0xf3, 0xa7, 0x3f, 0x16, 0x5d, 0xe3, 0xe7, 0xa2, 0x6b, 0xfc, 0x5a, 0x74, 0x8d, 0x77,
0x83, 0xbb, 0x36, 0xfe, 0xd6, 0x3f, 0xd3, 0xb8, 0xae, 0x17, 0xfc, 0xa3, 0xdf, 0x01, 0x00, 0x00,
0xff, 0xff, 0x5a, 0x5f, 0xbd, 0x73, 0xb9, 0x06, 0x00, 0x00,
var fileDescriptor_repository_d96dec39a34a8c7f = []byte{
// 636 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xcc, 0x55, 0xdf, 0x4e, 0xd4, 0x4e,
0x14, 0xa6, 0xb0, 0x2c, 0xbb, 0x67, 0x7f, 0x3f, 0x81, 0x09, 0x31, 0x93, 0x42, 0x48, 0xd3, 0xa8,
0xd9, 0x1b, 0xdb, 0x80, 0x37, 0xde, 0x18, 0xa3, 0xa0, 0x48, 0x84, 0x60, 0x4a, 0x62, 0xa2, 0x37,
0x66, 0xe8, 0x1e, 0xbb, 0x23, 0x6d, 0x67, 0x9c, 0x99, 0xdd, 0x04, 0x5f, 0xc2, 0x07, 0xf0, 0x85,
0xbc, 0xf4, 0x11, 0x0c, 0x77, 0x3c, 0x85, 0xa6, 0xb3, 0xed, 0x6e, 0x77, 0x21, 0xdc, 0x6c, 0x8c,
0xde, 0x9d, 0x7f, 0x3d, 0xdf, 0x99, 0xef, 0x7c, 0x9d, 0x81, 0x07, 0x0a, 0xa5, 0xd0, 0xa8, 0x86,
0xa8, 0x42, 0x6b, 0x72, 0x23, 0xd4, 0x45, 0xcd, 0x0c, 0xa4, 0x12, 0x46, 0x10, 0x98, 0x44, 0xdc,
0x8d, 0x44, 0x24, 0xc2, 0x86, 0xc3, 0xc2, 0x1a, 0x55, 0xb8, 0x5b, 0x89, 0x10, 0x49, 0x8a, 0x21,
0x93, 0x3c, 0x64, 0x79, 0x2e, 0x0c, 0x33, 0x5c, 0xe4, 0xba, 0xcc, 0xfa, 0xe7, 0x8f, 0x75, 0xc0,
0x85, 0xcd, 0xc6, 0x42, 0x61, 0x38, 0xdc, 0x09, 0x13, 0xcc, 0x51, 0x31, 0x83, 0xbd, 0xb2, 0xe6,
0x30, 0xe1, 0xa6, 0x3f, 0x38, 0x0b, 0x62, 0x91, 0x85, 0x4c, 0x59, 0x88, 0x4f, 0xd6, 0x78, 0x18,
0xf7, 0x42, 0x79, 0x9e, 0x14, 0x1f, 0xeb, 0x90, 0x49, 0x99, 0xf2, 0xd8, 0x36, 0x0f, 0x87, 0x3b,
0x2c, 0x95, 0x7d, 0x76, 0xad, 0x95, 0xff, 0xab, 0x01, 0xab, 0xc7, 0x2c, 0xe7, 0x1f, 0x51, 0x9b,
0x08, 0x3f, 0x0f, 0x50, 0x1b, 0xf2, 0x0e, 0x1a, 0xc5, 0x21, 0xa8, 0xe3, 0x39, 0xdd, 0xce, 0xee,
0x8b, 0x60, 0x82, 0x16, 0x54, 0x68, 0xd6, 0xf8, 0x10, 0xf7, 0x02, 0x79, 0x9e, 0x04, 0x05, 0x5a,
0x50, 0x43, 0x0b, 0x2a, 0xb4, 0x20, 0x1a, 0x73, 0x11, 0xd9, 0x96, 0xc4, 0x85, 0x96, 0xc2, 0x21,
0xd7, 0x5c, 0xe4, 0x74, 0xd1, 0x73, 0xba, 0xed, 0x68, 0xec, 0x13, 0x0a, 0x2b, 0xb9, 0xd8, 0x63,
0x71, 0x1f, 0xe9, 0x92, 0xe7, 0x74, 0x5b, 0x51, 0xe5, 0x12, 0x0f, 0x3a, 0x4c, 0xca, 0x23, 0x76,
0x86, 0xe9, 0x6b, 0xbc, 0xa0, 0x0d, 0xfb, 0x61, 0x3d, 0x44, 0xee, 0xc1, 0xff, 0x95, 0xfb, 0x96,
0xa5, 0x03, 0xa4, 0xcb, 0xb6, 0x66, 0x3a, 0x48, 0xbe, 0x3a, 0xb0, 0x19, 0x8b, 0x4c, 0x8a, 0x1c,
0x73, 0xf3, 0x86, 0x29, 0x96, 0xa1, 0x41, 0x75, 0x32, 0x44, 0xa5, 0x78, 0x0f, 0x35, 0x6d, 0x7a,
0x4b, 0xdd, 0xce, 0xee, 0xf1, 0x1c, 0x07, 0xde, 0xbb, 0xd6, 0x3d, 0xba, 0x0d, 0x91, 0x6c, 0x41,
0x3b, 0x67, 0x19, 0x6a, 0xc9, 0x62, 0xa4, 0x2d, 0x3b, 0xf3, 0x24, 0x40, 0xbe, 0xc0, 0x7a, 0x0d,
0xe5, 0x54, 0x0c, 0x54, 0x8c, 0x14, 0xec, 0x56, 0x8e, 0xe6, 0x18, 0xf2, 0xd9, 0x6c, 0xcf, 0xe8,
0x3a, 0x0c, 0x49, 0xa0, 0xdd, 0xc7, 0x34, 0xb3, 0x1b, 0xa4, 0x1d, 0x4b, 0xcc, 0xe1, 0x1c, 0x98,
0xaf, 0xaa, 0x5e, 0x23, 0x35, 0x4c, 0x7a, 0xfb, 0x57, 0x0e, 0xac, 0x4d, 0x14, 0xa8, 0xa5, 0xc8,
0x35, 0x16, 0xbc, 0x64, 0x65, 0x4c, 0x53, 0xc7, 0x5b, 0x2a, 0x78, 0x19, 0x07, 0xa6, 0x59, 0x5b,
0x9c, 0x65, 0xed, 0x2e, 0x34, 0x47, 0xff, 0xa9, 0x95, 0x51, 0x3b, 0x2a, 0xbd, 0x29, 0xed, 0x35,
0x66, 0xb4, 0x87, 0xd0, 0x94, 0xc5, 0x76, 0x34, 0x5d, 0xfe, 0x13, 0x1a, 0x28, 0x9b, 0xfb, 0xdf,
0x1c, 0xb8, 0x73, 0xc4, 0xb5, 0xd9, 0xe7, 0xea, 0x2f, 0xff, 0x6c, 0x04, 0x1a, 0x92, 0x99, 0x7e,
0x49, 0x91, 0xb5, 0x7d, 0x0f, 0x5a, 0x2f, 0x79, 0x8a, 0xc5, 0x80, 0x64, 0x03, 0x96, 0xb9, 0xc1,
0xac, 0x22, 0x7f, 0xe4, 0xd8, 0xf9, 0x0f, 0xd0, 0x14, 0x55, 0xff, 0xe0, 0xfc, 0xf7, 0x61, 0x75,
0x3c, 0x5c, 0xa9, 0x23, 0x02, 0x8d, 0x1e, 0x33, 0xcc, 0x4e, 0xf7, 0x5f, 0x64, 0xed, 0xdd, 0x2b,
0x07, 0xd6, 0x27, 0x58, 0xa7, 0xa8, 0x86, 0x3c, 0x46, 0x72, 0x02, 0x6b, 0x07, 0xe5, 0xdd, 0x58,
0xa9, 0x91, 0x6c, 0x06, 0xb5, 0xeb, 0x7d, 0xe6, 0x96, 0x74, 0xb7, 0x6e, 0x4e, 0x8e, 0x80, 0xfd,
0x05, 0xf2, 0x04, 0x56, 0xca, 0x55, 0x13, 0xb7, 0x5e, 0x3a, 0xbd, 0x7f, 0x77, 0xa3, 0x9e, 0xab,
0xe8, 0xf7, 0x17, 0xc8, 0x3e, 0xac, 0x94, 0x87, 0x99, 0xfe, 0x7c, 0x9a, 0x7e, 0x77, 0xf3, 0xc6,
0x5c, 0x35, 0xc4, 0xf3, 0xa7, 0xdf, 0x2f, 0xb7, 0x9d, 0x1f, 0x97, 0xdb, 0xce, 0xcf, 0xcb, 0x6d,
0xe7, 0xfd, 0xce, 0x6d, 0xef, 0xc6, 0x8d, 0xef, 0xdb, 0x59, 0xd3, 0x3e, 0x13, 0x8f, 0x7e, 0x07,
0x00, 0x00, 0xff, 0xff, 0x0d, 0x33, 0xc2, 0xf4, 0xff, 0x06, 0x00, 0x00,
}

View File

@@ -12,11 +12,14 @@ import "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.prot
message ManifestRequest {
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.Repository repo = 1;
string revision = 2;
string appLabel = 5;
bool noCache = 3;
string appLabelKey = 4;
string appLabelValue = 5;
repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ComponentParameter componentParameterOverrides = 6;
string namespace = 8;
github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.ApplicationSource applicationSource = 10;
repeated github.com.argoproj.argo_cd.pkg.apis.application.v1alpha1.HelmRepository helmRepos = 11;
}
message ManifestResponse {

View File

@@ -37,7 +37,7 @@ func (m *UpdatePasswordRequest) Reset() { *m = UpdatePasswordRequest{} }
func (m *UpdatePasswordRequest) String() string { return proto.CompactTextString(m) }
func (*UpdatePasswordRequest) ProtoMessage() {}
func (*UpdatePasswordRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_account_3e64cf795478a98b, []int{0}
return fileDescriptor_account_c12a236fbb4926f3, []int{0}
}
func (m *UpdatePasswordRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -90,7 +90,7 @@ func (m *UpdatePasswordResponse) Reset() { *m = UpdatePasswordResponse{}
func (m *UpdatePasswordResponse) String() string { return proto.CompactTextString(m) }
func (*UpdatePasswordResponse) ProtoMessage() {}
func (*UpdatePasswordResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_account_3e64cf795478a98b, []int{1}
return fileDescriptor_account_c12a236fbb4926f3, []int{1}
}
func (m *UpdatePasswordResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -566,10 +566,10 @@ var (
)
func init() {
proto.RegisterFile("server/account/account.proto", fileDescriptor_account_3e64cf795478a98b)
proto.RegisterFile("server/account/account.proto", fileDescriptor_account_c12a236fbb4926f3)
}
var fileDescriptor_account_3e64cf795478a98b = []byte{
var fileDescriptor_account_c12a236fbb4926f3 = []byte{
// 268 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x92, 0x29, 0x4e, 0x2d, 0x2a,
0x4b, 0x2d, 0xd2, 0x4f, 0x4c, 0x4e, 0xce, 0x2f, 0xcd, 0x2b, 0x81, 0xd1, 0x7a, 0x05, 0x45, 0xf9,

View File

@@ -38,6 +38,7 @@ import (
"github.com/argoproj/argo-cd/util/kube"
"github.com/argoproj/argo-cd/util/rbac"
"github.com/argoproj/argo-cd/util/session"
"github.com/argoproj/argo-cd/util/settings"
)
// Server provides a Application service
@@ -53,6 +54,7 @@ type Server struct {
projectLock *util.KeyLock
auditLogger *argo.AuditLogger
gitFactory git.ClientFactory
settingsMgr *settings.SettingsManager
}
// NewServer returns a new instance of the Application service
@@ -66,6 +68,7 @@ func NewServer(
db db.ArgoDB,
enf *rbac.Enforcer,
projectLock *util.KeyLock,
settingsMgr *settings.SettingsManager,
) ApplicationServiceServer {
return &Server{
@@ -80,6 +83,7 @@ func NewServer(
projectLock: projectLock,
auditLogger: argo.NewAuditLogger(namespace, kubeclientset, "argocd-server"),
gitFactory: git.NewFactory(),
settingsMgr: settingsMgr,
}
}
@@ -179,11 +183,16 @@ func (s *Server) GetManifests(ctx context.Context, q *ApplicationManifestQuery)
if q.Revision != "" {
revision = q.Revision
}
settings, err := s.settingsMgr.GetSettings()
if err != nil {
return nil, err
}
manifestInfo, err := repoClient.GenerateManifest(ctx, &repository.ManifestRequest{
Repo: repo,
Revision: revision,
ComponentParameterOverrides: overrides,
AppLabel: a.Name,
AppLabelKey: settings.GetAppInstanceLabelKey(),
AppLabelValue: a.Name,
Namespace: a.Spec.Destination.Namespace,
ApplicationSource: &a.Spec.Source,
})
@@ -204,8 +213,12 @@ func (s *Server) Get(ctx context.Context, q *ApplicationQuery) (*appv1.Applicati
if !s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, appRBACName(*a)) {
return nil, grpc.ErrPermissionDenied
}
if q.Refresh {
_, err = argoutil.RefreshApp(appIf, *q.Name)
if q.Refresh != nil {
refreshType := appv1.RefreshTypeNormal
if *q.Refresh == string(appv1.RefreshTypeHard) {
refreshType = appv1.RefreshTypeHard
}
_, err = argoutil.RefreshApp(appIf, *q.Name, refreshType)
if err != nil {
return nil, err
}

View File

@@ -41,7 +41,7 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
// ApplicationQuery is a query for application resources
type ApplicationQuery struct {
Name *string `protobuf:"bytes,1,opt,name=name" json:"name,omitempty"`
Refresh bool `protobuf:"varint,2,opt,name=refresh" json:"refresh"`
Refresh *string `protobuf:"bytes,2,opt,name=refresh" json:"refresh,omitempty"`
Projects []string `protobuf:"bytes,3,rep,name=project" json:"project,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
@@ -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_1f706f7a3fcdb3d9, []int{0}
return fileDescriptor_application_4bf1d189f28cefe9, []int{0}
}
func (m *ApplicationQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -88,11 +88,11 @@ func (m *ApplicationQuery) GetName() string {
return ""
}
func (m *ApplicationQuery) GetRefresh() bool {
if m != nil {
return m.Refresh
func (m *ApplicationQuery) GetRefresh() string {
if m != nil && m.Refresh != nil {
return *m.Refresh
}
return false
return ""
}
func (m *ApplicationQuery) GetProjects() []string {
@@ -117,7 +117,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_1f706f7a3fcdb3d9, []int{1}
return fileDescriptor_application_4bf1d189f28cefe9, []int{1}
}
func (m *ApplicationResourceEventsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -187,7 +187,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_1f706f7a3fcdb3d9, []int{2}
return fileDescriptor_application_4bf1d189f28cefe9, []int{2}
}
func (m *ApplicationManifestQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -240,7 +240,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_1f706f7a3fcdb3d9, []int{3}
return fileDescriptor_application_4bf1d189f28cefe9, []int{3}
}
func (m *ApplicationResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -281,7 +281,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_1f706f7a3fcdb3d9, []int{4}
return fileDescriptor_application_4bf1d189f28cefe9, []int{4}
}
func (m *ApplicationCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -335,7 +335,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_1f706f7a3fcdb3d9, []int{5}
return fileDescriptor_application_4bf1d189f28cefe9, []int{5}
}
func (m *ApplicationUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -383,7 +383,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_1f706f7a3fcdb3d9, []int{6}
return fileDescriptor_application_4bf1d189f28cefe9, []int{6}
}
func (m *ApplicationDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -444,7 +444,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_1f706f7a3fcdb3d9, []int{7}
return fileDescriptor_application_4bf1d189f28cefe9, []int{7}
}
func (m *ApplicationSyncRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -535,7 +535,7 @@ func (m *ParameterOverrides) Reset() { *m = ParameterOverrides{} }
func (m *ParameterOverrides) String() string { return proto.CompactTextString(m) }
func (*ParameterOverrides) ProtoMessage() {}
func (*ParameterOverrides) Descriptor() ([]byte, []int) {
return fileDescriptor_application_1f706f7a3fcdb3d9, []int{8}
return fileDescriptor_application_4bf1d189f28cefe9, []int{8}
}
func (m *ParameterOverrides) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -584,7 +584,7 @@ func (m *Parameter) Reset() { *m = Parameter{} }
func (m *Parameter) String() string { return proto.CompactTextString(m) }
func (*Parameter) ProtoMessage() {}
func (*Parameter) Descriptor() ([]byte, []int) {
return fileDescriptor_application_1f706f7a3fcdb3d9, []int{9}
return fileDescriptor_application_4bf1d189f28cefe9, []int{9}
}
func (m *Parameter) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -647,7 +647,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_1f706f7a3fcdb3d9, []int{10}
return fileDescriptor_application_4bf1d189f28cefe9, []int{10}
}
func (m *ApplicationUpdateSpecRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -704,7 +704,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_1f706f7a3fcdb3d9, []int{11}
return fileDescriptor_application_4bf1d189f28cefe9, []int{11}
}
func (m *ApplicationRollbackRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -777,7 +777,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_1f706f7a3fcdb3d9, []int{12}
return fileDescriptor_application_4bf1d189f28cefe9, []int{12}
}
func (m *ApplicationResourceRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -865,7 +865,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_1f706f7a3fcdb3d9, []int{13}
return fileDescriptor_application_4bf1d189f28cefe9, []int{13}
}
func (m *ApplicationResourceDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -954,7 +954,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_1f706f7a3fcdb3d9, []int{14}
return fileDescriptor_application_4bf1d189f28cefe9, []int{14}
}
func (m *ApplicationResourceResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1008,7 +1008,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_1f706f7a3fcdb3d9, []int{15}
return fileDescriptor_application_4bf1d189f28cefe9, []int{15}
}
func (m *ApplicationPodLogsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1105,7 +1105,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_1f706f7a3fcdb3d9, []int{16}
return fileDescriptor_application_4bf1d189f28cefe9, []int{16}
}
func (m *LogEntry) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1159,7 +1159,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_1f706f7a3fcdb3d9, []int{17}
return fileDescriptor_application_4bf1d189f28cefe9, []int{17}
}
func (m *OperationTerminateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1205,7 +1205,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_1f706f7a3fcdb3d9, []int{18}
return fileDescriptor_application_4bf1d189f28cefe9, []int{18}
}
func (m *OperationTerminateResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1962,14 +1962,12 @@ func (m *ApplicationQuery) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Name)))
i += copy(dAtA[i:], *m.Name)
}
dAtA[i] = 0x10
i++
if m.Refresh {
dAtA[i] = 1
} else {
dAtA[i] = 0
if m.Refresh != nil {
dAtA[i] = 0x12
i++
i = encodeVarintApplication(dAtA, i, uint64(len(*m.Refresh)))
i += copy(dAtA[i:], *m.Refresh)
}
i++
if len(m.Projects) > 0 {
for _, s := range m.Projects {
dAtA[i] = 0x1a
@@ -2730,7 +2728,10 @@ func (m *ApplicationQuery) Size() (n int) {
l = len(*m.Name)
n += 1 + l + sovApplication(uint64(l))
}
n += 2
if m.Refresh != nil {
l = len(*m.Refresh)
n += 1 + l + sovApplication(uint64(l))
}
if len(m.Projects) > 0 {
for _, s := range m.Projects {
l = len(s)
@@ -3117,10 +3118,10 @@ func (m *ApplicationQuery) Unmarshal(dAtA []byte) error {
m.Name = &s
iNdEx = postIndex
case 2:
if wireType != 0 {
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Refresh", wireType)
}
var v int
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowApplication
@@ -3130,12 +3131,22 @@ func (m *ApplicationQuery) Unmarshal(dAtA []byte) error {
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
stringLen |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Refresh = bool(v != 0)
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthApplication
}
postIndex := iNdEx + intStringLen
if postIndex > l {
return io.ErrUnexpectedEOF
}
s := string(dAtA[iNdEx:postIndex])
m.Refresh = &s
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Projects", wireType)
@@ -5846,112 +5857,112 @@ var (
)
func init() {
proto.RegisterFile("server/application/application.proto", fileDescriptor_application_1f706f7a3fcdb3d9)
proto.RegisterFile("server/application/application.proto", fileDescriptor_application_4bf1d189f28cefe9)
}
var fileDescriptor_application_1f706f7a3fcdb3d9 = []byte{
// 1635 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x6f, 0xdc, 0xc6,
0x15, 0xef, 0xec, 0x4a, 0x5a, 0xed, 0x93, 0x50, 0xb8, 0x53, 0x5b, 0x65, 0x69, 0x59, 0x5a, 0xd0,
0xb2, 0xbc, 0x96, 0x2b, 0xd2, 0x12, 0x8c, 0xd6, 0x10, 0x5c, 0xb8, 0x56, 0xad, 0xca, 0x32, 0x64,
0x5b, 0x5d, 0xd9, 0x28, 0xd0, 0x4b, 0x31, 0x26, 0x47, 0x2b, 0x56, 0xbb, 0x1c, 0x76, 0xc8, 0xdd,
0x62, 0x6b, 0xf8, 0x50, 0x23, 0xc8, 0x29, 0x88, 0x11, 0x24, 0x87, 0xdc, 0x12, 0xf8, 0x9c, 0x5b,
0x6e, 0x39, 0xe4, 0x16, 0xc0, 0xa7, 0x20, 0x40, 0x7c, 0x36, 0x0c, 0x21, 0x7f, 0x43, 0xce, 0xc1,
0x0c, 0xbf, 0x86, 0xd2, 0x2e, 0xd7, 0xb2, 0x37, 0x87, 0xdc, 0xc8, 0x37, 0x6f, 0xde, 0xfb, 0xbd,
0x4f, 0xbe, 0x47, 0x58, 0x08, 0x28, 0xef, 0x52, 0x6e, 0x11, 0xdf, 0x6f, 0xb9, 0x36, 0x09, 0x5d,
0xe6, 0xa9, 0xcf, 0xa6, 0xcf, 0x59, 0xc8, 0xf0, 0x94, 0x42, 0xd2, 0x4f, 0x37, 0x59, 0x93, 0x49,
0xba, 0x25, 0x9e, 0x22, 0x16, 0x7d, 0xb6, 0xc9, 0x58, 0xb3, 0x45, 0x2d, 0xe2, 0xbb, 0x16, 0xf1,
0x3c, 0x16, 0x4a, 0xe6, 0x20, 0x3e, 0x35, 0x0e, 0xae, 0x05, 0xa6, 0xcb, 0xe4, 0xa9, 0xcd, 0x38,
0xb5, 0xba, 0x2b, 0x56, 0x93, 0x7a, 0x94, 0x93, 0x90, 0x3a, 0x31, 0xcf, 0xd5, 0x8c, 0xa7, 0x4d,
0xec, 0x7d, 0xd7, 0xa3, 0xbc, 0x67, 0xf9, 0x07, 0x4d, 0x41, 0x08, 0xac, 0x36, 0x0d, 0x49, 0xbf,
0x5b, 0x5b, 0x4d, 0x37, 0xdc, 0xef, 0x3c, 0x32, 0x6d, 0xd6, 0xb6, 0x08, 0x97, 0xc0, 0xfe, 0x2d,
0x1f, 0x96, 0x6d, 0x27, 0xbb, 0xad, 0x9a, 0xd7, 0x5d, 0x21, 0x2d, 0x7f, 0x9f, 0x1c, 0x17, 0xb5,
0x5e, 0x24, 0x8a, 0x53, 0x9f, 0xc5, 0xbe, 0x92, 0x8f, 0x6e, 0xc8, 0x78, 0x4f, 0x79, 0x8c, 0x65,
0xdc, 0x2c, 0x92, 0x61, 0x33, 0x2f, 0xe4, 0xac, 0xd5, 0xa2, 0xdc, 0x12, 0xa2, 0x5c, 0x9b, 0x06,
0xc7, 0x9d, 0x6d, 0x78, 0x70, 0xea, 0x66, 0x46, 0xfc, 0x7b, 0x87, 0xf2, 0x1e, 0xc6, 0x30, 0xe6,
0x91, 0x36, 0xd5, 0x50, 0x0d, 0xd5, 0xab, 0x0d, 0xf9, 0x8c, 0xe7, 0xa0, 0xc2, 0xe9, 0x1e, 0xa7,
0xc1, 0xbe, 0x56, 0xaa, 0xa1, 0xfa, 0xe4, 0xfa, 0xd8, 0x8b, 0x57, 0xf3, 0xbf, 0x6a, 0x24, 0x44,
0xbc, 0x08, 0x15, 0xa1, 0x9d, 0xda, 0xa1, 0x56, 0xae, 0x95, 0xeb, 0xd5, 0xf5, 0xe9, 0xc3, 0x57,
0xf3, 0x93, 0x3b, 0x11, 0x29, 0x68, 0x24, 0x87, 0xc6, 0x57, 0x08, 0xe6, 0x14, 0x85, 0x0d, 0x1a,
0xb0, 0x0e, 0xb7, 0xe9, 0x46, 0x97, 0x7a, 0x61, 0x70, 0x54, 0x7d, 0x29, 0x55, 0xbf, 0x0a, 0xbf,
0xe1, 0x31, 0xeb, 0x3d, 0xd2, 0xa6, 0x81, 0x4f, 0x6c, 0xaa, 0x95, 0x04, 0x43, 0x0c, 0xe4, 0xf8,
0x31, 0xae, 0xc3, 0xb4, 0x4a, 0xd4, 0xca, 0x0a, 0x7b, 0xee, 0x04, 0x2f, 0xc2, 0x54, 0xf2, 0xfe,
0x70, 0xeb, 0x96, 0x36, 0xa6, 0x30, 0xaa, 0x07, 0xc6, 0x0e, 0x68, 0x0a, 0xf6, 0xbb, 0xc4, 0x73,
0xf7, 0x68, 0x10, 0x0e, 0x46, 0x5d, 0x83, 0x49, 0x4e, 0xbb, 0x6e, 0xe0, 0x32, 0x4f, 0x7a, 0x2d,
0x11, 0x9a, 0x52, 0x8d, 0x33, 0xf0, 0xdb, 0xbc, 0x37, 0x7c, 0xe6, 0x05, 0xd4, 0x78, 0x8e, 0x72,
0x9a, 0xfe, 0xca, 0x29, 0x09, 0x69, 0x83, 0xfe, 0xa7, 0x43, 0x83, 0x10, 0x7b, 0xa0, 0x56, 0x88,
0x54, 0x38, 0xb5, 0xfa, 0x37, 0x33, 0xcb, 0x05, 0x33, 0xc9, 0x05, 0xf9, 0xf0, 0x2f, 0xdb, 0x31,
0xfd, 0x83, 0xa6, 0x29, 0x52, 0xd3, 0x54, 0x13, 0x20, 0x49, 0x4d, 0x53, 0xd1, 0x94, 0x58, 0xad,
0xf0, 0xe1, 0x19, 0x98, 0xe8, 0xf8, 0x01, 0xe5, 0x61, 0x14, 0xf9, 0x46, 0xfc, 0x66, 0xbc, 0x97,
0x07, 0xf9, 0xd0, 0x77, 0x14, 0x90, 0xfb, 0x3f, 0x23, 0xc8, 0x1c, 0x3c, 0xe3, 0x76, 0x0e, 0xc5,
0x2d, 0xda, 0xa2, 0x19, 0x8a, 0x7e, 0x41, 0xd1, 0xa0, 0x62, 0x93, 0xc0, 0x26, 0x0e, 0x8d, 0xed,
0x49, 0x5e, 0x8d, 0xe7, 0x65, 0x98, 0x51, 0x44, 0xed, 0xf6, 0x3c, 0xbb, 0x48, 0xd0, 0xd0, 0xe8,
0xe2, 0x59, 0x98, 0x70, 0x78, 0xaf, 0xd1, 0xf1, 0xb4, 0xb2, 0x52, 0x33, 0x31, 0x0d, 0xeb, 0x30,
0xee, 0xf3, 0x8e, 0x47, 0xb5, 0x31, 0xe5, 0x30, 0x22, 0x61, 0x1b, 0x26, 0x83, 0x50, 0xb4, 0x8b,
0x66, 0x4f, 0x1b, 0xaf, 0xa1, 0xfa, 0xd4, 0xea, 0xe6, 0x3b, 0xf8, 0x4e, 0x58, 0xb2, 0x1b, 0x8b,
0x6b, 0xa4, 0x82, 0xf1, 0x9f, 0xa1, 0xea, 0x13, 0x4e, 0xda, 0x34, 0xa4, 0x5c, 0x9b, 0x90, 0x5a,
0xe6, 0x73, 0x02, 0x76, 0x92, 0xd3, 0xfb, 0x5d, 0xca, 0xb9, 0xeb, 0xd0, 0xa0, 0x91, 0xdd, 0xc0,
0x21, 0x54, 0x93, 0xe2, 0x08, 0xb4, 0x4a, 0xad, 0x5c, 0x9f, 0x5a, 0xdd, 0x79, 0x47, 0x90, 0xf7,
0x7d, 0xd1, 0x23, 0x95, 0xbe, 0x10, 0x7b, 0x25, 0x53, 0x64, 0xdc, 0x01, 0x7c, 0x1c, 0x16, 0xbe,
0x0a, 0x55, 0x96, 0xbc, 0x68, 0x48, 0x62, 0x99, 0xe9, 0x6f, 0x4a, 0x23, 0x63, 0x34, 0x28, 0x54,
0x53, 0x3a, 0xd6, 0xd4, 0x10, 0xc7, 0x7a, 0xa3, 0x40, 0xeb, 0x30, 0xde, 0x25, 0xad, 0x0e, 0xcd,
0x45, 0x39, 0x22, 0x61, 0x03, 0xaa, 0x36, 0x6b, 0xfb, 0xcc, 0xa3, 0x5e, 0x28, 0xa3, 0x9c, 0x9c,
0x67, 0x64, 0xe3, 0x53, 0x04, 0xb3, 0xc7, 0x0a, 0x65, 0xd7, 0xa7, 0x85, 0xd9, 0xe5, 0xc0, 0x58,
0xe0, 0x53, 0x5b, 0x36, 0xb9, 0xa9, 0xd5, 0x3b, 0xa3, 0xa9, 0x1c, 0xa1, 0x34, 0x31, 0x4d, 0x48,
0x37, 0xde, 0x47, 0xa0, 0xab, 0x95, 0xc5, 0x5a, 0xad, 0x47, 0xc4, 0x3e, 0x28, 0x02, 0xa6, 0x43,
0xc9, 0x75, 0x24, 0xac, 0xf2, 0x3a, 0x08, 0x51, 0x87, 0xaf, 0xe6, 0x4b, 0x5b, 0xb7, 0x1a, 0x25,
0xd7, 0x79, 0xfb, 0x84, 0x37, 0x5e, 0x1e, 0x01, 0x12, 0xc7, 0xbb, 0x08, 0x88, 0x01, 0x55, 0xaf,
0xef, 0xb7, 0x20, 0x23, 0x9f, 0xe0, 0x1b, 0x30, 0x07, 0x95, 0x2e, 0xe5, 0xb2, 0x98, 0xd5, 0xfe,
0x9f, 0x10, 0x05, 0xf8, 0x26, 0x67, 0x1d, 0x5f, 0x1b, 0x57, 0x4e, 0x23, 0x92, 0x48, 0x9d, 0x03,
0xd7, 0x73, 0xb4, 0x09, 0x35, 0x75, 0x04, 0xc5, 0xf8, 0x11, 0x41, 0xad, 0x8f, 0x59, 0xc3, 0xbb,
0xd4, 0x2f, 0xc0, 0x38, 0x71, 0x6b, 0x8f, 0x71, 0x9b, 0x6a, 0x95, 0x34, 0x9e, 0xa8, 0x11, 0x91,
0x8c, 0x1b, 0x70, 0xb6, 0x6f, 0x38, 0xa3, 0x0f, 0x9c, 0xe8, 0x9d, 0xed, 0xf8, 0xf3, 0x99, 0x2b,
0xb8, 0x94, 0x6a, 0x7c, 0x53, 0x82, 0xdf, 0x29, 0x12, 0x76, 0x98, 0xb3, 0xcd, 0x9a, 0x05, 0x13,
0xc2, 0x9b, 0x38, 0x4c, 0x83, 0x8a, 0xcf, 0x9c, 0xcc, 0x57, 0x8d, 0xe4, 0x35, 0x2a, 0x63, 0x2f,
0x24, 0x62, 0x0e, 0xcc, 0xb9, 0x28, 0x23, 0x0b, 0x77, 0x07, 0xae, 0x67, 0xd3, 0x5d, 0x6a, 0x33,
0xcf, 0x09, 0xa4, 0xaf, 0xca, 0x89, 0xbb, 0xd5, 0x13, 0x7c, 0x1b, 0xaa, 0xf2, 0xfd, 0x81, 0xdb,
0xa6, 0x71, 0x63, 0x5d, 0x32, 0xa3, 0x81, 0xd3, 0x54, 0x07, 0xce, 0xac, 0x70, 0xc5, 0xc0, 0x69,
0x76, 0x57, 0x4c, 0x71, 0xa3, 0x91, 0x5d, 0x16, 0xb8, 0x42, 0xe2, 0xb6, 0xb6, 0x5d, 0x4f, 0xf6,
0xd8, 0x4c, 0x61, 0x46, 0x16, 0x45, 0xb7, 0xc7, 0x5a, 0x2d, 0xf6, 0x5f, 0x6d, 0xb2, 0x56, 0xca,
0x8a, 0x2e, 0xa2, 0x19, 0xff, 0x83, 0xc9, 0x6d, 0xd6, 0xdc, 0xf0, 0x42, 0xde, 0x13, 0x69, 0x20,
0xcc, 0x11, 0xad, 0x4a, 0x75, 0x7a, 0x42, 0xc4, 0xf7, 0xa0, 0x1a, 0xba, 0x6d, 0xba, 0x1b, 0x92,
0xb6, 0x1f, 0x37, 0x9e, 0x13, 0xe0, 0x4e, 0x91, 0x25, 0x22, 0x0c, 0x0b, 0x7e, 0x9f, 0x76, 0xf4,
0x07, 0x94, 0xb7, 0x5d, 0x8f, 0x14, 0x66, 0xbd, 0x31, 0x0b, 0x7a, 0xbf, 0x0b, 0x51, 0xd2, 0xac,
0x7e, 0x7b, 0x06, 0xb0, 0xda, 0xcc, 0xa2, 0xa9, 0x16, 0x3f, 0x43, 0x30, 0xb6, 0xed, 0x06, 0x21,
0x3e, 0x97, 0xeb, 0x7f, 0x47, 0xc7, 0x5a, 0x7d, 0x44, 0x3d, 0x54, 0xa8, 0x32, 0x66, 0x9f, 0x7e,
0xff, 0xc3, 0xc7, 0xa5, 0x19, 0x7c, 0x5a, 0x2e, 0x19, 0xdd, 0x15, 0x75, 0xb2, 0x0e, 0xf0, 0x07,
0x08, 0xb0, 0x60, 0xcb, 0x4f, 0xb7, 0xf8, 0xf2, 0x20, 0x7c, 0x7d, 0xa6, 0x60, 0xfd, 0x9c, 0xe2,
0x78, 0x53, 0x6c, 0x31, 0xc2, 0xcd, 0x92, 0x41, 0x02, 0x58, 0x92, 0x00, 0x16, 0xb0, 0xd1, 0x0f,
0x80, 0xf5, 0x58, 0x78, 0xf3, 0x89, 0x45, 0x23, 0xbd, 0x9f, 0x21, 0x18, 0xff, 0x07, 0x09, 0xed,
0xfd, 0x61, 0x1e, 0xda, 0x19, 0x8d, 0x87, 0xa4, 0x2e, 0x09, 0xd5, 0x38, 0x2f, 0x61, 0x9e, 0xc3,
0x67, 0x13, 0x98, 0x41, 0xc8, 0x29, 0x69, 0xe7, 0xd0, 0x5e, 0x41, 0xf8, 0x39, 0x82, 0x89, 0x68,
0xc8, 0xc5, 0x17, 0x06, 0x41, 0xcc, 0x0d, 0xc1, 0xfa, 0x88, 0x46, 0x49, 0xe3, 0x92, 0x04, 0x78,
0xde, 0xe8, 0x1b, 0xc8, 0xb5, 0xdc, 0x1c, 0xfc, 0x11, 0x82, 0xf2, 0x26, 0x1d, 0x9a, 0x66, 0xa3,
0x42, 0x76, 0xcc, 0x75, 0x7d, 0x22, 0x8c, 0x9f, 0x22, 0x98, 0xde, 0xa4, 0x61, 0xb2, 0x8a, 0x04,
0x83, 0xdd, 0x97, 0xdb, 0x56, 0xf4, 0x59, 0x53, 0x59, 0x26, 0x93, 0xa3, 0x74, 0xfd, 0x58, 0x96,
0xaa, 0x2f, 0xe2, 0x0b, 0x45, 0xc9, 0xd5, 0x4e, 0x75, 0x7e, 0x8d, 0x60, 0x22, 0x1a, 0x6a, 0x06,
0xab, 0xcf, 0x6d, 0x07, 0x23, 0xf3, 0xd1, 0x86, 0x04, 0x7a, 0x43, 0xbf, 0xd2, 0x1f, 0xa8, 0x7a,
0x5f, 0x74, 0x2a, 0x87, 0x84, 0xc4, 0x94, 0xe8, 0xf3, 0x91, 0xfd, 0x12, 0x01, 0x64, 0x53, 0x19,
0xbe, 0x54, 0x6c, 0x84, 0x32, 0xb9, 0xe9, 0x23, 0x9c, 0xcb, 0x0c, 0x53, 0x1a, 0x53, 0xd7, 0x6b,
0x45, 0x5e, 0x17, 0x53, 0xdb, 0x9a, 0x9c, 0xdd, 0x70, 0x17, 0x26, 0xa2, 0x39, 0x62, 0xb0, 0xd7,
0x73, 0x73, 0x86, 0x5e, 0x2b, 0xe8, 0x3f, 0x51, 0xe0, 0xe3, 0x9c, 0x5b, 0x2a, 0xcc, 0xb9, 0xcf,
0x11, 0x8c, 0x89, 0x61, 0x1d, 0x9f, 0x1f, 0x24, 0x4f, 0xd9, 0x9c, 0x46, 0x16, 0xea, 0xcb, 0x12,
0xda, 0x05, 0xa3, 0xd8, 0x3b, 0x3d, 0xcf, 0x5e, 0x43, 0x4b, 0xf8, 0x35, 0x82, 0x53, 0x77, 0x89,
0x47, 0x9a, 0xd4, 0x49, 0x7a, 0x6b, 0x80, 0x6f, 0x14, 0x22, 0xc9, 0x7e, 0x97, 0x98, 0xc9, 0xef,
0x12, 0x33, 0xbd, 0x1b, 0x15, 0xcd, 0xd6, 0x89, 0x05, 0x1c, 0xc5, 0x90, 0x3a, 0xfa, 0x2f, 0xd2,
0x9a, 0x35, 0x7c, 0x6d, 0x68, 0xe2, 0xde, 0x4b, 0x8a, 0x4d, 0x08, 0x5a, 0x4e, 0xf7, 0x20, 0xfc,
0x12, 0xc1, 0x74, 0x22, 0xf7, 0x01, 0xa7, 0xf4, 0xdd, 0xcd, 0xdb, 0x78, 0x6b, 0x01, 0x42, 0x7f,
0x6a, 0xda, 0x75, 0x69, 0xda, 0x1f, 0xf1, 0xd5, 0x37, 0x34, 0x2d, 0x31, 0x69, 0x39, 0x14, 0x56,
0x7c, 0x81, 0x60, 0x32, 0xd9, 0x42, 0xf0, 0xc5, 0x81, 0x09, 0x9b, 0xdf, 0x53, 0x46, 0x96, 0x64,
0x96, 0xc4, 0x7e, 0xc9, 0x58, 0x28, 0x4a, 0x32, 0x1e, 0x2b, 0x17, 0x89, 0xf6, 0x09, 0x02, 0x9c,
0x0e, 0x2a, 0xe9, 0xe8, 0x82, 0x17, 0x73, 0xaa, 0x06, 0xce, 0x40, 0xfa, 0xc5, 0xa1, 0x7c, 0xf9,
0x8e, 0xbc, 0x54, 0xd8, 0x91, 0x59, 0xaa, 0xff, 0x43, 0x04, 0x53, 0x9b, 0x34, 0x9d, 0x3f, 0x0a,
0x1c, 0x99, 0xdf, 0xb3, 0xf4, 0xfa, 0x70, 0xc6, 0x18, 0xd1, 0x1f, 0x24, 0xa2, 0x45, 0x5c, 0xec,
0xaa, 0x04, 0xc0, 0x33, 0x04, 0xbf, 0x4e, 0x9a, 0x51, 0x4c, 0x5a, 0x1e, 0xa6, 0xea, 0xa4, 0xcd,
0x2b, 0x46, 0xb4, 0xf4, 0x66, 0x88, 0xfe, 0x8f, 0xa0, 0x12, 0x2f, 0x15, 0x78, 0x61, 0x90, 0x6c,
0x75, 0xeb, 0xd0, 0xcf, 0xe4, 0xb8, 0x92, 0xa1, 0xda, 0xf8, 0x93, 0x54, 0xbb, 0x82, 0xad, 0x22,
0xb5, 0x3e, 0x73, 0x02, 0xeb, 0x71, 0xbc, 0x6d, 0x3c, 0xb1, 0x5a, 0xac, 0x19, 0x5c, 0x41, 0xeb,
0xd7, 0x5f, 0x1c, 0xce, 0xa1, 0xef, 0x0e, 0xe7, 0xd0, 0xeb, 0xc3, 0x39, 0xf4, 0x4f, 0xb3, 0xe8,
0x6f, 0xee, 0xf1, 0x3f, 0xe7, 0x3f, 0x05, 0x00, 0x00, 0xff, 0xff, 0x69, 0x57, 0x6d, 0xdd, 0x4e,
0x17, 0x00, 0x00,
var fileDescriptor_application_4bf1d189f28cefe9 = []byte{
// 1634 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xd4, 0x58, 0xcd, 0x6f, 0x14, 0x47,
0x16, 0xdf, 0x9a, 0xb1, 0x3d, 0x9e, 0x67, 0x6b, 0xc5, 0xd6, 0x82, 0xb7, 0xb7, 0x31, 0xf6, 0xa8,
0x31, 0xc6, 0x98, 0x75, 0x37, 0xb6, 0xd0, 0x2e, 0xb2, 0x58, 0xb1, 0x78, 0xf1, 0x1a, 0x23, 0x03,
0xde, 0x31, 0x28, 0x52, 0x2e, 0x51, 0xd1, 0x5d, 0x1e, 0x77, 0x3c, 0xd3, 0xd5, 0xa9, 0xee, 0x99,
0x68, 0x82, 0x38, 0x04, 0x45, 0x39, 0x45, 0x41, 0x51, 0x72, 0xc8, 0x2d, 0x11, 0xe7, 0xdc, 0x72,
0xcb, 0x21, 0xb7, 0x48, 0x9c, 0xa2, 0x48, 0xe1, 0x8c, 0x90, 0x95, 0xbf, 0x21, 0xe7, 0xa8, 0xaa,
0xbf, 0xaa, 0xed, 0x99, 0x1e, 0x0c, 0x93, 0x43, 0x6e, 0x55, 0xaf, 0x5e, 0xbd, 0xf7, 0x7b, 0x1f,
0xf5, 0xfa, 0xbd, 0x86, 0xb9, 0x80, 0xf2, 0x0e, 0xe5, 0x16, 0xf1, 0xfd, 0xa6, 0x6b, 0x93, 0xd0,
0x65, 0x9e, 0xba, 0x36, 0x7d, 0xce, 0x42, 0x86, 0x27, 0x14, 0x92, 0x7e, 0xb2, 0xc1, 0x1a, 0x4c,
0xd2, 0x2d, 0xb1, 0x8a, 0x58, 0xf4, 0xe9, 0x06, 0x63, 0x8d, 0x26, 0xb5, 0x88, 0xef, 0x5a, 0xc4,
0xf3, 0x58, 0x28, 0x99, 0x83, 0xf8, 0xd4, 0xd8, 0xbf, 0x12, 0x98, 0x2e, 0x93, 0xa7, 0x36, 0xe3,
0xd4, 0xea, 0x2c, 0x5b, 0x0d, 0xea, 0x51, 0x4e, 0x42, 0xea, 0xc4, 0x3c, 0x97, 0x33, 0x9e, 0x16,
0xb1, 0xf7, 0x5c, 0x8f, 0xf2, 0xae, 0xe5, 0xef, 0x37, 0x04, 0x21, 0xb0, 0x5a, 0x34, 0x24, 0xbd,
0x6e, 0x6d, 0x36, 0xdc, 0x70, 0xaf, 0xfd, 0xc0, 0xb4, 0x59, 0xcb, 0x22, 0x5c, 0x02, 0x7b, 0x57,
0x2e, 0x96, 0x6c, 0x27, 0xbb, 0xad, 0x9a, 0xd7, 0x59, 0x26, 0x4d, 0x7f, 0x8f, 0x1c, 0x15, 0xb5,
0x56, 0x24, 0x8a, 0x53, 0x9f, 0xc5, 0xbe, 0x92, 0x4b, 0x37, 0x64, 0xbc, 0xab, 0x2c, 0x63, 0x19,
0xd7, 0x8b, 0x64, 0xd8, 0xcc, 0x0b, 0x39, 0x6b, 0x36, 0x29, 0xb7, 0x84, 0x28, 0xd7, 0xa6, 0xc1,
0x51, 0x67, 0x1b, 0x7b, 0x70, 0xe2, 0x7a, 0x46, 0xfc, 0x7f, 0x9b, 0xf2, 0x2e, 0xc6, 0x30, 0xe2,
0x91, 0x16, 0xd5, 0x50, 0x0d, 0x2d, 0x54, 0xeb, 0x72, 0x8d, 0x35, 0xa8, 0x70, 0xba, 0xcb, 0x69,
0xb0, 0xa7, 0x95, 0x24, 0x39, 0xd9, 0xe2, 0x79, 0xa8, 0x08, 0xbd, 0xd4, 0x0e, 0xb5, 0x72, 0xad,
0xbc, 0x50, 0x5d, 0x9b, 0x3c, 0x78, 0x31, 0x3b, 0xbe, 0x1d, 0x91, 0x82, 0x7a, 0x72, 0x68, 0x7c,
0x87, 0x60, 0x46, 0x51, 0x55, 0xa7, 0x01, 0x6b, 0x73, 0x9b, 0xae, 0x77, 0xa8, 0x17, 0x06, 0x87,
0x15, 0x97, 0x52, 0xc5, 0x2b, 0xf0, 0x17, 0x1e, 0xb3, 0xde, 0x21, 0x2d, 0x1a, 0xf8, 0xc4, 0xa6,
0x5a, 0x49, 0x30, 0xac, 0x8d, 0x3c, 0x7b, 0x31, 0xfb, 0xa7, 0xfa, 0xd1, 0x63, 0xbc, 0x00, 0x93,
0x2a, 0x51, 0x2b, 0x2b, 0xec, 0xb9, 0x13, 0x3c, 0x0f, 0x13, 0xc9, 0xfe, 0xfe, 0xe6, 0x0d, 0x6d,
0x44, 0x61, 0x54, 0x0f, 0x8c, 0x6d, 0xd0, 0x14, 0xec, 0xb7, 0x89, 0xe7, 0xee, 0xd2, 0x20, 0xec,
0x8f, 0xba, 0x06, 0xe3, 0x9c, 0x76, 0xdc, 0xc0, 0x65, 0x5e, 0xe4, 0xaf, 0x58, 0x68, 0x4a, 0x35,
0x4e, 0xc1, 0x5f, 0xf3, 0xde, 0xf0, 0x99, 0x17, 0x50, 0xe3, 0x29, 0xca, 0x69, 0xfa, 0x2f, 0xa7,
0x24, 0xa4, 0x75, 0xfa, 0x5e, 0x9b, 0x06, 0x21, 0xf6, 0x40, 0x7d, 0x1b, 0x52, 0xe1, 0xc4, 0xca,
0xff, 0xcc, 0x2c, 0x0b, 0xcc, 0x24, 0x0b, 0xe4, 0xe2, 0x1d, 0xdb, 0x31, 0xfd, 0xfd, 0x86, 0x29,
0x92, 0xd2, 0x54, 0x43, 0x9f, 0x24, 0xa5, 0xa9, 0x68, 0x4a, 0xac, 0x56, 0xf8, 0xf0, 0x14, 0x8c,
0xb5, 0xfd, 0x80, 0xf2, 0x50, 0xda, 0x30, 0x5e, 0x8f, 0x77, 0xc6, 0x47, 0x79, 0x90, 0xf7, 0x7d,
0x47, 0x01, 0xb9, 0xf7, 0x3b, 0x82, 0xcc, 0xc1, 0x33, 0x6e, 0xe6, 0x50, 0xdc, 0xa0, 0x4d, 0x9a,
0xa1, 0xe8, 0x15, 0x14, 0x0d, 0x2a, 0x36, 0x09, 0x6c, 0xe2, 0xd0, 0xd8, 0x9e, 0x64, 0x6b, 0x3c,
0x2d, 0xc3, 0x94, 0x22, 0x6a, 0xa7, 0xeb, 0xd9, 0x45, 0x82, 0x06, 0x46, 0x17, 0x4f, 0xc3, 0x98,
0xc3, 0xbb, 0xf5, 0xb6, 0xa7, 0x95, 0x85, 0xa6, 0xf8, 0x3c, 0xa6, 0x61, 0x1d, 0x46, 0x7d, 0xde,
0xf6, 0xa8, 0x36, 0xa2, 0x1c, 0x46, 0x24, 0x6c, 0xc3, 0x78, 0x10, 0x8a, 0x42, 0xd1, 0xe8, 0x6a,
0xa3, 0x35, 0xb4, 0x30, 0xb1, 0xb2, 0xf1, 0x06, 0xbe, 0x13, 0x96, 0xec, 0xc4, 0xe2, 0xea, 0xa9,
0x60, 0xfc, 0x6f, 0xa8, 0xfa, 0x84, 0x93, 0x16, 0x0d, 0x29, 0xd7, 0xc6, 0xa4, 0x96, 0xd9, 0x9c,
0x80, 0xed, 0xe4, 0xf4, 0x6e, 0x87, 0x72, 0xee, 0x3a, 0x34, 0xa8, 0x67, 0x37, 0x70, 0x08, 0xd5,
0xe4, 0x71, 0x04, 0x5a, 0xa5, 0x56, 0x5e, 0x98, 0x58, 0xd9, 0x7e, 0x43, 0x90, 0x77, 0x7d, 0x51,
0x1d, 0x95, 0xba, 0x10, 0x7b, 0x25, 0x53, 0x64, 0xdc, 0x02, 0x7c, 0x14, 0x16, 0xbe, 0x0c, 0x55,
0x96, 0x6c, 0x34, 0x24, 0xb1, 0x4c, 0xf5, 0x36, 0xa5, 0x9e, 0x31, 0x1a, 0x14, 0xaa, 0x29, 0x1d,
0x6b, 0x6a, 0x88, 0x63, 0xbd, 0x51, 0xa0, 0x75, 0x18, 0xed, 0x90, 0x66, 0x9b, 0xe6, 0xa2, 0x1c,
0x91, 0xb0, 0x01, 0x55, 0x9b, 0xb5, 0x7c, 0xe6, 0x51, 0x2f, 0x94, 0x51, 0x4e, 0xce, 0x33, 0xb2,
0xf1, 0x25, 0x82, 0xe9, 0x23, 0x0f, 0x65, 0xc7, 0xa7, 0x85, 0xd9, 0xe5, 0xc0, 0x48, 0xe0, 0x53,
0x5b, 0x16, 0xb9, 0x89, 0x95, 0x5b, 0xc3, 0x79, 0x39, 0x42, 0x69, 0x62, 0x9a, 0x90, 0x6e, 0x7c,
0x8c, 0x40, 0x57, 0x5f, 0x16, 0x6b, 0x36, 0x1f, 0x10, 0x7b, 0xbf, 0x08, 0x98, 0x0e, 0x25, 0xd7,
0x91, 0xb0, 0xca, 0x6b, 0x20, 0x44, 0x1d, 0xbc, 0x98, 0x2d, 0x6d, 0xde, 0xa8, 0x97, 0x5c, 0xe7,
0xf5, 0x13, 0xde, 0x78, 0x7e, 0x08, 0x48, 0x1c, 0xef, 0x22, 0x20, 0x06, 0x54, 0xbd, 0x9e, 0xdf,
0x82, 0x8c, 0x7c, 0x8c, 0x6f, 0xc0, 0x0c, 0x54, 0x3a, 0x94, 0xcb, 0xc7, 0xac, 0xd6, 0xff, 0x84,
0x28, 0xc0, 0x37, 0x38, 0x6b, 0xfb, 0xda, 0xa8, 0x72, 0x1a, 0x91, 0x44, 0xea, 0xec, 0xbb, 0x9e,
0xa3, 0x8d, 0xa9, 0xa9, 0x23, 0x28, 0xc6, 0xaf, 0x08, 0x6a, 0x3d, 0xcc, 0x1a, 0x5c, 0xa5, 0xfe,
0x00, 0xc6, 0x89, 0x5b, 0xbb, 0x8c, 0xdb, 0x54, 0xab, 0xa4, 0xf1, 0x44, 0xf5, 0x88, 0x64, 0x5c,
0x83, 0xd3, 0x3d, 0xc3, 0x19, 0x7d, 0xe0, 0x44, 0xed, 0x6c, 0xc5, 0x9f, 0xcf, 0xdc, 0x83, 0x4b,
0xa9, 0xc6, 0x0f, 0x25, 0xf8, 0x9b, 0x22, 0x61, 0x9b, 0x39, 0x5b, 0xac, 0x51, 0xd0, 0x21, 0xbc,
0x8a, 0xc3, 0x34, 0xa8, 0xf8, 0xcc, 0xc9, 0x7c, 0x55, 0x4f, 0xb6, 0xd1, 0x33, 0xf6, 0x42, 0x22,
0x3a, 0xc0, 0x9c, 0x8b, 0x32, 0xb2, 0x70, 0x77, 0xe0, 0x7a, 0x36, 0xdd, 0xa1, 0x36, 0xf3, 0x9c,
0x40, 0xfa, 0xaa, 0x9c, 0xb8, 0x5b, 0x3d, 0xc1, 0x37, 0xa1, 0x2a, 0xf7, 0xf7, 0xdc, 0x16, 0x8d,
0x0b, 0xeb, 0xa2, 0x19, 0xb5, 0x9a, 0xa6, 0xda, 0x6a, 0x66, 0x0f, 0x57, 0xb4, 0x9a, 0x66, 0x67,
0xd9, 0x14, 0x37, 0xea, 0xd9, 0x65, 0x81, 0x2b, 0x24, 0x6e, 0x73, 0xcb, 0xf5, 0x64, 0x8d, 0xcd,
0x14, 0x66, 0x64, 0xf1, 0xe8, 0x76, 0x59, 0xb3, 0xc9, 0xde, 0xd7, 0xc6, 0x6b, 0xa5, 0xec, 0xd1,
0x45, 0x34, 0xe3, 0x03, 0x18, 0xdf, 0x62, 0x8d, 0x75, 0x2f, 0xe4, 0x5d, 0x91, 0x06, 0xc2, 0x1c,
0x51, 0xaa, 0x54, 0xa7, 0x27, 0x44, 0x7c, 0x07, 0xaa, 0xa1, 0xdb, 0xa2, 0x3b, 0x21, 0x69, 0xf9,
0x71, 0xe1, 0x39, 0x06, 0xee, 0x14, 0x59, 0x22, 0xc2, 0xb0, 0xe0, 0xef, 0x69, 0x45, 0xbf, 0x47,
0x79, 0xcb, 0xf5, 0x48, 0x61, 0xd6, 0x1b, 0xd3, 0xa0, 0xf7, 0xba, 0x10, 0x25, 0xcd, 0xca, 0x8f,
0xa7, 0x00, 0xab, 0xc5, 0x2c, 0xea, 0x67, 0xf1, 0x13, 0x04, 0x23, 0x5b, 0x6e, 0x10, 0xe2, 0x33,
0xb9, 0xfa, 0x77, 0xb8, 0xa1, 0xd5, 0x87, 0x54, 0x43, 0x85, 0x2a, 0x63, 0xfa, 0xf1, 0xcf, 0xbf,
0x7c, 0x5e, 0x9a, 0xc2, 0x27, 0xe5, 0x78, 0xd1, 0x59, 0x56, 0x7b, 0xea, 0x00, 0x7f, 0x82, 0x00,
0x0b, 0xb6, 0x7c, 0x77, 0x8b, 0x2f, 0xf6, 0xc3, 0xd7, 0xa3, 0x0b, 0xd6, 0xcf, 0x28, 0x8e, 0x37,
0xc5, 0xfc, 0x22, 0xdc, 0x2c, 0x19, 0x24, 0x80, 0x45, 0x09, 0x60, 0x0e, 0x1b, 0xbd, 0x00, 0x58,
0x0f, 0x85, 0x37, 0x1f, 0x59, 0x34, 0xd2, 0xfb, 0x15, 0x82, 0xd1, 0xb7, 0x48, 0x68, 0xef, 0x0d,
0xf2, 0xd0, 0xf6, 0x70, 0x3c, 0x24, 0x75, 0x49, 0xa8, 0xc6, 0x59, 0x09, 0xf3, 0x0c, 0x3e, 0x9d,
0xc0, 0x0c, 0x42, 0x4e, 0x49, 0x2b, 0x87, 0xf6, 0x12, 0xc2, 0x4f, 0x11, 0x8c, 0x45, 0x4d, 0x2e,
0x3e, 0xd7, 0x0f, 0x62, 0xae, 0x09, 0xd6, 0x87, 0xd4, 0x4a, 0x1a, 0x17, 0x24, 0xc0, 0xb3, 0x46,
0xcf, 0x40, 0xae, 0xe6, 0xfa, 0xe0, 0xcf, 0x10, 0x94, 0x37, 0xe8, 0xc0, 0x34, 0x1b, 0x16, 0xb2,
0x23, 0xae, 0xeb, 0x11, 0x61, 0xfc, 0x18, 0xc1, 0xe4, 0x06, 0x0d, 0x93, 0x51, 0x24, 0xe8, 0xef,
0xbe, 0xdc, 0xb4, 0xa2, 0x4f, 0x9b, 0xca, 0x18, 0x99, 0x1c, 0xa5, 0xe3, 0xc7, 0x92, 0x54, 0x7d,
0x1e, 0x9f, 0x2b, 0x4a, 0xae, 0x56, 0xaa, 0xf3, 0x7b, 0x04, 0x63, 0x51, 0x53, 0xd3, 0x5f, 0x7d,
0x6e, 0x3a, 0x18, 0x9a, 0x8f, 0xd6, 0x25, 0xd0, 0x6b, 0xfa, 0xa5, 0xde, 0x40, 0xd5, 0xfb, 0xa2,
0x52, 0x39, 0x24, 0x24, 0xa6, 0x44, 0x9f, 0x8f, 0xec, 0xb7, 0x08, 0x20, 0xeb, 0xca, 0xf0, 0x85,
0x62, 0x23, 0x94, 0xce, 0x4d, 0x1f, 0x62, 0x5f, 0x66, 0x98, 0xd2, 0x98, 0x05, 0xbd, 0x56, 0xe4,
0x75, 0xd1, 0xb5, 0xad, 0xca, 0xde, 0x0d, 0x77, 0x60, 0x2c, 0xea, 0x23, 0xfa, 0x7b, 0x3d, 0xd7,
0x67, 0xe8, 0xb5, 0x82, 0xfa, 0x13, 0x05, 0x3e, 0xce, 0xb9, 0xc5, 0xc2, 0x9c, 0xfb, 0x1a, 0xc1,
0x88, 0x68, 0xd6, 0xf1, 0xd9, 0x7e, 0xf2, 0x94, 0xc9, 0x69, 0x68, 0xa1, 0xbe, 0x28, 0xa1, 0x9d,
0x33, 0x8a, 0xbd, 0xd3, 0xf5, 0xec, 0x55, 0xb4, 0x88, 0x5f, 0x22, 0x38, 0x71, 0x9b, 0x78, 0xa4,
0x41, 0x9d, 0xa4, 0xb6, 0x06, 0xf8, 0x5a, 0x21, 0x92, 0xec, 0x47, 0x89, 0x99, 0xfc, 0x28, 0x31,
0xd3, 0xbb, 0xd1, 0xa3, 0xd9, 0x3c, 0xb6, 0x80, 0xc3, 0x18, 0x52, 0x47, 0xff, 0x47, 0x5a, 0xb3,
0x8a, 0xaf, 0x0c, 0x4c, 0xdc, 0x3b, 0xc9, 0x63, 0x13, 0x82, 0x96, 0xd2, 0x39, 0x08, 0x3f, 0x47,
0x30, 0x99, 0xc8, 0xbd, 0xc7, 0x29, 0x7d, 0x73, 0xf3, 0xd6, 0x5f, 0x5b, 0x80, 0xd0, 0x9f, 0x9a,
0x76, 0x55, 0x9a, 0xf6, 0x4f, 0x7c, 0xf9, 0x15, 0x4d, 0x4b, 0x4c, 0x5a, 0x0a, 0x85, 0x15, 0xdf,
0x20, 0x18, 0x4f, 0xa6, 0x10, 0x7c, 0xbe, 0x6f, 0xc2, 0xe6, 0xe7, 0x94, 0xa1, 0x25, 0x99, 0x25,
0xb1, 0x5f, 0x30, 0xe6, 0x8a, 0x92, 0x8c, 0xc7, 0xca, 0x45, 0xa2, 0x7d, 0x81, 0x00, 0xa7, 0x8d,
0x4a, 0xda, 0xba, 0xe0, 0xf9, 0x9c, 0xaa, 0xbe, 0x3d, 0x90, 0x7e, 0x7e, 0x20, 0x5f, 0xbe, 0x22,
0x2f, 0x16, 0x56, 0x64, 0x96, 0xea, 0xff, 0x14, 0xc1, 0xc4, 0x06, 0x4d, 0xfb, 0x8f, 0x02, 0x47,
0xe6, 0xe7, 0x2c, 0x7d, 0x61, 0x30, 0x63, 0x8c, 0xe8, 0x1f, 0x12, 0xd1, 0x3c, 0x2e, 0x76, 0x55,
0x02, 0xe0, 0x09, 0x82, 0x3f, 0x27, 0xc5, 0x28, 0x26, 0x2d, 0x0d, 0x52, 0x75, 0xdc, 0xe2, 0x15,
0x23, 0x5a, 0x7c, 0x35, 0x44, 0x1f, 0x22, 0xa8, 0xc4, 0x43, 0x05, 0x9e, 0xeb, 0x27, 0x5b, 0x9d,
0x3a, 0xf4, 0x53, 0x39, 0xae, 0xa4, 0xa9, 0x36, 0xfe, 0x25, 0xd5, 0x2e, 0x63, 0xab, 0x48, 0xad,
0xcf, 0x9c, 0xc0, 0x7a, 0x18, 0x4f, 0x1b, 0x8f, 0xac, 0x26, 0x6b, 0x04, 0x97, 0xd0, 0xda, 0xd5,
0x67, 0x07, 0x33, 0xe8, 0xa7, 0x83, 0x19, 0xf4, 0xf2, 0x60, 0x06, 0xbd, 0x6d, 0x16, 0xfd, 0xc7,
0x3d, 0xfa, 0xcf, 0xfc, 0xb7, 0x00, 0x00, 0x00, 0xff, 0xff, 0x8c, 0x45, 0x31, 0x7c, 0x48, 0x17,
0x00, 0x00,
}

View File

@@ -18,7 +18,7 @@ import "github.com/argoproj/argo-cd/controller/services/application.proto";
// ApplicationQuery is a query for application resources
message ApplicationQuery {
optional string name = 1;
optional bool refresh = 2 [(gogoproto.nullable) = false];
optional string refresh = 2;
repeated string project = 3 [(gogoproto.customname) = "Projects"];
}

View File

@@ -119,6 +119,7 @@ func newTestAppServer(objects ...runtime.Object) *Server {
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
},
}
settingsMgr := settings.NewSettingsManager(kubeclientset, testNamespace)
objects = append(objects, defaultProj)
server := NewServer(
@@ -131,6 +132,7 @@ func newTestAppServer(objects ...runtime.Object) *Server {
db,
enforcer,
util.NewKeyLock(),
settingsMgr,
)
return server.(*Server)
}

View File

@@ -15,6 +15,7 @@ import (
"github.com/argoproj/argo-cd/common"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"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/db"
"github.com/argoproj/argo-cd/util/grpc"
@@ -55,7 +56,9 @@ func (s *Server) getConnectionState(ctx context.Context, cluster appv1.Cluster)
ModifiedAt: &now,
}
kubeClientset, err := kubernetes.NewForConfig(cluster.RESTConfig())
config := cluster.RESTConfig()
config.Timeout = time.Second
kubeClientset, err := kubernetes.NewForConfig(config)
if err == nil {
_, err = kubeClientset.Discovery().ServerVersion()
}
@@ -77,18 +80,29 @@ func (s *Server) getConnectionState(ctx context.Context, cluster appv1.Cluster)
// List returns list of clusters
func (s *Server) List(ctx context.Context, q *ClusterQuery) (*appv1.ClusterList, error) {
clusterList, err := s.db.ListClusters(ctx)
if clusterList != nil {
newItems := make([]appv1.Cluster, 0)
for _, clust := range clusterList.Items {
if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionGet, clust.Server) {
if clust.ConnectionState.Status == "" {
clust.ConnectionState = s.getConnectionState(ctx, clust)
}
newItems = append(newItems, *redact(&clust))
}
}
clusterList.Items = newItems
if err != nil {
return nil, err
}
newItems := make([]appv1.Cluster, 0)
for _, clust := range clusterList.Items {
if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionGet, clust.Server) {
newItems = append(newItems, *redact(&clust))
}
}
err = util.RunAllAsync(len(newItems), func(i int) error {
clust := newItems[i]
if clust.ConnectionState.Status == "" {
clust.ConnectionState = s.getConnectionState(ctx, clust)
}
newItems[i] = clust
return nil
})
if err != nil {
return nil, err
}
clusterList.Items = newItems
return clusterList, err
}

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_bf8d7367dfc95a3e, []int{0}
return fileDescriptor_cluster_0875510a34378ea0, []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_bf8d7367dfc95a3e, []int{1}
return fileDescriptor_cluster_0875510a34378ea0, []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_bf8d7367dfc95a3e, []int{2}
return fileDescriptor_cluster_0875510a34378ea0, []int{2}
}
func (m *ClusterCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -189,7 +189,7 @@ func (m *ClusterCreateFromKubeConfigRequest) Reset() { *m = ClusterCreat
func (m *ClusterCreateFromKubeConfigRequest) String() string { return proto.CompactTextString(m) }
func (*ClusterCreateFromKubeConfigRequest) ProtoMessage() {}
func (*ClusterCreateFromKubeConfigRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_cluster_bf8d7367dfc95a3e, []int{3}
return fileDescriptor_cluster_0875510a34378ea0, []int{3}
}
func (m *ClusterCreateFromKubeConfigRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -257,7 +257,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_bf8d7367dfc95a3e, []int{4}
return fileDescriptor_cluster_0875510a34378ea0, []int{4}
}
func (m *ClusterUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1393,10 +1393,10 @@ var (
)
func init() {
proto.RegisterFile("server/cluster/cluster.proto", fileDescriptor_cluster_bf8d7367dfc95a3e)
proto.RegisterFile("server/cluster/cluster.proto", fileDescriptor_cluster_0875510a34378ea0)
}
var fileDescriptor_cluster_bf8d7367dfc95a3e = []byte{
var fileDescriptor_cluster_0875510a34378ea0 = []byte{
// 564 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x95, 0xcd, 0x6e, 0x13, 0x31,
0x10, 0xc7, 0xe5, 0xb6, 0xda, 0x12, 0x83, 0xf8, 0xb0, 0x0a, 0x5a, 0xd2, 0x10, 0xa5, 0x3e, 0x54,

View File

@@ -46,7 +46,7 @@ func (m *ProjectCreateRequest) Reset() { *m = ProjectCreateRequest{} }
func (m *ProjectCreateRequest) String() string { return proto.CompactTextString(m) }
func (*ProjectCreateRequest) ProtoMessage() {}
func (*ProjectCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{0}
return fileDescriptor_project_082822b5d17b8c4e, []int{0}
}
func (m *ProjectCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -96,7 +96,7 @@ func (m *ProjectTokenDeleteRequest) Reset() { *m = ProjectTokenDeleteReq
func (m *ProjectTokenDeleteRequest) String() string { return proto.CompactTextString(m) }
func (*ProjectTokenDeleteRequest) ProtoMessage() {}
func (*ProjectTokenDeleteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{1}
return fileDescriptor_project_082822b5d17b8c4e, []int{1}
}
func (m *ProjectTokenDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -162,7 +162,7 @@ func (m *ProjectTokenCreateRequest) Reset() { *m = ProjectTokenCreateReq
func (m *ProjectTokenCreateRequest) String() string { return proto.CompactTextString(m) }
func (*ProjectTokenCreateRequest) ProtoMessage() {}
func (*ProjectTokenCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{2}
return fileDescriptor_project_082822b5d17b8c4e, []int{2}
}
func (m *ProjectTokenCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -231,7 +231,7 @@ func (m *ProjectTokenResponse) Reset() { *m = ProjectTokenResponse{} }
func (m *ProjectTokenResponse) String() string { return proto.CompactTextString(m) }
func (*ProjectTokenResponse) ProtoMessage() {}
func (*ProjectTokenResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{3}
return fileDescriptor_project_082822b5d17b8c4e, []int{3}
}
func (m *ProjectTokenResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -279,7 +279,7 @@ func (m *ProjectQuery) Reset() { *m = ProjectQuery{} }
func (m *ProjectQuery) String() string { return proto.CompactTextString(m) }
func (*ProjectQuery) ProtoMessage() {}
func (*ProjectQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{4}
return fileDescriptor_project_082822b5d17b8c4e, []int{4}
}
func (m *ProjectQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -326,7 +326,7 @@ func (m *ProjectUpdateRequest) Reset() { *m = ProjectUpdateRequest{} }
func (m *ProjectUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*ProjectUpdateRequest) ProtoMessage() {}
func (*ProjectUpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{5}
return fileDescriptor_project_082822b5d17b8c4e, []int{5}
}
func (m *ProjectUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -372,7 +372,7 @@ func (m *EmptyResponse) Reset() { *m = EmptyResponse{} }
func (m *EmptyResponse) String() string { return proto.CompactTextString(m) }
func (*EmptyResponse) ProtoMessage() {}
func (*EmptyResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_project_8d94583ca767d5b3, []int{6}
return fileDescriptor_project_082822b5d17b8c4e, []int{6}
}
func (m *EmptyResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1846,10 +1846,10 @@ var (
)
func init() {
proto.RegisterFile("server/project/project.proto", fileDescriptor_project_8d94583ca767d5b3)
proto.RegisterFile("server/project/project.proto", fileDescriptor_project_082822b5d17b8c4e)
}
var fileDescriptor_project_8d94583ca767d5b3 = []byte{
var fileDescriptor_project_082822b5d17b8c4e = []byte{
// 697 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x55, 0x5d, 0x6b, 0x13, 0x4d,
0x14, 0x66, 0x9a, 0xbe, 0x79, 0xdf, 0x4e, 0x5e, 0xb5, 0x0c, 0xad, 0xa6, 0xb1, 0x8d, 0x61, 0x2e,

View File

@@ -94,10 +94,17 @@ func (s *Server) List(ctx context.Context, q *RepoQuery) (*appsv1.RepositoryList
if urls != nil {
for _, url := range urls {
if s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, url) {
items = append(items, appsv1.Repository{Repo: url, ConnectionState: s.getConnectionState(ctx, url)})
items = append(items, appsv1.Repository{Repo: url})
}
}
}
err = util.RunAllAsync(len(items), func(i int) error {
items[i].ConnectionState = s.getConnectionState(ctx, items[i].Repo)
return nil
})
if err != nil {
return nil, err
}
return &appsv1.RepositoryList{Items: items}, nil
}

View File

@@ -46,7 +46,7 @@ func (m *RepoAppsQuery) Reset() { *m = RepoAppsQuery{} }
func (m *RepoAppsQuery) String() string { return proto.CompactTextString(m) }
func (*RepoAppsQuery) ProtoMessage() {}
func (*RepoAppsQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{0}
return fileDescriptor_repository_324bad698d34f88e, []int{0}
}
func (m *RepoAppsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -102,7 +102,7 @@ func (m *AppInfo) Reset() { *m = AppInfo{} }
func (m *AppInfo) String() string { return proto.CompactTextString(m) }
func (*AppInfo) ProtoMessage() {}
func (*AppInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{1}
return fileDescriptor_repository_324bad698d34f88e, []int{1}
}
func (m *AppInfo) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -159,7 +159,7 @@ func (m *RepoAppDetailsQuery) Reset() { *m = RepoAppDetailsQuery{} }
func (m *RepoAppDetailsQuery) String() string { return proto.CompactTextString(m) }
func (*RepoAppDetailsQuery) ProtoMessage() {}
func (*RepoAppDetailsQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{2}
return fileDescriptor_repository_324bad698d34f88e, []int{2}
}
func (m *RepoAppDetailsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -224,7 +224,7 @@ func (m *RepoAppDetailsResponse) Reset() { *m = RepoAppDetailsResponse{}
func (m *RepoAppDetailsResponse) String() string { return proto.CompactTextString(m) }
func (*RepoAppDetailsResponse) ProtoMessage() {}
func (*RepoAppDetailsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{3}
return fileDescriptor_repository_324bad698d34f88e, []int{3}
}
func (m *RepoAppDetailsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -293,7 +293,7 @@ func (m *RepoAppsResponse) Reset() { *m = RepoAppsResponse{} }
func (m *RepoAppsResponse) String() string { return proto.CompactTextString(m) }
func (*RepoAppsResponse) ProtoMessage() {}
func (*RepoAppsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{4}
return fileDescriptor_repository_324bad698d34f88e, []int{4}
}
func (m *RepoAppsResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -344,7 +344,7 @@ func (m *KsonnetAppSpec) Reset() { *m = KsonnetAppSpec{} }
func (m *KsonnetAppSpec) String() string { return proto.CompactTextString(m) }
func (*KsonnetAppSpec) ProtoMessage() {}
func (*KsonnetAppSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{5}
return fileDescriptor_repository_324bad698d34f88e, []int{5}
}
func (m *KsonnetAppSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -408,7 +408,7 @@ func (m *HelmAppSpec) Reset() { *m = HelmAppSpec{} }
func (m *HelmAppSpec) String() string { return proto.CompactTextString(m) }
func (*HelmAppSpec) ProtoMessage() {}
func (*HelmAppSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{6}
return fileDescriptor_repository_324bad698d34f88e, []int{6}
}
func (m *HelmAppSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -470,7 +470,7 @@ func (m *KustomizeAppSpec) Reset() { *m = KustomizeAppSpec{} }
func (m *KustomizeAppSpec) String() string { return proto.CompactTextString(m) }
func (*KustomizeAppSpec) ProtoMessage() {}
func (*KustomizeAppSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{7}
return fileDescriptor_repository_324bad698d34f88e, []int{7}
}
func (m *KustomizeAppSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -524,7 +524,7 @@ func (m *KsonnetEnvironment) Reset() { *m = KsonnetEnvironment{} }
func (m *KsonnetEnvironment) String() string { return proto.CompactTextString(m) }
func (*KsonnetEnvironment) ProtoMessage() {}
func (*KsonnetEnvironment) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{8}
return fileDescriptor_repository_324bad698d34f88e, []int{8}
}
func (m *KsonnetEnvironment) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -595,7 +595,7 @@ func (m *KsonnetEnvironmentDestination) Reset() { *m = KsonnetEnvironmen
func (m *KsonnetEnvironmentDestination) String() string { return proto.CompactTextString(m) }
func (*KsonnetEnvironmentDestination) ProtoMessage() {}
func (*KsonnetEnvironmentDestination) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{9}
return fileDescriptor_repository_324bad698d34f88e, []int{9}
}
func (m *KsonnetEnvironmentDestination) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -650,7 +650,7 @@ func (m *RepoQuery) Reset() { *m = RepoQuery{} }
func (m *RepoQuery) String() string { return proto.CompactTextString(m) }
func (*RepoQuery) ProtoMessage() {}
func (*RepoQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{10}
return fileDescriptor_repository_324bad698d34f88e, []int{10}
}
func (m *RepoQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -696,7 +696,7 @@ func (m *RepoResponse) Reset() { *m = RepoResponse{} }
func (m *RepoResponse) String() string { return proto.CompactTextString(m) }
func (*RepoResponse) ProtoMessage() {}
func (*RepoResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{11}
return fileDescriptor_repository_324bad698d34f88e, []int{11}
}
func (m *RepoResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -737,7 +737,7 @@ func (m *RepoCreateRequest) Reset() { *m = RepoCreateRequest{} }
func (m *RepoCreateRequest) String() string { return proto.CompactTextString(m) }
func (*RepoCreateRequest) ProtoMessage() {}
func (*RepoCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{12}
return fileDescriptor_repository_324bad698d34f88e, []int{12}
}
func (m *RepoCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -791,7 +791,7 @@ func (m *RepoUpdateRequest) Reset() { *m = RepoUpdateRequest{} }
func (m *RepoUpdateRequest) String() string { return proto.CompactTextString(m) }
func (*RepoUpdateRequest) ProtoMessage() {}
func (*RepoUpdateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_repository_3c54adc3c349824a, []int{13}
return fileDescriptor_repository_324bad698d34f88e, []int{13}
}
func (m *RepoUpdateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -3675,10 +3675,10 @@ var (
)
func init() {
proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_3c54adc3c349824a)
proto.RegisterFile("server/repository/repository.proto", fileDescriptor_repository_324bad698d34f88e)
}
var fileDescriptor_repository_3c54adc3c349824a = []byte{
var fileDescriptor_repository_324bad698d34f88e = []byte{
// 893 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x56, 0x5f, 0x6f, 0x1b, 0x45,
0x10, 0xd7, 0x25, 0xa9, 0x1b, 0x8f, 0xdb, 0x2a, 0xdd, 0x96, 0x60, 0x0e, 0xc7, 0x8d, 0x16, 0x09,

View File

@@ -4,11 +4,13 @@ import (
"context"
"crypto/tls"
"fmt"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path"
"regexp"
"strings"
"time"
@@ -103,6 +105,7 @@ var (
box = packr.NewBox("../util/rbac")
builtinPolicy string
clientConstraint = fmt.Sprintf(">= %s", minClientVersion)
baseHRefRegex = regexp.MustCompile(`<base href="(.*)">`)
)
func init() {
@@ -135,6 +138,7 @@ type ArgoCDServerOpts struct {
Namespace string
DexServerAddr string
StaticAssetsDir string
BaseHRef string
KubeClientset kubernetes.Interface
AppClientset appclientset.Interface
RepoClientset reposerver.Clientset
@@ -445,7 +449,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
repoService := repository.NewServer(a.RepoClientset, db, a.enf, argocache.NewInMemoryCache(repository.DefaultRepoStatusCacheExpiration))
sessionService := session.NewServer(a.sessionMgr)
projectLock := util.NewKeyLock()
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.RepoClientset, a.AppControllerClientset, kube.KubectlCmd{}, db, a.enf, projectLock)
applicationService := application.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.RepoClientset, a.AppControllerClientset, kube.KubectlCmd{}, db, a.enf, projectLock, a.settingsMgr)
projectService := project.NewServer(a.Namespace, a.KubeClientset, a.AppClientset, a.enf, projectLock, a.sessionMgr)
settingsService := settings.NewServer(a.settingsMgr)
accountService := account.NewServer(a.sessionMgr, a.settingsMgr)
@@ -540,7 +544,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int) *http.Server
// Serve UI static assets
if a.StaticAssetsDir != "" {
mux.HandleFunc("/", newStaticAssetsHandler(a.StaticAssetsDir))
mux.HandleFunc("/", newStaticAssetsHandler(a.StaticAssetsDir, a.BaseHRef))
}
return &httpS
}
@@ -596,8 +600,37 @@ func registerDownloadHandlers(mux *http.ServeMux, base string) {
}
}
func indexFilePath(srcPath string, baseHRef string) (string, error) {
if baseHRef == "/" {
return srcPath, nil
}
filePath := path.Join(os.TempDir(), fmt.Sprintf("index_%s.html", strings.Replace(strings.Trim(baseHRef, "/"), "/", "_", -1)))
f, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600)
if err != nil {
if os.IsExist(err) {
return filePath, nil
}
return "", err
}
defer util.Close(f)
data, err := ioutil.ReadFile(srcPath)
if err != nil {
return "", err
}
if baseHRef != "/" {
data = []byte(baseHRefRegex.ReplaceAllString(string(data), fmt.Sprintf(`<base href="/%s/">`, strings.Trim(baseHRef, "/"))))
}
_, err = f.Write(data)
if err != nil {
return "", err
}
return filePath, nil
}
// newStaticAssetsHandler returns an HTTP handler to serve UI static assets
func newStaticAssetsHandler(dir string) func(http.ResponseWriter, *http.Request) {
func newStaticAssetsHandler(dir string, baseHRef string) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) {
acceptHTML := false
for _, acceptType := range strings.Split(r.Header.Get("Accept"), ",") {
@@ -613,9 +646,14 @@ func newStaticAssetsHandler(dir string) func(http.ResponseWriter, *http.Request)
for k, v := range noCacheHeaders {
w.Header().Set(k, v)
}
http.ServeFile(w, r, dir+"/index.html")
indexHtmlPath, err := indexFilePath(path.Join(dir, "index.html"), baseHRef)
if err != nil {
http.Error(w, fmt.Sprintf("Unable to access index.html: %v", err), http.StatusInternalServerError)
return
}
http.ServeFile(w, r, indexHtmlPath)
} else {
http.ServeFile(w, r, dir+r.URL.Path)
http.ServeFile(w, r, path.Join(dir, r.URL.Path))
}
}
}

View File

@@ -47,7 +47,7 @@ func (m *SessionCreateRequest) Reset() { *m = SessionCreateRequest{} }
func (m *SessionCreateRequest) String() string { return proto.CompactTextString(m) }
func (*SessionCreateRequest) ProtoMessage() {}
func (*SessionCreateRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_session_217b926c109d1cc2, []int{0}
return fileDescriptor_session_8e535ce77fc5e082, []int{0}
}
func (m *SessionCreateRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -108,7 +108,7 @@ func (m *SessionDeleteRequest) Reset() { *m = SessionDeleteRequest{} }
func (m *SessionDeleteRequest) String() string { return proto.CompactTextString(m) }
func (*SessionDeleteRequest) ProtoMessage() {}
func (*SessionDeleteRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_session_217b926c109d1cc2, []int{1}
return fileDescriptor_session_8e535ce77fc5e082, []int{1}
}
func (m *SessionDeleteRequest) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -149,7 +149,7 @@ func (m *SessionResponse) Reset() { *m = SessionResponse{} }
func (m *SessionResponse) String() string { return proto.CompactTextString(m) }
func (*SessionResponse) ProtoMessage() {}
func (*SessionResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_session_217b926c109d1cc2, []int{2}
return fileDescriptor_session_8e535ce77fc5e082, []int{2}
}
func (m *SessionResponse) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -827,10 +827,10 @@ var (
)
func init() {
proto.RegisterFile("server/session/session.proto", fileDescriptor_session_217b926c109d1cc2)
proto.RegisterFile("server/session/session.proto", fileDescriptor_session_8e535ce77fc5e082)
}
var fileDescriptor_session_217b926c109d1cc2 = []byte{
var fileDescriptor_session_8e535ce77fc5e082 = []byte{
// 356 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x92, 0xb1, 0x4e, 0xeb, 0x30,
0x14, 0x86, 0xe5, 0x5e, 0xdd, 0xde, 0x7b, 0x3d, 0xdc, 0x8a, 0x28, 0x82, 0x28, 0x2a, 0x15, 0xca,

View File

@@ -42,7 +42,7 @@ func (m *SettingsQuery) Reset() { *m = SettingsQuery{} }
func (m *SettingsQuery) String() string { return proto.CompactTextString(m) }
func (*SettingsQuery) ProtoMessage() {}
func (*SettingsQuery) Descriptor() ([]byte, []int) {
return fileDescriptor_settings_90d4947f5a5e2583, []int{0}
return fileDescriptor_settings_902e174a76eb35c2, []int{0}
}
func (m *SettingsQuery) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -84,7 +84,7 @@ func (m *Settings) Reset() { *m = Settings{} }
func (m *Settings) String() string { return proto.CompactTextString(m) }
func (*Settings) ProtoMessage() {}
func (*Settings) Descriptor() ([]byte, []int) {
return fileDescriptor_settings_90d4947f5a5e2583, []int{1}
return fileDescriptor_settings_902e174a76eb35c2, []int{1}
}
func (m *Settings) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -145,7 +145,7 @@ func (m *DexConfig) Reset() { *m = DexConfig{} }
func (m *DexConfig) String() string { return proto.CompactTextString(m) }
func (*DexConfig) ProtoMessage() {}
func (*DexConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_settings_90d4947f5a5e2583, []int{2}
return fileDescriptor_settings_902e174a76eb35c2, []int{2}
}
func (m *DexConfig) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -193,7 +193,7 @@ func (m *Connector) Reset() { *m = Connector{} }
func (m *Connector) String() string { return proto.CompactTextString(m) }
func (*Connector) ProtoMessage() {}
func (*Connector) Descriptor() ([]byte, []int) {
return fileDescriptor_settings_90d4947f5a5e2583, []int{3}
return fileDescriptor_settings_902e174a76eb35c2, []int{3}
}
func (m *Connector) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -249,7 +249,7 @@ func (m *OIDCConfig) Reset() { *m = OIDCConfig{} }
func (m *OIDCConfig) String() string { return proto.CompactTextString(m) }
func (*OIDCConfig) ProtoMessage() {}
func (*OIDCConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_settings_90d4947f5a5e2583, []int{4}
return fileDescriptor_settings_902e174a76eb35c2, []int{4}
}
func (m *OIDCConfig) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1291,10 +1291,10 @@ var (
)
func init() {
proto.RegisterFile("server/settings/settings.proto", fileDescriptor_settings_90d4947f5a5e2583)
proto.RegisterFile("server/settings/settings.proto", fileDescriptor_settings_902e174a76eb35c2)
}
var fileDescriptor_settings_90d4947f5a5e2583 = []byte{
var fileDescriptor_settings_902e174a76eb35c2 = []byte{
// 397 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x52, 0xcd, 0x8a, 0xdb, 0x30,
0x18, 0x44, 0x71, 0x49, 0xe2, 0xaf, 0x3f, 0x69, 0xd5, 0x12, 0xdc, 0x50, 0x9c, 0xe0, 0x53, 0xa0,

View File

@@ -57,8 +57,7 @@
"in": "query"
},
{
"type": "boolean",
"format": "boolean",
"type": "string",
"name": "refresh",
"in": "query"
},
@@ -202,8 +201,7 @@
"required": true
},
{
"type": "boolean",
"format": "boolean",
"type": "string",
"name": "refresh",
"in": "query"
},
@@ -1224,8 +1222,7 @@
"in": "query"
},
{
"type": "boolean",
"format": "boolean",
"type": "string",
"name": "refresh",
"in": "query"
},
@@ -2486,6 +2483,18 @@
}
}
},
"v1alpha1ComparedTo": {
"type": "object",
"title": "ComparedTo contains application source and target which was used for resources comparison",
"properties": {
"destination": {
"$ref": "#/definitions/v1alpha1ApplicationDestination"
},
"source": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
}
}
},
"v1alpha1ComponentParameter": {
"type": "object",
"title": "ComponentParameter contains information about component parameter value",
@@ -2527,6 +2536,20 @@
}
}
},
"v1alpha1InfoItem": {
"type": "object",
"title": "InfoItem contains human readable information about object",
"properties": {
"name": {
"description": "Name is a human readable title for this piece of information.",
"type": "string"
},
"value": {
"description": "Value is human readable content.",
"type": "string"
}
}
},
"v1alpha1JWTToken": {
"type": "object",
"title": "JWTToken holds the issuedAt and expiresAt values of a token",
@@ -2687,6 +2710,12 @@
"group": {
"type": "string"
},
"info": {
"type": "array",
"items": {
"$ref": "#/definitions/v1alpha1InfoItem"
}
},
"kind": {
"type": "string"
},
@@ -2699,12 +2728,6 @@
"resourceVersion": {
"type": "string"
},
"tags": {
"type": "array",
"items": {
"type": "string"
}
},
"version": {
"type": "string"
}
@@ -2886,7 +2909,7 @@
"type": "object",
"properties": {
"comparedTo": {
"$ref": "#/definitions/v1alpha1ApplicationSource"
"$ref": "#/definitions/v1alpha1ComparedTo"
},
"revision": {
"type": "string"

View File

@@ -51,7 +51,7 @@ func (m *VersionMessage) Reset() { *m = VersionMessage{} }
func (m *VersionMessage) String() string { return proto.CompactTextString(m) }
func (*VersionMessage) ProtoMessage() {}
func (*VersionMessage) Descriptor() ([]byte, []int) {
return fileDescriptor_version_301443c925f6e1d7, []int{0}
return fileDescriptor_version_9a67e1897074bbcc, []int{0}
}
func (m *VersionMessage) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -781,10 +781,10 @@ var (
)
func init() {
proto.RegisterFile("server/version/version.proto", fileDescriptor_version_301443c925f6e1d7)
proto.RegisterFile("server/version/version.proto", fileDescriptor_version_9a67e1897074bbcc)
}
var fileDescriptor_version_301443c925f6e1d7 = []byte{
var fileDescriptor_version_9a67e1897074bbcc = []byte{
// 343 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x5c, 0x92, 0xcf, 0x4a, 0xc3, 0x40,
0x10, 0xc6, 0x49, 0xd5, 0xfe, 0x59, 0x4a, 0x0f, 0x8b, 0xd4, 0x25, 0x96, 0x22, 0x3d, 0x88, 0x08,

View File

@@ -2,7 +2,7 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: dummy-crd.argoproj.io
name: dummies.argoproj.io
spec:
group: argoproj.io
version: v1alpha1

View File

@@ -0,0 +1,32 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: extensions-deployment
labels:
app: extensions-deployment
spec:
replicas: 1
selector:
matchLabels:
app: extensions-deployment
template:
metadata:
labels:
app: extensions-deployment
spec:
containers:
- name: extensions-deployment
image: "gcr.io/heptio-images/ks-guestbook-demo:0.1"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http

View File

@@ -0,0 +1,9 @@
apiVersion: extensions/v1beta1
kind: NetworkPolicy
metadata:
name: allow-default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress

View File

@@ -0,0 +1,17 @@
apiVersion: extensions/v1beta1
kind: PodSecurityPolicy
metadata:
name: pod-security-example
spec:
privileged: false # Don't allow privileged pods!
# The rest fills in some required fields.
seLinux:
rule: RunAsAny
supplementalGroups:
rule: RunAsAny
runAsUser:
rule: RunAsAny
fsGroup:
rule: RunAsAny
volumes:
- '*'

View File

@@ -67,17 +67,13 @@ func FilterByProjects(apps []argoappv1.Application, projects []string) []argoapp
}
// RefreshApp updates the refresh annotation of an application to coerce the controller to process it
func RefreshApp(appIf v1alpha1.ApplicationInterface, name string) (*argoappv1.Application, error) {
refreshString := time.Now().UTC().Format(time.RFC3339)
func RefreshApp(appIf v1alpha1.ApplicationInterface, name string, refreshType argoappv1.RefreshType) (*argoappv1.Application, error) {
metadata := map[string]interface{}{
"metadata": map[string]interface{}{
"annotations": map[string]string{
common.AnnotationKeyRefresh: refreshString,
common.AnnotationKeyRefresh: string(refreshType),
},
},
"status": map[string]interface{}{
"observedAt": nil,
},
}
var err error
patch, err := json.Marshal(metadata)
@@ -91,7 +87,7 @@ func RefreshApp(appIf v1alpha1.ApplicationInterface, name string) (*argoappv1.Ap
return nil, err
}
} else {
log.Infof("Refreshed app '%s' for controller reprocessing (%s)", name, refreshString)
log.Infof("Requested app '%s' refresh", name)
return app, nil
}
time.Sleep(100 * time.Millisecond)
@@ -120,16 +116,11 @@ func WaitForRefresh(ctx context.Context, appIf v1alpha1.ApplicationInterface, na
if !ok {
return nil, fmt.Errorf("Application event object failed conversion: %v", next)
}
refreshTimestampStr := app.ObjectMeta.Annotations[common.AnnotationKeyRefresh]
if refreshTimestampStr == "" {
now := time.Now().UTC()
refreshTimestampStr = now.String()
annotations := app.GetAnnotations()
if annotations == nil {
annotations = make(map[string]string)
}
refreshTimestamp, err := time.Parse(time.RFC3339, refreshTimestampStr)
if err != nil {
return nil, fmt.Errorf("Unable to parse '%s': %v", common.AnnotationKeyRefresh, err)
}
if app.Status.ObservedAt.After(refreshTimestamp) || app.Status.ObservedAt.Time.Equal(refreshTimestamp) {
if _, ok := annotations[common.AnnotationKeyRefresh]; !ok {
return app, nil
}
}

View File

@@ -11,7 +11,6 @@ import (
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/watch"
"github.com/argoproj/argo-cd/common"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned/fake"
testcore "k8s.io/client-go/testing"
@@ -23,7 +22,7 @@ func TestRefreshApp(t *testing.T) {
testApp.Namespace = "default"
appClientset := appclientset.NewSimpleClientset(&testApp)
appIf := appClientset.ArgoprojV1alpha1().Applications("default")
_, err := RefreshApp(appIf, "test-app")
_, err := RefreshApp(appIf, "test-app", argoappv1.RefreshTypeNormal)
assert.Nil(t, err)
// For some reason, the fake Application inferface doesn't reflect the patch status after Patch(),
// so can't verify it was set in unit tests.
@@ -63,10 +62,6 @@ func TestWaitForRefresh(t *testing.T) {
var testApp argoappv1.Application
testApp.Name = "test-app"
testApp.Namespace = "default"
testApp.ObjectMeta.Annotations = map[string]string{
common.AnnotationKeyRefresh: time.Now().UTC().Format(time.RFC3339),
}
testApp.Status.ObservedAt = metav1.Now()
appClientset = appclientset.NewSimpleClientset()
appIf = appClientset.ArgoprojV1alpha1().Applications("default")

View File

@@ -1,13 +1,14 @@
package db
import (
"github.com/argoproj/argo-cd/util/settings"
"context"
"k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
appv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"golang.org/x/net/context"
"k8s.io/client-go/kubernetes"
"github.com/argoproj/argo-cd/util/settings"
)
type ArgoDB interface {

View File

@@ -33,14 +33,15 @@ type DiffResultList struct {
func Diff(config, live *unstructured.Unstructured) *DiffResult {
if config != nil {
config = stripTypeInformation(config)
EncodeSecretStringData(config)
Normalize(config)
}
if live != nil {
live = stripTypeInformation(live)
Normalize(live)
}
orig := GetLastAppliedConfigAnnotation(live)
if orig != nil && config != nil {
EncodeSecretStringData(orig)
Normalize(orig)
dr, err := ThreeWayDiff(orig, config, live)
if err == nil {
return dr
@@ -239,9 +240,21 @@ func (d *DiffResult) ASCIIFormat(left *unstructured.Unstructured, formatOpts for
return asciiFmt.Format(d.Diff)
}
// encodeSecretStringData mutates the supplied object and encodes stringData to data. If the object
// is not a secret, or is an invalid secret, then returns the same object
func EncodeSecretStringData(un *unstructured.Unstructured) {
func Normalize(un *unstructured.Unstructured) {
if un == nil {
return
}
gvk := un.GroupVersionKind()
if gvk.Group == "" && gvk.Kind == "Secret" {
NormalizeSecret(un)
} else if gvk.Group == "rbac.authorization.k8s.io" && (gvk.Kind == "ClusterRole" || gvk.Kind == "Role") {
normalizeRole(un)
}
}
// NormalizeSecret mutates the supplied object and encodes stringData to data, and converts nils to
// empty strings. If the object is not a secret, or is an invalid secret, then returns the same object.
func NormalizeSecret(un *unstructured.Unstructured) {
if un == nil {
return
}
@@ -252,29 +265,57 @@ func EncodeSecretStringData(un *unstructured.Unstructured) {
var secret corev1.Secret
err := runtime.DefaultUnstructuredConverter.FromUnstructured(un.Object, &secret)
if err != nil {
log.Warnf("object unable to convert to secret: %v", err)
return
}
if len(secret.StringData) == 0 {
return
// We normalize nils to empty string to handle: https://github.com/argoproj/argo-cd/issues/943
for k, v := range secret.Data {
if len(v) == 0 {
secret.Data[k] = []byte("")
}
}
if secret.Data == nil {
secret.Data = make(map[string][]byte)
}
for k, v := range secret.StringData {
secret.Data[k] = []byte(v)
if len(secret.StringData) > 0 {
if secret.Data == nil {
secret.Data = make(map[string][]byte)
}
for k, v := range secret.StringData {
secret.Data[k] = []byte(v)
}
delete(un.Object, "stringData")
}
newObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(&secret)
if err != nil {
log.Warnf("object unable to convert from secret: %v", err)
return
}
err = unstructured.SetNestedMap(un.Object, newObj["data"].(map[string]interface{}), "data")
if err != nil {
log.Warnf("failed to set secret.data: %v", err)
if secret.Data != nil {
err = unstructured.SetNestedMap(un.Object, newObj["data"].(map[string]interface{}), "data")
if err != nil {
log.Warnf("failed to set secret.data: %v", err)
return
}
}
}
// normalizeRole mutates the supplied Role/ClusterRole and sets rules to null if it is an empty list
func normalizeRole(un *unstructured.Unstructured) {
if un == nil {
return
}
delete(un.Object, "stringData")
gvk := un.GroupVersionKind()
if gvk.Group != "rbac.authorization.k8s.io" || (gvk.Kind != "Role" && gvk.Kind != "ClusterRole") {
return
}
rulesIf, ok := un.Object["rules"]
if !ok {
return
}
rules, ok := rulesIf.([]interface{})
if !ok {
return
}
if rules != nil && len(rules) == 0 {
un.Object["rules"] = nil
}
}
// JSONFormat returns the diff as a JSON string

View File

@@ -15,6 +15,7 @@ import (
"k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/errors"
"github.com/argoproj/argo-cd/test"
"github.com/argoproj/argo-cd/util/kube"
)
@@ -25,6 +26,15 @@ var (
}
)
func unmarshalFile(path string) *unstructured.Unstructured {
data, err := ioutil.ReadFile(path)
errors.CheckError(err)
var un unstructured.Unstructured
err = json.Unmarshal(data, &un.Object)
errors.CheckError(err)
return &un
}
func TestDiff(t *testing.T) {
leftDep := test.DemoDeployment()
leftUn := kube.MustToUnstructured(leftDep)
@@ -55,6 +65,19 @@ func TestDiffWithNils(t *testing.T) {
assert.True(t, diffRes.Diff.Modified())
}
func TestDiffNilFieldInLive(t *testing.T) {
leftDep := test.DemoDeployment()
rightDep := leftDep.DeepCopy()
leftUn := kube.MustToUnstructured(leftDep)
rightUn := kube.MustToUnstructured(rightDep)
err := unstructured.SetNestedField(rightUn.Object, nil, "spec")
assert.Nil(t, err)
diffRes := Diff(leftUn, rightUn)
assert.True(t, diffRes.Modified)
}
func TestDiffArraySame(t *testing.T) {
leftDep := test.DemoDeployment()
rightDep := leftDep.DeepCopy()
@@ -169,7 +192,7 @@ var demoConfig = `
"labels": {
"app.kubernetes.io/instance": "argocd-demo"
},
"name": "application-controller"
"name": "argocd-application-controller"
}
}
`
@@ -180,21 +203,21 @@ var demoLive = `
"kind": "ServiceAccount",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/instance\":\"argocd-demo\"},\"name\":\"application-controller\",\"namespace\":\"argocd-demo\"}}\n"
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"ServiceAccount\",\"metadata\":{\"annotations\":{},\"labels\":{\"app.kubernetes.io/instance\":\"argocd-demo\"},\"name\":\"argocd-application-controller\",\"namespace\":\"argocd-demo\"}}\n"
},
"creationTimestamp": "2018-04-16T22:08:57Z",
"labels": {
"app.kubernetes.io/instance": "argocd-demo"
},
"name": "application-controller",
"name": "argocd-application-controller",
"namespace": "argocd-demo",
"resourceVersion": "7584502",
"selfLink": "/api/v1/namespaces/argocd-demo/serviceaccounts/application-controller",
"selfLink": "/api/v1/namespaces/argocd-demo/serviceaccounts/argocd-application-controller",
"uid": "c22bb2b4-41c2-11e8-978a-028445d52ec8"
},
"secrets": [
{
"name": "application-controller-token-kfxct"
"name": "argocd-application-controller-token-kfxct"
}
]
}
@@ -221,34 +244,19 @@ func TestThreeWayDiffExample1(t *testing.T) {
}
func TestThreeWayDiffExample2(t *testing.T) {
configData, err := ioutil.ReadFile("testdata/elasticsearch-config.json")
assert.NoError(t, err)
liveData, err := ioutil.ReadFile("testdata/elasticsearch-live.json")
assert.NoError(t, err)
var configUn, liveUn unstructured.Unstructured
err = json.Unmarshal(configData, &configUn.Object)
assert.NoError(t, err)
err = json.Unmarshal(liveData, &liveUn.Object)
assert.NoError(t, err)
dr := Diff(&configUn, &liveUn)
configUn := unmarshalFile("testdata/elasticsearch-config.json")
liveUn := unmarshalFile("testdata/elasticsearch-live.json")
dr := Diff(configUn, liveUn)
assert.False(t, dr.Modified)
ascii, err := dr.ASCIIFormat(&liveUn, formatOpts)
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
}
// TestThreeWayDiffExample2WithDifference is same as TestThreeWayDiffExample2 but with differences
func TestThreeWayDiffExample2WithDifference(t *testing.T) {
configData, err := ioutil.ReadFile("testdata/elasticsearch-config.json")
assert.NoError(t, err)
liveData, err := ioutil.ReadFile("testdata/elasticsearch-live.json")
assert.NoError(t, err)
var configUn, liveUn unstructured.Unstructured
err = json.Unmarshal(configData, &configUn.Object)
assert.NoError(t, err)
err = json.Unmarshal(liveData, &liveUn.Object)
assert.NoError(t, err)
configUn := unmarshalFile("testdata/elasticsearch-config.json")
liveUn := unmarshalFile("testdata/elasticsearch-live.json")
labels := configUn.GetLabels()
// add a new label
labels["foo"] = "bar"
@@ -258,9 +266,9 @@ func TestThreeWayDiffExample2WithDifference(t *testing.T) {
delete(labels, "release")
configUn.SetLabels(labels)
dr := Diff(&configUn, &liveUn)
dr := Diff(configUn, liveUn)
assert.True(t, dr.Modified)
ascii, err := dr.ASCIIFormat(&liveUn, formatOpts)
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
@@ -288,18 +296,11 @@ func TestThreeWayDiffExample2WithDifference(t *testing.T) {
}
func TestThreeWayDiffExplicitNamespace(t *testing.T) {
configData, err := ioutil.ReadFile("testdata/spinnaker-sa-config.json")
assert.NoError(t, err)
liveData, err := ioutil.ReadFile("testdata/spinnaker-sa-live.json")
assert.NoError(t, err)
var configUn, liveUn unstructured.Unstructured
err = json.Unmarshal(configData, &configUn.Object)
assert.NoError(t, err)
err = json.Unmarshal(liveData, &liveUn.Object)
assert.NoError(t, err)
dr := Diff(&configUn, &liveUn)
configUn := unmarshalFile("testdata/spinnaker-sa-config.json")
liveUn := unmarshalFile("testdata/spinnaker-sa-live.json")
dr := Diff(configUn, liveUn)
assert.False(t, dr.Modified)
ascii, err := dr.ASCIIFormat(&liveUn, formatOpts)
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
}
@@ -445,3 +446,44 @@ func TestInvalidSecretStringData(t *testing.T) {
dr := Diff(&configUn, nil)
assert.True(t, dr.Modified)
}
func TestNullSecretData(t *testing.T) {
configUn := unmarshalFile("testdata/wordpress-config.json")
liveUn := unmarshalFile("testdata/wordpress-live.json")
dr := Diff(configUn, liveUn)
if !assert.False(t, dr.Modified) {
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
}
}
// TestRedactedSecretData tests we are able to perform diff on redacted secret data, which has
// invalid characters (*) for the the data byte array field.
func TestRedactedSecretData(t *testing.T) {
configUn := unmarshalFile("testdata/wordpress-config.json")
liveUn := unmarshalFile("testdata/wordpress-live.json")
configData := configUn.Object["data"].(map[string]interface{})
liveData := liveUn.Object["data"].(map[string]interface{})
configData["wordpress-password"] = "***"
configData["smtp-password"] = "***"
liveData["wordpress-password"] = "******"
liveData["smtp-password"] = "******"
dr := Diff(configUn, liveUn)
if !assert.True(t, dr.Modified) {
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
}
}
func TestNullRoleRule(t *testing.T) {
configUn := unmarshalFile("testdata/grafana-clusterrole-config.json")
liveUn := unmarshalFile("testdata/grafana-clusterrole-live.json")
dr := Diff(configUn, liveUn)
if !assert.False(t, dr.Modified) {
ascii, err := dr.ASCIIFormat(liveUn, formatOpts)
assert.Nil(t, err)
log.Println(ascii)
}
}

View File

@@ -0,0 +1,14 @@
{
"kind": "ClusterRole",
"apiVersion": "rbac.authorization.k8s.io/v1",
"metadata": {
"labels": {
"app": "grafana",
"chart": "grafana-1.21.2",
"release": "grafana",
"heritage": "Tiller"
},
"name": "grafana-clusterrole"
},
"rules": []
}

View File

@@ -0,0 +1,21 @@
{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"rbac.authorization.k8s.io/v1\",\"kind\":\"ClusterRole\",\"metadata\":{\"annotations\":{},\"labels\":{\"app\":\"grafana\",\"chart\":\"grafana-1.21.2\",\"heritage\":\"Tiller\",\"release\":\"grafana\"},\"name\":\"grafana-clusterrole\"},\"rules\":[]}\n"
},
"creationTimestamp": "2018-12-26T23:26:41Z",
"labels": {
"app": "grafana",
"chart": "grafana-1.21.2",
"heritage": "Tiller",
"release": "grafana"
},
"name": "grafana-clusterrole",
"resourceVersion": "13174",
"selfLink": "/apis/rbac.authorization.k8s.io/v1/clusterroles/grafana-clusterrole",
"uid": "b30316d3-0965-11e9-9673-ae0a6e5594a2"
},
"rules": null
}

View File

@@ -0,0 +1,18 @@
{
"apiVersion": "v1",
"kind": "Secret",
"metadata": {
"name": "wordpress-wordpress",
"labels": {
"app": "wordpress-wordpress",
"chart": "wordpress-5.0.1",
"release": "wordpress",
"heritage": "Tiller"
}
},
"type": "Opaque",
"data": {
"wordpress-password": "Skt2T0tjMk5PdQ==",
"smtp-password": ""
}
}

26
util/diff/testdata/wordpress-live.json vendored Normal file
View File

@@ -0,0 +1,26 @@
{
"apiVersion": "v1",
"data": {
"smtp-password": null,
"wordpress-password": "Skt2T0tjMk5PdQ=="
},
"kind": "Secret",
"metadata": {
"annotations": {
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"data\":{\"smtp-password\":\"\",\"wordpress-password\":\"Xkt2T0tjMk5PdQ==\"},\"kind\":\"Secret\",\"metadata\":{\"annotations\":{},\"labels\":{\"app\":\"wordpress-wordpress\",\"chart\":\"wordpress-5.0.1\",\"heritage\":\"Tiller\",\"release\":\"wordpress\"},\"name\":\"wordpress-wordpress\",\"namespace\":\"argocd\"},\"type\":\"Opaque\"}\n"
},
"creationTimestamp": "2018-12-19T09:15:40Z",
"labels": {
"app": "wordpress-wordpress",
"chart": "wordpress-5.0.1",
"heritage": "Tiller",
"release": "wordpress"
},
"name": "wordpress-wordpress",
"namespace": "argocd",
"resourceVersion": "27442",
"selfLink": "/api/v1/namespaces/argocd/secrets/wordpress-wordpress",
"uid": "a782f882-036e-11e9-92c4-ba8ba592c12d"
},
"type": "Opaque"
}

View File

@@ -55,7 +55,10 @@ func RemoveMapFields(config, live map[string]interface{}) map[string]interface{}
if !ok {
continue
}
result[k] = removeFields(v1, v2)
if v2 != nil {
v2 = removeFields(v1, v2)
}
result[k] = v2
}
return result
}
@@ -66,7 +69,10 @@ func removeListFields(config, live []interface{}) []interface{} {
result := make([]interface{}, 0, len(live))
for i, v2 := range live {
if len(config) > i {
result = append(result, removeFields(config[i], v2))
if v2 != nil {
v2 = removeFields(config[i], v2)
}
result = append(result, v2)
} else {
result = append(result, v2)
}

View File

@@ -125,14 +125,7 @@ func (k *ksonnetApp) Show(environment string) ([]*unstructured.Unstructured, err
if err != nil {
return nil, fmt.Errorf("`ks show` failed: %v", err)
}
data, err := kube.SplitYAML(out)
if err == nil {
// Address https://github.com/ksonnet/ksonnet/issues/707
for _, d := range data {
kube.UnsetLabel(d, "ksonnet.io/component")
}
}
return data, err
return kube.SplitYAML(out)
}
// Destination returns the deployment destination for an environment

View File

@@ -34,10 +34,19 @@ type Kubectl interface {
GetResource(config *rest.Config, gvk schema.GroupVersionKind, name string, namespace string) (*unstructured.Unstructured, error)
WatchResources(ctx context.Context, config *rest.Config, namespace string) (chan watch.Event, error)
GetResources(config *rest.Config, namespace string) ([]*unstructured.Unstructured, error)
GetAPIResources(config *rest.Config) ([]*metav1.APIResourceList, error)
}
type KubectlCmd struct{}
func (k KubectlCmd) GetAPIResources(config *rest.Config) ([]*metav1.APIResourceList, error) {
disco, err := discovery.NewDiscoveryClientForConfig(config)
if err != nil {
return nil, err
}
return disco.ServerResources()
}
// GetResources returns all kubernetes resources
func (k KubectlCmd) GetResources(config *rest.Config, namespace string) ([]*unstructured.Unstructured, error) {
@@ -203,7 +212,7 @@ func (k KubectlCmd) ApplyResource(config *rest.Config, obj *unstructured.Unstruc
// See: https://github.com/kubernetes/kubernetes/issues/71185. This is behavior which we do
// not want. We need to check if the namespace exists, before know if it is safe to run this
// command. Skip this for dryRuns.
if !dryRun {
if !dryRun && namespace != "" {
kubeClient, err := kubernetes.NewForConfig(config)
if err != nil {
return "", err
@@ -236,7 +245,10 @@ func (k KubectlCmd) ApplyResource(config *rest.Config, obj *unstructured.Unstruc
}
func runKubectl(kubeconfigPath string, namespace string, args []string, manifestBytes []byte, dryRun bool) (string, error) {
cmdArgs := append(append([]string{"--kubeconfig", kubeconfigPath, "-n", namespace}, args...), "-f", "-")
cmdArgs := append([]string{"--kubeconfig", kubeconfigPath, "-f", "-"}, args...)
if namespace != "" {
cmdArgs = append(cmdArgs, "-n", namespace)
}
if dryRun {
cmdArgs = append(cmdArgs, "--dry-run")
}

View File

@@ -5,7 +5,6 @@ import (
"context"
"encoding/json"
"fmt"
"os"
"reflect"
"regexp"
"strings"
@@ -50,25 +49,21 @@ const (
PersistentVolumeClaimKind = "PersistentVolumeClaim"
CustomResourceDefinitionKind = "CustomResourceDefinition"
PodKind = "Pod"
NetworkPolicyKind = "NetworkPolicy"
PodSecurityPolicyKind = "PodSecurityPolicy"
)
var (
// legacyLabeling decides whether or not to use legacy (v0.10 and below) labeling
legacyLabeling = false
// obsoleteExtensionsKinds contains list of obsolete kinds from extensions group which exist in apps group
obsoleteExtensionsKinds = map[string]bool{
DaemonSetKind: true,
ReplicaSetKind: true,
DeploymentKind: true,
// obsoleteExtensionsKinds contains list of obsolete kinds from extensions group and corresponding name of new group
obsoleteExtensionsKinds = map[string]string{
DaemonSetKind: "apps",
ReplicaSetKind: "apps",
DeploymentKind: "apps",
NetworkPolicyKind: "networking.k8s.io",
PodSecurityPolicyKind: "policy",
}
)
func init() {
val, _ := os.LookupEnv(common.EnvVarLegacyLabels)
legacyLabeling = bool(val == "1" || val == "true")
}
type ResourceKey struct {
Group string
Kind string
@@ -80,17 +75,17 @@ func (k *ResourceKey) String() string {
return fmt.Sprintf("%s/%s/%s/%s", k.Group, k.Kind, k.Namespace, k.Name)
}
func isObsoleteExtensionsGroupKind(group string, kind string) bool {
func isObsoleteExtensionsGroupKind(group string, kind string) (string, bool) {
if group == "extensions" {
_, ok := obsoleteExtensionsKinds[kind]
return ok
newGroup, ok := obsoleteExtensionsKinds[kind]
return newGroup, ok
}
return false
return "", false
}
func NewResourceKey(group string, kind string, namespace string, name string) ResourceKey {
if isObsoleteExtensionsGroupKind(group, kind) {
group = "apps"
if newGroup, ok := isObsoleteExtensionsGroupKind(group, kind); ok {
group = newGroup
}
return ResourceKey{Group: group, Kind: kind, Namespace: namespace, Name: name}
@@ -133,9 +128,9 @@ func MustToUnstructured(obj interface{}) *unstructured.Unstructured {
}
// GetAppInstanceLabel returns the application instance name from labels
func GetAppInstanceLabel(un *unstructured.Unstructured) string {
func GetAppInstanceLabel(un *unstructured.Unstructured, key string) string {
if labels := un.GetLabels(); labels != nil {
return labels[labelKey()]
return labels[key]
}
return ""
}
@@ -154,24 +149,16 @@ func UnsetLabel(target *unstructured.Unstructured, key string) {
}
}
func labelKey() string {
if legacyLabeling {
return common.LabelKeyLegacyApplicationName
}
return common.LabelKeyAppInstance
}
// SetAppInstanceLabel the recommended app.kubernetes.io/instance label against an unstructured object
// Uses the legacy labeling if environment variable is set
func SetAppInstanceLabel(target *unstructured.Unstructured, val string) error {
func SetAppInstanceLabel(target *unstructured.Unstructured, key, val string) error {
labels := target.GetLabels()
if labels == nil {
labels = make(map[string]string)
}
key := labelKey()
labels[key] = val
target.SetLabels(labels)
if !legacyLabeling {
if key != common.LabelKeyLegacyApplicationName {
// we no longer label the pod template sub resources in v0.11
return nil
}
@@ -295,7 +282,7 @@ func filterAPIResources(config *rest.Config, filter filterFunc, namespace string
continue
}
for _, apiResource := range apiResourcesList.APIResources {
if gv.Group == "" && apiResource.Kind == "Event" || isObsoleteExtensionsGroupKind(gv.Group, apiResource.Kind) {
if _, ok := isObsoleteExtensionsGroupKind(gv.Group, apiResource.Kind); ok || gv.Group == "" && apiResource.Kind == "Event" {
continue
}
if filter(apiResourcesList.GroupVersion, &apiResource) {

View File

@@ -102,7 +102,7 @@ func TestSetLabels(t *testing.T) {
err := yaml.Unmarshal([]byte(yamlStr), &obj)
assert.Nil(t, err)
err = SetAppInstanceLabel(&obj, "my-app")
err = SetAppInstanceLabel(&obj, common.LabelKeyAppInstance, "my-app")
assert.Nil(t, err)
manifestBytes, err := json.MarshalIndent(obj.Object, "", " ")
@@ -126,14 +126,12 @@ func TestSetLabels(t *testing.T) {
}
func TestSetLegacyLabels(t *testing.T) {
legacyLabeling = true
defer func() { legacyLabeling = false }()
for _, yamlStr := range []string{depWithoutSelector, depWithSelector} {
var obj unstructured.Unstructured
err := yaml.Unmarshal([]byte(yamlStr), &obj)
assert.Nil(t, err)
err = SetAppInstanceLabel(&obj, "my-app")
err = SetAppInstanceLabel(&obj, common.LabelKeyLegacyApplicationName, "my-app")
assert.Nil(t, err)
manifestBytes, err := json.MarshalIndent(obj.Object, "", " ")
@@ -152,15 +150,12 @@ func TestSetLegacyLabels(t *testing.T) {
}
func TestSetLegacyJobLabel(t *testing.T) {
legacyLabeling = true
defer func() { legacyLabeling = false }()
yamlBytes, err := ioutil.ReadFile("testdata/job.yaml")
assert.Nil(t, err)
var obj unstructured.Unstructured
err = yaml.Unmarshal(yamlBytes, &obj)
assert.Nil(t, err)
err = SetAppInstanceLabel(&obj, "my-app")
err = SetAppInstanceLabel(&obj, common.LabelKeyLegacyApplicationName, "my-app")
assert.Nil(t, err)
manifestBytes, err := json.MarshalIndent(obj.Object, "", " ")
@@ -186,7 +181,7 @@ func TestSetSvcLabel(t *testing.T) {
var obj unstructured.Unstructured
err = yaml.Unmarshal(yamlBytes, &obj)
assert.Nil(t, err)
err = SetAppInstanceLabel(&obj, "my-app")
err = SetAppInstanceLabel(&obj, common.LabelKeyAppInstance, "my-app")
assert.Nil(t, err)
manifestBytes, err := json.MarshalIndent(obj.Object, "", " ")

View File

@@ -3,6 +3,8 @@ package kubetest
import (
"context"
"k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/watch"
@@ -15,9 +17,14 @@ type KubectlOutput struct {
}
type MockKubectlCmd struct {
Resources []*unstructured.Unstructured
Commands map[string]KubectlOutput
Events chan watch.Event
APIResources []*v1.APIResourceList
Resources []*unstructured.Unstructured
Commands map[string]KubectlOutput
Events chan watch.Event
}
func (k MockKubectlCmd) GetAPIResources(config *rest.Config) ([]*v1.APIResourceList, error) {
return k.APIResources, nil
}
func (k MockKubectlCmd) GetResources(config *rest.Config, namespace string) ([]*unstructured.Unstructured, error) {

View File

@@ -28,22 +28,11 @@ type kustomize struct {
// KustomizeBuildOpts are options to a `kustomize build` command
type KustomizeBuildOpts struct {
// Namespace will run `kustomize edit set namespace` during manifest generation
Namespace string
// NamePrefix will run `kustomize edit set nameprefix` during manifest generation
NamePrefix string
}
func (k *kustomize) Build(opts KustomizeBuildOpts, overrides []*v1alpha1.ComponentParameter) ([]*unstructured.Unstructured, []*v1alpha1.ComponentParameter, error) {
if opts.Namespace != "" {
cmd := exec.Command("kustomize", "edit", "set", "namespace", opts.Namespace)
cmd.Dir = k.path
_, err := argoexec.RunCommandExt(cmd)
if err != nil {
return nil, nil, err
}
}
if opts.NamePrefix != "" {
cmd := exec.Command("kustomize", "edit", "set", "nameprefix", opts.NamePrefix)
cmd.Dir = k.path

View File

@@ -29,7 +29,6 @@ func TestKustomizeBuild(t *testing.T) {
namePrefix := "namePrefix-"
kustomize := NewKustomizeApp(appPath)
opts := KustomizeBuildOpts{
Namespace: "mynamespace",
NamePrefix: namePrefix,
}
objs, params, err := kustomize.Build(opts, []*v1alpha1.ComponentParameter{{
@@ -49,7 +48,6 @@ func TestKustomizeBuild(t *testing.T) {
case "Deployment":
assert.Equal(t, namePrefix+"nginx-deployment", obj.GetName())
}
assert.Equal(t, "mynamespace", obj.GetNamespace())
}
for _, param := range params {

View File

@@ -59,6 +59,8 @@ type ArgoCDSettings struct {
Repositories []RepoCredentials
// Repositories holds list of configured helm repositories
HelmRepositories []HelmRepoCredentials
// AppInstanceLabelKey is the configured application instance label key used to label apps. May be empty
AppInstanceLabelKey string
}
type OIDCConfig struct {
@@ -112,6 +114,8 @@ const (
settingsWebhookGitLabSecretKey = "webhook.gitlab.secret"
// settingsWebhookBitbucketUUID is the key for Bitbucket webhook UUID
settingsWebhookBitbucketUUIDKey = "webhook.bitbucket.uuid"
// settingsApplicationInstanceLabelKey is the key to configure injected app instance label key
settingsApplicationInstanceLabelKey = "application.instanceLabelKey"
)
// SettingsManager holds config info for a new manager with which to access Kubernetes ConfigMaps.
@@ -218,6 +222,7 @@ func (mgr *SettingsManager) updateSettingsFromConfigMap(settings *ArgoCDSettings
return err
}
}
settings.AppInstanceLabelKey = argoCDCM.Data[settingsApplicationInstanceLabelKey]
return nil
}
@@ -301,7 +306,6 @@ func (mgr *SettingsManager) SaveSettings(settings *ArgoCDSettings) error {
} else {
delete(argoCDCM.Data, settingsOIDCConfigKey)
}
if len(settings.Repositories) > 0 {
yamlStr, err := yaml.Marshal(settings.Repositories)
if err != nil {
@@ -311,7 +315,11 @@ func (mgr *SettingsManager) SaveSettings(settings *ArgoCDSettings) error {
} else {
delete(argoCDCM.Data, repositoriesKey)
}
if settings.AppInstanceLabelKey != "" {
argoCDCM.Data[settingsApplicationInstanceLabelKey] = settings.AppInstanceLabelKey
} else {
delete(argoCDCM.Data, settingsApplicationInstanceLabelKey)
}
if createCM {
_, err = mgr.clientset.CoreV1().ConfigMaps(mgr.namespace).Create(argoCDCM)
} else {
@@ -675,3 +683,10 @@ func ReplaceStringSecret(val string, secretValues map[string]string) string {
}
return secretVal
}
func (a *ArgoCDSettings) GetAppInstanceLabelKey() string {
if a.AppInstanceLabelKey == "" {
return common.LabelKeyAppInstance
}
return a.AppInstanceLabelKey
}

View File

@@ -6,6 +6,8 @@ import (
"regexp"
"strings"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
appclientset "github.com/argoproj/argo-cd/pkg/client/clientset/versioned"
"github.com/argoproj/argo-cd/util/argo"
"github.com/argoproj/argo-cd/util/settings"
@@ -132,7 +134,7 @@ func (a *ArgoCDWebhookHandler) HandleEvent(payload interface{}, header webhooks.
} else if targetRev != revision {
continue
}
_, err = argo.RefreshApp(appIf, app.ObjectMeta.Name)
_, err = argo.RefreshApp(appIf, app.ObjectMeta.Name, v1alpha1.RefreshTypeNormal)
if err != nil {
log.Warnf("Failed to refresh app '%s' for controller reprocessing: %v", app.ObjectMeta.Name, err)
continue