mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-02-28 21:48:46 +01:00
Compare commits
46 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6f3b02912 | ||
|
|
a6c84628ca | ||
|
|
ac694eb8f4 | ||
|
|
a2965ac6cd | ||
|
|
b87a3a8c94 | ||
|
|
35ab139a3f | ||
|
|
6f7af53bea | ||
|
|
684c033e72 | ||
|
|
113b53859d | ||
|
|
bd6e79da98 | ||
|
|
fd63155b0e | ||
|
|
85025e1dcb | ||
|
|
b3ba6e1844 | ||
|
|
870965d081 | ||
|
|
7415f47b2b | ||
|
|
a9c87d2ad7 | ||
|
|
0a4043099b | ||
|
|
ebab8ec625 | ||
|
|
c90d7baf31 | ||
|
|
d23e132bdf | ||
|
|
5698864d60 | ||
|
|
0c2f16b811 | ||
|
|
4e936006f7 | ||
|
|
365a1fc3e3 | ||
|
|
4a459f2f30 | ||
|
|
3bee2940f0 | ||
|
|
dffdb6bd03 | ||
|
|
330bcd2673 | ||
|
|
908c51bc5c | ||
|
|
c24062573f | ||
|
|
c279299281 | ||
|
|
24f8d82954 | ||
|
|
1ab570ad96 | ||
|
|
8612a99fe8 | ||
|
|
33fa128bad | ||
|
|
4e79aab03d | ||
|
|
7b89ae4424 | ||
|
|
2577d51796 | ||
|
|
2f8533efeb | ||
|
|
c698426a5c | ||
|
|
77556d9e64 | ||
|
|
1391ba7214 | ||
|
|
44e52c4ae7 | ||
|
|
4b55084a8f | ||
|
|
c689ea4957 | ||
|
|
ea9827791f |
2
.github/workflows/image.yaml
vendored
2
.github/workflows/image.yaml
vendored
@@ -86,7 +86,7 @@ jobs:
|
||||
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
|
||||
if: ${{ github.repository == 'argoproj/argo-cd' && github.event_name == 'push' }}
|
||||
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.7.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
with:
|
||||
image: ghcr.io/argoproj/argo-cd/argocd
|
||||
digest: ${{ needs.build-and-publish.outputs.image-digest }}
|
||||
|
||||
6
.github/workflows/release.yaml
vendored
6
.github/workflows/release.yaml
vendored
@@ -38,7 +38,7 @@ jobs:
|
||||
packages: write # for uploading attestations. (https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#known-issues)
|
||||
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.7.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v1.9.0
|
||||
with:
|
||||
image: quay.io/argoproj/argocd
|
||||
digest: ${{ needs.argocd-image.outputs.image-digest }}
|
||||
@@ -120,7 +120,7 @@ jobs:
|
||||
contents: write # Needed for release uploads
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.7.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
|
||||
with:
|
||||
base64-subjects: "${{ needs.goreleaser.outputs.hashes }}"
|
||||
provenance-name: "argocd-cli.intoto.jsonl"
|
||||
@@ -204,7 +204,7 @@ jobs:
|
||||
contents: write # Needed for release uploads
|
||||
if: github.repository == 'argoproj/argo-cd'
|
||||
# Must be refernced by a tag. https://github.com/slsa-framework/slsa-github-generator/blob/main/internal/builders/container/README.md#referencing-the-slsa-generator
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.7.0
|
||||
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.9.0
|
||||
with:
|
||||
base64-subjects: "${{ needs.generate-sbom.outputs.hashes }}"
|
||||
provenance-name: "argocd-sbom.intoto.jsonl"
|
||||
|
||||
@@ -4,7 +4,7 @@ ARG BASE_IMAGE=docker.io/library/ubuntu:22.04@sha256:0bced47fffa3361afa981854fca
|
||||
# Initial stage which pulls prepares build dependencies and CLI tooling we need for our final image
|
||||
# Also used as the image in CI jobs so needs all dependencies
|
||||
####################################################################################################
|
||||
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS builder
|
||||
FROM docker.io/library/golang:1.20.10@sha256:ed6c4a5918b0a1ffb97970f6493d742dc5c7ebf3ccbd417c215d52830b57b994 AS builder
|
||||
|
||||
RUN echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
|
||||
|
||||
@@ -101,7 +101,7 @@ RUN HOST_ARCH=$TARGETARCH NODE_ENV='production' NODE_ONLINE_ENV='online' NODE_OP
|
||||
####################################################################################################
|
||||
# Argo CD Build stage which performs the actual build of Argo CD binaries
|
||||
####################################################################################################
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS argocd-build
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.20.10@sha256:ed6c4a5918b0a1ffb97970f6493d742dc5c7ebf3ccbd417c215d52830b57b994 AS argocd-build
|
||||
|
||||
WORKDIR /go/src/github.com/argoproj/argo-cd
|
||||
|
||||
|
||||
1
USERS.md
1
USERS.md
@@ -200,6 +200,7 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Patreon](https://www.patreon.com/)
|
||||
1. [PayPay](https://paypay.ne.jp/)
|
||||
1. [Peloton Interactive](https://www.onepeloton.com/)
|
||||
1. [PGS](https://www.pgs.com)
|
||||
1. [Pigment](https://www.gopigment.com/)
|
||||
1. [Pipefy](https://www.pipefy.com/)
|
||||
1. [Pismo](https://pismo.io/)
|
||||
|
||||
@@ -58,10 +58,6 @@ const (
|
||||
// https://github.com/argoproj-labs/argocd-notifications/blob/33d345fa838829bb50fca5c08523aba380d2c12b/pkg/controller/state.go#L17
|
||||
NotifiedAnnotationKey = "notified.notifications.argoproj.io"
|
||||
ReconcileRequeueOnValidationError = time.Minute * 3
|
||||
|
||||
// LabelKeyAppSetInstance is the label key to use to uniquely identify the apps of an applicationset
|
||||
// The ArgoCD applicationset name is used as the instance name
|
||||
LabelKeyAppSetInstance = "argocd.argoproj.io/application-set-name"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -159,13 +155,15 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
||||
|
||||
if r.EnableProgressiveSyncs {
|
||||
if applicationSetInfo.Spec.Strategy == nil && len(applicationSetInfo.Status.ApplicationStatus) > 0 {
|
||||
// If appset used progressive sync but stopped, clean up the progressive sync application statuses
|
||||
log.Infof("Removing %v unnecessary AppStatus entries from ApplicationSet %v", len(applicationSetInfo.Status.ApplicationStatus), applicationSetInfo.Name)
|
||||
|
||||
err := r.setAppSetApplicationStatus(ctx, &applicationSetInfo, []argov1alpha1.ApplicationSetApplicationStatus{})
|
||||
if err != nil {
|
||||
return ctrl.Result{}, fmt.Errorf("failed to clear previous AppSet application statuses for %v: %w", applicationSetInfo.Name, err)
|
||||
}
|
||||
} else {
|
||||
} else if applicationSetInfo.Spec.Strategy != nil {
|
||||
// appset uses progressive sync
|
||||
applications, err := r.getCurrentApplications(ctx, applicationSetInfo)
|
||||
if err != nil {
|
||||
return ctrl.Result{}, fmt.Errorf("failed to get current applications for application set: %w", err)
|
||||
@@ -516,10 +514,6 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argov
|
||||
|
||||
for _, a := range t {
|
||||
tmplApplication := getTempApplication(a.Template)
|
||||
if tmplApplication.Labels == nil {
|
||||
tmplApplication.Labels = make(map[string]string)
|
||||
}
|
||||
tmplApplication.Labels[LabelKeyAppSetInstance] = applicationSetInfo.Name
|
||||
|
||||
for _, p := range a.Params {
|
||||
app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, p, applicationSetInfo.Spec.GoTemplate, applicationSetInfo.Spec.GoTemplateOptions)
|
||||
|
||||
@@ -165,9 +165,6 @@ func TestExtractApplications(t *testing.T) {
|
||||
if cc.generateParamsError == nil {
|
||||
for _, p := range cc.params {
|
||||
|
||||
tmpApplication := getTempApplication(cc.template)
|
||||
tmpApplication.Labels[LabelKeyAppSetInstance] = appSet.Name
|
||||
|
||||
if cc.rendererError != nil {
|
||||
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p, false, []string(nil)).
|
||||
Return(nil, cc.rendererError)
|
||||
@@ -289,21 +286,7 @@ func TestMergeTemplateApplications(t *testing.T) {
|
||||
|
||||
rendererMock := rendererMock{}
|
||||
|
||||
appSet := &v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSetSpec{
|
||||
Generators: []v1alpha1.ApplicationSetGenerator{generator},
|
||||
Template: cc.template,
|
||||
},
|
||||
}
|
||||
|
||||
tmpApplication := getTempApplication(cc.expectedMerged)
|
||||
tmpApplication.Labels[LabelKeyAppSetInstance] = appSet.Name
|
||||
|
||||
rendererMock.On("RenderTemplateParams", tmpApplication, cc.params[0], false, []string(nil)).
|
||||
rendererMock.On("RenderTemplateParams", getTempApplication(cc.expectedMerged), cc.params[0], false, []string(nil)).
|
||||
Return(&cc.expectedApps[0], nil)
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -317,7 +300,17 @@ func TestMergeTemplateApplications(t *testing.T) {
|
||||
KubeClientset: kubefake.NewSimpleClientset(),
|
||||
}
|
||||
|
||||
got, _, _ := r.generateApplications(*appSet)
|
||||
got, _, _ := r.generateApplications(v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "namespace",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSetSpec{
|
||||
Generators: []v1alpha1.ApplicationSetGenerator{generator},
|
||||
Template: cc.template,
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
assert.Equal(t, cc.expectedApps, got)
|
||||
})
|
||||
@@ -2169,7 +2162,7 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
assert.Nil(t, err)
|
||||
|
||||
retrievedApplicationSet.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
retrievedApplicationSet.Spec.Template.Labels = map[string]string{"argocd.argoproj.io/application-set-name": "name", "label-key": "label-value"}
|
||||
retrievedApplicationSet.Spec.Template.Labels = map[string]string{"label-key": "label-value"}
|
||||
|
||||
retrievedApplicationSet.Spec.Template.Spec.Source.Helm = &v1alpha1.ApplicationSourceHelm{
|
||||
Values: "global.test: test",
|
||||
@@ -2197,7 +2190,6 @@ func TestUpdateNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
|
||||
|
||||
assert.Nil(t, app.Spec.Source.Helm)
|
||||
assert.Nil(t, app.ObjectMeta.Annotations)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/application-set-name": "name"}, app.ObjectMeta.Labels)
|
||||
}
|
||||
|
||||
func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
@@ -2208,7 +2200,6 @@ func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
|
||||
assert.Nil(t, app.Spec.Source.Helm)
|
||||
assert.Nil(t, app.ObjectMeta.Annotations)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/application-set-name": "name"}, app.ObjectMeta.Labels)
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
@@ -2219,7 +2210,7 @@ func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
|
||||
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/application-set-name": "name", "label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
|
||||
@@ -2230,7 +2221,7 @@ func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
|
||||
|
||||
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
|
||||
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/application-set-name": "name", "label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
|
||||
@@ -2241,7 +2232,7 @@ func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *t
|
||||
|
||||
assert.Equal(t, "global.test: test", app.Spec.Source.Helm.Values)
|
||||
assert.Equal(t, map[string]string{"annotation-key": "annotation-value"}, app.ObjectMeta.Annotations)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/application-set-name": "name", "label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
assert.Equal(t, map[string]string{"label-key": "label-value"}, app.ObjectMeta.Labels)
|
||||
}
|
||||
|
||||
func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.ApplicationList {
|
||||
@@ -2449,8 +2440,7 @@ func TestGenerateAppsUsingPullRequestGenerator(t *testing.T) {
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "AppSet-branch1-1",
|
||||
Labels: map[string]string{
|
||||
"app1": "label1",
|
||||
LabelKeyAppSetInstance: "",
|
||||
"app1": "label1",
|
||||
},
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
|
||||
@@ -153,7 +153,7 @@ func InterpolateGenerator(requestedGenerator *argoprojiov1alpha1.ApplicationSetG
|
||||
interpolatedGenerator, err := render.RenderGeneratorParams(requestedGenerator, params, useGoTemplate, goTemplateOptions)
|
||||
if err != nil {
|
||||
log.WithError(err).WithField("interpolatedGenerator", interpolatedGenerator).Error("error interpolating generator with other generator's parameter")
|
||||
return *interpolatedGenerator, err
|
||||
return argoprojiov1alpha1.ApplicationSetGenerator{}, err
|
||||
}
|
||||
|
||||
return *interpolatedGenerator, nil
|
||||
|
||||
@@ -501,3 +501,60 @@ func TestInterpolateGenerator_go(t *testing.T) {
|
||||
assert.Equal(t, "production_01/west", interpolatedGenerator.Git.Files[0].Path)
|
||||
assert.Equal(t, "https://production-01.example.com", interpolatedGenerator.Git.Files[1].Path)
|
||||
}
|
||||
|
||||
func TestInterpolateGeneratorError(t *testing.T) {
|
||||
type args struct {
|
||||
requestedGenerator *argov1alpha1.ApplicationSetGenerator
|
||||
params map[string]interface{}
|
||||
useGoTemplate bool
|
||||
goTemplateOptions []string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want argov1alpha1.ApplicationSetGenerator
|
||||
expectedErrStr string
|
||||
}{
|
||||
{name: "Empty Gen", args: args{
|
||||
requestedGenerator: nil,
|
||||
params: nil,
|
||||
useGoTemplate: false,
|
||||
goTemplateOptions: nil,
|
||||
}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "generator is empty"},
|
||||
{name: "No Params", args: args{
|
||||
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{},
|
||||
params: map[string]interface{}{},
|
||||
useGoTemplate: false,
|
||||
goTemplateOptions: nil,
|
||||
}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: ""},
|
||||
{name: "Error templating", args: args{
|
||||
requestedGenerator: &argov1alpha1.ApplicationSetGenerator{Git: &argov1alpha1.GitGenerator{
|
||||
RepoURL: "foo",
|
||||
Files: []argov1alpha1.GitFileGeneratorItem{{Path: "bar/"}},
|
||||
Revision: "main",
|
||||
Values: map[string]string{
|
||||
"git_test": "{{ toPrettyJson . }}",
|
||||
"selection": "{{ default .override .test }}",
|
||||
"resolved": "{{ index .rmap (default .override .test) }}",
|
||||
},
|
||||
}},
|
||||
params: map[string]interface{}{
|
||||
"name": "in-cluster",
|
||||
"override": "foo",
|
||||
},
|
||||
useGoTemplate: true,
|
||||
goTemplateOptions: []string{},
|
||||
}, want: argov1alpha1.ApplicationSetGenerator{}, expectedErrStr: "failed to replace parameters in generator: failed to execute go template {{ index .rmap (default .override .test) }}: template: :1:3: executing \"\" at <index .rmap (default .override .test)>: error calling index: index of untyped nil"},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := InterpolateGenerator(tt.args.requestedGenerator, tt.args.params, tt.args.useGoTemplate, tt.args.goTemplateOptions)
|
||||
if tt.expectedErrStr != "" {
|
||||
assert.EqualError(t, err, tt.expectedErrStr)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
assert.Equalf(t, tt.want, got, "InterpolateGenerator(%v, %v, %v, %v)", tt.args.requestedGenerator, tt.args.params, tt.args.useGoTemplate, tt.args.goTemplateOptions)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,11 +26,13 @@ func NewGiteaService(ctx context.Context, token, url, owner, repo string, insecu
|
||||
if insecure {
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
|
||||
httpClient = &http.Client{
|
||||
Jar: cookieJar,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}}
|
||||
Jar: cookieJar,
|
||||
Transport: tr,
|
||||
}
|
||||
}
|
||||
client, err := gitea.NewClient(url, gitea.SetToken(token), gitea.SetHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
|
||||
@@ -32,9 +32,9 @@ func NewGitLabService(ctx context.Context, token, url, project string, labels []
|
||||
token = os.Getenv("GITLAB_TOKEN")
|
||||
}
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
|
||||
}
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = utils.GetTlsConfig(scmRootCAPath, insecure)
|
||||
|
||||
retryClient := retryablehttp.NewClient()
|
||||
retryClient.HTTPClient.Transport = tr
|
||||
|
||||
|
||||
@@ -27,11 +27,13 @@ func NewGiteaProvider(ctx context.Context, owner, token, url string, allBranches
|
||||
if insecure {
|
||||
cookieJar, _ := cookiejar.New(nil)
|
||||
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
|
||||
|
||||
httpClient = &http.Client{
|
||||
Jar: cookieJar,
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}}
|
||||
Jar: cookieJar,
|
||||
Transport: tr,
|
||||
}
|
||||
}
|
||||
client, err := gitea.NewClient(url, gitea.SetToken(token), gitea.SetHTTPClient(httpClient))
|
||||
if err != nil {
|
||||
|
||||
@@ -28,9 +28,9 @@ func NewGitlabProvider(ctx context.Context, organization string, token string, u
|
||||
}
|
||||
var client *gitlab.Client
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: utils.GetTlsConfig(scmRootCAPath, insecure),
|
||||
}
|
||||
tr := http.DefaultTransport.(*http.Transport).Clone()
|
||||
tr.TLSClientConfig = utils.GetTlsConfig(scmRootCAPath, insecure)
|
||||
|
||||
retryClient := retryablehttp.NewClient()
|
||||
retryClient.HTTPClient.Transport = tr
|
||||
|
||||
|
||||
@@ -55,6 +55,7 @@ func NewCommand() *cobra.Command {
|
||||
argocdRepoServerStrictTLS bool
|
||||
configMapName string
|
||||
secretName string
|
||||
applicationNamespaces []string
|
||||
)
|
||||
var command = cobra.Command{
|
||||
Use: "controller",
|
||||
@@ -138,7 +139,7 @@ func NewCommand() *cobra.Command {
|
||||
log.Infof("serving metrics on port %d", metricsPort)
|
||||
log.Infof("loading configuration %d", metricsPort)
|
||||
|
||||
ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, appLabelSelector, registry, secretName, configMapName)
|
||||
ctrl := notificationscontroller.NewController(k8sClient, dynamicClient, argocdService, namespace, applicationNamespaces, appLabelSelector, registry, secretName, configMapName)
|
||||
err = ctrl.Init(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -161,5 +162,6 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().BoolVar(&argocdRepoServerStrictTLS, "argocd-repo-server-strict-tls", false, "Perform strict validation of TLS certificates when connecting to repo server")
|
||||
command.Flags().StringVar(&configMapName, "config-map-name", "argocd-notifications-cm", "Set notifications ConfigMap name")
|
||||
command.Flags().StringVar(&secretName, "secret-name", "argocd-notifications-secret", "Set notifications Secret name")
|
||||
command.Flags().StringSliceVar(&applicationNamespaces, "application-namespaces", env.StringsFromEnv("ARGOCD_APPLICATION_NAMESPACES", []string{}, ","), "List of additional namespaces that this controller should send notifications for")
|
||||
return &command
|
||||
}
|
||||
|
||||
@@ -82,6 +82,8 @@ func NewCommand() *cobra.Command {
|
||||
allowOutOfBoundsSymlinks bool
|
||||
streamedManifestMaxTarSize string
|
||||
streamedManifestMaxExtractedSize string
|
||||
helmManifestMaxExtractedSize string
|
||||
disableManifestMaxExtractedSize bool
|
||||
)
|
||||
var command = cobra.Command{
|
||||
Use: cliName,
|
||||
@@ -120,6 +122,9 @@ func NewCommand() *cobra.Command {
|
||||
streamedManifestMaxExtractedSizeQuantity, err := resource.ParseQuantity(streamedManifestMaxExtractedSize)
|
||||
errors.CheckError(err)
|
||||
|
||||
helmManifestMaxExtractedSizeQuantity, err := resource.ParseQuantity(helmManifestMaxExtractedSize)
|
||||
errors.CheckError(err)
|
||||
|
||||
askPassServer := askpass.NewServer()
|
||||
metricsServer := metrics.NewMetricsServer()
|
||||
cacheutil.CollectMetrics(redisClient, metricsServer)
|
||||
@@ -134,6 +139,7 @@ func NewCommand() *cobra.Command {
|
||||
AllowOutOfBoundsSymlinks: allowOutOfBoundsSymlinks,
|
||||
StreamedManifestMaxExtractedSize: streamedManifestMaxExtractedSizeQuantity.ToDec().Value(),
|
||||
StreamedManifestMaxTarSize: streamedManifestMaxTarSizeQuantity.ToDec().Value(),
|
||||
HelmManifestMaxExtractedSize: helmManifestMaxExtractedSizeQuantity.ToDec().Value(),
|
||||
}, askPassServer)
|
||||
errors.CheckError(err)
|
||||
|
||||
@@ -216,6 +222,8 @@ func NewCommand() *cobra.Command {
|
||||
command.Flags().BoolVar(&allowOutOfBoundsSymlinks, "allow-oob-symlinks", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_ALLOW_OUT_OF_BOUNDS_SYMLINKS", false), "Allow out-of-bounds symlinks in repositories (not recommended)")
|
||||
command.Flags().StringVar(&streamedManifestMaxTarSize, "streamed-manifest-max-tar-size", env.StringFromEnv("ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_TAR_SIZE", "100M"), "Maximum size of streamed manifest archives")
|
||||
command.Flags().StringVar(&streamedManifestMaxExtractedSize, "streamed-manifest-max-extracted-size", env.StringFromEnv("ARGOCD_REPO_SERVER_STREAMED_MANIFEST_MAX_EXTRACTED_SIZE", "1G"), "Maximum size of streamed manifest archives when extracted")
|
||||
command.Flags().StringVar(&helmManifestMaxExtractedSize, "helm-manifest-max-extracted-size", env.StringFromEnv("ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE", "1G"), "Maximum size of helm manifest archives when extracted")
|
||||
command.Flags().BoolVar(&disableManifestMaxExtractedSize, "disable-helm-manifest-max-extracted-size", env.ParseBoolFromEnv("ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE", false), "Disable maximum size of helm manifest archives when extracted")
|
||||
tlsConfigCustomizerSrc = tls.AddTLSFlagsToCmd(&command)
|
||||
cacheSrc = reposervercache.AddCacheFlagsToCmd(&command, func(client *redis.Client) {
|
||||
redisClient = client
|
||||
|
||||
@@ -147,7 +147,7 @@ func NewApplicationSetCreateCommand(clientOpts *argocdclient.ClientOptions) *cob
|
||||
defer argoio.Close(conn)
|
||||
|
||||
// Get app before creating to see if it is being updated or no change
|
||||
existing, err := appIf.Get(ctx, &applicationset.ApplicationSetGetQuery{Name: appset.Name})
|
||||
existing, err := appIf.Get(ctx, &applicationset.ApplicationSetGetQuery{Name: appset.Name, AppsetNamespace: appset.Namespace})
|
||||
if grpc.UnwrapGRPCStatus(err).Code() != codes.NotFound {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
|
||||
@@ -120,11 +120,16 @@ func runCommand(ctx context.Context, command Command, path string, env []string)
|
||||
logCtx.Error(err.Error())
|
||||
return strings.TrimSuffix(output, "\n"), err
|
||||
}
|
||||
|
||||
logCtx = logCtx.WithFields(log.Fields{
|
||||
"stderr": stderr.String(),
|
||||
"command": command,
|
||||
})
|
||||
if len(output) == 0 {
|
||||
log.WithFields(log.Fields{
|
||||
"stderr": stderr.String(),
|
||||
"command": command,
|
||||
}).Warn("Plugin command returned zero output")
|
||||
logCtx.Warn("Plugin command returned zero output")
|
||||
} else {
|
||||
// Log stderr even on successfull commands to help develop plugins
|
||||
logCtx.Info("Plugin command successfull")
|
||||
}
|
||||
|
||||
return strings.TrimSuffix(output, "\n"), nil
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -335,6 +336,10 @@ func verifyGnuPGSignature(revision string, project *v1alpha1.AppProject, manifes
|
||||
return conditions
|
||||
}
|
||||
|
||||
func isManagedNamespace(ns *unstructured.Unstructured, app *v1alpha1.Application) bool {
|
||||
return ns != nil && ns.GetKind() == kubeutil.NamespaceKind && ns.GetName() == app.Spec.Destination.Namespace && app.Spec.SyncPolicy != nil && app.Spec.SyncPolicy.ManagedNamespaceMetadata != nil
|
||||
}
|
||||
|
||||
// CompareAppState compares application git state to the live app state, using the specified
|
||||
// revision and supplied source. If revision or overrides are empty, then compares against
|
||||
// revision and overrides in the app spec.
|
||||
@@ -494,6 +499,35 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
|
||||
LastTransitionTime: &now,
|
||||
})
|
||||
}
|
||||
|
||||
// For the case when a namespace is managed with `managedNamespaceMetadata` AND it has resource tracking
|
||||
// enabled (e.g. someone manually adds resource tracking labels or annotations), we need to do some
|
||||
// bookkeeping in order to prevent the managed namespace from being pruned.
|
||||
//
|
||||
// Live namespaces which are managed namespaces (i.e. application namespaces which are managed with
|
||||
// CreateNamespace=true and has non-nil managedNamespaceMetadata) will (usually) not have a corresponding
|
||||
// entry in source control. In order for the namespace not to risk being pruned, we'll need to generate a
|
||||
// namespace which we can compare the live namespace with. For that, we'll do the same as is done in
|
||||
// gitops-engine, the difference here being that we create a managed namespace which is only used for comparison.
|
||||
if isManagedNamespace(liveObj, app) {
|
||||
nsSpec := &v1.Namespace{TypeMeta: metav1.TypeMeta{APIVersion: "v1", Kind: kubeutil.NamespaceKind}, ObjectMeta: metav1.ObjectMeta{Name: liveObj.GetName()}}
|
||||
managedNs, err := kubeutil.ToUnstructured(nsSpec)
|
||||
|
||||
if err != nil {
|
||||
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error(), LastTransitionTime: &now})
|
||||
failedToLoadObjs = true
|
||||
continue
|
||||
}
|
||||
|
||||
// No need to care about the return value here, we just want the modified managedNs
|
||||
_, err = syncNamespace(m.resourceTracking, appLabelKey, trackingMethod, app.Name, app.Spec.SyncPolicy)(managedNs, liveObj)
|
||||
if err != nil {
|
||||
conditions = append(conditions, v1alpha1.ApplicationCondition{Type: v1alpha1.ApplicationConditionComparisonError, Message: err.Error(), LastTransitionTime: &now})
|
||||
failedToLoadObjs = true
|
||||
} else {
|
||||
targetObjs = append(targetObjs, managedNs)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -588,12 +622,22 @@ func (m *appStateManager) CompareAppState(app *v1alpha1.Application, project *v1
|
||||
} else {
|
||||
diffResult = diff.DiffResult{Modified: false, NormalizedLive: []byte("{}"), PredictedLive: []byte("{}")}
|
||||
}
|
||||
|
||||
// For the case when a namespace is managed with `managedNamespaceMetadata` AND it has resource tracking
|
||||
// enabled (e.g. someone manually adds resource tracking labels or annotations), we need to do some
|
||||
// bookkeeping in order to ensure that it's not considered `OutOfSync` (since it does not exist in source
|
||||
// control).
|
||||
//
|
||||
// This is in addition to the bookkeeping we do (see `isManagedNamespace` and its references) to prevent said
|
||||
// namespace from being pruned.
|
||||
isManagedNs := isManagedNamespace(targetObj, app) && liveObj == nil
|
||||
|
||||
if resState.Hook || ignore.Ignore(obj) || (targetObj != nil && hookutil.Skip(targetObj)) || !isSelfReferencedObj {
|
||||
// For resource hooks, skipped resources or objects that may have
|
||||
// been created by another controller with annotations copied from
|
||||
// the source object, don't store sync status, and do not affect
|
||||
// overall sync status
|
||||
} else if diffResult.Modified || targetObj == nil || liveObj == nil {
|
||||
} else if !isManagedNs && (diffResult.Modified || targetObj == nil || liveObj == nil) {
|
||||
// Set resource state to OutOfSync since one of the following is true:
|
||||
// * target and live resource are different
|
||||
// * target resource not defined and live resource is extra
|
||||
|
||||
@@ -89,6 +89,122 @@ func TestCompareAppStateNamespaceMetadataDiffers(t *testing.T) {
|
||||
assert.Len(t, app.Status.Conditions, 0)
|
||||
}
|
||||
|
||||
// TestCompareAppStateNamespaceMetadataDiffers tests comparison when managed namespace metadata differs to live and manifest ns
|
||||
func TestCompareAppStateNamespaceMetadataDiffersToManifest(t *testing.T) {
|
||||
ns := NewNamespace()
|
||||
ns.SetName(test.FakeDestNamespace)
|
||||
ns.SetNamespace(test.FakeDestNamespace)
|
||||
ns.SetAnnotations(map[string]string{"bar": "bat"})
|
||||
|
||||
app := newFakeApp()
|
||||
app.Spec.SyncPolicy.ManagedNamespaceMetadata = &argoappv1.ManagedNamespaceMetadata{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
app.Status.OperationState = &argoappv1.OperationState{
|
||||
SyncResult: &argoappv1.SyncOperationResult{},
|
||||
}
|
||||
|
||||
liveNs := ns.DeepCopy()
|
||||
liveNs.SetAnnotations(nil)
|
||||
|
||||
data := fakeData{
|
||||
manifestResponse: &apiclient.ManifestResponse{
|
||||
Manifests: []string{toJSON(t, liveNs)},
|
||||
Namespace: test.FakeDestNamespace,
|
||||
Server: test.FakeClusterURL,
|
||||
Revision: "abc123",
|
||||
},
|
||||
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
|
||||
kube.GetResourceKey(ns): ns,
|
||||
},
|
||||
}
|
||||
ctrl := newFakeController(&data)
|
||||
sources := make([]argoappv1.ApplicationSource, 0)
|
||||
sources = append(sources, app.Spec.GetSource())
|
||||
revisions := make([]string, 0)
|
||||
revisions = append(revisions, "")
|
||||
compRes := ctrl.appStateManager.CompareAppState(app, &defaultProj, revisions, sources, false, false, nil, false)
|
||||
assert.NotNil(t, compRes)
|
||||
assert.NotNil(t, compRes.syncStatus)
|
||||
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
|
||||
assert.Len(t, compRes.resources, 1)
|
||||
assert.Len(t, compRes.managedResources, 1)
|
||||
assert.NotNil(t, compRes.diffResultList)
|
||||
assert.Len(t, compRes.diffResultList.Diffs, 1)
|
||||
|
||||
result := NewNamespace()
|
||||
assert.NoError(t, json.Unmarshal(compRes.diffResultList.Diffs[0].PredictedLive, result))
|
||||
|
||||
labels := result.GetLabels()
|
||||
delete(labels, "kubernetes.io/metadata.name")
|
||||
|
||||
assert.Equal(t, map[string]string{}, labels)
|
||||
// Manifests override definitions in managedNamespaceMetadata
|
||||
assert.Equal(t, map[string]string{"bar": "bat"}, result.GetAnnotations())
|
||||
assert.Len(t, app.Status.Conditions, 0)
|
||||
}
|
||||
|
||||
// TestCompareAppStateNamespaceMetadata tests comparison when managed namespace metadata differs to live
|
||||
func TestCompareAppStateNamespaceMetadata(t *testing.T) {
|
||||
ns := NewNamespace()
|
||||
ns.SetName(test.FakeDestNamespace)
|
||||
ns.SetNamespace(test.FakeDestNamespace)
|
||||
ns.SetAnnotations(map[string]string{"bar": "bat"})
|
||||
|
||||
app := newFakeApp()
|
||||
app.Spec.SyncPolicy.ManagedNamespaceMetadata = &argoappv1.ManagedNamespaceMetadata{
|
||||
Labels: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
Annotations: map[string]string{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
app.Status.OperationState = &argoappv1.OperationState{
|
||||
SyncResult: &argoappv1.SyncOperationResult{},
|
||||
}
|
||||
|
||||
data := fakeData{
|
||||
manifestResponse: &apiclient.ManifestResponse{
|
||||
Manifests: []string{},
|
||||
Namespace: test.FakeDestNamespace,
|
||||
Server: test.FakeClusterURL,
|
||||
Revision: "abc123",
|
||||
},
|
||||
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
|
||||
kube.GetResourceKey(ns): ns,
|
||||
},
|
||||
}
|
||||
ctrl := newFakeController(&data)
|
||||
sources := make([]argoappv1.ApplicationSource, 0)
|
||||
sources = append(sources, app.Spec.GetSource())
|
||||
revisions := make([]string, 0)
|
||||
revisions = append(revisions, "")
|
||||
compRes := ctrl.appStateManager.CompareAppState(app, &defaultProj, revisions, sources, false, false, nil, false)
|
||||
assert.NotNil(t, compRes)
|
||||
assert.NotNil(t, compRes.syncStatus)
|
||||
assert.Equal(t, argoappv1.SyncStatusCodeOutOfSync, compRes.syncStatus.Status)
|
||||
assert.Len(t, compRes.resources, 1)
|
||||
assert.Len(t, compRes.managedResources, 1)
|
||||
assert.NotNil(t, compRes.diffResultList)
|
||||
assert.Len(t, compRes.diffResultList.Diffs, 1)
|
||||
|
||||
result := NewNamespace()
|
||||
assert.NoError(t, json.Unmarshal(compRes.diffResultList.Diffs[0].PredictedLive, result))
|
||||
|
||||
labels := result.GetLabels()
|
||||
delete(labels, "kubernetes.io/metadata.name")
|
||||
|
||||
assert.Equal(t, map[string]string{"foo": "bar"}, labels)
|
||||
assert.Equal(t, map[string]string{"argocd.argoproj.io/sync-options": "ServerSideApply=true", "bar": "bat", "foo": "bar"}, result.GetAnnotations())
|
||||
assert.Len(t, app.Status.Conditions, 0)
|
||||
}
|
||||
|
||||
// TestCompareAppStateNamespaceMetadataIsTheSame tests comparison when managed namespace metadata is the same
|
||||
func TestCompareAppStateNamespaceMetadataIsTheSame(t *testing.T) {
|
||||
app := newFakeApp()
|
||||
@@ -433,6 +549,47 @@ func TestCompareAppStateDuplicatedNamespacedResources(t *testing.T) {
|
||||
assert.Equal(t, 4, len(compRes.resources))
|
||||
}
|
||||
|
||||
func TestCompareAppStateManagedNamespaceMetadataWithLiveNsDoesNotGetPruned(t *testing.T) {
|
||||
app := newFakeApp()
|
||||
app.Spec.SyncPolicy = &argoappv1.SyncPolicy{
|
||||
ManagedNamespaceMetadata: &argoappv1.ManagedNamespaceMetadata{
|
||||
Labels: nil,
|
||||
Annotations: nil,
|
||||
},
|
||||
}
|
||||
|
||||
ns := NewNamespace()
|
||||
ns.SetName(test.FakeDestNamespace)
|
||||
ns.SetNamespace(test.FakeDestNamespace)
|
||||
ns.SetAnnotations(map[string]string{"argocd.argoproj.io/sync-options": "ServerSideApply=true"})
|
||||
|
||||
data := fakeData{
|
||||
manifestResponse: &apiclient.ManifestResponse{
|
||||
Manifests: []string{},
|
||||
Namespace: test.FakeDestNamespace,
|
||||
Server: test.FakeClusterURL,
|
||||
Revision: "abc123",
|
||||
},
|
||||
managedLiveObjs: map[kube.ResourceKey]*unstructured.Unstructured{
|
||||
kube.GetResourceKey(ns): ns,
|
||||
},
|
||||
}
|
||||
ctrl := newFakeController(&data)
|
||||
compRes := ctrl.appStateManager.CompareAppState(app, &defaultProj, []string{}, app.Spec.Sources, false, false, nil, false)
|
||||
|
||||
assert.NotNil(t, compRes)
|
||||
assert.Equal(t, 0, len(app.Status.Conditions))
|
||||
assert.NotNil(t, compRes)
|
||||
assert.NotNil(t, compRes.syncStatus)
|
||||
// Ensure that ns does not get pruned
|
||||
assert.NotNil(t, compRes.reconciliationResult.Target[0])
|
||||
assert.Equal(t, compRes.reconciliationResult.Target[0].GetName(), ns.GetName())
|
||||
assert.Equal(t, compRes.reconciliationResult.Target[0].GetAnnotations(), ns.GetAnnotations())
|
||||
assert.Equal(t, compRes.reconciliationResult.Target[0].GetLabels(), ns.GetLabels())
|
||||
assert.Len(t, compRes.resources, 1)
|
||||
assert.Len(t, compRes.managedResources, 1)
|
||||
}
|
||||
|
||||
var defaultProj = argoappv1.AppProject{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
|
||||
@@ -71,6 +71,8 @@ We supply a `ClusterRole` and `ClusterRoleBinding` suitable for this purpose in
|
||||
kubectl apply -f examples/k8s-rbac/argocd-server-applications/
|
||||
```
|
||||
|
||||
`argocd-notifications-controller-rbac-clusterrole.yaml` and `argocd-notifications-controller-rbac-clusterrolebinding.yaml` are used to support notifications controller to notify apps in all namespaces.
|
||||
|
||||
!!! note
|
||||
At some later point in time, we may make this cluster role part of the default installation manifests.
|
||||
|
||||
|
||||
@@ -38,16 +38,16 @@ With the ApplicationSet v0.1.0 release, one could *only* specify `url` and `clus
|
||||
spec:
|
||||
generators:
|
||||
- list:
|
||||
elements:
|
||||
# v0.1.0 form - requires cluster/url keys:
|
||||
- cluster: engineering-dev
|
||||
url: https://kubernetes.default.svc
|
||||
values:
|
||||
additional: value
|
||||
# v0.2.0+ form - does not require cluster/URL keys
|
||||
# (but they are still supported).
|
||||
- staging: "true"
|
||||
gitRepo: https://kubernetes.default.svc
|
||||
elements:
|
||||
# v0.1.0 form - requires cluster/url keys:
|
||||
- cluster: engineering-dev
|
||||
url: https://kubernetes.default.svc
|
||||
values:
|
||||
additional: value
|
||||
# v0.2.0+ form - does not require cluster/URL keys
|
||||
# (but they are still supported).
|
||||
- staging: "true"
|
||||
gitRepo: https://kubernetes.default.svc
|
||||
# (...)
|
||||
```
|
||||
|
||||
@@ -74,7 +74,6 @@ spec:
|
||||
files:
|
||||
- path: applicationset/examples/list-generator/list-elementsYaml-example.yaml
|
||||
- list:
|
||||
elements: []
|
||||
elementsYaml: "{{ .key.components | toJson }}"
|
||||
template:
|
||||
metadata:
|
||||
|
||||
@@ -406,7 +406,7 @@ spec:
|
||||
* `sha`: The Git commit SHA for the branch.
|
||||
* `short_sha`: The abbreviated Git commit SHA for the branch (8 chars or the length of the `sha` if it's shorter).
|
||||
* `short_sha_7`: The abbreviated Git commit SHA for the branch (7 chars or the length of the `sha` if it's shorter).
|
||||
* `labels`: A comma-separated list of repository labels.
|
||||
* `labels`: A comma-separated list of repository labels in case of Gitea, repository topics in case of Gitlab and Github. Not supported by Bitbucket Cloud, Bitbucket Server, or Azure DevOps.
|
||||
* `branchNormalized`: The value of `branch` normalized to contain only lowercase alphanumeric characters, '-' or '.'.
|
||||
|
||||
## Pass additional key-value pairs via `values` field
|
||||
|
||||
@@ -103,6 +103,7 @@ generators' templating:
|
||||
- `{{ path.filename }}` becomes `{{ .path.filename }}`
|
||||
- `{{ path.filenameNormalized }}` becomes `{{ .path.filenameNormalized }}`
|
||||
- `{{ path[n] }}` becomes `{{ index .path.segments n }}`
|
||||
- `{{ values }}` if being used in the file generator becomes `{{ .values }}`
|
||||
|
||||
Here is an example:
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ spec:
|
||||
args: [-c, 'echo "Initializing..."']
|
||||
# The generate command runs in the Application source directory each time manifests are generated. Standard output
|
||||
# must be ONLY valid Kubernetes Objects in either YAML or JSON. A non-zero exit code will fail manifest generation.
|
||||
# To write log messages from the command, write them to stderr, it will always be displayed.
|
||||
# Error output will be sent to the UI, so avoid printing sensitive information (such as secrets).
|
||||
generate:
|
||||
command: [sh, -c]
|
||||
@@ -50,18 +51,18 @@ spec:
|
||||
- |
|
||||
echo "{\"kind\": \"ConfigMap\", \"apiVersion\": \"v1\", \"metadata\": { \"name\": \"$ARGOCD_APP_NAME\", \"namespace\": \"$ARGOCD_APP_NAMESPACE\", \"annotations\": {\"Foo\": \"$ARGOCD_ENV_FOO\", \"KubeVersion\": \"$KUBE_VERSION\", \"KubeApiVersion\": \"$KUBE_API_VERSIONS\",\"Bar\": \"baz\"}}}"
|
||||
# The discovery config is applied to a repository. If every configured discovery tool matches, then the plugin may be
|
||||
# used to generate manifests for Applications using the repository. If the discovery config is omitted then the plugin
|
||||
# will not match any application but can still be invoked explicitly by specifying the plugin name in the app spec.
|
||||
# Only one of fileName, find.glob, or find.command should be specified. If multiple are specified then only the
|
||||
# used to generate manifests for Applications using the repository. If the discovery config is omitted then the plugin
|
||||
# will not match any application but can still be invoked explicitly by specifying the plugin name in the app spec.
|
||||
# Only one of fileName, find.glob, or find.command should be specified. If multiple are specified then only the
|
||||
# first (in that order) is evaluated.
|
||||
discover:
|
||||
# fileName is a glob pattern (https://pkg.go.dev/path/filepath#Glob) that is applied to the Application's source
|
||||
# fileName is a glob pattern (https://pkg.go.dev/path/filepath#Glob) that is applied to the Application's source
|
||||
# directory. If there is a match, this plugin may be used for the Application.
|
||||
fileName: "./subdir/s*.yaml"
|
||||
find:
|
||||
# This does the same thing as fileName, but it supports double-start (nested directory) glob patterns.
|
||||
glob: "**/Chart.yaml"
|
||||
# The find command runs in the repository's root directory. To match, it must exit with status code 0 _and_
|
||||
# The find command runs in the repository's root directory. To match, it must exit with status code 0 _and_
|
||||
# produce non-empty output to standard out.
|
||||
command: [sh, -c, find . -name env.yaml]
|
||||
# The parameters config describes what parameters the UI should display for an Application. It is up to the user to
|
||||
@@ -69,7 +70,7 @@ spec:
|
||||
# inform the "Parameters" tab in the App Details page of the UI.
|
||||
parameters:
|
||||
# Static parameter announcements are sent to the UI for _all_ Applications handled by this plugin.
|
||||
# Think of the `string`, `array`, and `map` values set here as "defaults". It is up to the plugin author to make
|
||||
# Think of the `string`, `array`, and `map` values set here as "defaults". It is up to the plugin author to make
|
||||
# sure that these default values actually reflect the plugin's behavior if the user doesn't explicitly set different
|
||||
# values for those parameters.
|
||||
static:
|
||||
@@ -112,13 +113,13 @@ spec:
|
||||
```
|
||||
|
||||
!!! note
|
||||
While the ConfigManagementPlugin _looks like_ a Kubernetes object, it is not actually a custom resource.
|
||||
While the ConfigManagementPlugin _looks like_ a Kubernetes object, it is not actually a custom resource.
|
||||
It only follows kubernetes-style spec conventions.
|
||||
|
||||
The `generate` command must print a valid Kubernetes YAML or JSON object stream to stdout. Both `init` and `generate` commands are executed inside the application source directory.
|
||||
|
||||
The `discover.fileName` is used as [glob](https://pkg.go.dev/path/filepath#Glob) pattern to determine whether an
|
||||
application repository is supported by the plugin or not.
|
||||
application repository is supported by the plugin or not.
|
||||
|
||||
```yaml
|
||||
discover:
|
||||
@@ -167,7 +168,7 @@ data:
|
||||
|
||||
#### Register the plugin sidecar
|
||||
|
||||
To install a plugin, patch argocd-repo-server to run the plugin container as a sidecar, with argocd-cmp-server as its
|
||||
To install a plugin, patch argocd-repo-server to run the plugin container as a sidecar, with argocd-cmp-server as its
|
||||
entrypoint. You can use either off-the-shelf or custom-built plugin image as sidecar image. For example:
|
||||
|
||||
```yaml
|
||||
@@ -187,7 +188,7 @@ containers:
|
||||
- mountPath: /home/argocd/cmp-server/config/plugin.yaml
|
||||
subPath: plugin.yaml
|
||||
name: my-plugin-config
|
||||
# Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps
|
||||
# Starting with v2.4, do NOT mount the same tmp volume as the repo-server container. The filesystem separation helps
|
||||
# mitigate path traversal attacks.
|
||||
- mountPath: /tmp
|
||||
name: cmp-tmp
|
||||
@@ -197,7 +198,7 @@ volumes:
|
||||
name: my-plugin-config
|
||||
- emptyDir: {}
|
||||
name: cmp-tmp
|
||||
```
|
||||
```
|
||||
|
||||
!!! important "Double-check these items"
|
||||
1. Make sure to use `/var/run/argocd/argocd-cmp-server` as an entrypoint. The `argocd-cmp-server` is a lightweight GRPC service that allows Argo CD to interact with the plugin.
|
||||
@@ -222,9 +223,9 @@ Plugin commands have access to
|
||||
value: bar
|
||||
- name: REV
|
||||
value: test-$ARGOCD_APP_REVISION
|
||||
|
||||
Before reaching the `init.command`, `generate.command`, and `discover.find.command` commands, Argo CD prefixes all
|
||||
user-supplied environment variables (#3 above) with `ARGOCD_ENV_`. This prevents users from directly setting
|
||||
|
||||
Before reaching the `init.command`, `generate.command`, and `discover.find.command` commands, Argo CD prefixes all
|
||||
user-supplied environment variables (#3 above) with `ARGOCD_ENV_`. This prevents users from directly setting
|
||||
potentially-sensitive environment variables.
|
||||
|
||||
4. Parameters in the Application spec:
|
||||
@@ -240,43 +241,43 @@ Plugin commands have access to
|
||||
- name: helm-parameters
|
||||
map:
|
||||
image.tag: v1.2.3
|
||||
|
||||
|
||||
The parameters are available as JSON in the `ARGOCD_APP_PARAMETERS` environment variable. The example above would
|
||||
produce this JSON:
|
||||
|
||||
|
||||
[{"name": "values-files", "array": ["values-dev.yaml"]}, {"name": "helm-parameters", "map": {"image.tag": "v1.2.3"}}]
|
||||
|
||||
|
||||
!!! note
|
||||
Parameter announcements, even if they specify defaults, are _not_ sent to the plugin in `ARGOCD_APP_PARAMETERS`.
|
||||
Only parameters explicitly set in the Application spec are sent to the plugin. It is up to the plugin to apply
|
||||
the same defaults as the ones announced to the UI.
|
||||
|
||||
|
||||
The same parameters are also available as individual environment variables. The names of the environment variables
|
||||
follows this convention:
|
||||
|
||||
|
||||
- name: some-string-param
|
||||
string: some-string-value
|
||||
# PARAM_SOME_STRING_PARAM=some-string-value
|
||||
|
||||
|
||||
- name: some-array-param
|
||||
value: [item1, item2]
|
||||
# PARAM_SOME_ARRAY_PARAM_0=item1
|
||||
# PARAM_SOME_ARRAY_PARAM_1=item2
|
||||
|
||||
|
||||
- name: some-map-param
|
||||
map:
|
||||
image.tag: v1.2.3
|
||||
# PARAM_SOME_MAP_PARAM_IMAGE_TAG=v1.2.3
|
||||
|
||||
!!! warning "Sanitize/escape user input"
|
||||
|
||||
!!! warning "Sanitize/escape user input"
|
||||
As part of Argo CD's manifest generation system, config management plugins are treated with a level of trust. Be
|
||||
sure to escape user input in your plugin to prevent malicious input from causing unwanted behavior.
|
||||
|
||||
## Using a config management plugin with an Application
|
||||
|
||||
You may leave the `name` field
|
||||
empty in the `plugin` section for the plugin to be automatically matched with the Application based on its discovery rules. If you do mention the name make sure
|
||||
it is either `<metadata.name>-<spec.version>` if version is mentioned in the `ConfigManagementPlugin` spec or else just `<metadata.name>`. When name is explicitly
|
||||
empty in the `plugin` section for the plugin to be automatically matched with the Application based on its discovery rules. If you do mention the name make sure
|
||||
it is either `<metadata.name>-<spec.version>` if version is mentioned in the `ConfigManagementPlugin` spec or else just `<metadata.name>`. When name is explicitly
|
||||
specified only that particular plugin will be used iff its discovery pattern/command matches the provided application repo.
|
||||
|
||||
```yaml
|
||||
@@ -305,17 +306,17 @@ If you don't need to set any environment variables, you can set an empty plugin
|
||||
|
||||
!!! important
|
||||
If your CMP command runs too long, the command will be killed, and the UI will show an error. The CMP server
|
||||
respects the timeouts set by the `server.repo.server.timeout.seconds` and `controller.repo.server.timeout.seconds`
|
||||
respects the timeouts set by the `server.repo.server.timeout.seconds` and `controller.repo.server.timeout.seconds`
|
||||
items in `argocd-cm`. Increase their values from the default of 60s.
|
||||
|
||||
Each CMP command will also independently timeout on the `ARGOCD_EXEC_TIMEOUT` set for the CMP sidecar. The default
|
||||
is 90s. So if you increase the repo server timeout greater than 90s, be sure to set `ARGOCD_EXEC_TIMEOUT` on the
|
||||
sidecar.
|
||||
|
||||
|
||||
!!! note
|
||||
Each Application can only have one config management plugin configured at a time. If you're converting an existing
|
||||
plugin configured through the `argocd-cm` ConfigMap to a sidecar, make sure to update the plugin name to either `<metadata.name>-<spec.version>`
|
||||
if version was mentioned in the `ConfigManagementPlugin` spec or else just use `<metadata.name>`. You can also remove the name altogether
|
||||
plugin configured through the `argocd-cm` ConfigMap to a sidecar, make sure to update the plugin name to either `<metadata.name>-<spec.version>`
|
||||
if version was mentioned in the `ConfigManagementPlugin` spec or else just use `<metadata.name>`. You can also remove the name altogether
|
||||
and let the automatic discovery to identify the plugin.
|
||||
|
||||
## Debugging a CMP
|
||||
@@ -329,6 +330,14 @@ If you are actively developing a sidecar-installed CMP, keep a few things in min
|
||||
image. If you're using a different, static tag, set `imagePullPolicy: Always` on the CMP's sidecar container.
|
||||
3. CMP errors are cached by the repo-server in Redis. Restarting the repo-server Pod will not clear the cache. Always
|
||||
do a "Hard Refresh" when actively developing a CMP so you have the latest output.
|
||||
4. Verify your sidecar has started properly by viewing the Pod and seeing that two containers are running `kubectl get pod -l app.kubernetes.io/component=repo-server -n argocd`
|
||||
5. Write log message to stderr and set the `--loglevel=info` flag in the sidecar. This will print everything written to stderr, even on successfull command execution.
|
||||
|
||||
|
||||
### Other Common Errors
|
||||
| Error Message | Cause |
|
||||
| -- | -- |
|
||||
| `no matches for kind "ConfigManagementPlugin" in version "argoproj.io/v1alpha1"` | The `ConfigManagementPlugin` CRD was deprecated in Argo CD 2.4 and removed in 2.8. This error means you've tried to put the configuration for your plugin directly into Kubernetes as a CRD. Refer to this [section of documentation](#write-the-plugin-configuration-file) for how to write the plugin configuration file and place it properly in the sidecar. |
|
||||
|
||||
## Plugin tar stream exclusions
|
||||
|
||||
@@ -391,14 +400,14 @@ spec:
|
||||
|
||||
### Write discovery rules for your plugin
|
||||
|
||||
Sidecar plugins can use either discovery rules or a plugin name to match Applications to plugins. If the discovery rule is omitted
|
||||
Sidecar plugins can use either discovery rules or a plugin name to match Applications to plugins. If the discovery rule is omitted
|
||||
then you have to explicitly specify the plugin by name in the app spec or else that particular plugin will not match any app.
|
||||
|
||||
If you want to use discovery instead of the plugin name to match applications to your plugin, write rules applicable to
|
||||
your plugin [using the instructions above](#1-write-the-plugin-configuration-file) and add them to your configuration
|
||||
If you want to use discovery instead of the plugin name to match applications to your plugin, write rules applicable to
|
||||
your plugin [using the instructions above](#1-write-the-plugin-configuration-file) and add them to your configuration
|
||||
file.
|
||||
|
||||
To use the name instead of discovery, update the name in your application manifest to `<metadata.name>-<spec.version>`
|
||||
To use the name instead of discovery, update the name in your application manifest to `<metadata.name>-<spec.version>`
|
||||
if version was mentioned in the `ConfigManagementPlugin` spec or else just use `<metadata.name>`. For example:
|
||||
|
||||
```yaml
|
||||
|
||||
@@ -98,7 +98,7 @@ The AppProject CRD is the Kubernetes resource object representing a logical grou
|
||||
It is defined by the following key pieces of information:
|
||||
|
||||
* `sourceRepos` reference to the repositories that applications within the project can pull manifests from.
|
||||
* `destinations` reference to clusters and namespaces that applications within the project can deploy into (don't use the `name` field, only the `server` field is matched).
|
||||
* `destinations` reference to clusters and namespaces that applications within the project can deploy into.
|
||||
* `roles` list of entities with definitions of their access to resources within the project.
|
||||
|
||||
!!!warning "Projects which can deploy to the Argo CD namespace grant admin access"
|
||||
|
||||
@@ -57,6 +57,13 @@ corresponds to the `action` path `action/extensions/DaemonSet/restart`. You can
|
||||
also use glob patterns in the action path: `action/*` (or regex patterns if you have
|
||||
[enabled the `regex` match mode](https://github.com/argoproj/argo-cd/blob/master/docs/operator-manual/argocd-rbac-cm.yaml)).
|
||||
|
||||
If the resource is not under a group (for examples, Pods or ConfigMaps), then omit the group name from your RBAC
|
||||
configuration:
|
||||
|
||||
```csv
|
||||
p, example-user, applications, action//Pod/maintenance-off, default/*, allow
|
||||
```
|
||||
|
||||
#### The `exec` resource
|
||||
|
||||
`exec` is a special resource. When enabled with the `create` action, this privilege allows a user to `exec` into Pods via
|
||||
|
||||
@@ -16,7 +16,9 @@ argocd-repo-server [flags]
|
||||
--address string Listen on given address for incoming connections (default "0.0.0.0")
|
||||
--allow-oob-symlinks Allow out-of-bounds symlinks in repositories (not recommended)
|
||||
--default-cache-expiration duration Cache expiration default (default 24h0m0s)
|
||||
--disable-helm-manifest-max-extracted-size Disable maximum size of helm manifest archives when extracted
|
||||
--disable-tls Disable TLS on the gRPC endpoint
|
||||
--helm-manifest-max-extracted-size string Maximum size of helm manifest archives when extracted (default "1G")
|
||||
-h, --help help for argocd-repo-server
|
||||
--logformat string Set the logging format. One of: text|json (default "text")
|
||||
--loglevel string Set the logging level. One of: debug|info|warn|error (default "info")
|
||||
|
||||
@@ -68,6 +68,15 @@ spec:
|
||||
|
||||
The above configuration will ignore differences from all fields owned by `kube-controller-manager` for all resources belonging to this application.
|
||||
|
||||
If you have a slash `/` in your pointer path, you can use the `~1` character. For example:
|
||||
|
||||
```yaml
|
||||
spec:
|
||||
ignoreDifferences:
|
||||
- kind: Node
|
||||
jsonPointers: /metadata/labels/node-role.kubernetes.io~1worker
|
||||
```
|
||||
|
||||
## System-Level Configuration
|
||||
|
||||
The comparison of resources with well-known issues can be customized at a system level. Ignored differences can be configured for a specified group and kind
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-notifications-controller-cluster-apps
|
||||
app.kubernetes.io/part-of: argocd
|
||||
app.kubernetes.io/component: notifications-controller
|
||||
name: argocd-notifications-controller-cluster-apps
|
||||
rules:
|
||||
- apiGroups:
|
||||
- "argoproj.io"
|
||||
resources:
|
||||
- "applications"
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- update
|
||||
- patch
|
||||
@@ -0,0 +1,16 @@
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/name: argocd-notifications-controller-cluster-apps
|
||||
app.kubernetes.io/part-of: argocd
|
||||
app.kubernetes.io/component: notifications-controller
|
||||
name: argocd-notifications-controller-cluster-apps
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: argocd-notifications-controller-cluster-apps
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: argocd-notifications-controller
|
||||
namespace: argocd
|
||||
@@ -1,8 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
yq e -o=json values.yaml | jq '{
|
||||
yq e -o=json values.yaml | jq '[{
|
||||
name: "helm-parameters",
|
||||
title: "Helm Parameters",
|
||||
collectionType: "map",
|
||||
map: [leaf_paths as $path | {"key": $path | join("."), "value": getpath($path)|tostring}] | from_entries
|
||||
}'
|
||||
}]'
|
||||
|
||||
26
go.mod
26
go.mod
@@ -20,7 +20,7 @@ require (
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.5.0
|
||||
github.com/casbin/casbin/v2 v2.71.1
|
||||
github.com/coreos/go-oidc/v3 v3.6.0
|
||||
github.com/cyphar/filepath-securejoin v0.2.3
|
||||
github.com/cyphar/filepath-securejoin v0.2.4
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/evanphx/json-patch v5.6.0+incompatible
|
||||
github.com/fsnotify/fsnotify v1.6.0
|
||||
@@ -77,13 +77,13 @@ require (
|
||||
go.opentelemetry.io/otel v1.16.0
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.16.0
|
||||
go.opentelemetry.io/otel/sdk v1.16.0
|
||||
golang.org/x/crypto v0.10.0
|
||||
golang.org/x/crypto v0.14.0
|
||||
golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1
|
||||
golang.org/x/oauth2 v0.9.0
|
||||
golang.org/x/oauth2 v0.10.0
|
||||
golang.org/x/sync v0.3.0
|
||||
golang.org/x/term v0.9.0
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1
|
||||
google.golang.org/grpc v1.56.1
|
||||
golang.org/x/term v0.13.0
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98
|
||||
google.golang.org/grpc v1.58.3
|
||||
google.golang.org/protobuf v1.31.0
|
||||
gopkg.in/go-playground/webhooks.v5 v5.17.0
|
||||
gopkg.in/square/go-jose.v2 v2.6.0
|
||||
@@ -113,13 +113,15 @@ require (
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
gopkg.in/retry.v1 v1.0.3 // indirect
|
||||
k8s.io/klog v1.0.0 // indirect
|
||||
nhooyr.io/websocket v1.8.7 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute v1.19.1 // indirect
|
||||
cloud.google.com/go/compute v1.21.0 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
|
||||
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
|
||||
@@ -241,12 +243,12 @@ require (
|
||||
go.opentelemetry.io/otel/trace v1.16.0 // indirect
|
||||
go.opentelemetry.io/proto/otlp v0.19.0 // indirect
|
||||
go.starlark.net v0.0.0-20220328144851-d1966c6b9fcd // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/net v0.11.0 // indirect
|
||||
golang.org/x/sys v0.9.0 // indirect
|
||||
golang.org/x/text v0.10.0 // indirect
|
||||
golang.org/x/mod v0.9.0 // indirect
|
||||
golang.org/x/net v0.17.0
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
golang.org/x/tools v0.7.0 // indirect
|
||||
gomodules.xyz/envconfig v1.3.1-0.20190308184047-426f31af0d45 // indirect
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
|
||||
gomodules.xyz/notify v0.1.1 // indirect
|
||||
|
||||
45
go.sum
45
go.sum
@@ -26,8 +26,8 @@ cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvf
|
||||
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
|
||||
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
|
||||
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
|
||||
cloud.google.com/go/compute v1.19.1 h1:am86mquDUgjGNWxiGn+5PGLbmgiWXlE/yNWpIpNvuXY=
|
||||
cloud.google.com/go/compute v1.19.1/go.mod h1:6ylj3a05WF8leseCdIf77NK0g1ey+nj5IKd5/kvShxE=
|
||||
cloud.google.com/go/compute v1.21.0 h1:JNBsyXVoOoNJtTQcnEY5uYpZIbeCTYIeDe0Xh1bySMk=
|
||||
cloud.google.com/go/compute v1.21.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
@@ -275,8 +275,9 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
|
||||
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
|
||||
github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
|
||||
github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -324,7 +325,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.m
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.10.1 h1:c0g45+xCJhdgFGw7a5QAfdS4byAbud7miNWJ1WwEVf8=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA=
|
||||
github.com/euank/go-kmsg-parser v2.0.0+incompatible/go.mod h1:MhmAMZ8V4CYH4ybgdRwPr2TU5ThnS43puaKEMpja1uw=
|
||||
github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMikGIFbs31qQ=
|
||||
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
|
||||
@@ -1311,8 +1312,9 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
||||
golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
|
||||
golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
@@ -1365,8 +1367,9 @@ golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI=
|
||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
|
||||
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -1435,8 +1438,9 @@ golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU=
|
||||
golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@@ -1453,8 +1457,9 @@ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ
|
||||
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE=
|
||||
golang.org/x/oauth2 v0.9.0 h1:BPpt2kU7oMRq3kCHAA1tbSEshXRw1LpG2ztgDwrzuAs=
|
||||
golang.org/x/oauth2 v0.9.0/go.mod h1:qYgFZaFiu6Wg24azG8bdV52QJXJGbZzIIsRCdVKzbLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -1582,8 +1587,9 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
|
||||
golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@@ -1593,8 +1599,9 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
|
||||
golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
|
||||
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek=
|
||||
golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
@@ -1610,8 +1617,9 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58=
|
||||
golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
@@ -1696,8 +1704,9 @@ golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA=
|
||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
|
||||
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -1799,8 +1808,12 @@ google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxH
|
||||
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
|
||||
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A=
|
||||
google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU=
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98 h1:Z0hjGZePRE0ZBWotvtrwxFNrNE9CUAGtplaDK5NNI/g=
|
||||
google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98 h1:FmF5cCW94Ij59cfpoLiwTgodWmm60eEV0CjlsVg2fuw=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230711160842-782d3b101e98/go.mod h1:rsr7RhLuwsDKL7RmgDDCUc6yaGr1iqceVb5Wv6f6YvQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
@@ -1830,8 +1843,8 @@ google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQ
|
||||
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
|
||||
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
|
||||
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
|
||||
google.golang.org/grpc v1.56.1 h1:z0dNfjIl0VpaZ9iSVjA6daGatAYwPGstTjt5vkRMFkQ=
|
||||
google.golang.org/grpc v1.56.1/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ=
|
||||
google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.8.2
|
||||
newTag: v2.8.7
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -48,6 +48,12 @@ spec:
|
||||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_APPLICATION_NAMESPACES
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: application.namespaces
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
workingDir: /app
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
|
||||
@@ -150,6 +150,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: argocd-cmd-params-cm
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
|
||||
@@ -36,3 +36,15 @@ rules:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create # supports triggering jobs from UI
|
||||
- apiGroups:
|
||||
- argoproj.io
|
||||
resources:
|
||||
- workflows
|
||||
verbs:
|
||||
- create # supports triggering workflows from UI
|
||||
|
||||
@@ -18880,7 +18880,7 @@ spec:
|
||||
key: applicationsetcontroller.allowed.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -19156,6 +19156,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
@@ -19168,7 +19180,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -19220,7 +19232,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -19439,7 +19451,7 @@ spec:
|
||||
key: controller.kubectl.parallelism.limit
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -12,4 +12,4 @@ resources:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.8.2
|
||||
newTag: v2.8.7
|
||||
|
||||
@@ -12,7 +12,7 @@ patches:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.8.2
|
||||
newTag: v2.8.7
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/applicationset-controller
|
||||
|
||||
@@ -1080,7 +1080,13 @@ spec:
|
||||
args:
|
||||
- /readonly/haproxy_init.sh
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
volumeMounts:
|
||||
- name: config-volume
|
||||
mountPath: /readonly
|
||||
@@ -1092,7 +1098,13 @@ spec:
|
||||
image: haproxy:2.6.14-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
@@ -1188,7 +1200,14 @@ spec:
|
||||
args:
|
||||
- /readonly-config/init.sh
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
env:
|
||||
- name: SENTINEL_ID_0
|
||||
value: 3c0d9c0320bb34888c2df5757c718ce6ca992ce6
|
||||
@@ -1213,7 +1232,14 @@ spec:
|
||||
args:
|
||||
- /data/conf/redis.conf
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 15
|
||||
@@ -1263,7 +1289,14 @@ spec:
|
||||
args:
|
||||
- /data/conf/sentinel.conf
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 30
|
||||
periodSeconds: 15
|
||||
@@ -1307,7 +1340,14 @@ spec:
|
||||
args:
|
||||
- /readonly-config/fix-split-brain.sh
|
||||
securityContext:
|
||||
null
|
||||
allowPrivilegeEscalation: false
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
seccompProfile:
|
||||
type: RuntimeDefault
|
||||
env:
|
||||
- name: SENTINEL_ID_0
|
||||
value: 3c0d9c0320bb34888c2df5757c718ce6ca992ce6
|
||||
|
||||
@@ -18763,6 +18763,18 @@ rules:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- argoproj.io
|
||||
resources:
|
||||
- workflows
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
@@ -20117,7 +20129,7 @@ spec:
|
||||
key: applicationsetcontroller.allowed.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -20240,7 +20252,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -20310,7 +20322,13 @@ spec:
|
||||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
- name: ARGOCD_APPLICATION_NAMESPACES
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: application.namespaces
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -20612,6 +20630,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
@@ -20624,7 +20654,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -20676,7 +20706,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -20965,7 +20995,7 @@ spec:
|
||||
key: server.enable.proxy.extension
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -21211,7 +21241,7 @@ spec:
|
||||
key: controller.kubectl.parallelism.limit
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -1635,7 +1635,7 @@ spec:
|
||||
key: applicationsetcontroller.allowed.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -1758,7 +1758,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1828,7 +1828,13 @@ spec:
|
||||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
- name: ARGOCD_APPLICATION_NAMESPACES
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: application.namespaces
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -2130,6 +2136,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
@@ -2142,7 +2160,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -2194,7 +2212,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2483,7 +2501,7 @@ spec:
|
||||
key: server.enable.proxy.extension
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2729,7 +2747,7 @@ spec:
|
||||
key: controller.kubectl.parallelism.limit
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -18722,6 +18722,18 @@ rules:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- apiGroups:
|
||||
- batch
|
||||
resources:
|
||||
- jobs
|
||||
verbs:
|
||||
- create
|
||||
- apiGroups:
|
||||
- argoproj.io
|
||||
resources:
|
||||
- workflows
|
||||
verbs:
|
||||
- create
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
@@ -19218,7 +19230,7 @@ spec:
|
||||
key: applicationsetcontroller.allowed.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -19341,7 +19353,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -19411,7 +19423,13 @@ spec:
|
||||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
- name: ARGOCD_APPLICATION_NAMESPACES
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: application.namespaces
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -19669,6 +19687,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
@@ -19681,7 +19711,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -19733,7 +19763,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -20020,7 +20050,7 @@ spec:
|
||||
key: server.enable.proxy.extension
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -20266,7 +20296,7 @@ spec:
|
||||
key: controller.kubectl.parallelism.limit
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -736,7 +736,7 @@ spec:
|
||||
key: applicationsetcontroller.allowed.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -859,7 +859,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -929,7 +929,13 @@ spec:
|
||||
key: notificationscontroller.log.level
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
- name: ARGOCD_APPLICATION_NAMESPACES
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: application.namespaces
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -1187,6 +1193,18 @@ spec:
|
||||
key: reposerver.streamed.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_REPO_SERVER_DISABLE_HELM_MANIFEST_MAX_EXTRACTED_SIZE
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
key: reposerver.disable.helm.manifest.max.extracted.size
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
- name: ARGOCD_GIT_MODULES_ENABLED
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
@@ -1199,7 +1217,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1251,7 +1269,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1538,7 +1556,7 @@ spec:
|
||||
key: server.enable.proxy.extension
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1784,7 +1802,7 @@ spec:
|
||||
key: controller.kubectl.parallelism.limit
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.8.2
|
||||
image: quay.io/argoproj/argocd:v2.8.7
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -6,10 +6,14 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/glob"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/notification/k8s"
|
||||
|
||||
service "github.com/argoproj/argo-cd/v2/util/notification/argocd"
|
||||
|
||||
argocert "github.com/argoproj/argo-cd/v2/util/cert"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/notification/settings"
|
||||
@@ -19,6 +23,7 @@ import (
|
||||
"github.com/argoproj/notifications-engine/pkg/controller"
|
||||
"github.com/argoproj/notifications-engine/pkg/services"
|
||||
"github.com/argoproj/notifications-engine/pkg/subscriptions"
|
||||
httputil "github.com/argoproj/notifications-engine/pkg/util/http"
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -53,14 +58,21 @@ func NewController(
|
||||
client dynamic.Interface,
|
||||
argocdService service.Service,
|
||||
namespace string,
|
||||
applicationNamespaces []string,
|
||||
appLabelSelector string,
|
||||
registry *controller.MetricsRegistry,
|
||||
secretName string,
|
||||
configMapName string,
|
||||
) *notificationController {
|
||||
appClient := client.Resource(applications)
|
||||
appInformer := newInformer(appClient.Namespace(namespace), appLabelSelector)
|
||||
appProjInformer := newInformer(newAppProjClient(client, namespace), "")
|
||||
var appClient dynamic.ResourceInterface
|
||||
namespaceableAppClient := client.Resource(applications)
|
||||
appClient = namespaceableAppClient
|
||||
if len(applicationNamespaces) == 0 {
|
||||
appClient = namespaceableAppClient.Namespace(namespace)
|
||||
}
|
||||
|
||||
appInformer := newInformer(appClient, namespace, applicationNamespaces, appLabelSelector)
|
||||
appProjInformer := newInformer(newAppProjClient(client, namespace), namespace, []string{namespace}, "")
|
||||
secretInformer := k8s.NewSecretInformer(k8sClient, namespace, secretName)
|
||||
configMapInformer := k8s.NewConfigMapInformer(k8sClient, namespace, configMapName)
|
||||
apiFactory := api.NewFactory(settings.GetFactorySettings(argocdService, secretName, configMapName), namespace, secretInformer, configMapInformer)
|
||||
@@ -71,12 +83,15 @@ func NewController(
|
||||
appInformer: appInformer,
|
||||
appProjInformer: appProjInformer,
|
||||
apiFactory: apiFactory}
|
||||
res.ctrl = controller.NewController(appClient, appInformer, apiFactory,
|
||||
res.ctrl = controller.NewController(namespaceableAppClient, appInformer, apiFactory,
|
||||
controller.WithSkipProcessing(func(obj v1.Object) (bool, string) {
|
||||
app, ok := (obj).(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
return false, ""
|
||||
}
|
||||
if checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces) {
|
||||
return true, "app is not in one of the application-namespaces, nor the notification controller namespace"
|
||||
}
|
||||
return !isAppSyncStatusRefreshed(app, log.WithField("app", obj.GetName())), "sync status out of date"
|
||||
}),
|
||||
controller.WithMetricsRegistry(registry),
|
||||
@@ -84,6 +99,11 @@ func NewController(
|
||||
return res
|
||||
}
|
||||
|
||||
// Check if app is not in the namespace where the controller is in, and also app is not in one of the applicationNamespaces
|
||||
func checkAppNotInAdditionalNamespaces(app *unstructured.Unstructured, namespace string, applicationNamespaces []string) bool {
|
||||
return namespace != app.GetNamespace() && !glob.MatchStringInList(applicationNamespaces, app.GetNamespace(), false)
|
||||
}
|
||||
|
||||
func (c *notificationController) alterDestinations(obj v1.Object, destinations services.Destinations, cfg api.Config) services.Destinations {
|
||||
app, ok := (obj).(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
@@ -97,21 +117,38 @@ func (c *notificationController) alterDestinations(obj v1.Object, destinations s
|
||||
return destinations
|
||||
}
|
||||
|
||||
func newInformer(resClient dynamic.ResourceInterface, selector string) cache.SharedIndexInformer {
|
||||
func newInformer(resClient dynamic.ResourceInterface, controllerNamespace string, applicationNamespaces []string, selector string) cache.SharedIndexInformer {
|
||||
informer := cache.NewSharedIndexInformer(
|
||||
&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (object runtime.Object, err error) {
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
// We are only interested in apps that exist in namespaces the
|
||||
// user wants to be enabled.
|
||||
options.LabelSelector = selector
|
||||
return resClient.List(context.Background(), options)
|
||||
appList, err := resClient.List(context.TODO(), options)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list applications: %w", err)
|
||||
}
|
||||
newItems := []unstructured.Unstructured{}
|
||||
for _, res := range appList.Items {
|
||||
if controllerNamespace == res.GetNamespace() || glob.MatchStringInList(applicationNamespaces, res.GetNamespace(), false) {
|
||||
newItems = append(newItems, res)
|
||||
}
|
||||
}
|
||||
appList.Items = newItems
|
||||
return appList, nil
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
options.LabelSelector = selector
|
||||
return resClient.Watch(context.Background(), options)
|
||||
return resClient.Watch(context.TODO(), options)
|
||||
},
|
||||
},
|
||||
&unstructured.Unstructured{},
|
||||
resyncPeriod,
|
||||
cache.Indexers{},
|
||||
cache.Indexers{
|
||||
cache.NamespaceIndex: func(obj interface{}) ([]string, error) {
|
||||
return cache.MetaNamespaceIndexFunc(obj)
|
||||
},
|
||||
},
|
||||
)
|
||||
return informer
|
||||
}
|
||||
@@ -126,6 +163,9 @@ type notificationController struct {
|
||||
}
|
||||
|
||||
func (c *notificationController) Init(ctx context.Context) error {
|
||||
// resolve certificates using injected "argocd-tls-certs-cm" ConfigMap
|
||||
httputil.SetCertResolver(argocert.GetCertificateForConnect)
|
||||
|
||||
go c.appInformer.Run(ctx.Done())
|
||||
go c.appProjInformer.Run(ctx.Done())
|
||||
go c.secretInformer.Run(ctx.Done())
|
||||
|
||||
@@ -115,6 +115,7 @@ func TestInit(t *testing.T) {
|
||||
dynamicClient,
|
||||
nil,
|
||||
"default",
|
||||
[]string{},
|
||||
appLabelSelector,
|
||||
nil,
|
||||
"my-secret",
|
||||
@@ -146,6 +147,7 @@ func TestInitTimeout(t *testing.T) {
|
||||
dynamicClient,
|
||||
nil,
|
||||
"default",
|
||||
[]string{},
|
||||
appLabelSelector,
|
||||
nil,
|
||||
"my-secret",
|
||||
@@ -164,3 +166,27 @@ func TestInitTimeout(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Timed out waiting for caches to sync", err.Error())
|
||||
}
|
||||
|
||||
func TestCheckAppNotInAdditionalNamespaces(t *testing.T) {
|
||||
app := &unstructured.Unstructured{
|
||||
Object: map[string]interface{}{
|
||||
"spec": map[string]interface{}{},
|
||||
},
|
||||
}
|
||||
namespace := "argocd"
|
||||
var applicationNamespaces []string
|
||||
applicationNamespaces = append(applicationNamespaces, "namespace1")
|
||||
applicationNamespaces = append(applicationNamespaces, "namespace2")
|
||||
|
||||
// app is in same namespace as controller's namespace
|
||||
app.SetNamespace(namespace)
|
||||
assert.False(t, checkAppNotInAdditionalNamespaces(app, namespace, applicationNamespaces))
|
||||
|
||||
// app is not in the namespace as controller's namespace, but it is in one of the applicationNamespaces
|
||||
app.SetNamespace("namespace2")
|
||||
assert.False(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
|
||||
|
||||
// app is not in the namespace as controller's namespace, and it is not in any of the applicationNamespaces
|
||||
app.SetNamespace("namespace3")
|
||||
assert.True(t, checkAppNotInAdditionalNamespaces(app, "", applicationNamespaces))
|
||||
}
|
||||
|
||||
@@ -221,10 +221,6 @@ func NewClient(opts *ClientOptions) (Client, error) {
|
||||
if c.ServerAddr == "" {
|
||||
return nil, errors.New("Argo CD server address unspecified")
|
||||
}
|
||||
if parts := strings.Split(c.ServerAddr, ":"); len(parts) == 1 {
|
||||
// If port is unspecified, assume the most likely port
|
||||
c.ServerAddr += ":443"
|
||||
}
|
||||
// Override auth-token if specified in env variable or CLI flag
|
||||
c.AuthToken = env.StringFromEnv(EnvArgoCDAuthToken, c.AuthToken)
|
||||
if opts.AuthToken != "" {
|
||||
@@ -280,6 +276,10 @@ func NewClient(opts *ClientOptions) (Client, error) {
|
||||
}
|
||||
}
|
||||
if !c.GRPCWeb {
|
||||
if parts := strings.Split(c.ServerAddr, ":"); len(parts) == 1 {
|
||||
// If port is unspecified, assume the most likely port
|
||||
c.ServerAddr += ":443"
|
||||
}
|
||||
// test if we need to set it to true
|
||||
// if a call to grpc failed, then try again with GRPCWeb
|
||||
conn, versionIf, err := c.NewVersionClient()
|
||||
|
||||
@@ -107,6 +107,8 @@ type RepoServerInitConstants struct {
|
||||
AllowOutOfBoundsSymlinks bool
|
||||
StreamedManifestMaxExtractedSize int64
|
||||
StreamedManifestMaxTarSize int64
|
||||
HelmManifestMaxExtractedSize int64
|
||||
DisableHelmManifestMaxExtractedSize bool
|
||||
}
|
||||
|
||||
// NewService returns a new instance of the Manifest service
|
||||
@@ -346,7 +348,7 @@ func (s *Service) runRepoOperation(
|
||||
if source.Helm != nil {
|
||||
helmPassCredentials = source.Helm.PassCredentials
|
||||
}
|
||||
chartPath, closer, err := helmClient.ExtractChart(source.Chart, revision, helmPassCredentials)
|
||||
chartPath, closer, err := helmClient.ExtractChart(source.Chart, revision, helmPassCredentials, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -400,9 +402,15 @@ func (s *Service) runRepoOperation(
|
||||
}
|
||||
}
|
||||
|
||||
commitSHA, err := gitClient.CommitSHA()
|
||||
if err != nil {
|
||||
return err
|
||||
var commitSHA string
|
||||
if hasMultipleSources {
|
||||
commitSHA = revision
|
||||
} else {
|
||||
commit, err := gitClient.CommitSHA()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get commit SHA: %w", err)
|
||||
}
|
||||
commitSHA = commit
|
||||
}
|
||||
|
||||
// double-check locking
|
||||
@@ -1345,7 +1353,7 @@ func GenerateManifests(ctx context.Context, appPath, repoRoot, revision string,
|
||||
pluginName = q.ApplicationSource.Plugin.Name
|
||||
}
|
||||
// if pluginName is provided it has to be `<metadata.name>-<spec.version>` or just `<metadata.name>` if plugin version is empty
|
||||
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, pluginName, env, q, q.Repo.GetGitCreds(gitCredsStore), opt.cmpTarDoneCh, opt.cmpTarExcludedGlobs)
|
||||
targetObjs, err = runConfigManagementPluginSidecars(ctx, appPath, repoRoot, pluginName, env, q, opt.cmpTarDoneCh, opt.cmpTarExcludedGlobs)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("plugin sidecar failed. %s", err.Error())
|
||||
}
|
||||
@@ -1804,25 +1812,17 @@ func makeJsonnetVm(appPath string, repoRoot string, sourceJsonnet v1alpha1.Appli
|
||||
return vm, nil
|
||||
}
|
||||
|
||||
func getPluginEnvs(env *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds) ([]string, error) {
|
||||
func getPluginEnvs(env *v1alpha1.Env, q *apiclient.ManifestRequest) ([]string, error) {
|
||||
envVars := env.Environ()
|
||||
envVars = append(envVars, "KUBE_VERSION="+text.SemVer(q.KubeVersion))
|
||||
envVars = append(envVars, "KUBE_API_VERSIONS="+strings.Join(q.ApiVersions, ","))
|
||||
|
||||
return getPluginParamEnvs(envVars, q.ApplicationSource.Plugin, creds)
|
||||
return getPluginParamEnvs(envVars, q.ApplicationSource.Plugin)
|
||||
}
|
||||
|
||||
// getPluginParamEnvs gets environment variables for plugin parameter announcement generation.
|
||||
func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlugin, creds git.Creds) ([]string, error) {
|
||||
func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlugin) ([]string, error) {
|
||||
env := envVars
|
||||
if creds != nil {
|
||||
closer, environ, err := creds.Environ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() { _ = closer.Close() }()
|
||||
env = append(env, environ...)
|
||||
}
|
||||
|
||||
parsedEnv := make(v1alpha1.Env, len(env))
|
||||
for i, v := range env {
|
||||
@@ -1849,9 +1849,9 @@ func getPluginParamEnvs(envVars []string, plugin *v1alpha1.ApplicationSourcePlug
|
||||
return env, nil
|
||||
}
|
||||
|
||||
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath, pluginName string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, creds git.Creds, tarDoneCh chan<- bool, tarExcludedGlobs []string) ([]*unstructured.Unstructured, error) {
|
||||
func runConfigManagementPluginSidecars(ctx context.Context, appPath, repoPath, pluginName string, envVars *v1alpha1.Env, q *apiclient.ManifestRequest, tarDoneCh chan<- bool, tarExcludedGlobs []string) ([]*unstructured.Unstructured, error) {
|
||||
// compute variables.
|
||||
env, err := getPluginEnvs(envVars, q, creds)
|
||||
env, err := getPluginEnvs(envVars, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -2093,8 +2093,6 @@ func populateKustomizeAppDetails(res *apiclient.RepoAppDetailsResponse, q *apicl
|
||||
func populatePluginAppDetails(ctx context.Context, res *apiclient.RepoAppDetailsResponse, appPath string, repoPath string, q *apiclient.RepoServerAppDetailsQuery, store git.CredsStore, tarExcludedGlobs []string) error {
|
||||
res.Plugin = &apiclient.PluginAppSpec{}
|
||||
|
||||
creds := q.Repo.GetGitCreds(store)
|
||||
|
||||
envVars := []string{
|
||||
fmt.Sprintf("ARGOCD_APP_NAME=%s", q.AppName),
|
||||
fmt.Sprintf("ARGOCD_APP_SOURCE_REPO_URL=%s", q.Repo.Repo),
|
||||
@@ -2102,7 +2100,7 @@ func populatePluginAppDetails(ctx context.Context, res *apiclient.RepoAppDetails
|
||||
fmt.Sprintf("ARGOCD_APP_SOURCE_TARGET_REVISION=%s", q.Source.TargetRevision),
|
||||
}
|
||||
|
||||
env, err := getPluginParamEnvs(envVars, q.Source.Plugin, creds)
|
||||
env, err := getPluginParamEnvs(envVars, q.Source.Plugin)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get env vars for plugin: %w", err)
|
||||
}
|
||||
@@ -2233,7 +2231,7 @@ func (s *Service) GetRevisionChartDetails(ctx context.Context, q *apiclient.Repo
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("helm client error: %v", err)
|
||||
}
|
||||
chartPath, closer, err := helmClient.ExtractChart(q.Name, revision, false)
|
||||
chartPath, closer, err := helmClient.ExtractChart(q.Name, revision, false, s.initConstants.HelmManifestMaxExtractedSize, s.initConstants.DisableHelmManifestMaxExtractedSize)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error extracting chart: %v", err)
|
||||
}
|
||||
|
||||
@@ -1818,6 +1818,44 @@ func TestGenerateManifestWithAnnotatedAndRegularGitTagHashes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGenerateManifestWithAnnotatedTagsAndMultiSourceApp(t *testing.T) {
|
||||
annotatedGitTaghash := "95249be61b028d566c29d47b19e65c5603388a41"
|
||||
|
||||
service := newServiceWithCommitSHA(".", annotatedGitTaghash)
|
||||
|
||||
refSources := map[string]*argoappv1.RefTarget{}
|
||||
|
||||
refSources["$global"] = &argoappv1.RefTarget{
|
||||
TargetRevision: annotatedGitTaghash,
|
||||
}
|
||||
|
||||
refSources["$default"] = &argoappv1.RefTarget{
|
||||
TargetRevision: annotatedGitTaghash,
|
||||
}
|
||||
|
||||
manifestRequest := &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
TargetRevision: annotatedGitTaghash,
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"$global/values.yaml", "$default/secrets.yaml"},
|
||||
},
|
||||
},
|
||||
HasMultipleSources: true,
|
||||
NoCache: true,
|
||||
RefSources: refSources,
|
||||
}
|
||||
|
||||
response, err := service.GenerateManifest(context.Background(), manifestRequest)
|
||||
if err != nil {
|
||||
t.Errorf("unexpected %s", err)
|
||||
}
|
||||
|
||||
if response.Revision != annotatedGitTaghash {
|
||||
t.Errorf("returned SHA %s is different from expected annotated tag %s", response.Revision, annotatedGitTaghash)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFindResources(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
|
||||
@@ -47,11 +47,7 @@ ownerRef.uid = obj.metadata.uid
|
||||
job.metadata.ownerReferences = {}
|
||||
job.metadata.ownerReferences[1] = ownerRef
|
||||
|
||||
job.spec = {}
|
||||
job.spec.suspend = false
|
||||
job.spec.template = {}
|
||||
job.spec.template.metadata = deepCopy(obj.spec.jobTemplate.spec.template.metadata)
|
||||
job.spec.template.spec = deepCopy(obj.spec.jobTemplate.spec.template.spec)
|
||||
job.spec = deepCopy(obj.spec.jobTemplate.spec)
|
||||
|
||||
impactedResource = {}
|
||||
impactedResource.operation = "create"
|
||||
|
||||
@@ -13,6 +13,7 @@ spec:
|
||||
annotations:
|
||||
my: annotation
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 100
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
annotations:
|
||||
my: annotation
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 100
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
health_status = {}
|
||||
|
||||
if obj.status ~= nil and obj.status.reconciliationStatus ~= nil then
|
||||
if obj.status.reconciliationStatus.success then
|
||||
if obj.status.reconciliationStatus.success or obj.status.reconciliationStatus.state == "DEPLOYED" then
|
||||
health_status.status = "Healthy"
|
||||
return health_status
|
||||
end
|
||||
|
||||
@@ -1,10 +1,16 @@
|
||||
tests:
|
||||
- healthStatus:
|
||||
status: Healthy
|
||||
inputPath: testdata/healthy_running.yaml
|
||||
inputPath: testdata/healthy_running_v0.1.x.yaml
|
||||
- healthStatus:
|
||||
status: Healthy
|
||||
inputPath: testdata/healthy_suspended.yaml
|
||||
inputPath: testdata/healthy_running_v1.x.yaml
|
||||
- healthStatus:
|
||||
status: Healthy
|
||||
inputPath: testdata/healthy_suspended_v0.1.x.yaml
|
||||
- healthStatus:
|
||||
status: Healthy
|
||||
inputPath: testdata/healthy_suspended_v1.x.yaml
|
||||
- healthStatus:
|
||||
status: Progressing
|
||||
message: Waiting for deploying
|
||||
|
||||
11
resource_customizations/flink.apache.org/FlinkDeployment/testdata/healthy_running_v1.x.yaml
vendored
Normal file
11
resource_customizations/flink.apache.org/FlinkDeployment/testdata/healthy_running_v1.x.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: flink.apache.org/v1alpha1
|
||||
kind: FlinkDeployment
|
||||
spec:
|
||||
job:
|
||||
state: running
|
||||
status:
|
||||
jobManagerDeploymentStatus: READY
|
||||
jobStatus:
|
||||
state: RUNNING
|
||||
reconciliationStatus:
|
||||
state: DEPLOYED
|
||||
11
resource_customizations/flink.apache.org/FlinkDeployment/testdata/healthy_suspended_v1.x.yaml
vendored
Normal file
11
resource_customizations/flink.apache.org/FlinkDeployment/testdata/healthy_suspended_v1.x.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
apiVersion: flink.apache.org/v1alpha1
|
||||
kind: FlinkDeployment
|
||||
spec:
|
||||
job:
|
||||
state: suspended
|
||||
status:
|
||||
jobManagerDeploymentStatus: MISSING
|
||||
jobStatus:
|
||||
state: SUSPENDED
|
||||
reconciliationStatus:
|
||||
state: DEPLOYED
|
||||
@@ -1383,9 +1383,10 @@ func (s *Server) WatchResourceTree(q *application.ResourcesQuery, ws application
|
||||
return err
|
||||
}
|
||||
|
||||
return s.cache.OnAppResourcesTreeChanged(ws.Context(), q.GetApplicationName(), func() error {
|
||||
cacheKey := argo.AppInstanceName(q.GetApplicationName(), q.GetAppNamespace(), s.ns)
|
||||
return s.cache.OnAppResourcesTreeChanged(ws.Context(), cacheKey, func() error {
|
||||
var tree appv1.ApplicationTree
|
||||
err := s.cache.GetAppResourcesTree(q.GetApplicationName(), &tree)
|
||||
err := s.cache.GetAppResourcesTree(cacheKey, &tree)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error getting app resource tree: %w", err)
|
||||
}
|
||||
|
||||
@@ -9,25 +9,28 @@ import (
|
||||
|
||||
healthutil "github.com/argoproj/gitops-engine/pkg/health"
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
validation "k8s.io/apimachinery/pkg/api/validation"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
appv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned"
|
||||
"github.com/argoproj/argo-cd/v2/util/argo"
|
||||
"github.com/argoproj/argo-cd/v2/util/assets"
|
||||
"github.com/argoproj/argo-cd/v2/util/security"
|
||||
"github.com/argoproj/argo-cd/v2/util/settings"
|
||||
)
|
||||
|
||||
//NewHandler creates handler serving to do api/badge endpoint
|
||||
func NewHandler(appClientset versioned.Interface, settingsMrg *settings.SettingsManager, namespace string) http.Handler {
|
||||
return &Handler{appClientset: appClientset, namespace: namespace, settingsMgr: settingsMrg}
|
||||
// NewHandler creates handler serving to do api/badge endpoint
|
||||
func NewHandler(appClientset versioned.Interface, settingsMrg *settings.SettingsManager, namespace string, enabledNamespaces []string) http.Handler {
|
||||
return &Handler{appClientset: appClientset, namespace: namespace, settingsMgr: settingsMrg, enabledNamespaces: enabledNamespaces}
|
||||
}
|
||||
|
||||
//Handler used to get application in order to access health/sync
|
||||
// Handler used to get application in order to access health/sync
|
||||
type Handler struct {
|
||||
namespace string
|
||||
appClientset versioned.Interface
|
||||
settingsMgr *settings.SettingsManager
|
||||
namespace string
|
||||
appClientset versioned.Interface
|
||||
settingsMgr *settings.SettingsManager
|
||||
enabledNamespaces []string
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -62,8 +65,8 @@ func replaceFirstGroupSubMatch(re *regexp.Regexp, str string, repl string) strin
|
||||
return result + str[lastIndex:]
|
||||
}
|
||||
|
||||
//ServeHTTP returns badge with health and sync status for application
|
||||
//(or an error badge if wrong query or application name is given)
|
||||
// ServeHTTP returns badge with health and sync status for application
|
||||
// (or an error badge if wrong query or application name is given)
|
||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
health := healthutil.HealthStatusUnknown
|
||||
status := appv1.SyncStatusCodeUnknown
|
||||
@@ -75,21 +78,50 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
enabled = sets.StatusBadgeEnabled
|
||||
}
|
||||
|
||||
//Sample url: http://localhost:8080/api/badge?name=123
|
||||
if name, ok := r.URL.Query()["name"]; ok && enabled {
|
||||
if app, err := h.appClientset.ArgoprojV1alpha1().Applications(h.namespace).Get(context.Background(), name[0], v1.GetOptions{}); err == nil {
|
||||
health = app.Status.Health.Status
|
||||
status = app.Status.Sync.Status
|
||||
if app.Status.OperationState != nil && app.Status.OperationState.SyncResult != nil {
|
||||
revision = app.Status.OperationState.SyncResult.Revision
|
||||
reqNs := ""
|
||||
if ns, ok := r.URL.Query()["namespace"]; ok && enabled {
|
||||
if errs := validation.NameIsDNSSubdomain(strings.ToLower(ns[0]), false); len(errs) == 0 {
|
||||
if security.IsNamespaceEnabled(ns[0], h.namespace, h.enabledNamespaces) {
|
||||
reqNs = ns[0]
|
||||
} else {
|
||||
notFound = true
|
||||
}
|
||||
} else if errors.IsNotFound(err) {
|
||||
notFound = true
|
||||
} else {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
reqNs = h.namespace
|
||||
}
|
||||
|
||||
//Sample url: http://localhost:8080/api/badge?name=123
|
||||
if name, ok := r.URL.Query()["name"]; ok && enabled && !notFound {
|
||||
if errs := validation.NameIsDNSLabel(strings.ToLower(name[0]), false); len(errs) == 0 {
|
||||
if app, err := h.appClientset.ArgoprojV1alpha1().Applications(reqNs).Get(context.Background(), name[0], v1.GetOptions{}); err == nil {
|
||||
health = app.Status.Health.Status
|
||||
status = app.Status.Sync.Status
|
||||
if app.Status.OperationState != nil && app.Status.OperationState.SyncResult != nil {
|
||||
revision = app.Status.OperationState.SyncResult.Revision
|
||||
}
|
||||
} else {
|
||||
if errors.IsNotFound(err) {
|
||||
notFound = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
//Sample url: http://localhost:8080/api/badge?project=default
|
||||
if projects, ok := r.URL.Query()["project"]; ok && enabled {
|
||||
if apps, err := h.appClientset.ArgoprojV1alpha1().Applications(h.namespace).List(context.Background(), v1.ListOptions{}); err == nil {
|
||||
if projects, ok := r.URL.Query()["project"]; ok && enabled && !notFound {
|
||||
for _, p := range projects {
|
||||
if errs := validation.NameIsDNSLabel(strings.ToLower(p), false); len(p) > 0 && len(errs) != 0 {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
}
|
||||
if apps, err := h.appClientset.ArgoprojV1alpha1().Applications(reqNs).List(context.Background(), v1.ListOptions{}); err == nil {
|
||||
applicationSet := argo.FilterByProjects(apps.Items, projects)
|
||||
for _, a := range applicationSet {
|
||||
if a.Status.Sync.Status != appv1.SyncStatusCodeSynced {
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/health"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
@@ -41,7 +42,19 @@ var (
|
||||
},
|
||||
}
|
||||
testApp = v1alpha1.Application{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "testApp", Namespace: "default"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "test-app", Namespace: "default"},
|
||||
Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeSynced},
|
||||
Health: v1alpha1.HealthStatus{Status: health.HealthStatusHealthy},
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
SyncResult: &v1alpha1.SyncOperationResult{
|
||||
Revision: "aa29b85",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
testApp2 = v1alpha1.Application{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "test-app", Namespace: "argocd-test"},
|
||||
Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{Status: v1alpha1.SyncStatusCodeSynced},
|
||||
Health: v1alpha1.HealthStatus{Status: health.HealthStatusHealthy},
|
||||
@@ -53,15 +66,15 @@ var (
|
||||
},
|
||||
}
|
||||
testProject = v1alpha1.AppProject{
|
||||
ObjectMeta: v1.ObjectMeta{Name: "testProject", Namespace: "default"},
|
||||
ObjectMeta: v1.ObjectMeta{Name: "test-project", Namespace: "default"},
|
||||
Spec: v1alpha1.AppProjectSpec{},
|
||||
}
|
||||
)
|
||||
|
||||
func TestHandlerFeatureIsEnabled(t *testing.T) {
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default")
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=testApp", nil)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default", []string{})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -81,6 +94,7 @@ func TestHandlerFeatureIsEnabled(t *testing.T) {
|
||||
func TestHandlerFeatureProjectIsEnabled(t *testing.T) {
|
||||
projectTests := []struct {
|
||||
testApp []*v1alpha1.Application
|
||||
response int
|
||||
apiEndPoint string
|
||||
namespace string
|
||||
health string
|
||||
@@ -89,42 +103,105 @@ func TestHandlerFeatureProjectIsEnabled(t *testing.T) {
|
||||
statusColor color.RGBA
|
||||
}{
|
||||
{createApplications([]string{"Healthy:Synced", "Healthy:Synced"}, []string{"default", "default"}, "test"),
|
||||
"/api/badge?project=default", "test", "Healthy", "Synced", Green, Green},
|
||||
{createApplications([]string{"Healthy:Synced", "Healthy:OutOfSync"}, []string{"testProject", "testProject"}, "default"),
|
||||
"/api/badge?project=testProject", "default", "Healthy", "OutOfSync", Green, Orange},
|
||||
http.StatusOK, "/api/badge?project=default", "test", "Healthy", "Synced", Green, Green},
|
||||
{createApplications([]string{"Healthy:Synced", "Healthy:OutOfSync"}, []string{"test-project", "test-project"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=test-project", "default", "Healthy", "OutOfSync", Green, Orange},
|
||||
{createApplications([]string{"Healthy:Synced", "Degraded:Synced"}, []string{"default", "default"}, "test"),
|
||||
"/api/badge?project=default", "test", "Degraded", "Synced", Red, Green},
|
||||
{createApplications([]string{"Healthy:Synced", "Degraded:OutOfSync"}, []string{"testProject", "testProject"}, "default"),
|
||||
"/api/badge?project=testProject", "default", "Degraded", "OutOfSync", Red, Orange},
|
||||
{createApplications([]string{"Healthy:Synced", "Healthy:Synced"}, []string{"testProject", "default"}, "test"),
|
||||
"/api/badge?project=default&project=testProject", "test", "Healthy", "Synced", Green, Green},
|
||||
{createApplications([]string{"Healthy:OutOfSync", "Healthy:Synced"}, []string{"testProject", "default"}, "default"),
|
||||
"/api/badge?project=default&project=testProject", "default", "Healthy", "OutOfSync", Green, Orange},
|
||||
{createApplications([]string{"Degraded:Synced", "Healthy:Synced"}, []string{"testProject", "default"}, "test"),
|
||||
"/api/badge?project=default&project=testProject", "test", "Degraded", "Synced", Red, Green},
|
||||
{createApplications([]string{"Degraded:OutOfSync", "Healthy:OutOfSync"}, []string{"testProject", "default"}, "default"),
|
||||
"/api/badge?project=default&project=testProject", "default", "Degraded", "OutOfSync", Red, Orange},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"testProject", "default"}, "default"),
|
||||
"/api/badge?project=", "default", "Unknown", "Unknown", Purple, Purple},
|
||||
http.StatusOK, "/api/badge?project=default", "test", "Degraded", "Synced", Red, Green},
|
||||
{createApplications([]string{"Healthy:Synced", "Degraded:OutOfSync"}, []string{"test-project", "test-project"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=test-project", "default", "Degraded", "OutOfSync", Red, Orange},
|
||||
{createApplications([]string{"Healthy:Synced", "Healthy:Synced"}, []string{"test-project", "default"}, "test"),
|
||||
http.StatusOK, "/api/badge?project=default&project=test-project", "test", "Healthy", "Synced", Green, Green},
|
||||
{createApplications([]string{"Healthy:OutOfSync", "Healthy:Synced"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=default&project=test-project", "default", "Healthy", "OutOfSync", Green, Orange},
|
||||
{createApplications([]string{"Degraded:Synced", "Healthy:Synced"}, []string{"test-project", "default"}, "test"),
|
||||
http.StatusOK, "/api/badge?project=default&project=test-project", "test", "Degraded", "Synced", Red, Green},
|
||||
{createApplications([]string{"Degraded:OutOfSync", "Healthy:OutOfSync"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=default&project=test-project", "default", "Degraded", "OutOfSync", Red, Orange},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=", "default", "Unknown", "Unknown", Purple, Purple},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusBadRequest, "/api/badge?project=test$project", "default", "Unknown", "Unknown", Purple, Purple},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusOK, "/api/badge?project=unknown", "default", "Unknown", "Unknown", Purple, Purple},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusBadRequest, "/api/badge?name=foo_bar", "default", "Unknown", "Unknown", Purple, Purple},
|
||||
{createApplications([]string{"Unknown:Unknown", "Unknown:Unknown"}, []string{"test-project", "default"}, "default"),
|
||||
http.StatusOK, "/api/badge?name=foobar", "default", "Not Found", "", Purple, Purple},
|
||||
}
|
||||
for _, tt := range projectTests {
|
||||
argoCDCm.ObjectMeta.Namespace = tt.namespace
|
||||
argoCDSecret.ObjectMeta.Namespace = tt.namespace
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), tt.namespace)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testProject, tt.testApp[0], tt.testApp[1]), settingsMgr, tt.namespace)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testProject, tt.testApp[0], tt.testApp[1]), settingsMgr, tt.namespace, []string{})
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, tt.apiEndPoint, nil)
|
||||
assert.NoError(t, err)
|
||||
handler.ServeHTTP(rr, req)
|
||||
require.Equal(t, tt.response, rr.Result().StatusCode)
|
||||
if rr.Result().StatusCode != 400 {
|
||||
assert.Equal(t, "private, no-store", rr.Header().Get("Cache-Control"))
|
||||
assert.Equal(t, "*", rr.Header().Get("Access-Control-Allow-Origin"))
|
||||
response := rr.Body.String()
|
||||
require.Greater(t, len(response), 2)
|
||||
assert.Equal(t, toRGBString(tt.healthColor), leftRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, toRGBString(tt.statusColor), rightRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, tt.health, leftTextPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, tt.status, rightTextPattern.FindStringSubmatch(response)[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandlerNamespacesIsEnabled(t *testing.T) {
|
||||
t.Run("Application in allowed namespace", func(t *testing.T) {
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp2), settingsMgr, "default", []string{"argocd-test"})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=argocd-test", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, "private, no-store", rr.Header().Get("Cache-Control"))
|
||||
assert.Equal(t, "*", rr.Header().Get("Access-Control-Allow-Origin"))
|
||||
response := rr.Body.String()
|
||||
assert.Equal(t, toRGBString(tt.healthColor), leftRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, toRGBString(tt.statusColor), rightRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, tt.health, leftTextPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, tt.status, rightTextPattern.FindStringSubmatch(response)[1])
|
||||
|
||||
}
|
||||
response := rr.Body.String()
|
||||
assert.Equal(t, toRGBString(Green), leftRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, toRGBString(Green), rightRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, "Healthy", leftTextPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, "Synced", rightTextPattern.FindStringSubmatch(response)[1])
|
||||
assert.NotContains(t, response, "(aa29b85)")
|
||||
})
|
||||
|
||||
t.Run("Application in disallowed namespace", func(t *testing.T) {
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp2), settingsMgr, "default", []string{"argocd-test"})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=kube-system", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusOK, rr.Result().StatusCode)
|
||||
response := rr.Body.String()
|
||||
assert.Equal(t, toRGBString(Purple), leftRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, toRGBString(Purple), rightRectColorPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, "Not Found", leftTextPattern.FindStringSubmatch(response)[1])
|
||||
assert.Equal(t, "", rightTextPattern.FindStringSubmatch(response)[1])
|
||||
|
||||
})
|
||||
|
||||
t.Run("Request with illegal namespace", func(t *testing.T) {
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp2), settingsMgr, "default", []string{"argocd-test"})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&namespace=kube()system", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rr, req)
|
||||
|
||||
assert.Equal(t, http.StatusBadRequest, rr.Result().StatusCode)
|
||||
})
|
||||
}
|
||||
|
||||
func createApplicationFeatureProjectIsEnabled(healthStatus health.HealthStatusCode, syncStatus v1alpha1.SyncStatusCode, appName, projectName, namespace string) *v1alpha1.Application {
|
||||
@@ -176,8 +253,8 @@ func createApplications(appCombo, projectName []string, namespace string) []*v1a
|
||||
}
|
||||
func TestHandlerFeatureIsEnabledRevisionIsEnabled(t *testing.T) {
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default")
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=testApp&revision=true", nil)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default", []string{})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -199,8 +276,8 @@ func TestHandlerRevisionIsEnabledNoOperationState(t *testing.T) {
|
||||
app.Status.OperationState = nil
|
||||
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default")
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=testApp&revision=true", nil)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default", []string{})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -222,8 +299,8 @@ func TestHandlerRevisionIsEnabledShortCommitSHA(t *testing.T) {
|
||||
app.Status.OperationState.SyncResult.Revision = "abc"
|
||||
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(&argoCDCm, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default")
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=testApp&revision=true", nil)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(app), settingsMgr, "default", []string{})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app&revision=true", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
@@ -239,8 +316,8 @@ func TestHandlerFeatureIsDisabled(t *testing.T) {
|
||||
delete(argoCDCmDisabled.Data, "statusbadge.enabled")
|
||||
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), fake.NewSimpleClientset(argoCDCmDisabled, &argoCDSecret), "default")
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default")
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=testApp", nil)
|
||||
handler := NewHandler(appclientset.NewSimpleClientset(&testApp), settingsMgr, "default", []string{})
|
||||
req, err := http.NewRequest(http.MethodGet, "/api/badge?name=test-app", nil)
|
||||
assert.NoError(t, err)
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
|
||||
@@ -951,7 +951,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
|
||||
Handler: &handlerSwitcher{
|
||||
handler: mux,
|
||||
urlToHandler: map[string]http.Handler{
|
||||
"/api/badge": badge.NewHandler(a.AppClientset, a.settingsMgr, a.Namespace),
|
||||
"/api/badge": badge.NewHandler(a.AppClientset, a.settingsMgr, a.Namespace, a.ApplicationNamespaces),
|
||||
common.LogoutEndpoint: logout.NewHandler(a.AppClientset, a.settingsMgr, a.sessionMgr, a.ArgoCDServerOpts.RootPath, a.ArgoCDServerOpts.BaseHRef, a.Namespace),
|
||||
},
|
||||
contentTypeToHandler: map[string]http.Handler{
|
||||
|
||||
@@ -8,7 +8,7 @@ RUN ln -s /usr/lib/$(uname -m)-linux-gnu /usr/lib/linux-gnu
|
||||
# Please make sure to also check the contained yarn version and update the references below when upgrading this image's version
|
||||
FROM docker.io/library/node:20.3.1@sha256:2f0b0c15f97441defa812268ee943bbfaaf666ea6cf7cac62ee3f127906b35c6 as node
|
||||
|
||||
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c as golang
|
||||
FROM docker.io/library/golang:1.20.10@sha256:ed6c4a5918b0a1ffb97970f6493d742dc5c7ebf3ccbd417c215d52830b57b994 as golang
|
||||
|
||||
FROM docker.io/library/registry:2.8@sha256:41f413c22d6156587e2a51f3e80c09808b8c70e82be149b82b5e0196a88d49b4 as registry
|
||||
|
||||
|
||||
@@ -1754,6 +1754,40 @@ func TestCompareOptionIgnoreExtraneous(t *testing.T) {
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced))
|
||||
}
|
||||
|
||||
func TestSourceNamespaceCanBeMigratedToManagedNamespaceWithoutBeingPrunedOrOutOfSync(t *testing.T) {
|
||||
Given(t).
|
||||
Prune(true).
|
||||
Path("guestbook-with-plain-namespace-manifest").
|
||||
When().
|
||||
PatchFile("guestbook-ui-namespace.yaml", fmt.Sprintf(`[{"op": "replace", "path": "/metadata/name", "value": "%s"}]`, DeploymentNamespace())).
|
||||
CreateApp().
|
||||
Sync().
|
||||
Then().
|
||||
Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
When().
|
||||
PatchApp(`[{
|
||||
"op": "add",
|
||||
"path": "/spec/syncPolicy",
|
||||
"value": { "prune": true, "syncOptions": ["PrunePropagationPolicy=foreground"], "managedNamespaceMetadata": { "labels": { "foo": "bar" } } }
|
||||
}]`).
|
||||
Sync().
|
||||
Then().
|
||||
Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
And(func(app *Application) {
|
||||
assert.Equal(t, &ManagedNamespaceMetadata{Labels: map[string]string{"foo": "bar"}}, app.Spec.SyncPolicy.ManagedNamespaceMetadata)
|
||||
}).
|
||||
When().
|
||||
DeleteFile("guestbook-ui-namespace.yaml").
|
||||
Refresh(RefreshTypeHard).
|
||||
Sync().
|
||||
Wait().
|
||||
Then().
|
||||
Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced))
|
||||
}
|
||||
|
||||
func TestSelfManagedApps(t *testing.T) {
|
||||
|
||||
Given(t).
|
||||
|
||||
@@ -48,7 +48,6 @@ var (
|
||||
Reason: v1alpha1.ApplicationSetReasonApplicationSetUpToDate,
|
||||
},
|
||||
}
|
||||
LabelKeyAppSetInstance = "argocd.argoproj.io/application-set-name"
|
||||
)
|
||||
|
||||
func TestSimpleListGeneratorExternalNamespace(t *testing.T) {
|
||||
@@ -59,11 +58,8 @@ func TestSimpleListGeneratorExternalNamespace(t *testing.T) {
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator-external",
|
||||
},
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
@@ -135,15 +131,13 @@ func TestSimpleListGeneratorExternalNamespace(t *testing.T) {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-list-generator-external",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
appset.Spec.Template.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-list-generator-external",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
|
||||
|
||||
@@ -164,11 +158,8 @@ func TestSimpleListGenerator(t *testing.T) {
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
},
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
@@ -235,10 +226,7 @@ func TestSimpleListGenerator(t *testing.T) {
|
||||
And(func() {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
@@ -265,9 +253,6 @@ func TestSimpleListGeneratorGoTemplate(t *testing.T) {
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -334,10 +319,7 @@ func TestSimpleListGeneratorGoTemplate(t *testing.T) {
|
||||
And(func() {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
@@ -364,9 +346,6 @@ func TestRenderHelmValuesObject(t *testing.T) {
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "test-values-object",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -443,9 +422,6 @@ func TestSyncPolicyCreateUpdate(t *testing.T) {
|
||||
Name: "my-cluster-guestbook-sync-policy-create-update",
|
||||
Namespace: utils.ArgoCDNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "sync-policy-create-update",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -515,15 +491,13 @@ func TestSyncPolicyCreateUpdate(t *testing.T) {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "sync-policy-create-update",
|
||||
"label-key": "label-value",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
appset.Spec.Template.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "sync-policy-create-update",
|
||||
"label-key": "label-value",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
applicationsSyncPolicy := argov1alpha1.ApplicationsSyncPolicyCreateUpdate
|
||||
appset.Spec.SyncPolicy = &argov1alpha1.ApplicationSetSyncPolicy{
|
||||
@@ -558,9 +532,6 @@ func TestSyncPolicyCreateDelete(t *testing.T) {
|
||||
Name: "my-cluster-guestbook-sync-policy-create-delete",
|
||||
Namespace: utils.ArgoCDNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "sync-policy-create-delete",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -661,9 +632,6 @@ func TestSyncPolicyCreateOnly(t *testing.T) {
|
||||
Name: "my-cluster-guestbook-sync-policy-create-only",
|
||||
Namespace: utils.ArgoCDNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "sync-policy-create-only",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -764,9 +732,6 @@ func TestSimpleGitDirectoryGenerator(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -848,10 +813,7 @@ func TestSimpleGitDirectoryGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -879,9 +841,6 @@ func TestSimpleGitDirectoryGeneratorGoTemplate(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -964,10 +923,7 @@ func TestSimpleGitDirectoryGeneratorGoTemplate(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -996,9 +952,6 @@ func TestSimpleGitFilesGenerator(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1079,10 +1032,7 @@ func TestSimpleGitFilesGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -1111,9 +1061,6 @@ func TestSimpleGitFilesGeneratorGoTemplate(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1195,10 +1142,7 @@ func TestSimpleGitFilesGeneratorGoTemplate(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -1557,9 +1501,6 @@ func TestSimpleSCMProviderGenerator(t *testing.T) {
|
||||
Name: "argo-cd-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-scm-provider-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1634,9 +1575,6 @@ func TestSimpleSCMProviderGeneratorGoTemplate(t *testing.T) {
|
||||
Name: "argo-cd-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-scm-provider-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1706,9 +1644,6 @@ func TestSCMProviderGeneratorSCMProviderNotAllowed(t *testing.T) {
|
||||
Name: "argo-cd-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-scm-provider-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1784,9 +1719,6 @@ func TestCustomApplicationFinalizers(t *testing.T) {
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1853,9 +1785,6 @@ func TestCustomApplicationFinalizersGoTemplate(t *testing.T) {
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-list-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -1963,9 +1892,6 @@ func TestSimplePullRequestGenerator(t *testing.T) {
|
||||
Name: "guestbook-1",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-pull-request-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -2043,10 +1969,7 @@ func TestSimplePullRequestGeneratorGoTemplate(t *testing.T) {
|
||||
Name: "guestbook-1",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
"app": "preview",
|
||||
LabelKeyAppSetInstance: "simple-pull-request-generator",
|
||||
},
|
||||
Labels: map[string]string{"app": "preview"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -2122,8 +2045,7 @@ func TestPullRequestGeneratorNotAllowedSCMProvider(t *testing.T) {
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
"app": "preview",
|
||||
LabelKeyAppSetInstance: "simple-pull-request-generator",
|
||||
"app": "preview",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
@@ -2206,9 +2128,6 @@ func TestGitGeneratorPrivateRepo(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator-private",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -2284,9 +2203,6 @@ func TestGitGeneratorPrivateRepoGoTemplate(t *testing.T) {
|
||||
Name: name,
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-git-generator-private",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
|
||||
@@ -24,11 +24,8 @@ func TestSimpleClusterGeneratorExternalNamespace(t *testing.T) {
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
@@ -104,15 +101,13 @@ func TestSimpleClusterGeneratorExternalNamespace(t *testing.T) {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
appset.Spec.Template.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
|
||||
|
||||
@@ -132,9 +127,6 @@ func TestSimpleClusterGenerator(t *testing.T) {
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -206,10 +198,7 @@ func TestSimpleClusterGenerator(t *testing.T) {
|
||||
And(func() {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
@@ -231,9 +220,6 @@ func TestClusterGeneratorWithLocalCluster(t *testing.T) {
|
||||
Name: "in-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "in-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -326,10 +312,7 @@ func TestClusterGeneratorWithLocalCluster(t *testing.T) {
|
||||
And(func() {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "in-cluster-generator",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
@@ -354,9 +337,6 @@ func TestSimpleClusterGeneratorAddingCluster(t *testing.T) {
|
||||
Name: "{{name}}-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -439,9 +419,6 @@ func TestSimpleClusterGeneratorDeletingCluster(t *testing.T) {
|
||||
Name: "{{name}}-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
|
||||
@@ -25,11 +25,8 @@ func TestSimpleClusterDecisionResourceGeneratorExternalNamespace(t *testing.T) {
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: utils.ArgoCDExternalNamespace,
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
@@ -113,15 +110,13 @@ func TestSimpleClusterDecisionResourceGeneratorExternalNamespace(t *testing.T) {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
appset.Spec.Template.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{*expectedAppNewMetadata})).
|
||||
|
||||
@@ -141,9 +136,6 @@ func TestSimpleClusterDecisionResourceGenerator(t *testing.T) {
|
||||
Name: "cluster1-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -223,10 +215,7 @@ func TestSimpleClusterDecisionResourceGenerator(t *testing.T) {
|
||||
And(func() {
|
||||
expectedAppNewMetadata = expectedAppNewNamespace.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
"label-key": "label-value",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
}).
|
||||
Update(func(appset *v1alpha1.ApplicationSet) {
|
||||
appset.Spec.Template.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
@@ -249,9 +238,6 @@ func TestSimpleClusterDecisionResourceGeneratorAddingCluster(t *testing.T) {
|
||||
Name: "{{name}}-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -347,9 +333,6 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterSecret(t *testing.
|
||||
Name: "{{name}}-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -447,9 +430,6 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterFromResource(t *te
|
||||
Name: "{{name}}-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "simple-cluster-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
|
||||
@@ -39,12 +39,7 @@ func TestCustomToolWithGitCreds(t *testing.T) {
|
||||
Then().
|
||||
Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
Expect(HealthIs(health.HealthStatusHealthy)).
|
||||
And(func(app *Application) {
|
||||
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitAskpass}")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "argocd", output)
|
||||
})
|
||||
Expect(HealthIs(health.HealthStatusHealthy))
|
||||
}
|
||||
|
||||
// make sure we can echo back the Git creds
|
||||
@@ -70,11 +65,6 @@ func TestCustomToolWithGitCredsTemplate(t *testing.T) {
|
||||
Expect(OperationPhaseIs(OperationSucceeded)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced)).
|
||||
Expect(HealthIs(health.HealthStatusHealthy)).
|
||||
And(func(app *Application) {
|
||||
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitAskpass}")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "argocd", output)
|
||||
}).
|
||||
And(func(app *Application) {
|
||||
output, err := Run("", "kubectl", "-n", DeploymentNamespace(), "get", "cm", ctx.AppName(), "-o", "jsonpath={.metadata.annotations.GitUsername}")
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -26,9 +26,6 @@ func TestListMatrixGenerator(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", cluster, name),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "matrix-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -128,10 +125,7 @@ func TestListMatrixGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "matrix-generator",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -156,9 +150,6 @@ func TestClusterMatrixGenerator(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", cluster, name),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "matrix-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -261,10 +252,7 @@ func TestClusterMatrixGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "matrix-generator",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -289,9 +277,6 @@ func TestMatrixTerminalMatrixGeneratorSelector(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", cluster, name),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "matrix-generator-nested-matrix",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -443,9 +428,6 @@ func TestMatrixTerminalMergeGeneratorSelector(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", name, nameSuffix),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "matrix-generator-nested-merge",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
|
||||
@@ -27,9 +27,6 @@ func TestListMergeGenerator(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", name, nameSuffix),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "merge-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -125,10 +122,7 @@ func TestListMergeGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "merge-generator",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -153,9 +147,6 @@ func TestClusterMergeGenerator(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s-%s", cluster, name, nameSuffix),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "merge-generator",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
@@ -276,10 +267,7 @@ func TestClusterMergeGenerator(t *testing.T) {
|
||||
for _, expectedApp := range expectedAppsNewNamespace {
|
||||
expectedAppNewMetadata := expectedApp.DeepCopy()
|
||||
expectedAppNewMetadata.ObjectMeta.Annotations = map[string]string{"annotation-key": "annotation-value"}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{
|
||||
"label-key": "label-value",
|
||||
LabelKeyAppSetInstance: "merge-generator",
|
||||
}
|
||||
expectedAppNewMetadata.ObjectMeta.Labels = map[string]string{"label-key": "label-value"}
|
||||
expectedAppsNewMetadata = append(expectedAppsNewMetadata, *expectedAppNewMetadata)
|
||||
}
|
||||
}).
|
||||
@@ -304,9 +292,6 @@ func TestMergeTerminalMergeGeneratorSelector(t *testing.T) {
|
||||
Name: fmt.Sprintf("%s-%s", name, nameSuffix),
|
||||
Namespace: utils.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
Labels: map[string]string{
|
||||
LabelKeyAppSetInstance: "merge-generator-nested-merge",
|
||||
},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
|
||||
23
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-deployment.yaml
vendored
Normal file
23
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-deployment.yaml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: guestbook-ui
|
||||
labels:
|
||||
test: "true"
|
||||
spec:
|
||||
replicas: 0
|
||||
revisionHistoryLimit: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app: guestbook-ui
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: guestbook-ui
|
||||
spec:
|
||||
containers:
|
||||
- image: quay.io/argoprojlabs/argocd-e2e-container:0.2
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: guestbook-ui
|
||||
ports:
|
||||
- containerPort: 80
|
||||
9
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-namespace.yaml
vendored
Normal file
9
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-namespace.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: guestbook-ui-with-namespace-manifest
|
||||
labels:
|
||||
test: "true"
|
||||
annotations:
|
||||
foo: bar
|
||||
something: else
|
||||
10
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-svc.yaml
vendored
Normal file
10
test/e2e/testdata/guestbook-with-plain-namespace-manifest/guestbook-ui-svc.yaml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: guestbook-ui
|
||||
spec:
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
selector:
|
||||
app: guestbook-ui
|
||||
@@ -1,6 +1,6 @@
|
||||
ARG BASE_IMAGE=docker.io/library/ubuntu:22.04
|
||||
|
||||
FROM docker.io/library/golang:1.20.6@sha256:8e5a0067e6b387263a01d06b91ef1a983f90e9638564f6e25392fd2695f7ab6c AS go
|
||||
FROM docker.io/library/golang:1.20.10@sha256:ed6c4a5918b0a1ffb97970f6493d742dc5c7ebf3ccbd417c215d52830b57b994 AS go
|
||||
|
||||
RUN go install github.com/mattn/goreman@latest && \
|
||||
go install github.com/kisielk/godepgraph@latest
|
||||
|
||||
@@ -32,7 +32,7 @@ export const RevisionMetadataRows = (props: {applicationName: string; applicatio
|
||||
<div className='columns small-9'>{m.description}</div>
|
||||
</div>
|
||||
)}
|
||||
{m.maintainers.length > 0 && (
|
||||
{m.maintainers && m.maintainers.length > 0 && (
|
||||
<div className='row'>
|
||||
<div className='columns small-3'>Maintainers:</div>
|
||||
<div className='columns small-9'>{m.maintainers.join(', ')}</div>
|
||||
|
||||
@@ -154,7 +154,7 @@ $header: 120px;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: map-get($breakpoints, xlarge)) {
|
||||
@media screen and (max-width: map-get($breakpoints, xxlarge)) {
|
||||
.page__content-wrapper {
|
||||
min-height: calc(100vh - 3 * 50px);
|
||||
}
|
||||
|
||||
@@ -459,7 +459,8 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
|
||||
<Tooltip
|
||||
content={AppUtils.userMsgsList[showToolTip?.msgKey] || 'Group Nodes'}
|
||||
visible={pref.groupNodes && showToolTip !== undefined && !showToolTip?.display}
|
||||
duration={showToolTip?.duration}>
|
||||
duration={showToolTip?.duration}
|
||||
zIndex={1}>
|
||||
<a
|
||||
className={`group-nodes-button group-nodes-button${!pref.groupNodes ? '' : '-on'}`}
|
||||
title={pref.view === 'tree' ? 'Group Nodes' : 'Collapse Pods'}
|
||||
@@ -669,7 +670,7 @@ export class ApplicationDetails extends React.Component<RouteComponentProps<{app
|
||||
<div className='columns small-9'>{m.description}</div>
|
||||
</div>
|
||||
)}
|
||||
{m.maintainers.length > 0 && (
|
||||
{m.maintainers && m.maintainers.length > 0 && (
|
||||
<div className='row white-box__details-row'>
|
||||
<div className='columns small-3'>Maintainers:</div>
|
||||
<div className='columns small-9'>{m.maintainers.join(', ')}</div>
|
||||
|
||||
@@ -85,7 +85,10 @@ export const ApplicationResourceList = ({
|
||||
<Consumer>
|
||||
{ctx => (
|
||||
<span className='application-details__external_link'>
|
||||
<a href={ctx.baseHref + 'applications/' + res.namespace + '/' + res.name} title='Open application'>
|
||||
<a
|
||||
href={ctx.baseHref + 'applications/' + res.namespace + '/' + res.name}
|
||||
onClick={e => e.stopPropagation()}
|
||||
title='Open application'>
|
||||
<i className='fa fa-external-link-alt' />
|
||||
</a>
|
||||
</span>
|
||||
|
||||
@@ -15,7 +15,7 @@ $deselected-text: #818d94;
|
||||
color: white;
|
||||
background-color: #0f2733;
|
||||
overflow: auto;
|
||||
z-index: 0;
|
||||
z-index: 2;
|
||||
|
||||
&__container {
|
||||
padding: 0 5px;
|
||||
|
||||
@@ -165,7 +165,7 @@ func (rt *resourceTracking) BuildAppInstanceValue(value AppInstanceValue) string
|
||||
//ParseAppInstanceValue parse resource tracking id from format <application-name>:<group>/<kind>:<namespace>/<name> to struct
|
||||
func (rt *resourceTracking) ParseAppInstanceValue(value string) (*AppInstanceValue, error) {
|
||||
var appInstanceValue AppInstanceValue
|
||||
parts := strings.Split(value, ":")
|
||||
parts := strings.SplitN(value, ":", 3)
|
||||
appInstanceValue.ApplicationName = parts[0]
|
||||
if len(parts) != 3 {
|
||||
return nil, WrongResourceTrackingFormat
|
||||
|
||||
@@ -89,6 +89,19 @@ func TestParseAppInstanceValue(t *testing.T) {
|
||||
assert.Equal(t, appInstanceValue.Name, "<name>")
|
||||
}
|
||||
|
||||
func TestParseAppInstanceValueColon(t *testing.T) {
|
||||
resourceTracking := NewResourceTracking()
|
||||
appInstanceValue, err := resourceTracking.ParseAppInstanceValue("app:<group>/<kind>:<namespace>/<name>:<colon>")
|
||||
if !assert.NoError(t, err) {
|
||||
t.Fatal()
|
||||
}
|
||||
assert.Equal(t, appInstanceValue.ApplicationName, "app")
|
||||
assert.Equal(t, appInstanceValue.Group, "<group>")
|
||||
assert.Equal(t, appInstanceValue.Kind, "<kind>")
|
||||
assert.Equal(t, appInstanceValue.Namespace, "<namespace>")
|
||||
assert.Equal(t, appInstanceValue.Name, "<name>:<colon>")
|
||||
}
|
||||
|
||||
func TestParseAppInstanceValueWrongFormat1(t *testing.T) {
|
||||
resourceTracking := NewResourceTracking()
|
||||
_, err := resourceTracking.ParseAppInstanceValue("app")
|
||||
|
||||
@@ -345,6 +345,9 @@ func clusterToSecret(c *appv1.Cluster, secret *apiv1.Secret) error {
|
||||
secret.Data = data
|
||||
|
||||
secret.Labels = c.Labels
|
||||
if c.Annotations != nil && c.Annotations[apiv1.LastAppliedConfigAnnotation] != "" {
|
||||
return status.Errorf(codes.InvalidArgument, "annotation %s cannot be set", apiv1.LastAppliedConfigAnnotation)
|
||||
}
|
||||
secret.Annotations = c.Annotations
|
||||
|
||||
if secret.Annotations == nil {
|
||||
@@ -403,6 +406,8 @@ func SecretToCluster(s *apiv1.Secret) (*appv1.Cluster, error) {
|
||||
annotations := map[string]string{}
|
||||
if s.Annotations != nil {
|
||||
annotations = collections.CopyStringMap(s.Annotations)
|
||||
// delete system annotations
|
||||
delete(annotations, apiv1.LastAppliedConfigAnnotation)
|
||||
delete(annotations, common.AnnotationKeyManagedBy)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
@@ -56,6 +58,24 @@ func Test_secretToCluster(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func Test_secretToCluster_LastAppliedConfigurationDropped(t *testing.T) {
|
||||
secret := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "mycluster",
|
||||
Namespace: fakeNamespace,
|
||||
Annotations: map[string]string{v1.LastAppliedConfigAnnotation: "val2"},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"name": []byte("test"),
|
||||
"server": []byte("http://mycluster"),
|
||||
"config": []byte("{\"username\":\"foo\"}"),
|
||||
},
|
||||
}
|
||||
cluster, err := SecretToCluster(secret)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, cluster.Annotations, 0)
|
||||
}
|
||||
|
||||
func TestClusterToSecret(t *testing.T) {
|
||||
cluster := &appv1.Cluster{
|
||||
Server: "server",
|
||||
@@ -78,6 +98,21 @@ func TestClusterToSecret(t *testing.T) {
|
||||
assert.Equal(t, cluster.Labels, s.Labels)
|
||||
}
|
||||
|
||||
func TestClusterToSecret_LastAppliedConfigurationRejected(t *testing.T) {
|
||||
cluster := &appv1.Cluster{
|
||||
Server: "server",
|
||||
Annotations: map[string]string{v1.LastAppliedConfigAnnotation: "val2"},
|
||||
Name: "test",
|
||||
Config: v1alpha1.ClusterConfig{},
|
||||
Project: "project",
|
||||
Namespaces: []string{"default"},
|
||||
}
|
||||
s := &v1.Secret{}
|
||||
err := clusterToSecret(cluster, s)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, codes.InvalidArgument, status.Code(err))
|
||||
}
|
||||
|
||||
func Test_secretToCluster_NoConfig(t *testing.T) {
|
||||
secret := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/sirupsen/logrus"
|
||||
"golang.org/x/net/proxy"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/credentials"
|
||||
@@ -63,7 +64,7 @@ func BlockingDial(ctx context.Context, network, address string, creds credential
|
||||
|
||||
dialer := func(ctx context.Context, address string) (net.Conn, error) {
|
||||
|
||||
conn, err := (&net.Dialer{Cancel: ctx.Done()}).Dial(network, address)
|
||||
conn, err := proxy.Dial(ctx, network, address)
|
||||
if err != nil {
|
||||
writeResult(err)
|
||||
return nil, err
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
executil "github.com/argoproj/argo-cd/v2/util/exec"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
@@ -25,7 +26,6 @@ import (
|
||||
"oras.land/oras-go/v2/registry/remote/auth"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/cache"
|
||||
executil "github.com/argoproj/argo-cd/v2/util/exec"
|
||||
argoio "github.com/argoproj/argo-cd/v2/util/io"
|
||||
"github.com/argoproj/argo-cd/v2/util/io/files"
|
||||
"github.com/argoproj/argo-cd/v2/util/proxy"
|
||||
@@ -52,7 +52,7 @@ type indexCache interface {
|
||||
|
||||
type Client interface {
|
||||
CleanChartCache(chart string, version string) error
|
||||
ExtractChart(chart string, version string, passCredentials bool) (string, argoio.Closer, error)
|
||||
ExtractChart(chart string, version string, passCredentials bool, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) (string, argoio.Closer, error)
|
||||
GetIndex(noCache bool) (*Index, error)
|
||||
GetTags(chart string, noCache bool) (*TagsList, error)
|
||||
TestHelmOCI() (bool, error)
|
||||
@@ -122,7 +122,21 @@ func (c *nativeHelmChart) CleanChartCache(chart string, version string) error {
|
||||
return os.RemoveAll(cachePath)
|
||||
}
|
||||
|
||||
func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredentials bool) (string, argoio.Closer, error) {
|
||||
func untarChart(tempDir string, cachedChartPath string, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) error {
|
||||
if disableManifestMaxExtractedSize {
|
||||
cmd := exec.Command("tar", "-zxvf", cachedChartPath)
|
||||
cmd.Dir = tempDir
|
||||
_, err := executil.Run(cmd)
|
||||
return err
|
||||
}
|
||||
reader, err := os.Open(cachedChartPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return files.Untgz(tempDir, reader, manifestMaxExtractedSize, false)
|
||||
}
|
||||
|
||||
func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredentials bool, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) (string, argoio.Closer, error) {
|
||||
// always use Helm V3 since we don't have chart content to determine correct Helm version
|
||||
helmCmd, err := NewCmdWithVersion("", HelmV3, c.enableOci, c.proxy)
|
||||
|
||||
@@ -196,15 +210,14 @@ func (c *nativeHelmChart) ExtractChart(chart string, version string, passCredent
|
||||
if len(infos) != 1 {
|
||||
return "", nil, fmt.Errorf("expected 1 file, found %v", len(infos))
|
||||
}
|
||||
|
||||
err = os.Rename(filepath.Join(tempDest, infos[0].Name()), cachedChartPath)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
}
|
||||
|
||||
cmd := exec.Command("tar", "-zxvf", cachedChartPath)
|
||||
cmd.Dir = tempDir
|
||||
_, err = executil.Run(cmd)
|
||||
err = untarChart(tempDir, cachedChartPath, manifestMaxExtractedSize, disableManifestMaxExtractedSize)
|
||||
if err != nil {
|
||||
_ = os.RemoveAll(tempDir)
|
||||
return "", nil, err
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -71,7 +72,7 @@ func TestIndex(t *testing.T) {
|
||||
|
||||
func Test_nativeHelmChart_ExtractChart(t *testing.T) {
|
||||
client := NewClient("https://argoproj.github.io/argo-helm", Creds{}, false, "")
|
||||
path, closer, err := client.ExtractChart("argo-cd", "0.7.1", false)
|
||||
path, closer, err := client.ExtractChart("argo-cd", "0.7.1", false, math.MaxInt64, true)
|
||||
assert.NoError(t, err)
|
||||
defer io.Close(closer)
|
||||
info, err := os.Stat(path)
|
||||
@@ -79,9 +80,15 @@ func Test_nativeHelmChart_ExtractChart(t *testing.T) {
|
||||
assert.True(t, info.IsDir())
|
||||
}
|
||||
|
||||
func Test_nativeHelmChart_ExtractChartWithLimiter(t *testing.T) {
|
||||
client := NewClient("https://argoproj.github.io/argo-helm", Creds{}, false, "")
|
||||
_, _, err := client.ExtractChart("argo-cd", "0.7.1", false, 100, false)
|
||||
assert.Error(t, err, "error while iterating on tar reader: unexpected EOF")
|
||||
}
|
||||
|
||||
func Test_nativeHelmChart_ExtractChart_insecure(t *testing.T) {
|
||||
client := NewClient("https://argoproj.github.io/argo-helm", Creds{InsecureSkipVerify: true}, false, "")
|
||||
path, closer, err := client.ExtractChart("argo-cd", "0.7.1", false)
|
||||
path, closer, err := client.ExtractChart("argo-cd", "0.7.1", false, math.MaxInt64, true)
|
||||
assert.NoError(t, err)
|
||||
defer io.Close(closer)
|
||||
info, err := os.Stat(path)
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
@@ -271,6 +272,10 @@ var (
|
||||
)
|
||||
|
||||
func cleanSetParameters(val string) string {
|
||||
// `{}` equal helm list parameters format, so don't escape `,`.
|
||||
if strings.HasPrefix(val, `{`) && strings.HasSuffix(val, `}`) {
|
||||
return val
|
||||
}
|
||||
return re.ReplaceAllString(val, `$1\,`)
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +165,7 @@ func TestHelmArgCleaner(t *testing.T) {
|
||||
`bar`: `bar`,
|
||||
`not, clean`: `not\, clean`,
|
||||
`a\,b,c`: `a\,b\,c`,
|
||||
`{a,b,c}`: `{a,b,c}`,
|
||||
} {
|
||||
cleaned := cleanSetParameters(input)
|
||||
assert.Equal(t, expected, cleaned)
|
||||
|
||||
@@ -29,7 +29,7 @@ func (_m *Client) CleanChartCache(chart string, version string) error {
|
||||
}
|
||||
|
||||
// ExtractChart provides a mock function with given fields: chart, version
|
||||
func (_m *Client) ExtractChart(chart string, version string, passCredentials bool) (string, io.Closer, error) {
|
||||
func (_m *Client) ExtractChart(chart string, version string, passCredentials bool, manifestMaxExtractedSize int64, disableManifestMaxExtractedSize bool) (string, io.Closer, error) {
|
||||
ret := _m.Called(chart, version)
|
||||
|
||||
var r0 string
|
||||
|
||||
@@ -19,7 +19,7 @@ const maxCookieLength = 4093
|
||||
|
||||
// max number of chunks a cookie can be broken into. To be compatible with
|
||||
// widest range of browsers, you shouldn't create more than 30 cookies per domain
|
||||
var maxCookieNumber = env.ParseNumFromEnv(common.EnvMaxCookieNumber, 20, 0, math.MaxInt64)
|
||||
var maxCookieNumber = env.ParseNumFromEnv(common.EnvMaxCookieNumber, 20, 0, math.MaxInt)
|
||||
|
||||
// MakeCookieMetadata generates a string representing a Web cookie. Yum!
|
||||
func MakeCookieMetadata(key, value string, flags ...string) ([]string, error) {
|
||||
|
||||
Reference in New Issue
Block a user