Compare commits

...

32 Commits

Author SHA1 Message Date
Alex Collins
3aaca0bbe8 Sets app status to unknown if there is an error. Closes #2577 (#2578) 2019-10-29 11:45:42 -07:00
Alexander Matyushentsev
85f62dff9e Update manifests to v1.2.5 2019-10-28 17:00:52 -07:00
Alexander Matyushentsev
97f08aaf4c Issue #2339 - Don't update 'status.reconciledAt' unless compared with latest git version (#2581) 2019-10-28 16:59:37 -07:00
Alex Collins
ad7a69a798 Adds flags for codegen and lint 2019-10-23 12:50:11 -07:00
Alex Collins
fc588538bc Increase test timeout to 10s as per master 2019-10-23 10:41:18 -07:00
Alexander Matyushentsev
675ae6a991 Issue #2185 - Manual sync don't trigger hooks (#2477) 2019-10-23 10:33:05 -07:00
Alex Collins
6cc0fd8b8c Increases lint deadline to 4m 2019-10-23 09:33:44 -07:00
Alexander Matyushentsev
26e1cf0438 Issue #2339 - Controller should compare with latest git revision if app has changed (#2543) 2019-10-22 15:28:23 -07:00
Alexander Matyushentsev
30d3fcb84a Unknown child app should not affect app health (#2544) 2019-10-22 15:28:17 -07:00
Alex Collins
3a3a7f5044 Update manifests to v1.2.4 2019-10-22 10:50:42 -07:00
Simon Behar
6c34dd828f Redact secrets in dex logs (#2538)
* Done

* Pre-commit

* Added test

* Pre-commit

* Goimports
2019-10-22 10:46:25 -07:00
Fred Dubois
de7003f530 Make argo-cd docker images openshift friendly (#2362)
In openshift clusters, the user id of your container can be arbitrary,
so you need to make the running images compatible with this behavior.

The problematic application for argo-cd was the repo server. When trying
to clone the repos it was getting the error "No user exists for uid
100083000" (100083000 was the random user id being injected by
openshift in my case). This was because the user 100083000 wasn't in the
/etc/passwd file.

The changes in this commit add a uid_entrypoint.sh script that, when the
container starts, modifies the /etc/passwd file to add an entry with the
current UID _only_ if the current UID isn't there.

References:
* Problematic behavior of ssh when user id isn't in the /etc/passwd file:
  https://unix.stackexchange.com/questions/524268/running-git-or-ssh-client-in-docker-as-user-no-user-exists-for-uid
* OpenShift guidelines on how to make your docker image runnable by
  arbitrary user ids:
  https://access.redhat.com/documentation/en-us/openshift_container_platform/3.11/html/creating_images/creating-images-guidelines#use-uid
2019-10-01 12:44:47 -07:00
Alexander Matyushentsev
8981903603 Update manifests to v1.2.3 2019-10-01 11:56:35 -07:00
Alexander Matyushentsev
509c567a40 Stop loggin /repository.RepositoryService/ValidateAccess parameters (#2387) 2019-10-01 11:55:00 -07:00
Alexander Matyushentsev
c722a71820 Add dest-server and dest-namespace field to reconciliation logs (#2388) 2019-10-01 11:54:55 -07:00
Alexander Matyushentsev
1aaf76f230 Update manifests to v1.2.2 2019-09-24 07:53:42 -07:00
Gregor Krmelj
71ad60e89f Add cache-control HTTP header to badge response (#2328)
Since we serve the badge as an image using HTTP GET, cache systems
(incl. GitHub's CDN - Fastly) like to cache the image thus the
badge becomes stale rendering it useless. Adding the appropriate
Cache-Control HTTP header we direct cache systems and web browsers
not to cache the contents of the response.
2019-09-24 07:45:06 -07:00
Gustav Paul
9c46f77bb1 util/localconfig: prefer HOME env var over os/user (#2326)
* util/localconfig: prefer HOME env var over os/user

The os/user package requires that the current user be in /etc/passwd.
That complicates executing the argocd command in a docker container
when the UID:GID of the executing user is overridden.

This is often done in order to have files generated inside a docker
container have their ownership set to match the uid/gid of the host
user.

For example,

```sh
docker run -ti -u "$(id -u "${USER}"):$(id -g "${USER}")" argocd:latest ...
```

* Makefile: use pinned dev image dependencies to run make lint
2019-09-24 07:21:52 -07:00
Alexander Matyushentsev
b6256aae9f Codegen (#2343) 2019-09-23 14:22:49 -07:00
Alexander Matyushentsev
f802190a24 Issue #2339 - Make sure controller uses latest git version if app reconciliation result expired (#2346) 2019-09-23 14:22:36 -07:00
Alexander Matyushentsev
e07c1edece Don't fix imports in auto-generated files (#2342) 2019-09-23 14:22:31 -07:00
Alex Collins
ed15da5271 Adds support for Github Enterprise URLs (#2344) 2019-09-23 13:24:52 -07:00
Jesse Suen
d34dbeac0d Add restart action to Deployment/StatefulSet/DaemonSet (#2300) 2019-09-13 02:57:25 -07:00
Alexander Matyushentsev
c4d3a54126 Merge branch 'release-1.2' of github.com:argoproj/argo-cd into release-1.2 2019-09-12 10:26:23 -07:00
Alex Collins
622671ece4 removed e2e tests that do not work and I should not have merged 2019-09-12 10:08:49 -07:00
Alex Collins
cf6a7abd30 ported FailOnErr from master 2019-09-12 09:56:43 -07:00
Alexander Matyushentsev
a6a394ba93 Update manifests to v1.2.1 2019-09-12 09:56:15 -07:00
Alex Collins
d315814020 Fixes issue diffing secrets (#2271)
# Conflicts:
#	test/e2e/app_management_test.go
2019-09-12 09:55:15 -07:00
Seiya Muramatsu
d46872d7e8 Add --self-heal flag to argocd cli (#2296) 2019-09-12 09:45:14 -07:00
Alexander Matyushentsev
ba7f0fcb47 Issue #2290 - Fix nil pointer dereference in application controller (#2291) 2019-09-12 09:44:59 -07:00
Alexander Matyushentsev
5fcfc22298 Issue #2022 - Support limiting number of concurrent kubectl fork/execs (#2264) 2019-09-12 09:43:35 -07:00
Mitz Amano
9e486dfad4 Fix degraded proxy support for http(s) git repository (#2243) (#2249) 2019-09-05 15:38:45 -07:00
77 changed files with 1586 additions and 368 deletions

View File

@@ -60,10 +60,8 @@ commands:
name: Install Go deps
command: |
set -x
go get github.com/golangci/golangci-lint/cmd/golangci-lint
go get github.com/jstemmer/go-junit-report
go get github.com/mattn/goreman
go get golang.org/x/tools/cmd/goimports
install_tools:
steps:
- run:
@@ -71,7 +69,14 @@ commands:
command: mkdir -p /tmp/dl
- restore_cache:
keys:
- dl-v6
- dl-v7
- run:
name: Install Kubectl v1.14.0
command: |
set -x
[ -e /tmp/dl/kubectl ] || curl -sLf -C - -o /tmp/dl/kubectl https://storage.googleapis.com/kubernetes-release/release/v1.14.0/bin/linux/amd64/kubectl
sudo cp /tmp/dl/kubectl /usr/local/bin/kubectl
sudo chmod +x /usr/local/bin/kubectl
- run:
name: Install Kubectx v0.6.3
command: |
@@ -119,7 +124,7 @@ commands:
sudo chmod +x /usr/local/go/bin/kustomize
kustomize version
- save_cache:
key: dl-v6
key: dl-v7
paths:
- /tmp/dl
save_go_cache:
@@ -208,14 +213,13 @@ jobs:
name: Create namespace
command: |
set -x
cat /etc/rancher/k3s/k3s.yaml | sed "s/localhost/`hostname`/" | tee ~/.kube/config
echo "127.0.0.1 `hostname`" | sudo tee -a /etc/hosts
kubectl create ns argocd-e2e
kubens argocd-e2e
# install the certificates (not 100% sure we need this)
sudo cp /var/lib/rancher/k3s/server/tls/token-ca.crt /usr/local/share/ca-certificates/k3s.crt
sudo update-ca-certificates
# create the kubecfg, again - not sure we need this
cat /etc/rancher/k3s/k3s.yaml | sed "s/localhost/`hostname`/" | tee ~/.kube/config
echo "127.0.0.1 `hostname`" | sudo tee -a /etc/hosts
- run:
name: Apply manifests
command: kustomize build test/manifests/base | kubectl apply -f -

View File

@@ -77,7 +77,9 @@ RUN echo 'deb http://deb.debian.org/debian stretch-backports main' >> /etc/apt/s
RUN groupadd -g 999 argocd && \
useradd -r -u 999 -g argocd argocd && \
mkdir -p /home/argocd && \
chown argocd:argocd /home/argocd && \
chown argocd:0 /home/argocd && \
chmod g=u /home/argocd && \
chmod g=u /etc/passwd && \
apt-get update && \
apt-get install -y git git-lfs && \
apt-get clean && \
@@ -89,6 +91,9 @@ COPY --from=builder /usr/local/bin/helm /usr/local/bin/helm
COPY --from=builder /usr/local/bin/kubectl /usr/local/bin/kubectl
COPY --from=builder /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY --from=builder /usr/local/bin/aws-iam-authenticator /usr/local/bin/aws-iam-authenticator
# script to add current (possibly arbitrary) user to /etc/passwd at runtime
# (if it's not already there, to be openshift friendly)
COPY uid_entrypoint.sh /usr/local/bin/uid_entrypoint.sh
# support for mounting configuration from a configmap
RUN mkdir -p /app/config/ssh && \

9
Gopkg.lock generated
View File

@@ -89,6 +89,14 @@
pruneopts = ""
revision = "3a771d992973f24aa725d07868b467d1ddfceafb"
[[projects]]
digest = "1:a6ee710e45210bafe11f2f28963571be2ac8809f9a7b675a6d2c02302a1ce1a9"
name = "github.com/bouk/monkey"
packages = ["."]
pruneopts = ""
revision = "5df1f207ff77e025801505ae4d903133a0b4353f"
version = "v1.0.0"
[[projects]]
digest = "1:e04162bd6a6d4950541bae744c968108e14913b1cebccf29f7650b573f44adb3"
name = "github.com/casbin/casbin"
@@ -1589,6 +1597,7 @@
"github.com/argoproj/pkg/errors",
"github.com/argoproj/pkg/exec",
"github.com/argoproj/pkg/time",
"github.com/bouk/monkey",
"github.com/casbin/casbin",
"github.com/casbin/casbin/model",
"github.com/casbin/casbin/persist",

View File

@@ -27,7 +27,9 @@ DEV_IMAGE?=false
LINT_GOGC?=off
LINT_CONCURRENCY?=8
# Set timeout for linter
LINT_DEADLINE?=1m0s
LINT_DEADLINE?=4m0s
CODEGEN=true
LINT=true
override LDFLAGS += \
-X ${PACKAGE}.version=${VERSION} \
@@ -74,7 +76,7 @@ codegen-local: protogen clientgen openapigen manifests-local
.PHONY: codegen
codegen: dev-tools-image
$(call run-in-dev-tool,make codegen-local)
@if [ "$(CODGEN)" = "true" ]; then $(call run-in-dev-tool,make codegen-local) ; fi
.PHONY: cli
cli: clean-debug
@@ -153,12 +155,16 @@ builder-image:
dep-ensure:
dep ensure -no-vendor
.PHONY: lint
lint:
.PHONY: lint-local
lint-local: build
# golangci-lint does not do a good job of formatting imports
goimports -local github.com/argoproj/argo-cd -w `find . ! -path './vendor/*' ! -path './pkg/client/*' -type f -name '*.go'`
goimports -local github.com/argoproj/argo-cd -w `find . ! -path './vendor/*' ! -path './pkg/client/*' ! -path '*.pb.go' ! -path '*.gw.go' -type f -name '*.go'`
GOGC=$(LINT_GOGC) golangci-lint run --fix --verbose --concurrency $(LINT_CONCURRENCY) --deadline $(LINT_DEADLINE)
.PHONY: lint
lint: dev-tools-image
@if [ "$(LINT)" = "true" ]; then $(call run-in-dev-tool,make lint-local LINT_CONCURRENCY=$(LINT_CONCURRENCY) LINT_DEADLINE=$(LINT_DEADLINE) LINT_GOGC=$(LINT_GOGC)); fi
.PHONY: build
build:
go build -v `go list ./... | grep -v 'resource_customizations\|test/e2e'`

View File

@@ -1 +1 @@
1.2.0
1.2.5

View File

@@ -46,6 +46,7 @@ func newCommand() *cobra.Command {
logLevel string
glogLevel int
metricsPort int
kubectlParallelismLimit int64
cacheSrc func() (*cache.Cache, error)
)
var command = cobra.Command{
@@ -84,7 +85,8 @@ func newCommand() *cobra.Command {
cache,
resyncDuration,
time.Duration(selfHealTimeoutSeconds)*time.Second,
metricsPort)
metricsPort,
kubectlParallelismLimit)
errors.CheckError(err)
log.Infof("Application Controller (version: %s) starting (namespace: %s)", common.GetVersion(), namespace)
@@ -109,6 +111,7 @@ func newCommand() *cobra.Command {
command.Flags().IntVar(&glogLevel, "gloglevel", 0, "Set the glog logging level")
command.Flags().IntVar(&metricsPort, "metrics-port", common.DefaultPortArgoCDMetrics, "Start metrics server on given port")
command.Flags().IntVar(&selfHealTimeoutSeconds, "self-heal-timeout-seconds", 5, "Specifies timeout between application self heal attempts")
command.Flags().Int64Var(&kubectlParallelismLimit, "kubectl-parallelism-limit", 0, "Number of allowed concurrent kubectl fork/execs.")
cacheSrc = cache.AddCacheFlagsToCmd(&command)
return &command

View File

@@ -8,6 +8,7 @@ import (
"io/ioutil"
"os"
"os/exec"
"regexp"
"syscall"
"github.com/ghodss/yaml"
@@ -108,7 +109,7 @@ func NewRunDexCommand() *cobra.Command {
} else {
err = ioutil.WriteFile("/tmp/dex.yaml", dexCfgBytes, 0644)
errors.CheckError(err)
log.Info(string(dexCfgBytes))
log.Info(redactor(string(dexCfgBytes)))
cmd = exec.Command("dex", "serve", "/tmp/dex.yaml")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
@@ -554,6 +555,11 @@ func NewClusterConfig() *cobra.Command {
return command
}
func redactor(dirtyString string) string {
dirtyString = regexp.MustCompile("(clientSecret: )[^ \n]*").ReplaceAllString(dirtyString, "$1********")
return regexp.MustCompile("(secret: )[^ \n]*").ReplaceAllString(dirtyString, "$1********")
}
func main() {
if err := NewCommand().Execute(); err != nil {
fmt.Println(err)

View File

@@ -0,0 +1,73 @@
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
var textToRedact = `
- config:
clientID: aabbccddeeff00112233
clientSecret: $dex.github.clientSecret
orgs:
- name: your-github-org
redirectURI: https://argocd.example.com/api/dex/callback
id: github
name: GitHub
type: github
grpc:
addr: 0.0.0.0:5557
issuer: https://argocd.example.com/api/dex
oauth2:
skipApprovalScreen: true
staticClients:
- id: argo-cd
name: Argo CD
redirectURIs:
- https://argocd.example.com/auth/callback
secret: Dis9M-GA11oTwZVQQWdDklPQw-sWXZkWJFyyEhMs
- id: argo-cd-cli
name: Argo CD CLI
public: true
redirectURIs:
- http://localhost
storage:
type: memory
web:
http: 0.0.0.0:5556`
var expectedRedaction = `
- config:
clientID: aabbccddeeff00112233
clientSecret: ********
orgs:
- name: your-github-org
redirectURI: https://argocd.example.com/api/dex/callback
id: github
name: GitHub
type: github
grpc:
addr: 0.0.0.0:5557
issuer: https://argocd.example.com/api/dex
oauth2:
skipApprovalScreen: true
staticClients:
- id: argo-cd
name: Argo CD
redirectURIs:
- https://argocd.example.com/auth/callback
secret: ********
- id: argo-cd-cli
name: Argo CD CLI
public: true
redirectURIs:
- http://localhost
storage:
type: memory
web:
http: 0.0.0.0:5556`
func TestSecretsRedactor(t *testing.T) {
assert.Equal(t, expectedRedaction, redactor(textToRedact))
}

View File

@@ -5,11 +5,8 @@ import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net/url"
"os"
"os/exec"
"path"
"path/filepath"
"reflect"
"regexp"
@@ -20,7 +17,6 @@ import (
"time"
"github.com/ghodss/yaml"
"github.com/google/shlex"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
@@ -444,6 +440,12 @@ func setAppOptions(flags *pflag.FlagSet, app *argoappv1.Application, appOpts *ap
}
app.Spec.SyncPolicy.Automated.Prune = appOpts.autoPrune
}
if flags.Changed("self-heal") {
if app.Spec.SyncPolicy == nil || app.Spec.SyncPolicy.Automated == nil {
log.Fatal("Cannot set --self-helf: application not configured with automatic sync")
}
app.Spec.SyncPolicy.Automated.SelfHeal = appOpts.selfHeal
}
return visited
}
@@ -544,6 +546,7 @@ type appOptions struct {
project string
syncPolicy string
autoPrune bool
selfHeal bool
namePrefix string
directoryRecurse bool
configManagementPlugin string
@@ -565,6 +568,7 @@ func addAppFlags(command *cobra.Command, opts *appOptions) {
command.Flags().StringVar(&opts.project, "project", "", "Application project name")
command.Flags().StringVar(&opts.syncPolicy, "sync-policy", "", "Set the sync policy (one of: automated, none)")
command.Flags().BoolVar(&opts.autoPrune, "auto-prune", false, "Set automatic pruning when sync is automated")
command.Flags().BoolVar(&opts.selfHeal, "self-heal", false, "Set self healing when sync is automated")
command.Flags().StringVar(&opts.namePrefix, "nameprefix", "", "Kustomize nameprefix")
command.Flags().BoolVar(&opts.directoryRecurse, "directory-recurse", false, "Recurse directory")
command.Flags().StringVar(&opts.configManagementPlugin, "config-management-plugin", "", "Config management plugin name")
@@ -871,7 +875,8 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
}
foundDiffs = true
printDiff(item.key.Name, target, live)
err = diff.PrintDiff(item.key.Name, target, live)
errors.CheckError(err)
}
}
if foundDiffs {
@@ -886,43 +891,6 @@ func NewApplicationDiffCommand(clientOpts *argocdclient.ClientOptions) *cobra.Co
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, 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 (

View File

@@ -12,6 +12,7 @@ import (
"time"
log "github.com/sirupsen/logrus"
"golang.org/x/sync/semaphore"
v1 "k8s.io/api/core/v1"
apierr "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -85,6 +86,7 @@ type ApplicationController struct {
refreshRequestedApps map[string]CompareWith
refreshRequestedAppsMutex *sync.Mutex
metricsServer *metrics.MetricsServer
kubectlSemaphore *semaphore.Weighted
}
type ApplicationControllerConfig struct {
@@ -103,6 +105,7 @@ func NewApplicationController(
appResyncPeriod time.Duration,
selfHealTimeout time.Duration,
metricsPort int,
kubectlParallelismLimit int64,
) (*ApplicationController, error) {
db := db.NewDB(namespace, settingsMgr, kubeClientset)
kubectlCmd := kube.KubectlCmd{}
@@ -123,7 +126,12 @@ func NewApplicationController(
settingsMgr: settingsMgr,
selfHealTimeout: selfHealTimeout,
}
if kubectlParallelismLimit > 0 {
ctrl.kubectlSemaphore = semaphore.NewWeighted(kubectlParallelismLimit)
}
kubectlCmd.OnKubectlRun = ctrl.onKubectlRun
appInformer, appLister := ctrl.newApplicationInformerAndLister()
projInformer := v1alpha1.NewAppProjectInformer(applicationClientset, namespace, appResyncPeriod, cache.Indexers{})
metricsAddr := fmt.Sprintf("0.0.0.0:%d", metricsPort)
ctrl.metricsServer = metrics.NewMetricsServer(metricsAddr, appLister, func() error {
@@ -141,6 +149,23 @@ func NewApplicationController(
return &ctrl, nil
}
func (ctrl *ApplicationController) onKubectlRun(command string) (util.Closer, error) {
ctrl.metricsServer.IncKubectlExec(command)
if ctrl.kubectlSemaphore != nil {
if err := ctrl.kubectlSemaphore.Acquire(context.Background(), 1); err != nil {
return nil, err
}
ctrl.metricsServer.IncKubectlExecPending(command)
}
return util.NewCloser(func() error {
if ctrl.kubectlSemaphore != nil {
ctrl.kubectlSemaphore.Release(1)
ctrl.metricsServer.DecKubectlExecPending(command)
}
return nil
}), nil
}
func isSelfReferencedApp(app *appv1.Application, ref v1.ObjectReference) bool {
gvk := ref.GroupVersionKind()
return ref.UID == app.UID &&
@@ -647,7 +672,13 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
defer func() {
reconcileDuration := time.Since(startTime)
ctrl.metricsServer.IncReconcile(origApp, reconcileDuration)
logCtx := log.WithFields(log.Fields{"application": origApp.Name, "time_ms": reconcileDuration.Seconds() * 1e3, "level": comparisonLevel})
logCtx := log.WithFields(log.Fields{
"application": origApp.Name,
"time_ms": reconcileDuration.Seconds() * 1e3,
"level": comparisonLevel,
"dest-server": origApp.Spec.Destination.Server,
"dest-namespace": origApp.Spec.Destination.Namespace,
})
logCtx.Info("Reconciliation completed")
}()
@@ -683,7 +714,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
}
var localManifests []string
if opState := app.Status.OperationState; opState != nil {
if opState := app.Status.OperationState; opState != nil && opState.Operation.Sync != nil {
localManifests = opState.Operation.Sync.Manifests
}
@@ -692,6 +723,7 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
revision = app.Status.Sync.Revision
}
observedAt := metav1.Now()
compareResult := ctrl.appStateManager.CompareAppState(app, revision, app.Spec.Source, refreshType == appv1.RefreshTypeHard, localManifests)
ctrl.normalizeApplication(origApp, app, compareResult.appSourceType)
@@ -710,8 +742,10 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
conditions = append(conditions, *syncErrCond)
}
app.Status.ObservedAt = &compareResult.reconciledAt
app.Status.ReconciledAt = &compareResult.reconciledAt
if app.Status.ReconciledAt == nil || comparisonLevel == CompareWithLatest {
app.Status.ReconciledAt = &observedAt
}
app.Status.ObservedAt = &observedAt
app.Status.Sync = *compareResult.syncStatus
app.Status.Health = *compareResult.healthStatus
app.Status.Resources = compareResult.resources
@@ -731,21 +765,22 @@ func (ctrl *ApplicationController) needRefreshAppStatus(app *appv1.Application,
compareWith := CompareWithLatest
refreshType := appv1.RefreshTypeNormal
expired := app.Status.ReconciledAt == nil || app.Status.ReconciledAt.Add(statusRefreshTimeout).Before(time.Now().UTC())
if requestedType, ok := app.IsRefreshRequested(); ok {
// user requested app refresh.
refreshType = requestedType
reason = fmt.Sprintf("%s refresh requested", refreshType)
} else if requested, level := ctrl.isRefreshRequested(app.Name); requested {
compareWith = level
reason = fmt.Sprintf("controller refresh requested")
} else if app.Status.Sync.Status == appv1.SyncStatusCodeUnknown && expired {
reason = "comparison status unknown"
} else if expired {
reason = fmt.Sprintf("comparison expired. reconciledAt: %v, expiry: %v", app.Status.ReconciledAt, statusRefreshTimeout)
} 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.destination differs"
} else if expired {
reason = fmt.Sprintf("comparison expired. reconciledAt: %v, expiry: %v", app.Status.ReconciledAt, statusRefreshTimeout)
} else if requested, level := ctrl.isRefreshRequested(app.Name); requested {
compareWith = level
reason = fmt.Sprintf("controller refresh requested")
}
if reason != "" {
logCtx.Infof("Refreshing app status (%s), level (%d)", reason, compareWith)
return true, refreshType, compareWith

View File

@@ -2,6 +2,7 @@ package controller
import (
"context"
"encoding/json"
"testing"
"time"
@@ -83,6 +84,7 @@ func newFakeController(data *fakeData) *ApplicationController {
time.Minute,
time.Minute,
common.DefaultPortArgoCDMetrics,
0,
)
if err != nil {
panic(err)
@@ -524,13 +526,107 @@ func TestNeedRefreshAppStatus(t *testing.T) {
assert.Equal(t, argoappv1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
// execute hard refresh if app has refresh annotation
app.Annotations = map[string]string{
common.AnnotationKeyRefresh: string(argoappv1.RefreshTypeHard),
{
// refresh app using the 'latest' level if comparison expired
app := app.DeepCopy()
ctrl.requestAppRefresh(app.Name, CompareWithRecent)
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Minute)
assert.True(t, needRefresh)
assert.Equal(t, argoappv1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
}
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, argoappv1.RefreshTypeHard, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
{
app := app.DeepCopy()
// execute hard refresh if app has refresh annotation
reconciledAt := metav1.NewTime(time.Now().UTC().Add(-1 * time.Hour))
app.Status.ReconciledAt = &reconciledAt
app.Annotations = map[string]string{
common.AnnotationKeyRefresh: string(argoappv1.RefreshTypeHard),
}
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, argoappv1.RefreshTypeHard, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
}
{
app := app.DeepCopy()
// ensure that CompareWithLatest level is used if application source has changed
ctrl.requestAppRefresh(app.Name, ComparisonWithNothing)
// sample app source change
app.Spec.Source.Helm = &argoappv1.ApplicationSourceHelm{
Parameters: []argoappv1.HelmParameter{{
Name: "foo",
Value: "bar",
}},
}
needRefresh, refreshType, compareWith = ctrl.needRefreshAppStatus(app, 1*time.Hour)
assert.True(t, needRefresh)
assert.Equal(t, argoappv1.RefreshTypeNormal, refreshType)
assert.Equal(t, CompareWithLatest, compareWith)
}
}
func TestUpdateReconciledAt(t *testing.T) {
app := newFakeApp()
reconciledAt := metav1.NewTime(time.Now().Add(-1 * time.Second))
app.Status = argoappv1.ApplicationStatus{ReconciledAt: &reconciledAt}
app.Status.Sync = argoappv1.SyncStatus{ComparedTo: argoappv1.ComparedTo{Source: app.Spec.Source, Destination: app.Spec.Destination}}
ctrl := newFakeController(&fakeData{
apps: []runtime.Object{app, &defaultProj},
manifestResponse: &apiclient.ManifestResponse{
Manifests: []string{},
Namespace: test.FakeDestNamespace,
Server: test.FakeClusterURL,
Revision: "abc123",
},
managedLiveObjs: make(map[kube.ResourceKey]*unstructured.Unstructured),
})
key, _ := cache.MetaNamespaceKeyFunc(app)
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
fakeAppCs.ReactionChain = nil
receivedPatch := map[string]interface{}{}
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
if patchAction, ok := action.(kubetesting.PatchAction); ok {
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
}
return true, nil, nil
})
t.Run("UpdatedOnFullReconciliation", func(t *testing.T) {
receivedPatch = map[string]interface{}{}
ctrl.requestAppRefresh(app.Name, CompareWithLatest)
ctrl.appRefreshQueue.Add(key)
ctrl.processAppRefreshQueueItem()
_, updated, err := unstructured.NestedString(receivedPatch, "status", "reconciledAt")
assert.NoError(t, err)
assert.True(t, updated)
_, updated, err = unstructured.NestedString(receivedPatch, "status", "observedAt")
assert.NoError(t, err)
assert.True(t, updated)
})
t.Run("NotUpdatedOnPartialReconciliation", func(t *testing.T) {
receivedPatch = map[string]interface{}{}
ctrl.appRefreshQueue.Add(key)
ctrl.requestAppRefresh(app.Name, CompareWithRecent)
ctrl.processAppRefreshQueueItem()
_, updated, err := unstructured.NestedString(receivedPatch, "status", "reconciledAt")
assert.NoError(t, err)
assert.False(t, updated)
_, updated, err = unstructured.NestedString(receivedPatch, "status", "observedAt")
assert.NoError(t, err)
assert.True(t, updated)
})
}

View File

@@ -18,9 +18,11 @@ import (
type MetricsServer struct {
*http.Server
syncCounter *prometheus.CounterVec
k8sRequestCounter *prometheus.CounterVec
reconcileHistogram *prometheus.HistogramVec
syncCounter *prometheus.CounterVec
k8sRequestCounter *prometheus.CounterVec
kubectlExecCounter *prometheus.CounterVec
kubectlExecPendingGauge *prometheus.GaugeVec
reconcileHistogram *prometheus.HistogramVec
}
const (
@@ -76,6 +78,16 @@ func NewMetricsServer(addr string, appLister applister.ApplicationLister, health
append(descAppDefaultLabels, "phase"),
)
appRegistry.MustRegister(syncCounter)
kubectlExecCounter := prometheus.NewCounterVec(prometheus.CounterOpts{
Name: "argocd_kubectl_exec_total",
Help: "Number of kubectl executions",
}, []string{"command"})
appRegistry.MustRegister(kubectlExecCounter)
kubectlExecPendingGauge := prometheus.NewGaugeVec(prometheus.GaugeOpts{
Name: "argocd_kubectl_exec_pending",
Help: "Number of pending kubectl executions",
}, []string{"command"})
appRegistry.MustRegister(kubectlExecPendingGauge)
k8sRequestCounter := prometheus.NewCounterVec(
prometheus.CounterOpts{
Name: "argocd_app_k8s_request_total",
@@ -102,9 +114,11 @@ func NewMetricsServer(addr string, appLister applister.ApplicationLister, health
Addr: addr,
Handler: mux,
},
syncCounter: syncCounter,
k8sRequestCounter: k8sRequestCounter,
reconcileHistogram: reconcileHistogram,
syncCounter: syncCounter,
k8sRequestCounter: k8sRequestCounter,
reconcileHistogram: reconcileHistogram,
kubectlExecCounter: kubectlExecCounter,
kubectlExecPendingGauge: kubectlExecPendingGauge,
}
}
@@ -126,6 +140,18 @@ func (m *MetricsServer) IncReconcile(app *argoappv1.Application, duration time.D
m.reconcileHistogram.WithLabelValues(app.Namespace, app.Name, app.Spec.GetProject()).Observe(duration.Seconds())
}
func (m *MetricsServer) IncKubectlExec(command string) {
m.kubectlExecCounter.WithLabelValues(command).Inc()
}
func (m *MetricsServer) IncKubectlExecPending(command string) {
m.kubectlExecPendingGauge.WithLabelValues(command).Inc()
}
func (m *MetricsServer) DecKubectlExecPending(command string) {
m.kubectlExecPendingGauge.WithLabelValues(command).Dec()
}
type appCollector struct {
store applister.ApplicationLister
}

View File

@@ -61,7 +61,6 @@ type AppStateManager interface {
}
type comparisonResult struct {
reconciledAt metav1.Time
syncStatus *v1alpha1.SyncStatus
healthStatus *v1alpha1.HealthStatus
resources []v1alpha1.ResourceStatus
@@ -255,13 +254,11 @@ func (m *appStateManager) getComparisonSettings(app *appv1.Application) (string,
// revision and supplied source. If revision or overrides are empty, then compares against
// revision and overrides in the app spec.
func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision string, source v1alpha1.ApplicationSource, noCache bool, localManifests []string) *comparisonResult {
reconciledAt := metav1.Now()
appLabelKey, resourceOverrides, diffNormalizer, err := m.getComparisonSettings(app)
// return unknown comparison result if basic comparison settings cannot be loaded
if err != nil {
return &comparisonResult{
reconciledAt: reconciledAt,
syncStatus: &v1alpha1.SyncStatus{
ComparedTo: appv1.ComparedTo{Source: source, Destination: app.Spec.Destination},
Status: appv1.SyncStatusCodeUnknown,
@@ -415,6 +412,10 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision st
} else {
resState.Status = v1alpha1.SyncStatusCodeSynced
}
// we can't say anything about the status if we were unable to get the target objects
if failedToLoadObjs {
resState.Status = v1alpha1.SyncStatusCodeUnknown
}
managedResources[i] = managedResource{
Name: resState.Name,
Namespace: resState.Namespace,
@@ -452,7 +453,6 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, revision st
}
compRes := comparisonResult{
reconciledAt: reconciledAt,
syncStatus: &syncStatus,
healthStatus: healthStatus,
resources: resourceSummaries,

View File

@@ -11,6 +11,10 @@ func CheckError(err error) {
}
}
func FailOnErr(_ interface{}, err error) {
// panics if there is an error.
// This returns the first value so you can use it if you cast it:
// text := FailOrErr(Foo)).(string)
func FailOnErr(v interface{}, err error) interface{} {
CheckError(err)
return v
}

View File

@@ -12,7 +12,7 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: v1.2.0
newTag: v1.2.5
- name: argoproj/argocd-ui
newName: argoproj/argocd-ui
newTag: v1.2.0
newTag: v1.2.5

View File

@@ -21,6 +21,7 @@ spec:
image: argoproj/argocd:latest
imagePullPolicy: Always
command:
- uid_entrypoint.sh
- argocd-repo-server
- --redis
- argocd-redis:6379

View File

@@ -1020,6 +1020,8 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
format: date-time
type: string
operationState:
@@ -1486,6 +1488,8 @@ spec:
- startedAt
type: object
reconciledAt:
description: ReconciledAt indicates when the application state was reconciled
using the latest git version
format: date-time
type: string
resources:

View File

@@ -18,7 +18,7 @@ bases:
images:
- name: argoproj/argocd
newName: argoproj/argocd
newTag: v1.2.0
newTag: v1.2.5
- name: argoproj/argocd-ui
newName: argoproj/argocd-ui
newTag: v1.2.0
newTag: v1.2.5

View File

@@ -23,6 +23,7 @@ spec:
containers:
- name: argocd-repo-server
command:
- uid_entrypoint.sh
- argocd-repo-server
- --sentinel
- argocd-redis-ha-announce-0:26379

View File

@@ -1021,6 +1021,8 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
format: date-time
type: string
operationState:
@@ -1487,6 +1489,8 @@ spec:
- startedAt
type: object
reconciledAt:
description: ReconciledAt indicates when the application state was reconciled
using the latest git version
format: date-time
type: string
resources:
@@ -2901,7 +2905,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2955,7 +2959,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -3001,6 +3005,7 @@ spec:
automountServiceAccountToken: false
containers:
- command:
- uid_entrypoint.sh
- argocd-repo-server
- --sentinel
- argocd-redis-ha-announce-0:26379
@@ -3010,7 +3015,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -3084,7 +3089,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -1021,6 +1021,8 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
format: date-time
type: string
operationState:
@@ -1487,6 +1489,8 @@ spec:
- startedAt
type: object
reconciledAt:
description: ReconciledAt indicates when the application state was reconciled
using the latest git version
format: date-time
type: string
resources:
@@ -2816,7 +2820,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2870,7 +2874,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2916,6 +2920,7 @@ spec:
automountServiceAccountToken: false
containers:
- command:
- uid_entrypoint.sh
- argocd-repo-server
- --sentinel
- argocd-redis-ha-announce-0:26379
@@ -2925,7 +2930,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2999,7 +3004,7 @@ spec:
- argocd-redis-ha-announce-2:26379
- --sentinelmaster
- argocd
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -1021,6 +1021,8 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
format: date-time
type: string
operationState:
@@ -1487,6 +1489,8 @@ spec:
- startedAt
type: object
reconciledAt:
description: ReconciledAt indicates when the application state was reconciled
using the latest git version
format: date-time
type: string
resources:
@@ -2665,7 +2669,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2719,7 +2723,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2779,10 +2783,11 @@ spec:
automountServiceAccountToken: false
containers:
- command:
- uid_entrypoint.sh
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2833,7 +2838,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -1021,6 +1021,8 @@ spec:
type: object
type: array
observedAt:
description: ObservedAt indicates when the application state was updated
without querying latest git state
format: date-time
type: string
operationState:
@@ -1487,6 +1489,8 @@ spec:
- startedAt
type: object
reconciledAt:
description: ReconciledAt indicates when the application state was reconciled
using the latest git version
format: date-time
type: string
resources:
@@ -2580,7 +2584,7 @@ spec:
- "20"
- --operation-processors
- "10"
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:
@@ -2634,7 +2638,7 @@ spec:
- cp
- /usr/local/bin/argocd-util
- /shared
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
name: copyutil
volumeMounts:
@@ -2694,10 +2698,11 @@ spec:
automountServiceAccountToken: false
containers:
- command:
- uid_entrypoint.sh
- argocd-repo-server
- --redis
- argocd-redis:6379
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
initialDelaySeconds: 5
@@ -2748,7 +2753,7 @@ spec:
- argocd-server
- --staticassets
- /shared/app
image: argoproj/argocd:v1.2.0
image: argoproj/argocd:v1.2.5
imagePullPolicy: Always
livenessProbe:
httpGet:

View File

@@ -36,6 +36,7 @@ import (
versionpkg "github.com/argoproj/argo-cd/pkg/apiclient/version"
"github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
argoappv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util"
grpc_util "github.com/argoproj/argo-cd/util/grpc"
"github.com/argoproj/argo-cd/util/localconfig"
oidcutil "github.com/argoproj/argo-cd/util/oidc"
@@ -387,7 +388,7 @@ func (c *client) newConn() (*grpc.ClientConn, io.Closer, error) {
}
conn, e := grpc_util.BlockingDial(context.Background(), network, serverAddr, creds, dialOpts...)
closers = append(closers, conn)
return conn, &inlineCloser{close: func() error {
return conn, util.NewCloser(func() error {
var firstErr error
for i := range closers {
err := closers[i].Close()
@@ -396,7 +397,7 @@ func (c *client) newConn() (*grpc.ClientConn, io.Closer, error) {
}
}
return firstErr
}}, e
}), e
}
func (c *client) tlsConfig() (*tls.Config, error) {

View File

@@ -43,14 +43,6 @@ func (noopCodec) String() string {
return "bytes"
}
type inlineCloser struct {
close func() error
}
func (c *inlineCloser) Close() error {
return c.close()
}
func toFrame(msg []byte) []byte {
frame := append([]byte{0, 0, 0, 0}, msg...)
binary.BigEndian.PutUint32(frame, uint32(len(msg)))
@@ -185,7 +177,7 @@ func (c *client) useGRPCProxy() (net.Addr, io.Closer, error) {
}
c.proxyUsersCount = c.proxyUsersCount + 1
return c.proxyListener.Addr(), &inlineCloser{close: func() error {
return c.proxyListener.Addr(), util.NewCloser(func() error {
c.proxyMutex.Lock()
defer c.proxyMutex.Unlock()
c.proxyUsersCount = c.proxyUsersCount - 1
@@ -196,5 +188,5 @@ func (c *client) useGRPCProxy() (net.Addr, io.Closer, error) {
return nil
}
return nil
}}, nil
}), nil
}

View File

@@ -33,7 +33,7 @@ const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
func (m *AWSAuthConfig) Reset() { *m = AWSAuthConfig{} }
func (*AWSAuthConfig) ProtoMessage() {}
func (*AWSAuthConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{0}
return fileDescriptor_generated_438690de2f872566, []int{0}
}
func (m *AWSAuthConfig) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -61,7 +61,7 @@ var xxx_messageInfo_AWSAuthConfig proto.InternalMessageInfo
func (m *AppProject) Reset() { *m = AppProject{} }
func (*AppProject) ProtoMessage() {}
func (*AppProject) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{1}
return fileDescriptor_generated_438690de2f872566, []int{1}
}
func (m *AppProject) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -89,7 +89,7 @@ var xxx_messageInfo_AppProject proto.InternalMessageInfo
func (m *AppProjectList) Reset() { *m = AppProjectList{} }
func (*AppProjectList) ProtoMessage() {}
func (*AppProjectList) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{2}
return fileDescriptor_generated_438690de2f872566, []int{2}
}
func (m *AppProjectList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -117,7 +117,7 @@ var xxx_messageInfo_AppProjectList proto.InternalMessageInfo
func (m *AppProjectSpec) Reset() { *m = AppProjectSpec{} }
func (*AppProjectSpec) ProtoMessage() {}
func (*AppProjectSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{3}
return fileDescriptor_generated_438690de2f872566, []int{3}
}
func (m *AppProjectSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -145,7 +145,7 @@ var xxx_messageInfo_AppProjectSpec proto.InternalMessageInfo
func (m *Application) Reset() { *m = Application{} }
func (*Application) ProtoMessage() {}
func (*Application) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{4}
return fileDescriptor_generated_438690de2f872566, []int{4}
}
func (m *Application) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -173,7 +173,7 @@ var xxx_messageInfo_Application proto.InternalMessageInfo
func (m *ApplicationCondition) Reset() { *m = ApplicationCondition{} }
func (*ApplicationCondition) ProtoMessage() {}
func (*ApplicationCondition) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{5}
return fileDescriptor_generated_438690de2f872566, []int{5}
}
func (m *ApplicationCondition) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -201,7 +201,7 @@ var xxx_messageInfo_ApplicationCondition proto.InternalMessageInfo
func (m *ApplicationDestination) Reset() { *m = ApplicationDestination{} }
func (*ApplicationDestination) ProtoMessage() {}
func (*ApplicationDestination) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{6}
return fileDescriptor_generated_438690de2f872566, []int{6}
}
func (m *ApplicationDestination) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -229,7 +229,7 @@ var xxx_messageInfo_ApplicationDestination proto.InternalMessageInfo
func (m *ApplicationList) Reset() { *m = ApplicationList{} }
func (*ApplicationList) ProtoMessage() {}
func (*ApplicationList) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{7}
return fileDescriptor_generated_438690de2f872566, []int{7}
}
func (m *ApplicationList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -257,7 +257,7 @@ var xxx_messageInfo_ApplicationList proto.InternalMessageInfo
func (m *ApplicationSource) Reset() { *m = ApplicationSource{} }
func (*ApplicationSource) ProtoMessage() {}
func (*ApplicationSource) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{8}
return fileDescriptor_generated_438690de2f872566, []int{8}
}
func (m *ApplicationSource) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -285,7 +285,7 @@ var xxx_messageInfo_ApplicationSource proto.InternalMessageInfo
func (m *ApplicationSourceDirectory) Reset() { *m = ApplicationSourceDirectory{} }
func (*ApplicationSourceDirectory) ProtoMessage() {}
func (*ApplicationSourceDirectory) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{9}
return fileDescriptor_generated_438690de2f872566, []int{9}
}
func (m *ApplicationSourceDirectory) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -313,7 +313,7 @@ var xxx_messageInfo_ApplicationSourceDirectory proto.InternalMessageInfo
func (m *ApplicationSourceHelm) Reset() { *m = ApplicationSourceHelm{} }
func (*ApplicationSourceHelm) ProtoMessage() {}
func (*ApplicationSourceHelm) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{10}
return fileDescriptor_generated_438690de2f872566, []int{10}
}
func (m *ApplicationSourceHelm) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -341,7 +341,7 @@ var xxx_messageInfo_ApplicationSourceHelm proto.InternalMessageInfo
func (m *ApplicationSourceJsonnet) Reset() { *m = ApplicationSourceJsonnet{} }
func (*ApplicationSourceJsonnet) ProtoMessage() {}
func (*ApplicationSourceJsonnet) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{11}
return fileDescriptor_generated_438690de2f872566, []int{11}
}
func (m *ApplicationSourceJsonnet) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -369,7 +369,7 @@ var xxx_messageInfo_ApplicationSourceJsonnet proto.InternalMessageInfo
func (m *ApplicationSourceKsonnet) Reset() { *m = ApplicationSourceKsonnet{} }
func (*ApplicationSourceKsonnet) ProtoMessage() {}
func (*ApplicationSourceKsonnet) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{12}
return fileDescriptor_generated_438690de2f872566, []int{12}
}
func (m *ApplicationSourceKsonnet) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -397,7 +397,7 @@ var xxx_messageInfo_ApplicationSourceKsonnet proto.InternalMessageInfo
func (m *ApplicationSourceKustomize) Reset() { *m = ApplicationSourceKustomize{} }
func (*ApplicationSourceKustomize) ProtoMessage() {}
func (*ApplicationSourceKustomize) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{13}
return fileDescriptor_generated_438690de2f872566, []int{13}
}
func (m *ApplicationSourceKustomize) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -425,7 +425,7 @@ var xxx_messageInfo_ApplicationSourceKustomize proto.InternalMessageInfo
func (m *ApplicationSourcePlugin) Reset() { *m = ApplicationSourcePlugin{} }
func (*ApplicationSourcePlugin) ProtoMessage() {}
func (*ApplicationSourcePlugin) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{14}
return fileDescriptor_generated_438690de2f872566, []int{14}
}
func (m *ApplicationSourcePlugin) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -453,7 +453,7 @@ var xxx_messageInfo_ApplicationSourcePlugin proto.InternalMessageInfo
func (m *ApplicationSpec) Reset() { *m = ApplicationSpec{} }
func (*ApplicationSpec) ProtoMessage() {}
func (*ApplicationSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{15}
return fileDescriptor_generated_438690de2f872566, []int{15}
}
func (m *ApplicationSpec) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -481,7 +481,7 @@ var xxx_messageInfo_ApplicationSpec proto.InternalMessageInfo
func (m *ApplicationStatus) Reset() { *m = ApplicationStatus{} }
func (*ApplicationStatus) ProtoMessage() {}
func (*ApplicationStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{16}
return fileDescriptor_generated_438690de2f872566, []int{16}
}
func (m *ApplicationStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -509,7 +509,7 @@ var xxx_messageInfo_ApplicationStatus proto.InternalMessageInfo
func (m *ApplicationSummary) Reset() { *m = ApplicationSummary{} }
func (*ApplicationSummary) ProtoMessage() {}
func (*ApplicationSummary) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{17}
return fileDescriptor_generated_438690de2f872566, []int{17}
}
func (m *ApplicationSummary) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -537,7 +537,7 @@ var xxx_messageInfo_ApplicationSummary proto.InternalMessageInfo
func (m *ApplicationTree) Reset() { *m = ApplicationTree{} }
func (*ApplicationTree) ProtoMessage() {}
func (*ApplicationTree) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{18}
return fileDescriptor_generated_438690de2f872566, []int{18}
}
func (m *ApplicationTree) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -565,7 +565,7 @@ var xxx_messageInfo_ApplicationTree proto.InternalMessageInfo
func (m *ApplicationWatchEvent) Reset() { *m = ApplicationWatchEvent{} }
func (*ApplicationWatchEvent) ProtoMessage() {}
func (*ApplicationWatchEvent) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{19}
return fileDescriptor_generated_438690de2f872566, []int{19}
}
func (m *ApplicationWatchEvent) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -593,7 +593,7 @@ var xxx_messageInfo_ApplicationWatchEvent proto.InternalMessageInfo
func (m *Cluster) Reset() { *m = Cluster{} }
func (*Cluster) ProtoMessage() {}
func (*Cluster) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{20}
return fileDescriptor_generated_438690de2f872566, []int{20}
}
func (m *Cluster) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -621,7 +621,7 @@ var xxx_messageInfo_Cluster proto.InternalMessageInfo
func (m *ClusterConfig) Reset() { *m = ClusterConfig{} }
func (*ClusterConfig) ProtoMessage() {}
func (*ClusterConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{21}
return fileDescriptor_generated_438690de2f872566, []int{21}
}
func (m *ClusterConfig) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -649,7 +649,7 @@ var xxx_messageInfo_ClusterConfig proto.InternalMessageInfo
func (m *ClusterList) Reset() { *m = ClusterList{} }
func (*ClusterList) ProtoMessage() {}
func (*ClusterList) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{22}
return fileDescriptor_generated_438690de2f872566, []int{22}
}
func (m *ClusterList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -677,7 +677,7 @@ var xxx_messageInfo_ClusterList proto.InternalMessageInfo
func (m *Command) Reset() { *m = Command{} }
func (*Command) ProtoMessage() {}
func (*Command) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{23}
return fileDescriptor_generated_438690de2f872566, []int{23}
}
func (m *Command) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -705,7 +705,7 @@ var xxx_messageInfo_Command proto.InternalMessageInfo
func (m *ComparedTo) Reset() { *m = ComparedTo{} }
func (*ComparedTo) ProtoMessage() {}
func (*ComparedTo) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{24}
return fileDescriptor_generated_438690de2f872566, []int{24}
}
func (m *ComparedTo) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -733,7 +733,7 @@ var xxx_messageInfo_ComparedTo proto.InternalMessageInfo
func (m *ComponentParameter) Reset() { *m = ComponentParameter{} }
func (*ComponentParameter) ProtoMessage() {}
func (*ComponentParameter) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{25}
return fileDescriptor_generated_438690de2f872566, []int{25}
}
func (m *ComponentParameter) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -761,7 +761,7 @@ var xxx_messageInfo_ComponentParameter proto.InternalMessageInfo
func (m *ConfigManagementPlugin) Reset() { *m = ConfigManagementPlugin{} }
func (*ConfigManagementPlugin) ProtoMessage() {}
func (*ConfigManagementPlugin) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{26}
return fileDescriptor_generated_438690de2f872566, []int{26}
}
func (m *ConfigManagementPlugin) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -789,7 +789,7 @@ var xxx_messageInfo_ConfigManagementPlugin proto.InternalMessageInfo
func (m *ConnectionState) Reset() { *m = ConnectionState{} }
func (*ConnectionState) ProtoMessage() {}
func (*ConnectionState) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{27}
return fileDescriptor_generated_438690de2f872566, []int{27}
}
func (m *ConnectionState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -817,7 +817,7 @@ var xxx_messageInfo_ConnectionState proto.InternalMessageInfo
func (m *EnvEntry) Reset() { *m = EnvEntry{} }
func (*EnvEntry) ProtoMessage() {}
func (*EnvEntry) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{28}
return fileDescriptor_generated_438690de2f872566, []int{28}
}
func (m *EnvEntry) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -845,7 +845,7 @@ var xxx_messageInfo_EnvEntry proto.InternalMessageInfo
func (m *HealthStatus) Reset() { *m = HealthStatus{} }
func (*HealthStatus) ProtoMessage() {}
func (*HealthStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{29}
return fileDescriptor_generated_438690de2f872566, []int{29}
}
func (m *HealthStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -873,7 +873,7 @@ var xxx_messageInfo_HealthStatus proto.InternalMessageInfo
func (m *HelmParameter) Reset() { *m = HelmParameter{} }
func (*HelmParameter) ProtoMessage() {}
func (*HelmParameter) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{30}
return fileDescriptor_generated_438690de2f872566, []int{30}
}
func (m *HelmParameter) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -901,7 +901,7 @@ var xxx_messageInfo_HelmParameter proto.InternalMessageInfo
func (m *HelmRepository) Reset() { *m = HelmRepository{} }
func (*HelmRepository) ProtoMessage() {}
func (*HelmRepository) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{31}
return fileDescriptor_generated_438690de2f872566, []int{31}
}
func (m *HelmRepository) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -929,7 +929,7 @@ var xxx_messageInfo_HelmRepository proto.InternalMessageInfo
func (m *Info) Reset() { *m = Info{} }
func (*Info) ProtoMessage() {}
func (*Info) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{32}
return fileDescriptor_generated_438690de2f872566, []int{32}
}
func (m *Info) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -957,7 +957,7 @@ var xxx_messageInfo_Info proto.InternalMessageInfo
func (m *InfoItem) Reset() { *m = InfoItem{} }
func (*InfoItem) ProtoMessage() {}
func (*InfoItem) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{33}
return fileDescriptor_generated_438690de2f872566, []int{33}
}
func (m *InfoItem) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -985,7 +985,7 @@ var xxx_messageInfo_InfoItem proto.InternalMessageInfo
func (m *JWTToken) Reset() { *m = JWTToken{} }
func (*JWTToken) ProtoMessage() {}
func (*JWTToken) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{34}
return fileDescriptor_generated_438690de2f872566, []int{34}
}
func (m *JWTToken) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1013,7 +1013,7 @@ var xxx_messageInfo_JWTToken proto.InternalMessageInfo
func (m *JsonnetVar) Reset() { *m = JsonnetVar{} }
func (*JsonnetVar) ProtoMessage() {}
func (*JsonnetVar) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{35}
return fileDescriptor_generated_438690de2f872566, []int{35}
}
func (m *JsonnetVar) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1041,7 +1041,7 @@ var xxx_messageInfo_JsonnetVar proto.InternalMessageInfo
func (m *KsonnetParameter) Reset() { *m = KsonnetParameter{} }
func (*KsonnetParameter) ProtoMessage() {}
func (*KsonnetParameter) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{36}
return fileDescriptor_generated_438690de2f872566, []int{36}
}
func (m *KsonnetParameter) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1069,7 +1069,7 @@ var xxx_messageInfo_KsonnetParameter proto.InternalMessageInfo
func (m *KustomizeOptions) Reset() { *m = KustomizeOptions{} }
func (*KustomizeOptions) ProtoMessage() {}
func (*KustomizeOptions) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{37}
return fileDescriptor_generated_438690de2f872566, []int{37}
}
func (m *KustomizeOptions) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1097,7 +1097,7 @@ var xxx_messageInfo_KustomizeOptions proto.InternalMessageInfo
func (m *Operation) Reset() { *m = Operation{} }
func (*Operation) ProtoMessage() {}
func (*Operation) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{38}
return fileDescriptor_generated_438690de2f872566, []int{38}
}
func (m *Operation) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1125,7 +1125,7 @@ var xxx_messageInfo_Operation proto.InternalMessageInfo
func (m *OperationState) Reset() { *m = OperationState{} }
func (*OperationState) ProtoMessage() {}
func (*OperationState) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{39}
return fileDescriptor_generated_438690de2f872566, []int{39}
}
func (m *OperationState) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1153,7 +1153,7 @@ var xxx_messageInfo_OperationState proto.InternalMessageInfo
func (m *ProjectRole) Reset() { *m = ProjectRole{} }
func (*ProjectRole) ProtoMessage() {}
func (*ProjectRole) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{40}
return fileDescriptor_generated_438690de2f872566, []int{40}
}
func (m *ProjectRole) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1181,7 +1181,7 @@ var xxx_messageInfo_ProjectRole proto.InternalMessageInfo
func (m *Repository) Reset() { *m = Repository{} }
func (*Repository) ProtoMessage() {}
func (*Repository) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{41}
return fileDescriptor_generated_438690de2f872566, []int{41}
}
func (m *Repository) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1209,7 +1209,7 @@ var xxx_messageInfo_Repository proto.InternalMessageInfo
func (m *RepositoryCertificate) Reset() { *m = RepositoryCertificate{} }
func (*RepositoryCertificate) ProtoMessage() {}
func (*RepositoryCertificate) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{42}
return fileDescriptor_generated_438690de2f872566, []int{42}
}
func (m *RepositoryCertificate) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1237,7 +1237,7 @@ var xxx_messageInfo_RepositoryCertificate proto.InternalMessageInfo
func (m *RepositoryCertificateList) Reset() { *m = RepositoryCertificateList{} }
func (*RepositoryCertificateList) ProtoMessage() {}
func (*RepositoryCertificateList) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{43}
return fileDescriptor_generated_438690de2f872566, []int{43}
}
func (m *RepositoryCertificateList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1265,7 +1265,7 @@ var xxx_messageInfo_RepositoryCertificateList proto.InternalMessageInfo
func (m *RepositoryList) Reset() { *m = RepositoryList{} }
func (*RepositoryList) ProtoMessage() {}
func (*RepositoryList) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{44}
return fileDescriptor_generated_438690de2f872566, []int{44}
}
func (m *RepositoryList) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1293,7 +1293,7 @@ var xxx_messageInfo_RepositoryList proto.InternalMessageInfo
func (m *ResourceAction) Reset() { *m = ResourceAction{} }
func (*ResourceAction) ProtoMessage() {}
func (*ResourceAction) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{45}
return fileDescriptor_generated_438690de2f872566, []int{45}
}
func (m *ResourceAction) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1321,7 +1321,7 @@ var xxx_messageInfo_ResourceAction proto.InternalMessageInfo
func (m *ResourceActionDefinition) Reset() { *m = ResourceActionDefinition{} }
func (*ResourceActionDefinition) ProtoMessage() {}
func (*ResourceActionDefinition) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{46}
return fileDescriptor_generated_438690de2f872566, []int{46}
}
func (m *ResourceActionDefinition) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1349,7 +1349,7 @@ var xxx_messageInfo_ResourceActionDefinition proto.InternalMessageInfo
func (m *ResourceActionParam) Reset() { *m = ResourceActionParam{} }
func (*ResourceActionParam) ProtoMessage() {}
func (*ResourceActionParam) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{47}
return fileDescriptor_generated_438690de2f872566, []int{47}
}
func (m *ResourceActionParam) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1377,7 +1377,7 @@ var xxx_messageInfo_ResourceActionParam proto.InternalMessageInfo
func (m *ResourceActions) Reset() { *m = ResourceActions{} }
func (*ResourceActions) ProtoMessage() {}
func (*ResourceActions) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{48}
return fileDescriptor_generated_438690de2f872566, []int{48}
}
func (m *ResourceActions) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1405,7 +1405,7 @@ var xxx_messageInfo_ResourceActions proto.InternalMessageInfo
func (m *ResourceDiff) Reset() { *m = ResourceDiff{} }
func (*ResourceDiff) ProtoMessage() {}
func (*ResourceDiff) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{49}
return fileDescriptor_generated_438690de2f872566, []int{49}
}
func (m *ResourceDiff) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1433,7 +1433,7 @@ var xxx_messageInfo_ResourceDiff proto.InternalMessageInfo
func (m *ResourceIgnoreDifferences) Reset() { *m = ResourceIgnoreDifferences{} }
func (*ResourceIgnoreDifferences) ProtoMessage() {}
func (*ResourceIgnoreDifferences) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{50}
return fileDescriptor_generated_438690de2f872566, []int{50}
}
func (m *ResourceIgnoreDifferences) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1461,7 +1461,7 @@ var xxx_messageInfo_ResourceIgnoreDifferences proto.InternalMessageInfo
func (m *ResourceNetworkingInfo) Reset() { *m = ResourceNetworkingInfo{} }
func (*ResourceNetworkingInfo) ProtoMessage() {}
func (*ResourceNetworkingInfo) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{51}
return fileDescriptor_generated_438690de2f872566, []int{51}
}
func (m *ResourceNetworkingInfo) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1489,7 +1489,7 @@ var xxx_messageInfo_ResourceNetworkingInfo proto.InternalMessageInfo
func (m *ResourceNode) Reset() { *m = ResourceNode{} }
func (*ResourceNode) ProtoMessage() {}
func (*ResourceNode) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{52}
return fileDescriptor_generated_438690de2f872566, []int{52}
}
func (m *ResourceNode) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1517,7 +1517,7 @@ var xxx_messageInfo_ResourceNode proto.InternalMessageInfo
func (m *ResourceOverride) Reset() { *m = ResourceOverride{} }
func (*ResourceOverride) ProtoMessage() {}
func (*ResourceOverride) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{53}
return fileDescriptor_generated_438690de2f872566, []int{53}
}
func (m *ResourceOverride) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1545,7 +1545,7 @@ var xxx_messageInfo_ResourceOverride proto.InternalMessageInfo
func (m *ResourceRef) Reset() { *m = ResourceRef{} }
func (*ResourceRef) ProtoMessage() {}
func (*ResourceRef) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{54}
return fileDescriptor_generated_438690de2f872566, []int{54}
}
func (m *ResourceRef) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1573,7 +1573,7 @@ var xxx_messageInfo_ResourceRef proto.InternalMessageInfo
func (m *ResourceResult) Reset() { *m = ResourceResult{} }
func (*ResourceResult) ProtoMessage() {}
func (*ResourceResult) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{55}
return fileDescriptor_generated_438690de2f872566, []int{55}
}
func (m *ResourceResult) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1601,7 +1601,7 @@ var xxx_messageInfo_ResourceResult proto.InternalMessageInfo
func (m *ResourceStatus) Reset() { *m = ResourceStatus{} }
func (*ResourceStatus) ProtoMessage() {}
func (*ResourceStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{56}
return fileDescriptor_generated_438690de2f872566, []int{56}
}
func (m *ResourceStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1629,7 +1629,7 @@ var xxx_messageInfo_ResourceStatus proto.InternalMessageInfo
func (m *RevisionHistory) Reset() { *m = RevisionHistory{} }
func (*RevisionHistory) ProtoMessage() {}
func (*RevisionHistory) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{57}
return fileDescriptor_generated_438690de2f872566, []int{57}
}
func (m *RevisionHistory) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1657,7 +1657,7 @@ var xxx_messageInfo_RevisionHistory proto.InternalMessageInfo
func (m *RevisionMetadata) Reset() { *m = RevisionMetadata{} }
func (*RevisionMetadata) ProtoMessage() {}
func (*RevisionMetadata) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{58}
return fileDescriptor_generated_438690de2f872566, []int{58}
}
func (m *RevisionMetadata) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1685,7 +1685,7 @@ var xxx_messageInfo_RevisionMetadata proto.InternalMessageInfo
func (m *SyncOperation) Reset() { *m = SyncOperation{} }
func (*SyncOperation) ProtoMessage() {}
func (*SyncOperation) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{59}
return fileDescriptor_generated_438690de2f872566, []int{59}
}
func (m *SyncOperation) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1713,7 +1713,7 @@ var xxx_messageInfo_SyncOperation proto.InternalMessageInfo
func (m *SyncOperationResource) Reset() { *m = SyncOperationResource{} }
func (*SyncOperationResource) ProtoMessage() {}
func (*SyncOperationResource) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{60}
return fileDescriptor_generated_438690de2f872566, []int{60}
}
func (m *SyncOperationResource) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1741,7 +1741,7 @@ var xxx_messageInfo_SyncOperationResource proto.InternalMessageInfo
func (m *SyncOperationResult) Reset() { *m = SyncOperationResult{} }
func (*SyncOperationResult) ProtoMessage() {}
func (*SyncOperationResult) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{61}
return fileDescriptor_generated_438690de2f872566, []int{61}
}
func (m *SyncOperationResult) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1769,7 +1769,7 @@ var xxx_messageInfo_SyncOperationResult proto.InternalMessageInfo
func (m *SyncPolicy) Reset() { *m = SyncPolicy{} }
func (*SyncPolicy) ProtoMessage() {}
func (*SyncPolicy) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{62}
return fileDescriptor_generated_438690de2f872566, []int{62}
}
func (m *SyncPolicy) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1797,7 +1797,7 @@ var xxx_messageInfo_SyncPolicy proto.InternalMessageInfo
func (m *SyncPolicyAutomated) Reset() { *m = SyncPolicyAutomated{} }
func (*SyncPolicyAutomated) ProtoMessage() {}
func (*SyncPolicyAutomated) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{63}
return fileDescriptor_generated_438690de2f872566, []int{63}
}
func (m *SyncPolicyAutomated) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1825,7 +1825,7 @@ var xxx_messageInfo_SyncPolicyAutomated proto.InternalMessageInfo
func (m *SyncStatus) Reset() { *m = SyncStatus{} }
func (*SyncStatus) ProtoMessage() {}
func (*SyncStatus) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{64}
return fileDescriptor_generated_438690de2f872566, []int{64}
}
func (m *SyncStatus) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1853,7 +1853,7 @@ var xxx_messageInfo_SyncStatus proto.InternalMessageInfo
func (m *SyncStrategy) Reset() { *m = SyncStrategy{} }
func (*SyncStrategy) ProtoMessage() {}
func (*SyncStrategy) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{65}
return fileDescriptor_generated_438690de2f872566, []int{65}
}
func (m *SyncStrategy) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1881,7 +1881,7 @@ var xxx_messageInfo_SyncStrategy proto.InternalMessageInfo
func (m *SyncStrategyApply) Reset() { *m = SyncStrategyApply{} }
func (*SyncStrategyApply) ProtoMessage() {}
func (*SyncStrategyApply) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{66}
return fileDescriptor_generated_438690de2f872566, []int{66}
}
func (m *SyncStrategyApply) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1909,7 +1909,7 @@ var xxx_messageInfo_SyncStrategyApply proto.InternalMessageInfo
func (m *SyncStrategyHook) Reset() { *m = SyncStrategyHook{} }
func (*SyncStrategyHook) ProtoMessage() {}
func (*SyncStrategyHook) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{67}
return fileDescriptor_generated_438690de2f872566, []int{67}
}
func (m *SyncStrategyHook) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -1937,7 +1937,7 @@ var xxx_messageInfo_SyncStrategyHook proto.InternalMessageInfo
func (m *TLSClientConfig) Reset() { *m = TLSClientConfig{} }
func (*TLSClientConfig) ProtoMessage() {}
func (*TLSClientConfig) Descriptor() ([]byte, []int) {
return fileDescriptor_generated_5166844f4e566460, []int{68}
return fileDescriptor_generated_438690de2f872566, []int{68}
}
func (m *TLSClientConfig) XXX_Unmarshal(b []byte) error {
return m.Unmarshal(b)
@@ -18109,10 +18109,10 @@ var (
)
func init() {
proto.RegisterFile("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto", fileDescriptor_generated_5166844f4e566460)
proto.RegisterFile("github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1/generated.proto", fileDescriptor_generated_438690de2f872566)
}
var fileDescriptor_generated_5166844f4e566460 = []byte{
var fileDescriptor_generated_438690de2f872566 = []byte{
// 4429 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe4, 0x3b, 0x4b, 0x8c, 0x1c, 0xc7,
0x75, 0xec, 0xf9, 0xef, 0xdb, 0x0f, 0xb9, 0x25, 0x51, 0x1e, 0x2f, 0x24, 0x2e, 0xd1, 0x44, 0x6c,

View File

@@ -224,10 +224,12 @@ message ApplicationStatus {
repeated ApplicationCondition conditions = 5;
// ReconciledAt indicates when the application state was reconciled using the latest git version
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time reconciledAt = 6;
optional OperationState operationState = 7;
// ObservedAt indicates when the application state was updated without querying latest git state
optional k8s.io.apimachinery.pkg.apis.meta.v1.Time observedAt = 8;
optional string sourceType = 9;

View File

@@ -861,7 +861,8 @@ func schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref common.Reference
},
"reconciledAt": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
Description: "ReconciledAt indicates when the application state was reconciled using the latest git version",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
"operationState": {
@@ -871,7 +872,8 @@ func schema_pkg_apis_application_v1alpha1_ApplicationStatus(ref common.Reference
},
"observedAt": {
SchemaProps: spec.SchemaProps{
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
Description: "ObservedAt indicates when the application state was updated without querying latest git state",
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Time"),
},
},
"sourceType": {

View File

@@ -288,16 +288,18 @@ type ApplicationDestination struct {
// ApplicationStatus contains information about application sync, health status
type ApplicationStatus struct {
Resources []ResourceStatus `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"`
Sync SyncStatus `json:"sync,omitempty" protobuf:"bytes,2,opt,name=sync"`
Health HealthStatus `json:"health,omitempty" protobuf:"bytes,3,opt,name=health"`
History []RevisionHistory `json:"history,omitempty" protobuf:"bytes,4,opt,name=history"`
Conditions []ApplicationCondition `json:"conditions,omitempty" protobuf:"bytes,5,opt,name=conditions"`
ReconciledAt *metav1.Time `json:"reconciledAt,omitempty" protobuf:"bytes,6,opt,name=reconciledAt"`
OperationState *OperationState `json:"operationState,omitempty" protobuf:"bytes,7,opt,name=operationState"`
ObservedAt *metav1.Time `json:"observedAt,omitempty" protobuf:"bytes,8,opt,name=observedAt"`
SourceType ApplicationSourceType `json:"sourceType,omitempty" protobuf:"bytes,9,opt,name=sourceType"`
Summary ApplicationSummary `json:"summary,omitempty" protobuf:"bytes,10,opt,name=summary"`
Resources []ResourceStatus `json:"resources,omitempty" protobuf:"bytes,1,opt,name=resources"`
Sync SyncStatus `json:"sync,omitempty" protobuf:"bytes,2,opt,name=sync"`
Health HealthStatus `json:"health,omitempty" protobuf:"bytes,3,opt,name=health"`
History []RevisionHistory `json:"history,omitempty" protobuf:"bytes,4,opt,name=history"`
Conditions []ApplicationCondition `json:"conditions,omitempty" protobuf:"bytes,5,opt,name=conditions"`
// ReconciledAt indicates when the application state was reconciled using the latest git version
ReconciledAt *metav1.Time `json:"reconciledAt,omitempty" protobuf:"bytes,6,opt,name=reconciledAt"`
OperationState *OperationState `json:"operationState,omitempty" protobuf:"bytes,7,opt,name=operationState"`
// ObservedAt indicates when the application state was updated without querying latest git state
ObservedAt *metav1.Time `json:"observedAt,omitempty" protobuf:"bytes,8,opt,name=observedAt"`
SourceType ApplicationSourceType `json:"sourceType,omitempty" protobuf:"bytes,9,opt,name=sourceType"`
Summary ApplicationSummary `json:"summary,omitempty" protobuf:"bytes,10,opt,name=summary"`
}
// Operation contains requested operation parameters.

View File

@@ -0,0 +1,4 @@
actionTests:
- action: restart
inputPath: testdata/daemonset.yaml
expectedOutputPath: testdata/daemonset-restarted.yaml

View File

@@ -0,0 +1,3 @@
actions = {}
actions["restart"] = {}
return actions

View File

@@ -0,0 +1,9 @@
local os = require("os")
if obj.spec.template.metadata == nil then
obj.spec.template.metadata = {}
end
if obj.spec.template.metadata.annotations == nil then
obj.spec.template.metadata.annotations = {}
end
obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
return obj

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
annotations:
deprecated.daemonset.template.generation: "3"
creationTimestamp: "2019-09-13T08:52:50Z"
generation: 3
labels:
app.kubernetes.io/instance: extensions
name: daemonset
namespace: statefulset
resourceVersion: "7472656"
selfLink: /apis/apps/v1/namespaces/statefulset/daemonsets/daemonset
uid: de04d075-d603-11e9-9e69-42010aa8005f
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
name: daemonset
template:
metadata:
annotations:
kubectl.kubernetes.io/restartedAt: "0001-01-01T00:00:00Z"
labels:
name: daemonset
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
status:
currentNumberScheduled: 4
desiredNumberScheduled: 4
numberAvailable: 4
numberMisscheduled: 0
numberReady: 4
observedGeneration: 3
updatedNumberScheduled: 4

View File

@@ -0,0 +1,48 @@
apiVersion: apps/v1
kind: DaemonSet
metadata:
annotations:
deprecated.daemonset.template.generation: "3"
creationTimestamp: "2019-09-13T08:52:50Z"
generation: 3
labels:
app.kubernetes.io/instance: extensions
name: daemonset
namespace: statefulset
resourceVersion: "7472656"
selfLink: /apis/apps/v1/namespaces/statefulset/daemonsets/daemonset
uid: de04d075-d603-11e9-9e69-42010aa8005f
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
name: daemonset
template:
metadata:
labels:
name: daemonset
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
maxUnavailable: 1
type: RollingUpdate
status:
currentNumberScheduled: 4
desiredNumberScheduled: 4
numberAvailable: 4
numberMisscheduled: 0
numberReady: 4
observedGeneration: 3
updatedNumberScheduled: 4

View File

@@ -0,0 +1,4 @@
actionTests:
- action: restart
inputPath: testdata/deployment.yaml
expectedOutputPath: testdata/deployment-restarted.yaml

View File

@@ -0,0 +1,3 @@
actions = {}
actions["restart"] = {}
return actions

View File

@@ -0,0 +1,9 @@
local os = require("os")
if obj.spec.template.metadata == nil then
obj.spec.template.metadata = {}
end
if obj.spec.template.metadata.annotations == nil then
obj.spec.template.metadata.annotations = {}
end
obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
return obj

View File

@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2019-09-12T01:33:53Z"
generation: 1
name: nginx-deploy
namespace: default
resourceVersion: "6897444"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deploy
uid: 61689d6d-d4fd-11e9-9e69-42010aa8005f
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
annotations:
kubectl.kubernetes.io/restartedAt: "0001-01-01T00:00:00Z"
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:33:53Z"
message: Deployment does not have minimum availability.
reason: MinimumReplicasUnavailable
status: "False"
type: Available
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:34:05Z"
message: ReplicaSet "nginx-deploy-9cb4784bd" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 2
replicas: 3
unavailableReplicas: 1
updatedReplicas: 3

View File

@@ -0,0 +1,61 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2019-09-12T01:33:53Z"
generation: 1
name: nginx-deploy
namespace: default
resourceVersion: "6897444"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deploy
uid: 61689d6d-d4fd-11e9-9e69-42010aa8005f
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:33:53Z"
message: Deployment does not have minimum availability.
reason: MinimumReplicasUnavailable
status: "False"
type: Available
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:34:05Z"
message: ReplicaSet "nginx-deploy-9cb4784bd" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 2
replicas: 3
unavailableReplicas: 1
updatedReplicas: 3

View File

@@ -0,0 +1,4 @@
actionTests:
- action: restart
inputPath: testdata/statefulset.yaml
expectedOutputPath: testdata/statefulset-restarted.yaml

View File

@@ -0,0 +1,3 @@
actions = {}
actions["restart"] = {}
return actions

View File

@@ -0,0 +1,9 @@
local os = require("os")
if obj.spec.template.metadata == nil then
obj.spec.template.metadata = {}
end
if obj.spec.template.metadata.annotations == nil then
obj.spec.template.metadata.annotations = {}
end
obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
return obj

View File

@@ -0,0 +1,52 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
creationTimestamp: "2019-09-13T08:52:54Z"
generation: 2
labels:
app.kubernetes.io/instance: extensions
name: statefulset
namespace: statefulset
resourceVersion: "7471813"
selfLink: /apis/apps/v1/namespaces/statefulset/statefulsets/statefulset
uid: dfe8fadf-d603-11e9-9e69-42010aa8005f
spec:
podManagementPolicy: OrderedReady
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: statefulset
serviceName: statefulset
template:
metadata:
labels:
app: statefulset
annotations:
kubectl.kubernetes.io/restartedAt: "0001-01-01T00:00:00Z"
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
status:
collisionCount: 0
currentReplicas: 3
currentRevision: statefulset-85b7f767c6
observedGeneration: 2
readyReplicas: 3
replicas: 3
updateRevision: statefulset-85b7f767c6
updatedReplicas: 3

View File

@@ -0,0 +1,50 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
creationTimestamp: "2019-09-13T08:52:54Z"
generation: 2
labels:
app.kubernetes.io/instance: extensions
name: statefulset
namespace: statefulset
resourceVersion: "7471813"
selfLink: /apis/apps/v1/namespaces/statefulset/statefulsets/statefulset
uid: dfe8fadf-d603-11e9-9e69-42010aa8005f
spec:
podManagementPolicy: OrderedReady
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: statefulset
serviceName: statefulset
template:
metadata:
labels:
app: statefulset
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
updateStrategy:
rollingUpdate:
partition: 0
type: RollingUpdate
status:
collisionCount: 0
currentReplicas: 3
currentRevision: statefulset-85b7f767c6
observedGeneration: 2
readyReplicas: 3
replicas: 3
updateRevision: statefulset-85b7f767c6
updatedReplicas: 3

View File

@@ -7,13 +7,13 @@ import (
"path/filepath"
"strings"
"testing"
"time"
"github.com/bouk/monkey"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
"github.com/yudai/gojsondiff/formatter"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/argoproj/argo-cd/errors"
appsv1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/util/diff"
"github.com/argoproj/argo-cd/util/lua"
@@ -47,14 +47,14 @@ func TestLuaResourceActionsScript(t *testing.T) {
if !strings.Contains(path, "action_test.yaml") {
return nil
}
errors.CheckError(err)
assert.NoError(t, err)
dir := filepath.Dir(path)
//TODO: Change to path
yamlBytes, err := ioutil.ReadFile(dir + "/action_test.yaml")
errors.CheckError(err)
assert.NoError(t, err)
var resourceTest ActionTestStructure
err = yaml.Unmarshal(yamlBytes, &resourceTest)
errors.CheckError(err)
assert.NoError(t, err)
for i := range resourceTest.DiscoveryTests {
test := resourceTest.DiscoveryTests[i]
testName := fmt.Sprintf("discovery/%s", test.InputPath)
@@ -64,9 +64,9 @@ func TestLuaResourceActionsScript(t *testing.T) {
}
obj := getObj(filepath.Join(dir, test.InputPath))
discoveryLua, err := vm.GetResourceActionDiscovery(obj)
errors.CheckError(err)
assert.NoError(t, err)
result, err := vm.ExecuteResourceActionDiscovery(obj, discoveryLua)
errors.CheckError(err)
assert.NoError(t, err)
assert.Equal(t, test.Result, result)
})
}
@@ -75,20 +75,28 @@ func TestLuaResourceActionsScript(t *testing.T) {
testName := fmt.Sprintf("actions/%s/%s", test.Action, test.InputPath)
t.Run(testName, func(t *testing.T) {
vm := lua.VM{
UseOpenLibs: true,
// Uncomment the following line if you need to use lua libraries debugging
// purposes. Otherwise, leave this false to ensure tests reflect the same
// privileges that API server has.
//UseOpenLibs: true,
}
obj := getObj(filepath.Join(dir, test.InputPath))
action, err := vm.GetResourceAction(obj, test.Action)
errors.CheckError(err)
assert.NoError(t, err)
// freeze time so that lua test has predictable time output (will return 0001-01-01T00:00:00Z)
patch := monkey.Patch(time.Now, func() time.Time { return time.Time{} })
result, err := vm.ExecuteResourceAction(obj, action.ActionLua)
errors.CheckError(err)
patch.Unpatch()
assert.NoError(t, err)
expectedObj := getObj(filepath.Join(dir, test.ExpectedOutputPath))
// Ideally, we would use a assert.Equal to detect the difference, but the Lua VM returns a object with float64 instead of the originial int32. As a result, the assert.Equal is never true despite that the change has been applied.
// Ideally, we would use a assert.Equal to detect the difference, but the Lua VM returns a object with float64 instead of the original int32. As a result, the assert.Equal is never true despite that the change has been applied.
diffResult := diff.Diff(expectedObj, result, testNormalizer{})
if diffResult.Modified {
output, err := diffResult.ASCIIFormat(expectedObj, formatter.AsciiFormatterConfig{})
errors.CheckError(err)
assert.Fail(t, "Output does not match input:", output)
t.Error("Output does not match input:")
err = diff.PrintDiff(test.Action, expectedObj, result)
assert.NoError(t, err)
}
})
}

View File

@@ -0,0 +1,4 @@
actionTests:
- action: restart
inputPath: testdata/daemonset.yaml
expectedOutputPath: testdata/daemonset-restarted.yaml

View File

@@ -0,0 +1,3 @@
actions = {}
actions["restart"] = {}
return actions

View File

@@ -0,0 +1,9 @@
local os = require("os")
if obj.spec.template.metadata == nil then
obj.spec.template.metadata = {}
end
if obj.spec.template.metadata.annotations == nil then
obj.spec.template.metadata.annotations = {}
end
obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
return obj

View File

@@ -0,0 +1,47 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
annotations:
creationTimestamp: "2019-09-13T08:52:50Z"
generation: 2
labels:
app.kubernetes.io/instance: extensions
name: extensions-daemonset
namespace: statefulset
resourceVersion: "7471358"
selfLink: /apis/extensions/v1beta1/namespaces/statefulset/daemonsets/extensions-daemonset
uid: de09964a-d603-11e9-9e69-42010aa8005f
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
name: extensions-daemonset
template:
metadata:
annotations:
kubectl.kubernetes.io/restartedAt: "0001-01-01T00:00:00Z"
labels:
name: extensions-daemonset
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
templateGeneration: 2
updateStrategy:
type: OnDelete
status:
currentNumberScheduled: 4
desiredNumberScheduled: 4
numberAvailable: 4
numberMisscheduled: 0
numberReady: 4
observedGeneration: 2

View File

@@ -0,0 +1,45 @@
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
annotations:
creationTimestamp: "2019-09-13T08:52:50Z"
generation: 2
labels:
app.kubernetes.io/instance: extensions
name: extensions-daemonset
namespace: statefulset
resourceVersion: "7471358"
selfLink: /apis/extensions/v1beta1/namespaces/statefulset/daemonsets/extensions-daemonset
uid: de09964a-d603-11e9-9e69-42010aa8005f
spec:
revisionHistoryLimit: 10
selector:
matchLabels:
name: extensions-daemonset
template:
metadata:
labels:
name: extensions-daemonset
spec:
containers:
- image: k8s.gcr.io/nginx-slim:0.8
imagePullPolicy: IfNotPresent
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
templateGeneration: 2
updateStrategy:
type: OnDelete
status:
currentNumberScheduled: 4
desiredNumberScheduled: 4
numberAvailable: 4
numberMisscheduled: 0
numberReady: 4
observedGeneration: 2

View File

@@ -0,0 +1,4 @@
actionTests:
- action: restart
inputPath: testdata/deployment.yaml
expectedOutputPath: testdata/deployment-restarted.yaml

View File

@@ -0,0 +1,3 @@
actions = {}
actions["restart"] = {}
return actions

View File

@@ -0,0 +1,9 @@
local os = require("os")
if obj.spec.template.metadata == nil then
obj.spec.template.metadata = {}
end
if obj.spec.template.metadata.annotations == nil then
obj.spec.template.metadata.annotations = {}
end
obj.spec.template.metadata.annotations["kubectl.kubernetes.io/restartedAt"] = os.date("!%Y-%m-%dT%XZ")
return obj

View File

@@ -0,0 +1,63 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2019-09-12T01:33:53Z"
generation: 1
name: nginx-deploy
namespace: default
resourceVersion: "6897444"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deploy
uid: 61689d6d-d4fd-11e9-9e69-42010aa8005f
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
annotations:
kubectl.kubernetes.io/restartedAt: "0001-01-01T00:00:00Z"
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:33:53Z"
message: Deployment does not have minimum availability.
reason: MinimumReplicasUnavailable
status: "False"
type: Available
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:34:05Z"
message: ReplicaSet "nginx-deploy-9cb4784bd" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 2
replicas: 3
unavailableReplicas: 1
updatedReplicas: 3

View File

@@ -0,0 +1,61 @@
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
deployment.kubernetes.io/revision: "1"
creationTimestamp: "2019-09-12T01:33:53Z"
generation: 1
name: nginx-deploy
namespace: default
resourceVersion: "6897444"
selfLink: /apis/apps/v1/namespaces/default/deployments/nginx-deploy
uid: 61689d6d-d4fd-11e9-9e69-42010aa8005f
spec:
progressDeadlineSeconds: 600
replicas: 3
revisionHistoryLimit: 10
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: nginx
spec:
containers:
- image: nginx:latest
imagePullPolicy: Always
name: nginx
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status:
availableReplicas: 2
conditions:
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:33:53Z"
message: Deployment does not have minimum availability.
reason: MinimumReplicasUnavailable
status: "False"
type: Available
- lastTransitionTime: "2019-09-12T01:33:53Z"
lastUpdateTime: "2019-09-12T01:34:05Z"
message: ReplicaSet "nginx-deploy-9cb4784bd" is progressing.
reason: ReplicaSetUpdated
status: "True"
type: Progressing
observedGeneration: 1
readyReplicas: 2
replicas: 3
unavailableReplicas: 1
updatedReplicas: 3

View File

@@ -121,6 +121,9 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
badge = replaceFirstGroupSubMatch(rightText1Pattern, badge, rightText)
badge = replaceFirstGroupSubMatch(rightText2Pattern, badge, rightText)
w.Header().Set("Content-Type", "image/svg+xml")
//Ask cache's to not cache the contents in order prevent the badge from becoming stale
w.Header().Set("Cache-Control", "private, no-store")
w.WriteHeader(http.StatusOK)
_, _ = w.Write([]byte(badge))
}

View File

@@ -54,6 +54,8 @@ func TestHandlerFeatureIsEnabled(t *testing.T) {
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, "private, no-store", rr.Header().Get("Cache-Control"))
response := rr.Body.String()
assert.Equal(t, success, leftPathColorPattern.FindStringSubmatch(response)[1])
assert.Equal(t, success, rightPathColorPattern.FindStringSubmatch(response)[1])
@@ -74,6 +76,8 @@ func TestHandlerFeatureIsDisabled(t *testing.T) {
rr := httptest.NewRecorder()
handler.ServeHTTP(rr, req)
assert.Equal(t, "private, no-store", rr.Header().Get("Cache-Control"))
response := rr.Body.String()
assert.Equal(t, unknown, leftPathColorPattern.FindStringSubmatch(response)[1])
assert.Equal(t, unknown, rightPathColorPattern.FindStringSubmatch(response)[1])

View File

@@ -419,6 +419,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
"/account.AccountService/UpdatePassword": true,
"/repository.RepositoryService/Create": true,
"/repository.RepositoryService/Update": true,
"/repository.RepositoryService/ValidateAccess": true,
"/application.ApplicationService/PatchResource": true,
}
// NOTE: notice we do not configure the gRPC server here with TLS (e.g. grpc.Creds(creds))

View File

@@ -17,12 +17,12 @@ import (
"k8s.io/apimachinery/pkg/types"
"github.com/argoproj/argo-cd/common"
"github.com/argoproj/argo-cd/errors"
. "github.com/argoproj/argo-cd/errors"
applicationpkg "github.com/argoproj/argo-cd/pkg/apiclient/application"
repositorypkg "github.com/argoproj/argo-cd/pkg/apiclient/repository"
. "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/argoproj/argo-cd/reposerver/apiclient"
"github.com/argoproj/argo-cd/test/e2e/fixture"
. "github.com/argoproj/argo-cd/test/e2e/fixture"
. "github.com/argoproj/argo-cd/test/e2e/fixture/app"
"github.com/argoproj/argo-cd/util"
. "github.com/argoproj/argo-cd/util/argo"
@@ -44,18 +44,18 @@ func TestAppCreation(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
And(func(app *Application) {
assert.Equal(t, fixture.Name(), app.Name)
assert.Equal(t, fixture.RepoURL(fixture.RepoURLTypeFile), app.Spec.Source.RepoURL)
assert.Equal(t, Name(), app.Name)
assert.Equal(t, RepoURL(RepoURLTypeFile), app.Spec.Source.RepoURL)
assert.Equal(t, guestbookPath, app.Spec.Source.Path)
assert.Equal(t, fixture.DeploymentNamespace(), app.Spec.Destination.Namespace)
assert.Equal(t, DeploymentNamespace(), app.Spec.Destination.Namespace)
assert.Equal(t, common.KubernetesInternalAPIServerAddr, app.Spec.Destination.Server)
}).
Expect(Event(EventReasonResourceCreated, "create")).
And(func(_ *Application) {
// app should be listed
output, err := fixture.RunCli("app", "list")
output, err := RunCli("app", "list")
assert.NoError(t, err)
assert.Contains(t, output, fixture.Name())
assert.Contains(t, output, Name())
})
}
@@ -83,9 +83,9 @@ func TestAppDeletion(t *testing.T) {
Expect(DoesNotExist()).
Expect(Event(EventReasonResourceDeleted, "delete"))
output, err := fixture.RunCli("app", "list")
output, err := RunCli("app", "list")
assert.NoError(t, err)
assert.NotContains(t, output, fixture.Name())
assert.NotContains(t, output, Name())
}
func TestTrackAppStateAndSyncApp(t *testing.T) {
@@ -95,10 +95,10 @@ func TestTrackAppStateAndSyncApp(t *testing.T) {
Create().
Sync().
Then().
Expect(Success(fmt.Sprintf("apps Deployment %s guestbook-ui OutOfSync Missing", fixture.DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("Service %s guestbook-ui OutOfSync Missing", fixture.DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("Service %s guestbook-ui Synced Healthy service/guestbook-ui created", fixture.DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("apps Deployment %s guestbook-ui Synced Healthy deployment.apps/guestbook-ui created", fixture.DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("apps Deployment %s guestbook-ui OutOfSync Missing", DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("Service %s guestbook-ui OutOfSync Missing", DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("Service %s guestbook-ui Synced Healthy service/guestbook-ui created", DeploymentNamespace()))).
Expect(Success(fmt.Sprintf("apps Deployment %s guestbook-ui Synced Healthy deployment.apps/guestbook-ui created", DeploymentNamespace()))).
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(Event(EventReasonResourceUpdated, "sync")).
@@ -134,11 +134,11 @@ func TestAppRollbackSuccessful(t *testing.T) {
patch, _, err := diff.CreateTwoWayMergePatch(app, appWithHistory, &Application{})
assert.NoError(t, err)
app, err = fixture.AppClientset.ArgoprojV1alpha1().Applications(fixture.ArgoCDNamespace).Patch(app.Name, types.MergePatchType, patch)
app, err = AppClientset.ArgoprojV1alpha1().Applications(ArgoCDNamespace).Patch(app.Name, types.MergePatchType, patch)
assert.NoError(t, err)
// sync app and make sure it reaches InSync state
_, err = fixture.RunCli("app", "rollback", app.Name, "1")
_, err = RunCli("app", "rollback", app.Name, "1")
assert.NoError(t, err)
}).
@@ -184,7 +184,7 @@ func TestManipulateApplicationResources(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
manifests, err := fixture.RunCli("app", "manifests", app.Name, "--source", "live")
manifests, err := RunCli("app", "manifests", app.Name, "--source", "live")
assert.NoError(t, err)
resources, err := kube.SplitYAML(manifests)
assert.NoError(t, err)
@@ -201,7 +201,7 @@ func TestManipulateApplicationResources(t *testing.T) {
deployment := resources[index]
closer, client, err := fixture.ArgoCDClientset.NewApplicationClient()
closer, client, err := ArgoCDClientset.NewApplicationClient()
assert.NoError(t, err)
defer util.Close(closer)
@@ -243,7 +243,7 @@ func assetSecretDataHidden(t *testing.T, manifest string) {
}
func TestAppWithSecrets(t *testing.T) {
closer, client, err := fixture.ArgoCDClientset.NewApplicationClient()
closer, client, err := ArgoCDClientset.NewApplicationClient()
assert.NoError(t, err)
defer util.Close(closer)
@@ -255,49 +255,45 @@ func TestAppWithSecrets(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, err := client.GetResource(context.Background(), &applicationpkg.ApplicationResourceRequest{
res := FailOnErr(client.GetResource(context.Background(), &applicationpkg.ApplicationResourceRequest{
Namespace: app.Spec.Destination.Namespace,
Kind: kube.SecretKind,
Group: "",
Name: &app.Name,
Version: "v1",
ResourceName: "test-secret",
})
assert.NoError(t, err)
})).(*applicationpkg.ApplicationResourceResponse)
assetSecretDataHidden(t, res.Manifest)
diffOutput, err := fixture.RunCli("app", "diff", app.Name)
assert.NoError(t, err)
diffOutput := FailOnErr(RunCli("app", "diff", app.Name)).(string)
assert.Empty(t, diffOutput)
// patch secret and make sure app is out of sync and diff detects the change
_, err = fixture.KubeClientset.CoreV1().Secrets(fixture.DeploymentNamespace()).Patch(
"test-secret", types.JSONPatchType, []byte(`[{"op": "remove", "path": "/data/username"}]`))
assert.NoError(t, err)
FailOnErr(KubeClientset.CoreV1().Secrets(DeploymentNamespace()).Patch(
"test-secret", types.JSONPatchType, []byte(`[
{"op": "remove", "path": "/data/username"},
{"op": "add", "path": "/stringData", "value": {"password": "foo"}}
]`)))
}).
When().
Refresh(RefreshTypeNormal).
Then().
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
And(func(app *Application) {
diffOutput, err := fixture.RunCli("app", "diff", app.Name)
diffOutput, err := RunCli("app", "diff", app.Name)
assert.Error(t, err)
assert.Contains(t, diffOutput, "username: +++++++++")
assert.Contains(t, diffOutput, "username: ++++++++")
assert.Contains(t, diffOutput, "password: ++++++++++++")
// local diff should ignore secrets
diffOutput, err = fixture.RunCli("app", "diff", app.Name, "--local", "testdata/secrets")
assert.NoError(t, err)
diffOutput = FailOnErr(RunCli("app", "diff", app.Name, "--local", "testdata/secrets")).(string)
assert.Empty(t, diffOutput)
// ignore missing field and make sure diff shows no difference
app.Spec.IgnoreDifferences = []ResourceIgnoreDifferences{{
Kind: kube.SecretKind, JSONPointers: []string{"/data/username"},
Kind: kube.SecretKind, JSONPointers: []string{"/data/username", "/data/password"},
}}
_, err = client.UpdateSpec(context.Background(), &applicationpkg.ApplicationUpdateSpecRequest{Name: &app.Name, Spec: app.Spec})
assert.NoError(t, err)
FailOnErr(client.UpdateSpec(context.Background(), &applicationpkg.ApplicationUpdateSpecRequest{Name: &app.Name, Spec: app.Spec}))
}).
When().
Refresh(RefreshTypeNormal).
@@ -305,8 +301,7 @@ func TestAppWithSecrets(t *testing.T) {
Expect(OperationPhaseIs(OperationSucceeded)).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
diffOutput, err := fixture.RunCli("app", "diff", app.Name)
assert.NoError(t, err)
diffOutput := FailOnErr(RunCli("app", "diff", app.Name)).(string)
assert.Empty(t, diffOutput)
})
}
@@ -321,7 +316,7 @@ func TestResourceDiffing(t *testing.T) {
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
// Patch deployment
_, err := fixture.KubeClientset.AppsV1().Deployments(fixture.DeploymentNamespace()).Patch(
_, err := KubeClientset.AppsV1().Deployments(DeploymentNamespace()).Patch(
"guestbook-ui", types.JSONPatchType, []byte(`[{ "op": "replace", "path": "/spec/template/spec/containers/0/image", "value": "test" }]`))
assert.NoError(t, err)
}).
@@ -330,9 +325,9 @@ func TestResourceDiffing(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeOutOfSync)).
And(func(app *Application) {
diffOutput, err := fixture.RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
diffOutput, err := RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
assert.Error(t, err)
assert.Contains(t, diffOutput, fmt.Sprintf("===== apps/Deployment %s/guestbook-ui ======", fixture.DeploymentNamespace()))
assert.Contains(t, diffOutput, fmt.Sprintf("===== apps/Deployment %s/guestbook-ui ======", DeploymentNamespace()))
}).
Given().
ResourceOverrides(map[string]ResourceOverride{"apps/Deployment": {IgnoreDifferences: ` jsonPointers: ["/spec/template/spec/containers/0/image"]`}}).
@@ -341,7 +336,7 @@ func TestResourceDiffing(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
diffOutput, err := fixture.RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
diffOutput, err := RunCli("app", "diff", app.Name, "--local", "testdata/guestbook")
assert.NoError(t, err)
assert.Empty(t, diffOutput)
})
@@ -366,7 +361,7 @@ func TestConfigMap(t *testing.T) {
func TestFailedConversion(t *testing.T) {
defer func() {
errors.FailOnErr(fixture.Run("", "kubectl", "delete", "apiservice", "v1beta1.metrics.k8s.io"))
FailOnErr(Run("", "kubectl", "delete", "apiservice", "v1beta1.metrics.k8s.io"))
}()
testEdgeCasesApplicationResources(t, "failed-conversion", HealthStatusProgressing)
@@ -383,7 +378,7 @@ func testEdgeCasesApplicationResources(t *testing.T, appPath string, statusCode
Expect(SyncStatusIs(SyncStatusCodeSynced)).
Expect(HealthIs(statusCode)).
And(func(app *Application) {
diffOutput, err := fixture.RunCli("app", "diff", app.Name, "--local", path.Join("testdata", appPath))
diffOutput, err := RunCli("app", "diff", app.Name, "--local", path.Join("testdata", appPath))
assert.Empty(t, diffOutput)
assert.NoError(t, err)
})
@@ -401,7 +396,7 @@ func TestKsonnetApp(t *testing.T) {
Sync().
Then().
And(func(app *Application) {
closer, client, err := fixture.ArgoCDClientset.NewRepoClient()
closer, client, err := ArgoCDClientset.NewRepoClient()
assert.NoError(t, err)
defer util.Close(closer)
@@ -440,7 +435,7 @@ func TestResourceAction(t *testing.T) {
Then().
And(func(app *Application) {
closer, client, err := fixture.ArgoCDClientset.NewApplicationClient()
closer, client, err := ArgoCDClientset.NewApplicationClient()
assert.NoError(t, err)
defer util.Close(closer)
@@ -449,7 +444,7 @@ func TestResourceAction(t *testing.T) {
Group: "apps",
Kind: "Deployment",
Version: "v1",
Namespace: fixture.DeploymentNamespace(),
Namespace: DeploymentNamespace(),
ResourceName: "guestbook-ui",
})
assert.NoError(t, err)
@@ -459,13 +454,13 @@ func TestResourceAction(t *testing.T) {
Group: "apps",
Kind: "Deployment",
Version: "v1",
Namespace: fixture.DeploymentNamespace(),
Namespace: DeploymentNamespace(),
ResourceName: "guestbook-ui",
Action: "sample",
})
assert.NoError(t, err)
deployment, err := fixture.KubeClientset.AppsV1().Deployments(fixture.DeploymentNamespace()).Get("guestbook-ui", metav1.GetOptions{})
deployment, err := KubeClientset.AppsV1().Deployments(DeploymentNamespace()).Get("guestbook-ui", metav1.GetOptions{})
assert.NoError(t, err)
assert.Equal(t, "test", deployment.Labels["sample"])
@@ -480,11 +475,11 @@ func TestSyncResourceByLabel(t *testing.T) {
Sync().
Then().
And(func(app *Application) {
_, _ = fixture.RunCli("app", "sync", app.Name, "--label", fmt.Sprintf("app.kubernetes.io/instance=%s", app.Name))
_, _ = RunCli("app", "sync", app.Name, "--label", fmt.Sprintf("app.kubernetes.io/instance=%s", app.Name))
}).
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
_, err := fixture.RunCli("app", "sync", app.Name, "--label", "this-label=does-not-exist")
_, err := RunCli("app", "sync", app.Name, "--label", "this-label=does-not-exist")
assert.Error(t, err)
assert.Contains(t, err.Error(), "level=fatal")
})
@@ -498,7 +493,7 @@ func TestLocalManifestSync(t *testing.T) {
Sync().
Then().
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
res, _ := RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 80")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.2")
}).
@@ -509,7 +504,7 @@ func TestLocalManifestSync(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
res, _ := RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 81")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.3")
}).
@@ -520,7 +515,7 @@ func TestLocalManifestSync(t *testing.T) {
Then().
Expect(SyncStatusIs(SyncStatusCodeSynced)).
And(func(app *Application) {
res, _ := fixture.RunCli("app", "manifests", app.Name)
res, _ := RunCli("app", "manifests", app.Name)
assert.Contains(t, res, "containerPort: 80")
assert.Contains(t, res, "image: gcr.io/heptio-images/ks-guestbook-demo:0.2")
})
@@ -534,10 +529,10 @@ func TestNoLocalSyncWithAutosyncEnabled(t *testing.T) {
Sync().
Then().
And(func(app *Application) {
_, err := fixture.RunCli("app", "set", app.Name, "--sync-policy", "automated")
_, err := RunCli("app", "set", app.Name, "--sync-policy", "automated")
assert.NoError(t, err)
_, err = fixture.RunCli("app", "sync", app.Name, "--local", guestbookPathLocal)
_, err = RunCli("app", "sync", app.Name, "--local", guestbookPathLocal)
assert.Error(t, err)
})
}
@@ -556,44 +551,44 @@ func TestSyncAsync(t *testing.T) {
}
func TestPermissions(t *testing.T) {
fixture.EnsureCleanState(t)
appName := fixture.Name()
_, err := fixture.RunCli("proj", "create", "test")
EnsureCleanState(t)
appName := Name()
_, err := RunCli("proj", "create", "test")
assert.NoError(t, err)
// make sure app cannot be created without permissions in project
_, err = fixture.RunCli("app", "create", appName, "--repo", fixture.RepoURL(fixture.RepoURLTypeFile),
"--path", guestbookPath, "--project", "test", "--dest-server", common.KubernetesInternalAPIServerAddr, "--dest-namespace", fixture.DeploymentNamespace())
_, err = RunCli("app", "create", appName, "--repo", RepoURL(RepoURLTypeFile),
"--path", guestbookPath, "--project", "test", "--dest-server", common.KubernetesInternalAPIServerAddr, "--dest-namespace", DeploymentNamespace())
assert.Error(t, err)
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'test'", fixture.RepoURL(fixture.RepoURLTypeFile))
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'test'", common.KubernetesInternalAPIServerAddr, fixture.DeploymentNamespace())
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'test'", RepoURL(RepoURLTypeFile))
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'test'", common.KubernetesInternalAPIServerAddr, DeploymentNamespace())
assert.Contains(t, err.Error(), sourceError)
assert.Contains(t, err.Error(), destinationError)
proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Get("test", metav1.GetOptions{})
proj, err := AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Get("test", metav1.GetOptions{})
assert.NoError(t, err)
proj.Spec.Destinations = []ApplicationDestination{{Server: "*", Namespace: "*"}}
proj.Spec.SourceRepos = []string{"*"}
proj, err = fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Update(proj)
proj, err = AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Update(proj)
assert.NoError(t, err)
// make sure controller report permissions issues in conditions
_, err = fixture.RunCli("app", "create", appName, "--repo", fixture.RepoURL(fixture.RepoURLTypeFile),
"--path", guestbookPath, "--project", "test", "--dest-server", common.KubernetesInternalAPIServerAddr, "--dest-namespace", fixture.DeploymentNamespace())
_, err = RunCli("app", "create", appName, "--repo", RepoURL(RepoURLTypeFile),
"--path", guestbookPath, "--project", "test", "--dest-server", common.KubernetesInternalAPIServerAddr, "--dest-namespace", DeploymentNamespace())
assert.NoError(t, err)
defer func() {
err = fixture.AppClientset.ArgoprojV1alpha1().Applications(fixture.ArgoCDNamespace).Delete(appName, &metav1.DeleteOptions{})
err = AppClientset.ArgoprojV1alpha1().Applications(ArgoCDNamespace).Delete(appName, &metav1.DeleteOptions{})
assert.NoError(t, err)
}()
proj.Spec.Destinations = []ApplicationDestination{}
proj.Spec.SourceRepos = []string{}
_, err = fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Update(proj)
_, err = AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Update(proj)
assert.NoError(t, err)
time.Sleep(1 * time.Second)
closer, client, err := fixture.ArgoCDClientset.NewApplicationClient()
closer, client, err := ArgoCDClientset.NewApplicationClient()
assert.NoError(t, err)
defer util.Close(closer)
@@ -697,7 +692,7 @@ func TestSelfManagedApps(t *testing.T) {
Given(t).
Path("self-managed-app").
When().
PatchFile("resources.yaml", fmt.Sprintf(`[{"op": "replace", "path": "/spec/source/repoURL", "value": "%s"}]`, fixture.RepoURL(fixture.RepoURLTypeFile))).
PatchFile("resources.yaml", fmt.Sprintf(`[{"op": "replace", "path": "/spec/source/repoURL", "value": "%s"}]`, RepoURL(RepoURLTypeFile))).
Create().
Sync().
Then().
@@ -709,7 +704,7 @@ func TestSelfManagedApps(t *testing.T) {
reconciledCount := 0
var lastReconciledAt *metav1.Time
for event := range fixture.ArgoCDClientset.WatchApplicationWithRetry(ctx, a.Name) {
for event := range ArgoCDClientset.WatchApplicationWithRetry(ctx, a.Name) {
reconciledAt := event.Application.Status.ReconciledAt
if reconciledAt == nil {
reconciledAt = &metav1.Time{}

View File

@@ -35,7 +35,7 @@ type Context struct {
func Given(t *testing.T) *Context {
fixture.EnsureCleanState(t)
return &Context{t: t, destServer: KubernetesInternalAPIServerAddr, repoURLType: fixture.RepoURLTypeFile, name: fixture.Name(), timeout: 5, project: "default", prune: true}
return &Context{t: t, destServer: KubernetesInternalAPIServerAddr, repoURLType: fixture.RepoURLTypeFile, name: fixture.Name(), timeout: 10, project: "default", prune: true}
}
func (c *Context) CustomCACertAdded() *Context {

View File

@@ -29,6 +29,7 @@ func TestPostSyncHookSuccessful(t *testing.T) {
// make sure we can run a standard sync hook
func testHookSuccessful(t *testing.T, hookType HookType, podHookPhase OperationPhase) {
Given(t).
Timeout(10).
Path("hook").
When().
PatchFile("hook.yaml", fmt.Sprintf(`[{"op": "replace", "path": "/metadata/annotations", "value": {"argocd.argoproj.io/hook": "%s"}}]`, hookType)).

View File

@@ -16,7 +16,7 @@ export const ApplicationSyncPanel = ({application, selectedResource, hide}: {
const [form, setForm] = React.useState<FormApi>(null);
const isVisible = !!(selectedResource && application);
const appResources = (application && selectedResource && application.status && application.status.resources || []).sort(
(first, second) => nodeKey(first).localeCompare(nodeKey(second)));
(first, second) => nodeKey(first).localeCompare(nodeKey(second))).filter((item) => !item.hook);
const syncResIndex = appResources.findIndex((item) => nodeKey(item) === selectedResource);
const syncStrategy = {} as models.SyncStrategy;
@@ -36,7 +36,7 @@ export const ApplicationSyncPanel = ({application, selectedResource, hide}: {
<Form
defaultValues={{
revision: application.spec.source.targetRevision || 'HEAD',
resources: appResources.filter((item) => !item.hook).map((_, i) => i === syncResIndex || syncResIndex === -1),
resources: appResources.map((_, i) => i === syncResIndex || syncResIndex === -1),
}}
validateError={(values) => ({
resources: values.resources.every((item: boolean) => !item) && 'Select at least one resource',

View File

@@ -2,9 +2,12 @@ import {repoUrl, revisionUrl} from './urls';
function testExample(http: string, ssl: string, revision: string, expectedRepoUrl: string, expectedRevisionUrl: string) {
expect(repoUrl(http)).toBe(expectedRepoUrl);
expect(repoUrl(ssl)).toBe(expectedRepoUrl);
expect(revisionUrl(http, revision)).toBe(expectedRevisionUrl);
expect(revisionUrl(ssl, revision)).toBe(expectedRevisionUrl);
expect(repoUrl(http)).toBe(expectedRepoUrl);
expect(revisionUrl(http, revision)).toBe(expectedRevisionUrl);
expect(revisionUrl(ssl, revision)).toBe(expectedRevisionUrl);
}
test('github.com', () => {
@@ -16,6 +19,15 @@ test('github.com', () => {
'https://github.com/argoproj/argo-cd/commit/024dee09f543ce7bb5af7ca50260504d89dfda94');
});
// for enterprise github installations
test('github.my-enterprise.com', () => {
testExample(
'https://github.my-enterprise.com/my-org/my-repo.git',
'git@github.my-enterprise.com:my-org/my-repo.git',
'a06f2be80a4da89abb8ced904beab75b3ec6db0e',
'https://github.my-enterprise.com/my-org/my-repo',
'https://github.my-enterprise.com/my-org/my-repo/commit/a06f2be80a4da89abb8ced904beab75b3ec6db0e');
});
test('gitlab.com', () => {
testExample(

View File

@@ -1,7 +1,9 @@
import {GitUrl} from 'git-url-parse';
const GitUrlParse = require('git-url-parse');
function supportedSource(source: string): boolean {
return ['github.com', 'gitlab.com', 'bitbucket.org'].indexOf(source) >= 0;
function supportedSource(parsed: GitUrl): boolean {
return parsed.resource.startsWith('github') || ['gitlab.com', 'bitbucket.org'].indexOf(parsed.source) >= 0;
}
function protocol(proto: string): string {
@@ -11,7 +13,7 @@ function protocol(proto: string): string {
export function repoUrl(url: string): string {
const parsed = GitUrlParse(url);
if (!supportedSource(parsed.source)) {
if (!supportedSource(parsed)) {
return null;
}
@@ -22,7 +24,7 @@ export function revisionUrl(url: string, revision: string): string {
const parsed = GitUrlParse(url);
if (!supportedSource(parsed.source)) {
if (!supportedSource(parsed)) {
return null;
}

12
uid_entrypoint.sh Executable file
View File

@@ -0,0 +1,12 @@
#!/bin/bash
# Make sure that if we are using an arbitrary UID that it appears in /etc/passwd,
# otherwise this will cause issues with things like cloning with git+ssh
# reference: https://access.redhat.com/documentation/en-us/openshift_container_platform/3.11/html/creating_images/creating-images-guidelines#use-uid
if ! whoami &> /dev/null; then
if [ -w /etc/passwd ]; then
echo "${USER_NAME:-default}:x:$(id -u):0:${USER_NAME:-default} user:/home/argocd:/sbin/nologin" >> /etc/passwd
fi
fi
exec "$@"

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"hash/fnv"
"net/url"
"reflect"
"strings"
"golang.org/x/net/context"
@@ -141,8 +142,12 @@ func (db *db) WatchClusters(ctx context.Context, callback func(*ClusterEvent)) e
next.Type = watch.Modified
cluster = &localCluster
} else if next.Type == watch.Added {
localCls = cluster
next.Type = watch.Modified
if !reflect.DeepEqual(localCls.Config, cluster.Config) {
localCls = cluster
next.Type = watch.Modified
} else {
continue
}
} else {
localCls = cluster
}

View File

@@ -4,8 +4,14 @@ import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"reflect"
"github.com/ghodss/yaml"
"github.com/google/shlex"
log "github.com/sirupsen/logrus"
"github.com/yudai/gojsondiff"
"github.com/yudai/gojsondiff/formatter"
@@ -388,7 +394,7 @@ func HideSecretData(target *unstructured.Unstructured, live *unstructured.Unstru
for k := range keys {
// we use "+" rather than the more common "*"
nextReplacement := "+++++++++"
nextReplacement := "++++++++"
valToReplacement := make(map[string]string)
for _, obj := range []*unstructured.Unstructured{target, live, orig} {
var data map[string]interface{}
@@ -410,7 +416,7 @@ func HideSecretData(target *unstructured.Unstructured, live *unstructured.Unstru
replacement, ok := valToReplacement[val]
if !ok {
replacement = nextReplacement
nextReplacement = nextReplacement + "+"
nextReplacement = nextReplacement + "++++"
valToReplacement[val] = replacement
}
data[k] = replacement
@@ -477,3 +483,50 @@ func remarshal(obj *unstructured.Unstructured) *unstructured.Unstructured {
unstrBody = jsonutil.RemoveMapFields(obj.Object, unstrBody)
return &unstructured.Unstructured{Object: unstrBody}
}
// PrintDiff prints a diff between two unstructured objects to stdout using an external diff utility
// Honors the diff utility set in the KUBECTL_EXTERNAL_DIFF environment variable
func PrintDiff(name string, live *unstructured.Unstructured, target *unstructured.Unstructured) error {
tempDir, err := ioutil.TempDir("", "argocd-diff")
if err != nil {
return err
}
targetFile := path.Join(tempDir, name)
targetData := []byte("")
if target != nil {
targetData, err = yaml.Marshal(target)
if err != nil {
return err
}
}
err = ioutil.WriteFile(targetFile, targetData, 0644)
if err != nil {
return err
}
liveFile := path.Join(tempDir, fmt.Sprintf("%s-live.yaml", name))
liveData := []byte("")
if live != nil {
liveData, err = yaml.Marshal(live)
if err != nil {
return err
}
}
err = ioutil.WriteFile(liveFile, liveData, 0644)
if err != nil {
return err
}
cmdBinary := "diff"
var args []string
if envDiff := os.Getenv("KUBECTL_EXTERNAL_DIFF"); envDiff != "" {
parts, err := shlex.Split(envDiff)
if err != nil {
return err
}
cmdBinary = parts[0]
args = parts[1:]
}
cmd := exec.Command(cmdBinary, append(args, liveFile, targetFile)...)
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
return cmd.Run()
}

View File

@@ -533,10 +533,10 @@ func secretData(obj *unstructured.Unstructured) map[string]interface{} {
return data
}
const (
replacement1 = "+++++++++"
replacement2 = "++++++++++"
replacement3 = "+++++++++++"
var (
replacement1 = strings.Repeat("+", 8)
replacement2 = strings.Repeat("+", 12)
replacement3 = strings.Repeat("+", 16)
)
func TestHideSecretDataSameKeysDifferentValues(t *testing.T) {

View File

@@ -94,7 +94,14 @@ func (f *factory) NewClient(rawRepoURL string, path string, creds Creds, insecur
// - Otherwise (and on non-fatal errors), a default HTTP client is returned.
func GetRepoHTTPClient(repoURL string, insecure bool, creds Creds) *http.Client {
// Default HTTP client
var customHTTPClient *http.Client = &http.Client{}
var customHTTPClient *http.Client = &http.Client{
// 15 second timeout
Timeout: 15 * time.Second,
// don't follow redirect
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
},
}
// Callback function to return any configured client certificate
// We never return err, but an empty cert instead.
@@ -122,19 +129,11 @@ func GetRepoHTTPClient(repoURL string, insecure bool, creds Creds) *http.Client
}
if insecure {
customHTTPClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
GetClientCertificate: clientCertFunc,
},
},
// 15 second timeout
Timeout: 15 * time.Second,
// don't follow redirect
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
customHTTPClient.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
GetClientCertificate: clientCertFunc,
},
}
} else {
@@ -147,33 +146,19 @@ func GetRepoHTTPClient(repoURL string, insecure bool, creds Creds) *http.Client
return customHTTPClient
} else if len(serverCertificatePem) > 0 {
certPool := certutil.GetCertPoolFromPEMData(serverCertificatePem)
customHTTPClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
RootCAs: certPool,
GetClientCertificate: clientCertFunc,
},
},
// 15 second timeout
Timeout: 15 * time.Second,
// don't follow redirect
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
customHTTPClient.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
RootCAs: certPool,
GetClientCertificate: clientCertFunc,
},
}
} else {
// else no custom certificate stored.
customHTTPClient = &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
GetClientCertificate: clientCertFunc,
},
},
// 15 second timeout
Timeout: 15 * time.Second,
// don't follow redirect
CheckRedirect: func(req *http.Request, via []*http.Request) error {
return http.ErrUseLastResponse
customHTTPClient.Transport = &http.Transport{
Proxy: http.ProxyFromEnvironment,
TLSClientConfig: &tls.Config{
GetClientCertificate: clientCertFunc,
},
}
}

View File

@@ -63,7 +63,7 @@ func ignoreLiveObjectHealth(liveObj *unstructured.Unstructured, resHealth appv1.
return true
}
gvk := liveObj.GroupVersionKind()
if gvk.Group == "argoproj.io" && gvk.Kind == "Application" && resHealth.Status == appv1.HealthStatusMissing {
if gvk.Group == "argoproj.io" && gvk.Kind == "Application" && (resHealth.Status == appv1.HealthStatusMissing || resHealth.Status == appv1.HealthStatusUnknown) {
// Covers the app-of-apps corner case where child app is deployed but that app itself
// has a status of 'Missing', which we don't want to cause the parent's health status
// to also be Missing

View File

@@ -115,6 +115,7 @@ func TestAppOfAppsHealth(t *testing.T) {
}
missingApp, missingStatus := newAppLiveObj("foo", appv1.HealthStatusMissing)
unknownApp, unknownStatus := newAppLiveObj("fooz", appv1.HealthStatusUnknown)
healthyApp, healthyStatus := newAppLiveObj("bar", appv1.HealthStatusHealthy)
degradedApp, degradedStatus := newAppLiveObj("baz", appv1.HealthStatusDegraded)
@@ -127,6 +128,15 @@ func TestAppOfAppsHealth(t *testing.T) {
assert.Equal(t, appv1.HealthStatusHealthy, healthStatus.Status)
}
// verify unknown child app does not affect app health
{
unknownAndHealthyStatuses := []appv1.ResourceStatus{unknownStatus, healthyStatus}
unknownAndHealthyLiveObjects := []*unstructured.Unstructured{unknownApp, healthyApp}
healthStatus, err := SetApplicationHealth(unknownAndHealthyStatuses, unknownAndHealthyLiveObjects, nil, noFilter)
assert.NoError(t, err)
assert.Equal(t, appv1.HealthStatusHealthy, healthStatus.Status)
}
// verify degraded does affect
{
degradedAndHealthyStatuses := []appv1.ResourceStatus{degradedStatus, healthyStatus}

View File

@@ -33,7 +33,9 @@ type Kubectl interface {
GetAPIResources(config *rest.Config, resourceFilter ResourceFilter) ([]APIResourceInfo, error)
}
type KubectlCmd struct{}
type KubectlCmd struct {
OnKubectlRun func(command string) (util.Closer, error)
}
type APIResourceInfo struct {
GroupKind schema.GroupKind
@@ -214,7 +216,7 @@ func (k KubectlCmd) ApplyResource(config *rest.Config, obj *unstructured.Unstruc
return "", err
}
}
outReconcile, err := runKubectl(f.Name(), namespace, []string{"auth", "reconcile"}, manifestBytes, dryRun)
outReconcile, err := k.runKubectl(f.Name(), namespace, []string{"auth", "reconcile"}, manifestBytes, dryRun)
if err != nil {
return "", err
}
@@ -231,7 +233,7 @@ func (k KubectlCmd) ApplyResource(config *rest.Config, obj *unstructured.Unstruc
if !validate {
applyArgs = append(applyArgs, "--validate=false")
}
outApply, err := runKubectl(f.Name(), namespace, applyArgs, manifestBytes, dryRun)
outApply, err := k.runKubectl(f.Name(), namespace, applyArgs, manifestBytes, dryRun)
if err != nil {
return "", err
}
@@ -251,7 +253,27 @@ func convertKubectlError(err error) error {
return fmt.Errorf(errorStr)
}
func runKubectl(kubeconfigPath string, namespace string, args []string, manifestBytes []byte, dryRun bool) (string, error) {
func (k *KubectlCmd) processKubectlRun(args []string) (util.Closer, error) {
if k.OnKubectlRun != nil {
cmd := "unknown"
if len(args) > 0 {
cmd = args[0]
}
return k.OnKubectlRun(cmd)
}
return util.NewCloser(func() error {
return nil
// do nothing
}), nil
}
func (k *KubectlCmd) runKubectl(kubeconfigPath string, namespace string, args []string, manifestBytes []byte, dryRun bool) (string, error) {
closer, err := k.processKubectlRun(args)
if err != nil {
return "", err
}
defer util.Close(closer)
cmdArgs := append([]string{"--kubeconfig", kubeconfigPath, "-f", "-"}, args...)
if namespace != "" {
cmdArgs = append(cmdArgs, "-n", namespace)
@@ -304,6 +326,13 @@ func (k KubectlCmd) ConvertToVersion(obj *unstructured.Unstructured, group strin
return nil, err
}
defer util.DeleteFile(f.Name())
closer, err := k.processKubectlRun([]string{"convert"})
if err != nil {
return nil, err
}
defer util.Close(closer)
outputVersion := fmt.Sprintf("%s/%s", group, version)
cmd := exec.Command("kubectl", "convert", "--output-version", outputVersion, "-o", "json", "--local=true", "-f", f.Name())
cmd.Stdin = bytes.NewReader(manifestBytes)

View File

@@ -2,34 +2,28 @@ package kube
import (
"io/ioutil"
"os"
"testing"
"github.com/argoproj/argo-cd/util"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestConvertToVersion(t *testing.T) {
/*
ctl_test.go:22:
Error Trace: ctl_test.go:22
Error: Expected nil, but got: &errors.errorString{s:"failed to convert Deployment/nginx-deployment to apps/v1"}
Test: TestConvertToVersion
panic: runtime error: invalid memory address or nil pointer dereference
/home/circleci/sdk/go1.11.4/src/testing/testing.go:792 +0x387
/home/circleci/sdk/go1.11.4/src/runtime/panic.go:513 +0x1b9
/home/circleci/.go_workspace/src/github.com/argoproj/argo-cd/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go:200 +0x3a
/home/circleci/.go_workspace/src/github.com/argoproj/argo-cd/vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured/unstructured.go:396 +0x5b
/home/circleci/.go_workspace/src/github.com/argoproj/argo-cd/util/kube/ctl_test.go:23 +0x1e4
/home/circleci/sdk/go1.11.4/src/testing/testing.go:827 +0xbf
/home/circleci/sdk/go1.11.4/src/testing/testing.go:878 +0x35c
*/
if os.Getenv("CIRCLECI") == "true" {
t.SkipNow()
callbackExecuted := false
closerExecuted := false
kubectl := KubectlCmd{
func(command string) (util.Closer, error) {
callbackExecuted = true
return util.NewCloser(func() error {
closerExecuted = true
return nil
}), nil
},
}
kubectl := KubectlCmd{}
yamlBytes, err := ioutil.ReadFile("testdata/nginx.yaml")
assert.Nil(t, err)
var obj unstructured.Unstructured
@@ -42,6 +36,8 @@ func TestConvertToVersion(t *testing.T) {
gvk := newObj.GroupVersionKind()
assert.Equal(t, "apps", gvk.Group)
assert.Equal(t, "v1", gvk.Version)
assert.True(t, callbackExecuted)
assert.True(t, closerExecuted)
// converting it again should not have any affect
newObj, err = kubectl.ConvertToVersion(&obj, "apps", "v1")
@@ -50,3 +46,21 @@ func TestConvertToVersion(t *testing.T) {
assert.Equal(t, "apps", gvk.Group)
assert.Equal(t, "v1", gvk.Version)
}
func TestRunKubectl(t *testing.T) {
callbackExecuted := false
closerExecuted := false
kubectl := KubectlCmd{
func(command string) (util.Closer, error) {
callbackExecuted = true
return util.NewCloser(func() error {
closerExecuted = true
return nil
}), nil
},
}
_, _ = kubectl.runKubectl("/dev/null", "default", []string{"command-name"}, nil, false)
assert.True(t, callbackExecuted)
assert.True(t, closerExecuted)
}

View File

@@ -234,11 +234,15 @@ func (l *LocalConfig) IsEmpty() bool {
// DefaultConfigDir returns the local configuration path for settings such as cached authentication tokens.
func DefaultConfigDir() (string, error) {
usr, err := user.Current()
if err != nil {
return "", err
homeDir := os.Getenv("HOME")
if homeDir == "" {
usr, err := user.Current()
if err != nil {
return "", err
}
homeDir = usr.HomeDir
}
return path.Join(usr.HomeDir, ".argocd"), nil
return path.Join(homeDir, ".argocd"), nil
}
// DefaultLocalConfigPath returns the local configuration path for settings such as cached authentication tokens.

View File

@@ -45,7 +45,7 @@ func (vm VM) runLua(obj *unstructured.Unstructured, script string) (*lua.LState,
SkipOpenLibs: !vm.UseOpenLibs,
})
defer l.Close()
// Opens table library to allow access to functions to manulate tables
// Opens table library to allow access to functions to manipulate tables
for _, pair := range []struct {
n string
f lua.LGFunction
@@ -53,6 +53,8 @@ func (vm VM) runLua(obj *unstructured.Unstructured, script string) (*lua.LState,
{lua.LoadLibName, lua.OpenPackage},
{lua.BaseLibName, lua.OpenBase},
{lua.TabLibName, lua.OpenTable},
// load our 'safe' version of the os library
{lua.OsLibName, OpenSafeOs},
} {
if err := l.CallByParam(lua.P{
Fn: l.NewFunction(pair.f),
@@ -62,6 +64,8 @@ func (vm VM) runLua(obj *unstructured.Unstructured, script string) (*lua.LState,
panic(err)
}
}
// preload our 'safe' version of the os library. Allows the 'local os = require("os")' to work
l.PreloadModule(lua.OsLibName, SafeOsLoader)
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()

184
util/lua/oslib_safe.go Normal file
View File

@@ -0,0 +1,184 @@
package lua
// oslib_safe contains a subset of the lua os library. For security reasons, we do not expose
// the entirety of lua os library to custom actions, such as ones which can exit, read files, etc.
// Only the safe functions like os.time(), os.date() are exposed. Implementation was copied from
// github.com/yuin/gopher-lua.
import (
"fmt"
"strings"
"time"
lua "github.com/yuin/gopher-lua"
)
func OpenSafeOs(L *lua.LState) int {
tabmod := L.RegisterModule(lua.TabLibName, osFuncs)
L.Push(tabmod)
return 1
}
func SafeOsLoader(L *lua.LState) int {
mod := L.SetFuncs(L.NewTable(), osFuncs)
L.Push(mod)
return 1
}
var osFuncs = map[string]lua.LGFunction{
"time": osTime,
"date": osDate,
}
func osTime(L *lua.LState) int {
if L.GetTop() == 0 {
L.Push(lua.LNumber(time.Now().Unix()))
} else {
tbl := L.CheckTable(1)
sec := getIntField(tbl, "sec", 0)
min := getIntField(tbl, "min", 0)
hour := getIntField(tbl, "hour", 12)
day := getIntField(tbl, "day", -1)
month := getIntField(tbl, "month", -1)
year := getIntField(tbl, "year", -1)
isdst := getBoolField(tbl, "isdst", false)
t := time.Date(year, time.Month(month), day, hour, min, sec, 0, time.Local)
// TODO dst
if false {
print(isdst)
}
L.Push(lua.LNumber(t.Unix()))
}
return 1
}
func getIntField(tb *lua.LTable, key string, v int) int {
ret := tb.RawGetString(key)
if ln, ok := ret.(lua.LNumber); ok {
return int(ln)
}
return v
}
func getBoolField(tb *lua.LTable, key string, v bool) bool {
ret := tb.RawGetString(key)
if lb, ok := ret.(lua.LBool); ok {
return bool(lb)
}
return v
}
func osDate(L *lua.LState) int {
t := time.Now()
cfmt := "%c"
if L.GetTop() >= 1 {
cfmt = L.CheckString(1)
if strings.HasPrefix(cfmt, "!") {
t = time.Now().UTC()
cfmt = strings.TrimLeft(cfmt, "!")
}
if L.GetTop() >= 2 {
t = time.Unix(L.CheckInt64(2), 0)
}
if strings.HasPrefix(cfmt, "*t") {
ret := L.NewTable()
ret.RawSetString("year", lua.LNumber(t.Year()))
ret.RawSetString("month", lua.LNumber(t.Month()))
ret.RawSetString("day", lua.LNumber(t.Day()))
ret.RawSetString("hour", lua.LNumber(t.Hour()))
ret.RawSetString("min", lua.LNumber(t.Minute()))
ret.RawSetString("sec", lua.LNumber(t.Second()))
ret.RawSetString("wday", lua.LNumber(t.Weekday()+1))
// TODO yday & dst
ret.RawSetString("yday", lua.LNumber(0))
ret.RawSetString("isdst", lua.LFalse)
L.Push(ret)
return 1
}
}
L.Push(lua.LString(strftime(t, cfmt)))
return 1
}
var cDateFlagToGo = map[byte]string{
'a': "mon", 'A': "Monday", 'b': "Jan", 'B': "January", 'c': "02 Jan 06 15:04 MST", 'd': "02",
'F': "2006-01-02", 'H': "15", 'I': "03", 'm': "01", 'M': "04", 'p': "PM", 'P': "pm", 'S': "05",
'x': "15/04/05", 'X': "15:04:05", 'y': "06", 'Y': "2006", 'z': "-0700", 'Z': "MST"}
func strftime(t time.Time, cfmt string) string {
sc := newFlagScanner('%', "", "", cfmt)
for c, eos := sc.Next(); !eos; c, eos = sc.Next() {
if !sc.ChangeFlag {
if sc.HasFlag {
if v, ok := cDateFlagToGo[c]; ok {
sc.AppendString(t.Format(v))
} else {
switch c {
case 'w':
sc.AppendString(fmt.Sprint(int(t.Weekday())))
default:
sc.AppendChar('%')
sc.AppendChar(c)
}
}
sc.HasFlag = false
} else {
sc.AppendChar(c)
}
}
}
return sc.String()
}
type flagScanner struct {
flag byte
start string
end string
buf []byte
str string
Length int
Pos int
HasFlag bool
ChangeFlag bool
}
func newFlagScanner(flag byte, start, end, str string) *flagScanner {
return &flagScanner{flag, start, end, make([]byte, 0, len(str)), str, len(str), 0, false, false}
}
func (fs *flagScanner) AppendString(str string) { fs.buf = append(fs.buf, str...) }
func (fs *flagScanner) AppendChar(ch byte) { fs.buf = append(fs.buf, ch) }
func (fs *flagScanner) String() string { return string(fs.buf) }
func (fs *flagScanner) Next() (byte, bool) {
c := byte('\000')
fs.ChangeFlag = false
if fs.Pos == fs.Length {
if fs.HasFlag {
fs.AppendString(fs.end)
}
return c, true
} else {
c = fs.str[fs.Pos]
if c == fs.flag {
if fs.Pos < (fs.Length-1) && fs.str[fs.Pos+1] == fs.flag {
fs.HasFlag = false
fs.AppendChar(fs.flag)
fs.Pos += 2
return fs.Next()
} else if fs.Pos != fs.Length-1 {
if fs.HasFlag {
fs.AppendString(fs.end)
}
fs.AppendString(fs.start)
fs.ChangeFlag = true
fs.HasFlag = true
}
}
}
fs.Pos++
return c, false
}

View File

@@ -30,6 +30,18 @@ type Closer interface {
Close() error
}
type inlineCloser struct {
close func() error
}
func (c *inlineCloser) Close() error {
return c.close()
}
func NewCloser(close func() error) Closer {
return &inlineCloser{close: close}
}
// Close is a convenience function to close a object that has a Close() method, ignoring any errors
// Used to satisfy errcheck lint
func Close(c Closer) {