mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-04-06 08:48:46 +02:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d4a3138ac0 | ||
|
|
bd78134a69 | ||
|
|
8b79185134 | ||
|
|
54ac05b91e | ||
|
|
93f7846dbb | ||
|
|
e7d8b31a7b | ||
|
|
1383a1b6b9 | ||
|
|
5638e70929 | ||
|
|
42cc36adbb | ||
|
|
7b9438ecff | ||
|
|
e4a0246c4d | ||
|
|
05edb2a9ca | ||
|
|
089247df0f | ||
|
|
540e3a57b9 | ||
|
|
b980386388 | ||
|
|
c4b283ce0c | ||
|
|
d1c052d7bf | ||
|
|
c0f780c380 | ||
|
|
e1284e19e0 | ||
|
|
9e313e539b | ||
|
|
0d1709f73b | ||
|
|
bfbceff5da | ||
|
|
0e71f09990 | ||
|
|
07880f3c1d | ||
|
|
24b198bf51 | ||
|
|
5fd645feac | ||
|
|
b5c13b6139 | ||
|
|
d75b23bf92 | ||
|
|
ac80860eda | ||
|
|
c2bd38a11a | ||
|
|
13844b90ad | ||
|
|
3f344d54a4 | ||
|
|
e01bb5303a | ||
|
|
320abb8d64 | ||
|
|
46342a9e82 | ||
|
|
cf17283ebe |
@@ -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.21.9@sha256:7d0dcbe5807b1ad7272a598fbf9d7af15b5e2bed4fd6c4c2b5b3684df0b317dd AS builder
|
||||
FROM docker.io/library/golang:1.21.10@sha256:16438a8e66c0c984f732e815ee5b7d715b8e33e81bac6d6a3750b1067744e7ca AS builder
|
||||
|
||||
RUN echo 'deb http://archive.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.21.9@sha256:7d0dcbe5807b1ad7272a598fbf9d7af15b5e2bed4fd6c4c2b5b3684df0b317dd AS argocd-build
|
||||
FROM --platform=$BUILDPLATFORM docker.io/library/golang:1.21.10@sha256:16438a8e66c0c984f732e815ee5b7d715b8e33e81bac6d6a3750b1067744e7ca AS argocd-build
|
||||
|
||||
WORKDIR /go/src/github.com/argoproj/argo-cd
|
||||
|
||||
|
||||
@@ -127,20 +127,18 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
||||
// Log a warning if there are unrecognized generators
|
||||
_ = utils.CheckInvalidGenerators(&applicationSetInfo)
|
||||
// desiredApplications is the main list of all expected Applications from all generators in this appset.
|
||||
desiredApplications, applicationSetReason, generatorsErr := r.generateApplications(logCtx, applicationSetInfo)
|
||||
if generatorsErr != nil {
|
||||
desiredApplications, applicationSetReason, err := r.generateApplications(logCtx, applicationSetInfo)
|
||||
if err != nil {
|
||||
_ = r.setApplicationSetStatusCondition(ctx,
|
||||
&applicationSetInfo,
|
||||
argov1alpha1.ApplicationSetCondition{
|
||||
Type: argov1alpha1.ApplicationSetConditionErrorOccurred,
|
||||
Message: generatorsErr.Error(),
|
||||
Message: err.Error(),
|
||||
Reason: string(applicationSetReason),
|
||||
Status: argov1alpha1.ApplicationSetConditionStatusTrue,
|
||||
}, parametersGenerated,
|
||||
)
|
||||
if len(desiredApplications) < 1 {
|
||||
return ctrl.Result{}, generatorsErr
|
||||
}
|
||||
return ctrl.Result{RequeueAfter: ReconcileRequeueOnValidationError}, err
|
||||
}
|
||||
|
||||
parametersGenerated = true
|
||||
@@ -314,7 +312,7 @@ func (r *ApplicationSetReconciler) Reconcile(ctx context.Context, req ctrl.Reque
|
||||
|
||||
requeueAfter := r.getMinRequeueAfter(&applicationSetInfo)
|
||||
|
||||
if len(validateErrors) == 0 && generatorsErr == nil {
|
||||
if len(validateErrors) == 0 {
|
||||
if err := r.setApplicationSetStatusCondition(ctx,
|
||||
&applicationSetInfo,
|
||||
argov1alpha1.ApplicationSetCondition{
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/applicationset/generators/mocks"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
@@ -110,7 +113,6 @@ func (r *rendererMock) RenderTemplateParams(tmpl *v1alpha1.Application, syncPoli
|
||||
}
|
||||
|
||||
return args.Get(0).(*v1alpha1.Application), args.Error(1)
|
||||
|
||||
}
|
||||
|
||||
func (r *rendererMock) Replace(tmpl string, replaceMap map[string]interface{}, useGoTemplate bool, goTemplateOptions []string) (string, error) {
|
||||
@@ -179,7 +181,6 @@ func TestExtractApplications(t *testing.T) {
|
||||
}
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
appSet := &v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
@@ -206,7 +207,6 @@ func TestExtractApplications(t *testing.T) {
|
||||
|
||||
if cc.generateParamsError == nil {
|
||||
for _, p := range cc.params {
|
||||
|
||||
if cc.rendererError != nil {
|
||||
rendererMock.On("RenderTemplateParams", getTempApplication(cc.template), p, false, []string(nil)).
|
||||
Return(nil, cc.rendererError)
|
||||
@@ -253,10 +253,8 @@ func TestExtractApplications(t *testing.T) {
|
||||
if cc.generateParamsError == nil {
|
||||
rendererMock.AssertNumberOfCalls(t, "RenderTemplateParams", len(cc.params))
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestMergeTemplateApplications(t *testing.T) {
|
||||
@@ -315,7 +313,6 @@ func TestMergeTemplateApplications(t *testing.T) {
|
||||
cc := c
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
generatorMock := generatorMock{}
|
||||
generator := v1alpha1.ApplicationSetGenerator{
|
||||
List: &v1alpha1.ListGenerator{},
|
||||
@@ -358,11 +355,9 @@ func TestMergeTemplateApplications(t *testing.T) {
|
||||
assert.Equal(t, cc.expectedApps, got)
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -870,7 +865,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "Ensure that configured preserved annotations are preserved from an existing app",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -937,7 +933,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "Ensure that the app spec is normalized before applying",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -991,7 +988,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
// For this use case: https://github.com/argoproj/argo-cd/issues/9101#issuecomment-1191138278
|
||||
name: "Ensure that ignored targetRevision difference doesn't cause an update, even if another field changes",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
@@ -1082,7 +1080,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
// For this use case: https://github.com/argoproj/argo-cd/pull/14743#issuecomment-1761954799
|
||||
name: "ignore parameters added to a multi-source app in the cluster",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
@@ -1183,7 +1182,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "Demonstrate limitation of MergePatch", // Maybe we can fix this in Argo CD 3.0: https://github.com/argoproj/argo-cd/issues/15975
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -1281,7 +1281,8 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
}, {
|
||||
},
|
||||
{
|
||||
name: "Ensure that argocd post-delete finalizers are preserved from an existing app",
|
||||
appSet: v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -1348,9 +1349,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
||||
initObjs := []crtclient.Object{&c.appSet}
|
||||
|
||||
for _, a := range c.existingApps {
|
||||
@@ -1386,7 +1385,6 @@ func TestCreateOrUpdateInCluster(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -1422,7 +1420,6 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
||||
appSet := v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
@@ -1480,9 +1477,9 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
KubeClientset: kubeclientset,
|
||||
Cache: &fakeCache{},
|
||||
}
|
||||
//settingsMgr := settings.NewSettingsManager(context.TODO(), kubeclientset, "namespace")
|
||||
//argoDB := db.NewDB("namespace", settingsMgr, r.KubeClientset)
|
||||
//clusterList, err := argoDB.ListClusters(context.Background())
|
||||
// settingsMgr := settings.NewSettingsManager(context.TODO(), kubeclientset, "namespace")
|
||||
// argoDB := db.NewDB("namespace", settingsMgr, r.KubeClientset)
|
||||
// clusterList, err := argoDB.ListClusters(context.Background())
|
||||
clusterList, err := utils.ListClusters(context.Background(), kubeclientset, "namespace")
|
||||
assert.NoError(t, err, "Unexpected error")
|
||||
|
||||
@@ -1505,13 +1502,11 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) {
|
||||
|
||||
bytes, _ := json.MarshalIndent(retrievedApp, "", " ")
|
||||
t.Log("Contents of app after call:", string(bytes))
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -1583,9 +1578,7 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
|
||||
expectFinalizerRemoved: false,
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
|
||||
appSet := v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
@@ -1665,7 +1658,6 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) {
|
||||
|
||||
bytes, _ := json.MarshalIndent(retrievedApp, "", " ")
|
||||
t.Log("Contents of app after call:", string(bytes))
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1746,7 +1738,6 @@ func TestRemoveOwnerReferencesOnDeleteAppSet(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateApplications(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -1950,7 +1941,6 @@ func TestCreateApplications(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteInCluster(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -2152,8 +2142,59 @@ func TestGetMinRequeueAfter(t *testing.T) {
|
||||
assert.Equal(t, time.Duration(1)*time.Second, got)
|
||||
}
|
||||
|
||||
func TestValidateGeneratedApplications(t *testing.T) {
|
||||
func TestRequeueGeneratorFails(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
err = v1alpha1.AddToScheme(scheme)
|
||||
require.NoError(t, err)
|
||||
|
||||
appSet := v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "argocd",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSetSpec{
|
||||
Generators: []v1alpha1.ApplicationSetGenerator{{
|
||||
PullRequest: &v1alpha1.PullRequestGenerator{},
|
||||
}},
|
||||
},
|
||||
}
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).Build()
|
||||
|
||||
generator := v1alpha1.ApplicationSetGenerator{
|
||||
PullRequest: &v1alpha1.PullRequestGenerator{},
|
||||
}
|
||||
|
||||
generatorMock := mocks.Generator{}
|
||||
generatorMock.On("GetTemplate", &generator).
|
||||
Return(&v1alpha1.ApplicationSetTemplate{})
|
||||
generatorMock.On("GenerateParams", &generator, mock.AnythingOfType("*v1alpha1.ApplicationSet"), mock.Anything).
|
||||
Return([]map[string]interface{}{}, fmt.Errorf("Simulated error generating params that could be related to an external service/API call"))
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Recorder: record.NewFakeRecorder(0),
|
||||
Cache: &fakeCache{},
|
||||
Generators: map[string]generators.Generator{
|
||||
"PullRequest": &generatorMock,
|
||||
},
|
||||
}
|
||||
|
||||
req := ctrl.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "argocd",
|
||||
Name: "name",
|
||||
},
|
||||
}
|
||||
|
||||
res, err := r.Reconcile(context.Background(), req)
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, ReconcileRequeueOnValidationError, res.RequeueAfter)
|
||||
}
|
||||
|
||||
func TestValidateGeneratedApplications(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -2313,9 +2354,7 @@ func TestValidateGeneratedApplications(t *testing.T) {
|
||||
validationErrors: map[int]error{0: fmt.Errorf("application destination spec is invalid: unable to find destination server: there are no clusters with this name: nonexistent-cluster")},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
secret := &corev1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-secret",
|
||||
@@ -2393,7 +2432,6 @@ func TestValidateGeneratedApplications(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -2488,91 +2526,6 @@ func TestReconcilerValidationProjectErrorBehaviour(t *testing.T) {
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestReconcilerCreateAppsRecoveringRenderError(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
err = v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
|
||||
project := v1alpha1.AppProject{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "default", Namespace: "argocd"},
|
||||
}
|
||||
appSet := v1alpha1.ApplicationSet{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "name",
|
||||
Namespace: "argocd",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSetSpec{
|
||||
GoTemplate: true,
|
||||
Generators: []v1alpha1.ApplicationSetGenerator{
|
||||
{
|
||||
List: &v1alpha1.ListGenerator{
|
||||
Elements: []apiextensionsv1.JSON{{
|
||||
Raw: []byte(`{"name": "very-good-app"}`),
|
||||
}, {
|
||||
Raw: []byte(`{"name": "bad-app"}`),
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
Template: v1alpha1.ApplicationSetTemplate{
|
||||
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
|
||||
Name: "{{ index (splitList \"-\" .name ) 2 }}",
|
||||
Namespace: "argocd",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Source: &v1alpha1.ApplicationSource{RepoURL: "https://github.com/argoproj/argocd-example-apps", Path: "guestbook"},
|
||||
Project: "default",
|
||||
Destination: v1alpha1.ApplicationDestination{Server: "https://kubernetes.default.svc"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset()
|
||||
argoDBMock := dbmocks.ArgoDB{}
|
||||
argoObjs := []runtime.Object{&project}
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&appSet).WithIndex(&v1alpha1.Application{}, ".metadata.controller", appControllerIndexer).Build()
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
Client: client,
|
||||
Scheme: scheme,
|
||||
Renderer: &utils.Render{},
|
||||
Recorder: record.NewFakeRecorder(1),
|
||||
Cache: &fakeCache{},
|
||||
Generators: map[string]generators.Generator{
|
||||
"List": generators.NewListGenerator(),
|
||||
},
|
||||
ArgoDB: &argoDBMock,
|
||||
ArgoAppClientset: appclientset.NewSimpleClientset(argoObjs...),
|
||||
KubeClientset: kubeclientset,
|
||||
Policy: v1alpha1.ApplicationsSyncPolicySync,
|
||||
ArgoCDNamespace: "argocd",
|
||||
}
|
||||
|
||||
req := ctrl.Request{
|
||||
NamespacedName: types.NamespacedName{
|
||||
Namespace: "argocd",
|
||||
Name: "name",
|
||||
},
|
||||
}
|
||||
|
||||
// Verify that on generatorsError, no error is returned, but the object is requeued
|
||||
res, err := r.Reconcile(context.Background(), req)
|
||||
assert.Nil(t, err)
|
||||
assert.True(t, res.RequeueAfter == ReconcileRequeueOnValidationError)
|
||||
|
||||
var app v1alpha1.Application
|
||||
|
||||
// make sure good app got created
|
||||
err = r.Client.Get(context.TODO(), crtclient.ObjectKey{Namespace: "argocd", Name: "app"}, &app)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, app.Name, "app")
|
||||
}
|
||||
|
||||
func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
@@ -2631,7 +2584,6 @@ func TestSetApplicationSetStatusCondition(t *testing.T) {
|
||||
}
|
||||
|
||||
func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.Application {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -2748,7 +2700,6 @@ func applicationsUpdateSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
}
|
||||
|
||||
func TestUpdateNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
|
||||
|
||||
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 1, true)
|
||||
@@ -2758,7 +2709,6 @@ func TestUpdateNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateDelete
|
||||
|
||||
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 1, true)
|
||||
@@ -2768,7 +2718,6 @@ func TestUpdateNotPerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateUpdate
|
||||
|
||||
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, true)
|
||||
@@ -2779,7 +2728,6 @@ func TestUpdatePerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicySync
|
||||
|
||||
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, true)
|
||||
@@ -2790,7 +2738,6 @@ func TestUpdatePerformedWithSyncPolicySync(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
|
||||
|
||||
app := applicationsUpdateSyncPolicyTest(t, applicationsSyncPolicy, 2, false)
|
||||
@@ -2801,7 +2748,6 @@ func TestUpdatePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *t
|
||||
}
|
||||
|
||||
func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alpha1.ApplicationsSyncPolicy, recordBuffer int, allowPolicyOverride bool) v1alpha1.ApplicationList {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -2919,7 +2865,6 @@ func applicationsDeleteSyncPolicyTest(t *testing.T, applicationsSyncPolicy v1alp
|
||||
}
|
||||
|
||||
func TestDeleteNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
|
||||
|
||||
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 1, true)
|
||||
@@ -2928,7 +2873,6 @@ func TestDeleteNotPerformedWithSyncPolicyCreateOnly(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteNotPerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateUpdate
|
||||
|
||||
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 2, true)
|
||||
@@ -2937,7 +2881,6 @@ func TestDeleteNotPerformedWithSyncPolicyCreateUpdate(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeletePerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateDelete
|
||||
|
||||
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, true)
|
||||
@@ -2946,7 +2889,6 @@ func TestDeletePerformedWithSyncPolicyCreateDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeletePerformedWithSyncPolicySync(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicySync
|
||||
|
||||
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, true)
|
||||
@@ -2955,7 +2897,6 @@ func TestDeletePerformedWithSyncPolicySync(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeletePerformedWithSyncPolicyCreateOnlyAndAllowPolicyOverrideFalse(t *testing.T) {
|
||||
|
||||
applicationsSyncPolicy := v1alpha1.ApplicationsSyncPolicyCreateOnly
|
||||
|
||||
apps := applicationsDeleteSyncPolicyTest(t, applicationsSyncPolicy, 3, false)
|
||||
@@ -2976,16 +2917,18 @@ func TestGenerateAppsUsingPullRequestGenerator(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
name: "Generate an application from a go template application set manifest using a pull request generator",
|
||||
params: []map[string]interface{}{{
|
||||
"number": "1",
|
||||
"branch": "branch1",
|
||||
"branch_slug": "branchSlug1",
|
||||
"head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958",
|
||||
"head_short_sha": "089d92cb",
|
||||
"branch_slugify_default": "feat/a_really+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature",
|
||||
"branch_slugify_smarttruncate_disabled": "feat/areallylongpullrequestnametotestargoslugificationandbranchnameshorteningfeature",
|
||||
"branch_slugify_smarttruncate_enabled": "feat/testwithsmarttruncateenabledramdomlonglistofcharacters",
|
||||
"labels": []string{"label1"}},
|
||||
params: []map[string]interface{}{
|
||||
{
|
||||
"number": "1",
|
||||
"branch": "branch1",
|
||||
"branch_slug": "branchSlug1",
|
||||
"head_sha": "089d92cbf9ff857a39e6feccd32798ca700fb958",
|
||||
"head_short_sha": "089d92cb",
|
||||
"branch_slugify_default": "feat/a_really+long_pull_request_name_to_test_argo_slugification_and_branch_name_shortening_feature",
|
||||
"branch_slugify_smarttruncate_disabled": "feat/areallylongpullrequestnametotestargoslugificationandbranchnameshorteningfeature",
|
||||
"branch_slugify_smarttruncate_enabled": "feat/testwithsmarttruncateenabledramdomlonglistofcharacters",
|
||||
"labels": []string{"label1"},
|
||||
},
|
||||
},
|
||||
template: v1alpha1.ApplicationSetTemplate{
|
||||
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{
|
||||
@@ -3033,9 +2976,7 @@ func TestGenerateAppsUsingPullRequestGenerator(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cases.name, func(t *testing.T) {
|
||||
|
||||
generatorMock := generatorMock{}
|
||||
generator := v1alpha1.ApplicationSetGenerator{
|
||||
PullRequest: &v1alpha1.PullRequestGenerator{},
|
||||
@@ -3329,9 +3270,7 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
|
||||
expectedAppStatuses: nil,
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
client := fake.NewClientBuilder().WithScheme(scheme).WithObjects(&cc.appSet).Build()
|
||||
|
||||
r := ApplicationSetReconciler{
|
||||
@@ -3357,7 +3296,6 @@ func TestSetApplicationSetApplicationStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuildAppDependencyList(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -4093,9 +4031,7 @@ func TestBuildAppDependencyList(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoDBMock := dbmocks.ArgoDB{}
|
||||
argoObjs := []runtime.Object{}
|
||||
@@ -4120,7 +4056,6 @@ func TestBuildAppDependencyList(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBuildAppSyncMap(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -4687,9 +4622,7 @@ func TestBuildAppSyncMap(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoDBMock := dbmocks.ArgoDB{}
|
||||
argoObjs := []runtime.Object{}
|
||||
@@ -4713,7 +4646,6 @@ func TestBuildAppSyncMap(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -5345,9 +5277,7 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoDBMock := dbmocks.ArgoDB{}
|
||||
argoObjs := []runtime.Object{}
|
||||
@@ -5379,7 +5309,6 @@ func TestUpdateApplicationSetApplicationStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) {
|
||||
|
||||
scheme := runtime.NewScheme()
|
||||
err := v1alpha1.AddToScheme(scheme)
|
||||
assert.Nil(t, err)
|
||||
@@ -6099,9 +6028,7 @@ func TestUpdateApplicationSetApplicationStatusProgress(t *testing.T) {
|
||||
},
|
||||
},
|
||||
} {
|
||||
|
||||
t.Run(cc.name, func(t *testing.T) {
|
||||
|
||||
kubeclientset := kubefake.NewSimpleClientset([]runtime.Object{}...)
|
||||
argoDBMock := dbmocks.ArgoDB{}
|
||||
argoObjs := []runtime.Object{}
|
||||
@@ -6165,60 +6092,64 @@ func TestOwnsHandler(t *testing.T) {
|
||||
ResourceVersion: "bar",
|
||||
}},
|
||||
}}, want: false},
|
||||
{name: "ApplicationHealthStatusDiff", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: "Unknown",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: "Healthy",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{name: "ApplicationHealthStatusDiff", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: "Unknown",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Health: v1alpha1.HealthStatus{
|
||||
Status: "Healthy",
|
||||
},
|
||||
}},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: true},
|
||||
{name: "ApplicationSyncStatusDiff", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: "OutOfSync",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: "Synced",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{name: "ApplicationSyncStatusDiff", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: "OutOfSync",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
Sync: v1alpha1.SyncStatus{
|
||||
Status: "Synced",
|
||||
},
|
||||
}},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: true},
|
||||
{name: "ApplicationOperationStateDiff", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
Phase: "foo",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
Phase: "bar",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{name: "ApplicationOperationStateDiff", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
Phase: "foo",
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
Phase: "bar",
|
||||
},
|
||||
}},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: true},
|
||||
{name: "ApplicationOperationStartedAtDiff", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
StartedAt: now,
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
StartedAt: metav1.NewTime(now.Add(time.Minute * 1)),
|
||||
},
|
||||
}},
|
||||
},
|
||||
{name: "ApplicationOperationStartedAtDiff", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
StartedAt: now,
|
||||
},
|
||||
}},
|
||||
ObjectNew: &v1alpha1.Application{Status: v1alpha1.ApplicationStatus{
|
||||
OperationState: &v1alpha1.OperationState{
|
||||
StartedAt: metav1.NewTime(now.Add(time.Minute * 1)),
|
||||
},
|
||||
}},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: true},
|
||||
{name: "SameApplicationGeneration", args: args{e: event.UpdateEvent{
|
||||
@@ -6257,48 +6188,50 @@ func TestOwnsHandler(t *testing.T) {
|
||||
ObjectOld: &v1alpha1.Application{ObjectMeta: metav1.ObjectMeta{Finalizers: []string{}}},
|
||||
ObjectNew: &v1alpha1.Application{ObjectMeta: metav1.ObjectMeta{Finalizers: nil}},
|
||||
}}, want: false},
|
||||
{name: "ApplicationDestinationSame", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
{name: "ApplicationDestinationSame", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
ObjectNew: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ObjectNew: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: false},
|
||||
{name: "ApplicationDestinationDiff", args: args{e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
{name: "ApplicationDestinationDiff", args: args{
|
||||
e: event.UpdateEvent{
|
||||
ObjectOld: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "server",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
ObjectNew: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "notSameServer",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
ObjectNew: &v1alpha1.Application{
|
||||
Spec: v1alpha1.ApplicationSpec{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "notSameServer",
|
||||
Namespace: "ns",
|
||||
Name: "name",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
enableProgressiveSyncs: true,
|
||||
}, want: true},
|
||||
{name: "NotAnAppOld", args: args{e: event.UpdateEvent{
|
||||
|
||||
@@ -7,6 +7,8 @@ import (
|
||||
argoprojiov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/vektra/mockery/v2@v2.40.2 --name=Generator
|
||||
|
||||
// Generator defines the interface implemented by all ApplicationSet generators.
|
||||
type Generator interface {
|
||||
// GenerateParams interprets the ApplicationSet and generates all relevant parameters for the application template.
|
||||
|
||||
98
applicationset/generators/mocks/Generator.go
Normal file
98
applicationset/generators/mocks/Generator.go
Normal file
@@ -0,0 +1,98 @@
|
||||
// Code generated by mockery v2.40.2. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
v1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
)
|
||||
|
||||
// Generator is an autogenerated mock type for the Generator type
|
||||
type Generator struct {
|
||||
mock.Mock
|
||||
}
|
||||
|
||||
// GenerateParams provides a mock function with given fields: appSetGenerator, applicationSetInfo
|
||||
func (_m *Generator) GenerateParams(appSetGenerator *v1alpha1.ApplicationSetGenerator, applicationSetInfo *v1alpha1.ApplicationSet) ([]map[string]interface{}, error) {
|
||||
ret := _m.Called(appSetGenerator, applicationSetInfo)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GenerateParams")
|
||||
}
|
||||
|
||||
var r0 []map[string]interface{}
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet) ([]map[string]interface{}, error)); ok {
|
||||
return rf(appSetGenerator, applicationSetInfo)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet) []map[string]interface{}); ok {
|
||||
r0 = rf(appSetGenerator, applicationSetInfo)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]map[string]interface{})
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(*v1alpha1.ApplicationSetGenerator, *v1alpha1.ApplicationSet) error); ok {
|
||||
r1 = rf(appSetGenerator, applicationSetInfo)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetRequeueAfter provides a mock function with given fields: appSetGenerator
|
||||
func (_m *Generator) GetRequeueAfter(appSetGenerator *v1alpha1.ApplicationSetGenerator) time.Duration {
|
||||
ret := _m.Called(appSetGenerator)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetRequeueAfter")
|
||||
}
|
||||
|
||||
var r0 time.Duration
|
||||
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) time.Duration); ok {
|
||||
r0 = rf(appSetGenerator)
|
||||
} else {
|
||||
r0 = ret.Get(0).(time.Duration)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetTemplate provides a mock function with given fields: appSetGenerator
|
||||
func (_m *Generator) GetTemplate(appSetGenerator *v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate {
|
||||
ret := _m.Called(appSetGenerator)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetTemplate")
|
||||
}
|
||||
|
||||
var r0 *v1alpha1.ApplicationSetTemplate
|
||||
if rf, ok := ret.Get(0).(func(*v1alpha1.ApplicationSetGenerator) *v1alpha1.ApplicationSetTemplate); ok {
|
||||
r0 = rf(appSetGenerator)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v1alpha1.ApplicationSetTemplate)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewGenerator creates a new instance of Generator. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
// The first argument is typically a *testing.T value.
|
||||
func NewGenerator(t interface {
|
||||
mock.TestingT
|
||||
Cleanup(func())
|
||||
}) *Generator {
|
||||
mock := &Generator{}
|
||||
mock.Mock.Test(t)
|
||||
|
||||
t.Cleanup(func() { mock.AssertExpectations(t) })
|
||||
|
||||
return mock
|
||||
}
|
||||
@@ -104,7 +104,17 @@ func loadClusters(ctx context.Context, kubeClient *kubernetes.Clientset, appClie
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
client := redis.NewClient(&redis.Options{Addr: fmt.Sprintf("localhost:%d", port)})
|
||||
|
||||
redisOptions := &redis.Options{Addr: fmt.Sprintf("localhost:%d", port)}
|
||||
|
||||
secret, err := kubeClient.CoreV1().Secrets(namespace).Get(context.Background(), defaulRedisInitialPasswordSecretName, v1.GetOptions{})
|
||||
if err == nil {
|
||||
if _, ok := secret.Data[defaultResisInitialPasswordKey]; ok {
|
||||
redisOptions.Password = string(secret.Data[defaultResisInitialPasswordKey])
|
||||
}
|
||||
}
|
||||
|
||||
client := redis.NewClient(redisOptions)
|
||||
compressionType, err := cacheutil.CompressionTypeFromString(redisCompressionStr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -781,8 +781,6 @@ func NewApplicationSetCommand(clientOpts *argocdclient.ClientOptions) *cobra.Com
|
||||
}
|
||||
}
|
||||
|
||||
// sourcePosition startes with 1, thus, it needs to be decreased by 1 to find the correct index in the list of sources
|
||||
sourcePosition = sourcePosition - 1
|
||||
visited := cmdutil.SetAppSpecOptions(c.Flags(), &app.Spec, &appOpts, sourcePosition)
|
||||
if visited == 0 {
|
||||
log.Error("Please set at least one option to update")
|
||||
|
||||
@@ -1763,6 +1763,22 @@ func (ctrl *ApplicationController) normalizeApplication(orig, app *appv1.Applica
|
||||
}
|
||||
}
|
||||
|
||||
func createMergePatch(orig, new interface{}) ([]byte, bool, error) {
|
||||
origBytes, err := json.Marshal(orig)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
newBytes, err := json.Marshal(new)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
patch, err := jsonpatch.CreateMergePatch(origBytes, newBytes)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
return patch, string(patch) != "{}", nil
|
||||
}
|
||||
|
||||
// persistAppStatus persists updates to application status. If no changes were made, it is a no-op
|
||||
func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, newStatus *appv1.ApplicationStatus) (patchMs time.Duration) {
|
||||
logCtx := log.WithFields(log.Fields{"application": orig.QualifiedName()})
|
||||
@@ -1782,9 +1798,9 @@ func (ctrl *ApplicationController) persistAppStatus(orig *appv1.Application, new
|
||||
}
|
||||
delete(newAnnotations, appv1.AnnotationKeyRefresh)
|
||||
}
|
||||
patch, modified, err := diff.CreateTwoWayMergePatch(
|
||||
patch, modified, err := createMergePatch(
|
||||
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: orig.GetAnnotations()}, Status: orig.Status},
|
||||
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus}, appv1.Application{})
|
||||
&appv1.Application{ObjectMeta: metav1.ObjectMeta{Annotations: newAnnotations}, Status: *newStatus})
|
||||
if err != nil {
|
||||
logCtx.Errorf("Error constructing app status patch: %v", err)
|
||||
return
|
||||
|
||||
@@ -989,7 +989,7 @@ func TestNormalizeApplication(t *testing.T) {
|
||||
normalized := false
|
||||
fakeAppCs.AddReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
if string(patchAction.GetPatch()) == `{"spec":{"project":"default"},"status":{"sync":{"comparedTo":{"destination":{},"source":{"repoURL":""}}}}}` {
|
||||
if string(patchAction.GetPatch()) == `{"spec":{"project":"default"}}` {
|
||||
normalized = true
|
||||
}
|
||||
}
|
||||
@@ -1914,3 +1914,65 @@ func TestAddControllerNamespace(t *testing.T) {
|
||||
assert.Equal(t, test.FakeArgoCDNamespace, updatedApp.Status.ControllerNamespace)
|
||||
})
|
||||
}
|
||||
|
||||
func TestHelmValuesObjectHasReplaceStrategy(t *testing.T) {
|
||||
app := v1alpha1.Application{
|
||||
Status: v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{
|
||||
Source: v1alpha1.ApplicationSource{
|
||||
Helm: &v1alpha1.ApplicationSourceHelm{
|
||||
ValuesObject: &runtime.RawExtension{
|
||||
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
appModified := v1alpha1.Application{
|
||||
Status: v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{ComparedTo: v1alpha1.ComparedTo{
|
||||
Source: v1alpha1.ApplicationSource{
|
||||
Helm: &v1alpha1.ApplicationSourceHelm{
|
||||
ValuesObject: &runtime.RawExtension{
|
||||
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value-modified1"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
patch, _, err := createMergePatch(
|
||||
app,
|
||||
appModified)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, `{"status":{"sync":{"comparedTo":{"source":{"helm":{"valuesObject":{"key":["value-modified1"]}}}}}}}`, string(patch))
|
||||
}
|
||||
|
||||
func TestAppStatusIsReplaced(t *testing.T) {
|
||||
original := &v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{
|
||||
ComparedTo: v1alpha1.ComparedTo{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Server: "https://mycluster",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
updated := &v1alpha1.ApplicationStatus{Sync: v1alpha1.SyncStatus{
|
||||
ComparedTo: v1alpha1.ComparedTo{
|
||||
Destination: v1alpha1.ApplicationDestination{
|
||||
Name: "mycluster",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
patchData, ok, err := createMergePatch(original, updated)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.True(t, ok)
|
||||
patchObj := map[string]interface{}{}
|
||||
require.NoError(t, json.Unmarshal(patchData, &patchObj))
|
||||
|
||||
val, has, err := unstructured.NestedFieldNoCopy(patchObj, "sync", "comparedTo", "destination", "server")
|
||||
require.NoError(t, err)
|
||||
require.True(t, has)
|
||||
require.Nil(t, val)
|
||||
}
|
||||
|
||||
@@ -1,48 +1,83 @@
|
||||
setTimeout(function() {
|
||||
const callbackName = 'callback_' + new Date().getTime();
|
||||
window[callbackName] = function (response) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = response.html;
|
||||
document.querySelector(".md-header__inner > .md-header__title").appendChild(div);
|
||||
const container = div.querySelector('.rst-versions');
|
||||
var caret = document.createElement('div');
|
||||
caret.innerHTML = "<i class='fa fa-caret-down dropdown-caret'></i>"
|
||||
caret.classList.add('dropdown-caret')
|
||||
div.querySelector('.rst-current-version').appendChild(caret);
|
||||
const targetNode = document.querySelector('.md-header__inner');
|
||||
const observerOptions = {
|
||||
childList: true,
|
||||
subtree: true
|
||||
};
|
||||
|
||||
const observerCallback = function(mutationsList, observer) {
|
||||
for (let mutation of mutationsList) {
|
||||
if (mutation.type === 'childList') {
|
||||
const titleElement = document.querySelector('.md-header__inner > .md-header__title');
|
||||
if (titleElement) {
|
||||
initializeVersionDropdown();
|
||||
observer.disconnect();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const observer = new MutationObserver(observerCallback);
|
||||
observer.observe(targetNode, observerOptions);
|
||||
|
||||
function getCurrentVersion() {
|
||||
const currentVersion = window.location.href.match(/\/en\/(release-(?:v\d+|[\d\.]+|\w+)|latest|stable)\//);
|
||||
if (currentVersion && currentVersion.length > 1) {
|
||||
return currentVersion[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function initializeVersionDropdown() {
|
||||
const callbackName = 'callback_' + new Date().getTime();
|
||||
window[callbackName] = function(response) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = response.html;
|
||||
document.querySelector(".md-header__inner > .md-header__title").appendChild(div);
|
||||
const container = div.querySelector('.rst-versions');
|
||||
var caret = document.createElement('div');
|
||||
caret.innerHTML = "<i class='fa fa-caret-down dropdown-caret'></i>";
|
||||
caret.classList.add('dropdown-caret');
|
||||
div.querySelector('.rst-current-version').appendChild(caret);
|
||||
|
||||
div.querySelector('.rst-current-version').addEventListener('click', function() {
|
||||
container.classList.toggle('shift-up');
|
||||
});
|
||||
};
|
||||
|
||||
var CSSLink = document.createElement('link');
|
||||
CSSLink.rel='stylesheet';
|
||||
CSSLink.rel = 'stylesheet';
|
||||
CSSLink.href = '/assets/versions.css';
|
||||
document.getElementsByTagName('head')[0].appendChild(CSSLink);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://argo-cd.readthedocs.io/_/api/v2/footer_html/?'+
|
||||
'callback=' + callbackName + '&project=argo-cd&page=&theme=mkdocs&format=jsonp&docroot=docs&source_suffix=.md&version=' + (window['READTHEDOCS_DATA'] || { version: 'latest' }).version;
|
||||
const currentVersion = getCurrentVersion();
|
||||
script.src = 'https://argo-cd.readthedocs.io/_/api/v2/footer_html/?' +
|
||||
'callback=' + callbackName + '&project=argo-cd&page=&theme=mkdocs&format=jsonp&docroot=docs&source_suffix=.md&version=' + (currentVersion || 'latest');
|
||||
document.getElementsByTagName('head')[0].appendChild(script);
|
||||
}, 0);
|
||||
}
|
||||
|
||||
// VERSION WARNINGS
|
||||
window.addEventListener("DOMContentLoaded", function() {
|
||||
var rtdData = window['READTHEDOCS_DATA'] || { version: 'latest' };
|
||||
var margin = 30;
|
||||
var headerHeight = document.getElementsByClassName("md-header")[0].offsetHeight;
|
||||
if (rtdData.version === "latest") {
|
||||
document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>You are viewing the docs for an unreleased version of Argo CD, <a href='https://argo-cd.readthedocs.io/en/stable/'>click here to go to the latest stable version.</a></div>"
|
||||
var bannerHeight = document.getElementById('announce-msg').offsetHeight + margin
|
||||
document.querySelector("header.md-header").style.top = bannerHeight +"px";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 76.25em){ .md-sidebar { height: 0; top:"+ (bannerHeight+headerHeight)+"px !important; }}"
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 60em){ .md-sidebar--secondary { height: 0; top:"+ (bannerHeight+headerHeight)+"px !important; }}"
|
||||
}
|
||||
else if (rtdData.version !== "stable") {
|
||||
document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>You are viewing the docs for a previous version of Argo CD, <a href='https://argo-cd.readthedocs.io/en/stable/'>click here to go to the latest stable version.</a></div>"
|
||||
var bannerHeight = document.getElementById('announce-msg').offsetHeight + margin
|
||||
document.querySelector("header.md-header").style.top = bannerHeight +"px";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 76.25em){ .md-sidebar { height: 0; top:"+ (bannerHeight+headerHeight)+"px !important; }}"
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 60em){ .md-sidebar--secondary { height: 0; top:"+ (bannerHeight+headerHeight)+"px !important; }}"
|
||||
var headerHeight = document.getElementsByClassName("md-header")[0].offsetHeight;
|
||||
const currentVersion = getCurrentVersion();
|
||||
if (currentVersion) {
|
||||
if (currentVersion === "latest") {
|
||||
document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>You are viewing the docs for an unreleased version of Argo CD, <a href='https://argo-cd.readthedocs.io/en/stable/'>click here to go to the latest stable version.</a></div>";
|
||||
var bannerHeight = document.getElementById('announce-msg').offsetHeight + margin;
|
||||
document.querySelector("header.md-header").style.top = bannerHeight + "px";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 76.25em){ .md-sidebar { height: 0; top:" + (bannerHeight + headerHeight) + "px !important; }}";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 60em){ .md-sidebar--secondary { height: 0; top:" + (bannerHeight + headerHeight) + "px !important; }}";
|
||||
} else if (currentVersion !== "stable") {
|
||||
document.querySelector("div[data-md-component=announce]").innerHTML = "<div id='announce-msg'>You are viewing the docs for a previous version of Argo CD, <a href='https://argo-cd.readthedocs.io/en/stable/'>click here to go to the latest stable version.</a></div>";
|
||||
var bannerHeight = document.getElementById('announce-msg').offsetHeight + margin;
|
||||
document.querySelector("header.md-header").style.top = bannerHeight + "px";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 76.25em){ .md-sidebar { height: 0; top:" + (bannerHeight + headerHeight) + "px !important; }}";
|
||||
document.querySelector('style').textContent +=
|
||||
"@media screen and (min-width: 60em){ .md-sidebar--secondary { height: 0; top:" + (bannerHeight + headerHeight) + "px !important; }}";
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -326,7 +326,7 @@ As with other generators, clusters *must* already be defined within Argo CD, in
|
||||
In addition to the flattened key/value pairs from the configuration file, the following generator parameters are provided:
|
||||
|
||||
- `{{.path.path}}`: The path to the directory containing matching configuration file within the Git repository. Example: `/clusters/clusterA`, if the config file was `/clusters/clusterA/config.json`
|
||||
- `{{index .path n}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `index .path 0: clusters`, `index .path 1: clusterA`
|
||||
- `{{index .path.segments n}}`: The path to the matching configuration file within the Git repository, split into array elements (`n` - array index). Example: `index .path.segments 0: clusters`, `index .path.segments 1: clusterA`
|
||||
- `{{.path.basename}}`: Basename of the path to the directory containing the configuration file (e.g. `clusterA`, with the above example.)
|
||||
- `{{.path.basenameNormalized}}`: This field is the same as `.path.basename` with unsupported characters replaced with `-` (e.g. a `path` of `/directory/directory_2`, and `.path.basename` of `directory_2` would produce `directory-2` here).
|
||||
- `{{.path.filename}}`: The matched filename. e.g., `config.json` in the above example.
|
||||
@@ -360,7 +360,7 @@ spec:
|
||||
files:
|
||||
- path: "applicationset/examples/git-generator-files-discovery/cluster-config/**/config.json"
|
||||
values:
|
||||
base_dir: "{{index .path 0}}/{{index .path 1}}/{{index .path 2}}"
|
||||
base_dir: "{{index .path.segments 0}}/{{index .path.segments 1}}/{{index .path.segments 2}}"
|
||||
template:
|
||||
metadata:
|
||||
name: '{{.cluster.name}}-guestbook'
|
||||
|
||||
@@ -410,3 +410,6 @@ data:
|
||||
cluster:
|
||||
name: some-cluster
|
||||
server: https://some-cluster
|
||||
|
||||
# The maximum size of the payload that can be sent to the webhook server.
|
||||
webhook.maxPayloadSizeMB: 1024
|
||||
@@ -19,6 +19,7 @@ URL configured in the Git provider should use the `/api/webhook` endpoint of you
|
||||
(e.g. `https://argocd.example.com/api/webhook`). If you wish to use a shared secret, input an
|
||||
arbitrary value in the secret. This value will be used when configuring the webhook in the next step.
|
||||
|
||||
To prevent DDoS attacks with unauthenticated webhook events (the `/api/webhook` endpoint currently lacks rate limiting protection), it is recommended to limit the payload size. You can achieve this by configuring the `argocd-cm` ConfigMap with the `webhook.maxPayloadSizeMB` attribute. The default value is 1GB.
|
||||
## Github
|
||||
|
||||

|
||||
|
||||
2
go.mod
2
go.mod
@@ -13,7 +13,7 @@ require (
|
||||
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
|
||||
github.com/alicebob/miniredis/v2 v2.30.4
|
||||
github.com/antonmedv/expr v1.15.2
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240416142647-fbecbb86e412
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240715141605-18ba62e1f1fb
|
||||
github.com/argoproj/notifications-engine v0.4.1-0.20240403133627-f48567108f01
|
||||
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1
|
||||
github.com/aws/aws-sdk-go v1.50.8
|
||||
|
||||
4
go.sum
4
go.sum
@@ -696,8 +696,8 @@ github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU=
|
||||
github.com/appscode/go v0.0.0-20191119085241-0887d8ec2ecc/go.mod h1:OawnOmAL4ZX3YaPdN+8HTNwBveT1jMsqP74moa9XUbE=
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240416142647-fbecbb86e412 h1:je2wJpWtaoS55mA5MBPCeDnKMeF42pkxO9Oa5KbWrdg=
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240416142647-fbecbb86e412/go.mod h1:gWE8uROi7hIkWGNAVM+8FWkMfo0vZ03SLx/aFw/DBzg=
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240715141605-18ba62e1f1fb h1:PbngWUqmtdVxU5qRR0Dngeo6AXhxY3qZi6RlpfCLbuI=
|
||||
github.com/argoproj/gitops-engine v0.7.1-0.20240715141605-18ba62e1f1fb/go.mod h1:d4eLldeEFyZIcVySAMhXhnh1tTa4qfvPYfut9B8UClw=
|
||||
github.com/argoproj/notifications-engine v0.4.1-0.20240403133627-f48567108f01 h1:/V8+HM0VPPTrdjTwUrkIj5a+SjaU//tJwfIXJ1QAOvg=
|
||||
github.com/argoproj/notifications-engine v0.4.1-0.20240403133627-f48567108f01/go.mod h1:N0A4sEws2soZjEpY4hgZpQS8mRIEw6otzwfkgc3g9uQ=
|
||||
github.com/argoproj/pkg v0.13.7-0.20230626144333-d56162821bd1 h1:qsHwwOJ21K2Ao0xPju1sNuqphyMnMYkyB3ZLoLtxWpo=
|
||||
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.11.2
|
||||
newTag: v2.11.9
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -40,7 +40,7 @@ spec:
|
||||
serviceAccountName: argocd-redis
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: Always
|
||||
args:
|
||||
- "--save"
|
||||
|
||||
@@ -21224,7 +21224,7 @@ spec:
|
||||
key: applicationsetcontroller.enable.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -21326,7 +21326,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -21342,7 +21342,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -21583,7 +21583,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -21635,7 +21635,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -21907,7 +21907,7 @@ spec:
|
||||
key: controller.ignore.normalizer.jq.timeout
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
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.11.2
|
||||
newTag: v2.11.9
|
||||
|
||||
@@ -12,7 +12,7 @@ patches:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.11.2
|
||||
newTag: v2.11.9
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/applicationset-controller
|
||||
|
||||
@@ -1219,7 +1219,7 @@ spec:
|
||||
automountServiceAccountToken: false
|
||||
initContainers:
|
||||
- name: config-init
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
{}
|
||||
@@ -1258,7 +1258,7 @@ spec:
|
||||
|
||||
containers:
|
||||
- name: redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-server
|
||||
@@ -1321,7 +1321,7 @@ spec:
|
||||
- /bin/sh
|
||||
- /readonly-config/trigger-failover-if-master.sh
|
||||
- name: sentinel
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- redis-sentinel
|
||||
@@ -1378,7 +1378,7 @@ spec:
|
||||
{}
|
||||
|
||||
- name: split-brain-fix
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
command:
|
||||
- sh
|
||||
|
||||
@@ -25,7 +25,7 @@ redis-ha:
|
||||
enabled: true
|
||||
image:
|
||||
repository: redis
|
||||
tag: 7.0.14-alpine
|
||||
tag: 7.0.15-alpine
|
||||
containerSecurityContext: null
|
||||
sentinel:
|
||||
bind: "0.0.0.0"
|
||||
|
||||
@@ -22565,7 +22565,7 @@ spec:
|
||||
key: applicationsetcontroller.enable.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -22688,7 +22688,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -22770,7 +22770,7 @@ spec:
|
||||
key: notificationscontroller.selfservice.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -22889,7 +22889,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -23158,7 +23158,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -23210,7 +23210,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -23534,7 +23534,7 @@ spec:
|
||||
key: server.api.content.types
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -23833,7 +23833,7 @@ spec:
|
||||
key: controller.ignore.normalizer.jq.timeout
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -23916,7 +23916,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -23976,7 +23976,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle: {}
|
||||
livenessProbe:
|
||||
@@ -24034,7 +24034,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -24069,7 +24069,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
@@ -1686,7 +1686,7 @@ spec:
|
||||
key: applicationsetcontroller.enable.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -1809,7 +1809,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1891,7 +1891,7 @@ spec:
|
||||
key: notificationscontroller.selfservice.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -2010,7 +2010,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -2279,7 +2279,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -2331,7 +2331,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -2655,7 +2655,7 @@ spec:
|
||||
key: server.api.content.types
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2954,7 +2954,7 @@ spec:
|
||||
key: controller.ignore.normalizer.jq.timeout
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
@@ -3037,7 +3037,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle:
|
||||
preStop:
|
||||
@@ -3097,7 +3097,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle: {}
|
||||
livenessProbe:
|
||||
@@ -3155,7 +3155,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: split-brain-fix
|
||||
resources: {}
|
||||
@@ -3190,7 +3190,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
securityContext:
|
||||
|
||||
@@ -21682,7 +21682,7 @@ spec:
|
||||
key: applicationsetcontroller.enable.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -21805,7 +21805,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -21887,7 +21887,7 @@ spec:
|
||||
key: notificationscontroller.selfservice.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -21971,7 +21971,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -21987,7 +21987,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -22228,7 +22228,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -22280,7 +22280,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -22602,7 +22602,7 @@ spec:
|
||||
key: server.api.content.types
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -22901,7 +22901,7 @@ spec:
|
||||
key: controller.ignore.normalizer.jq.timeout
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -803,7 +803,7 @@ spec:
|
||||
key: applicationsetcontroller.enable.scm.providers
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-applicationset-controller
|
||||
ports:
|
||||
@@ -926,7 +926,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
securityContext:
|
||||
@@ -1008,7 +1008,7 @@ spec:
|
||||
key: notificationscontroller.selfservice.enabled
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
@@ -1092,7 +1092,7 @@ spec:
|
||||
secretKeyRef:
|
||||
key: auth
|
||||
name: argocd-redis
|
||||
image: redis:7.0.14-alpine
|
||||
image: redis:7.0.15-alpine
|
||||
imagePullPolicy: Always
|
||||
name: redis
|
||||
ports:
|
||||
@@ -1108,7 +1108,7 @@ spec:
|
||||
- argocd
|
||||
- admin
|
||||
- redis-initial-password
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: secret-init
|
||||
securityContext:
|
||||
@@ -1349,7 +1349,7 @@ spec:
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1401,7 +1401,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /var/run/argocd/argocd-cmp-server
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
name: copyutil
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
@@ -1723,7 +1723,7 @@ spec:
|
||||
key: server.api.content.types
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -2022,7 +2022,7 @@ spec:
|
||||
key: controller.ignore.normalizer.jq.timeout
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.11.2
|
||||
image: quay.io/argoproj/argocd:v2.11.9
|
||||
imagePullPolicy: Always
|
||||
name: argocd-application-controller
|
||||
ports:
|
||||
|
||||
@@ -2227,7 +2227,6 @@ message SyncStatus {
|
||||
optional string status = 1;
|
||||
|
||||
// ComparedTo contains information about what has been compared
|
||||
// +patchStrategy=replace
|
||||
optional ComparedTo comparedTo = 2;
|
||||
|
||||
// Revision contains information about the revision the comparison has been performed to
|
||||
|
||||
@@ -7705,11 +7705,6 @@ func schema_pkg_apis_application_v1alpha1_SyncStatus(ref common.ReferenceCallbac
|
||||
},
|
||||
},
|
||||
"comparedTo": {
|
||||
VendorExtensible: spec.VendorExtensible{
|
||||
Extensions: spec.Extensions{
|
||||
"x-kubernetes-patch-strategy": "replace",
|
||||
},
|
||||
},
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ComparedTo contains information about what has been compared",
|
||||
Default: map[string]interface{}{},
|
||||
|
||||
@@ -3,6 +3,7 @@ package v1alpha1
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/cert"
|
||||
"github.com/argoproj/argo-cd/v2/util/git"
|
||||
@@ -227,21 +228,22 @@ func getCAPath(repoURL string) string {
|
||||
}
|
||||
|
||||
hostname := ""
|
||||
// url.Parse() will happily parse most things thrown at it. When the URL
|
||||
// is either https or oci, we use the parsed hostname to retrieve the cert,
|
||||
// otherwise we'll use the parsed path (OCI repos are often specified as
|
||||
// hostname, without protocol).
|
||||
parsedURL, err := url.Parse(repoURL)
|
||||
var parsedURL *url.URL
|
||||
var err error
|
||||
// Without schema in url, url.Parse() treats the url as differently
|
||||
// and may incorrectly parses the hostname if url contains a path or port.
|
||||
// To ensure proper parsing, prepend a dummy schema.
|
||||
if !strings.Contains(repoURL, "://") {
|
||||
parsedURL, err = url.Parse("protocol://" + repoURL)
|
||||
} else {
|
||||
parsedURL, err = url.Parse(repoURL)
|
||||
}
|
||||
if err != nil {
|
||||
log.Warnf("Could not parse repo URL '%s': %v", repoURL, err)
|
||||
return ""
|
||||
}
|
||||
if parsedURL.Scheme == "https" || parsedURL.Scheme == "oci" {
|
||||
hostname = parsedURL.Host
|
||||
} else if parsedURL.Scheme == "" {
|
||||
hostname = parsedURL.Path
|
||||
}
|
||||
|
||||
hostname = parsedURL.Hostname()
|
||||
if hostname == "" {
|
||||
log.Warnf("Could not get hostname for repository '%s'", repoURL)
|
||||
return ""
|
||||
|
||||
@@ -1509,8 +1509,7 @@ type SyncStatus struct {
|
||||
// Status is the sync state of the comparison
|
||||
Status SyncStatusCode `json:"status" protobuf:"bytes,1,opt,name=status,casttype=SyncStatusCode"`
|
||||
// ComparedTo contains information about what has been compared
|
||||
// +patchStrategy=replace
|
||||
ComparedTo ComparedTo `json:"comparedTo,omitempty" protobuf:"bytes,2,opt,name=comparedTo" patchStrategy:"replace"`
|
||||
ComparedTo ComparedTo `json:"comparedTo,omitempty" protobuf:"bytes,2,opt,name=comparedTo"`
|
||||
// Revision contains information about the revision the comparison has been performed to
|
||||
Revision string `json:"revision,omitempty" protobuf:"bytes,3,opt,name=revision"`
|
||||
// Revisions contains information about the revisions of multiple sources the comparison has been performed to
|
||||
|
||||
@@ -11,13 +11,9 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/diff"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
argocdcommon "github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/stretchr/testify/require"
|
||||
"k8s.io/utils/pointer"
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/sync/common"
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -3174,18 +3170,25 @@ func TestGetCAPath(t *testing.T) {
|
||||
"https://foo.example.com",
|
||||
"oci://foo.example.com",
|
||||
"foo.example.com",
|
||||
"foo.example.com/charts",
|
||||
"https://foo.example.com:5000",
|
||||
"foo.example.com:5000",
|
||||
"foo.example.com:5000/charts",
|
||||
"ssh://foo.example.com",
|
||||
}
|
||||
invalidpath := []string{
|
||||
"https://bar.example.com",
|
||||
"oci://bar.example.com",
|
||||
"bar.example.com",
|
||||
"ssh://foo.example.com",
|
||||
"git@example.com:organization/reponame.git",
|
||||
"ssh://bar.example.com",
|
||||
"git@foo.example.com:organization/reponame.git",
|
||||
"ssh://git@foo.example.com:organization/reponame.git",
|
||||
"/some/invalid/thing",
|
||||
"../another/invalid/thing",
|
||||
"./also/invalid",
|
||||
"$invalid/as/well",
|
||||
"..",
|
||||
"://invalid",
|
||||
}
|
||||
|
||||
for _, str := range validcert {
|
||||
@@ -3670,35 +3673,3 @@ func TestApplicationSpec_GetSourcePtrByIndex(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHelmValuesObjectHasReplaceStrategy(t *testing.T) {
|
||||
app := Application{
|
||||
Status: ApplicationStatus{Sync: SyncStatus{ComparedTo: ComparedTo{
|
||||
Source: ApplicationSource{
|
||||
Helm: &ApplicationSourceHelm{
|
||||
ValuesObject: &runtime.RawExtension{
|
||||
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
appModified := Application{
|
||||
Status: ApplicationStatus{Sync: SyncStatus{ComparedTo: ComparedTo{
|
||||
Source: ApplicationSource{
|
||||
Helm: &ApplicationSourceHelm{
|
||||
ValuesObject: &runtime.RawExtension{
|
||||
Object: &unstructured.Unstructured{Object: map[string]interface{}{"key": []string{"value-modified1"}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}},
|
||||
}
|
||||
|
||||
patch, _, err := diff.CreateTwoWayMergePatch(
|
||||
app,
|
||||
appModified, Application{})
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, `{"status":{"sync":{"comparedTo":{"destination":{},"source":{"helm":{"valuesObject":{"key":["value-modified1"]}},"repoURL":""}}}}}`, string(patch))
|
||||
}
|
||||
|
||||
@@ -2731,7 +2731,10 @@ func (s *Service) UpdateRevisionForPaths(_ context.Context, request *apiclient.U
|
||||
return nil, status.Errorf(codes.Internal, "unable to get changed files for repo %s with revision %s: %v", repo.Repo, revision, err)
|
||||
}
|
||||
|
||||
changed := apppathutil.AppFilesHaveChanged(refreshPaths, files)
|
||||
changed := false
|
||||
if len(files) != 0 {
|
||||
changed = apppathutil.AppFilesHaveChanged(refreshPaths, files)
|
||||
}
|
||||
|
||||
if !changed {
|
||||
logCtx.Debugf("no changes found for application %s in repo %s from revision %s to revision %s", request.AppName, repo.Repo, syncedRevision, revision)
|
||||
|
||||
@@ -469,15 +469,16 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
|
||||
}
|
||||
|
||||
sources := make([]appv1.ApplicationSource, 0)
|
||||
appSpec := a.Spec.DeepCopy()
|
||||
if a.Spec.HasMultipleSources() {
|
||||
numOfSources := int64(len(a.Spec.GetSources()))
|
||||
for i, pos := range q.SourcePositions {
|
||||
if pos <= 0 || pos > numOfSources {
|
||||
return fmt.Errorf("source position is out of range")
|
||||
}
|
||||
a.Spec.Sources[pos-1].TargetRevision = q.Revisions[i]
|
||||
appSpec.Sources[pos-1].TargetRevision = q.Revisions[i]
|
||||
}
|
||||
sources = a.Spec.GetSources()
|
||||
sources = appSpec.GetSources()
|
||||
} else {
|
||||
source := a.Spec.GetSource()
|
||||
if q.GetRevision() != "" {
|
||||
@@ -487,7 +488,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
|
||||
}
|
||||
|
||||
// Store the map of all sources having ref field into a map for applications with sources field
|
||||
refSources, err := argo.GetRefSources(context.Background(), a.Spec, s.db)
|
||||
refSources, err := argo.GetRefSources(context.Background(), *appSpec, s.db)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get ref sources: %v", err)
|
||||
}
|
||||
@@ -560,7 +561,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
|
||||
manifestInfo.Manifests[i] = string(data)
|
||||
}
|
||||
}
|
||||
manifests.Manifests = manifestInfo.Manifests
|
||||
manifests.Manifests = append(manifests.Manifests, manifestInfo.Manifests...)
|
||||
}
|
||||
|
||||
return manifests, nil
|
||||
|
||||
@@ -225,7 +225,7 @@ func (s *terminalHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
fieldLog.Info("terminal session starting")
|
||||
|
||||
session, err := newTerminalSession(w, r, nil, s.sessionManager)
|
||||
session, err := newTerminalSession(ctx, w, r, nil, s.sessionManager, appRBACName, s.enf)
|
||||
if err != nil {
|
||||
http.Error(w, "Failed to start terminal session", http.StatusBadRequest)
|
||||
return
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
httputil "github.com/argoproj/argo-cd/v2/util/http"
|
||||
util_session "github.com/argoproj/argo-cd/v2/util/session"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
|
||||
httputil "github.com/argoproj/argo-cd/v2/util/http"
|
||||
"github.com/argoproj/argo-cd/v2/util/rbac"
|
||||
util_session "github.com/argoproj/argo-cd/v2/util/session"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
@@ -31,6 +35,7 @@ var upgrader = func() websocket.Upgrader {
|
||||
|
||||
// terminalSession implements PtyHandler
|
||||
type terminalSession struct {
|
||||
ctx context.Context
|
||||
wsConn *websocket.Conn
|
||||
sizeChan chan remotecommand.TerminalSize
|
||||
doneChan chan struct{}
|
||||
@@ -39,6 +44,8 @@ type terminalSession struct {
|
||||
writeLock sync.Mutex
|
||||
sessionManager *util_session.SessionManager
|
||||
token *string
|
||||
appRBACName string
|
||||
enf *rbac.Enforcer
|
||||
}
|
||||
|
||||
// getToken get auth token from web socket request
|
||||
@@ -48,7 +55,7 @@ func getToken(r *http.Request) (string, error) {
|
||||
}
|
||||
|
||||
// newTerminalSession create terminalSession
|
||||
func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager *util_session.SessionManager) (*terminalSession, error) {
|
||||
func newTerminalSession(ctx context.Context, w http.ResponseWriter, r *http.Request, responseHeader http.Header, sessionManager *util_session.SessionManager, appRBACName string, enf *rbac.Enforcer) (*terminalSession, error) {
|
||||
token, err := getToken(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -59,12 +66,15 @@ func newTerminalSession(w http.ResponseWriter, r *http.Request, responseHeader h
|
||||
return nil, err
|
||||
}
|
||||
session := &terminalSession{
|
||||
ctx: ctx,
|
||||
wsConn: conn,
|
||||
tty: true,
|
||||
sizeChan: make(chan remotecommand.TerminalSize),
|
||||
doneChan: make(chan struct{}),
|
||||
sessionManager: sessionManager,
|
||||
token: &token,
|
||||
appRBACName: appRBACName,
|
||||
enf: enf,
|
||||
}
|
||||
return session, nil
|
||||
}
|
||||
@@ -125,6 +135,29 @@ func (t *terminalSession) reconnect() (int, error) {
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
func (t *terminalSession) validatePermissions(p []byte) (int, error) {
|
||||
permissionDeniedMessage, _ := json.Marshal(TerminalMessage{
|
||||
Operation: "stdout",
|
||||
Data: "Permission denied",
|
||||
})
|
||||
if err := t.enf.EnforceErr(t.ctx.Value("claims"), rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, t.appRBACName); err != nil {
|
||||
err = t.wsConn.WriteMessage(websocket.TextMessage, permissionDeniedMessage)
|
||||
if err != nil {
|
||||
log.Errorf("permission denied message err: %v", err)
|
||||
}
|
||||
return copy(p, EndOfTransmission), permissionDeniedErr
|
||||
}
|
||||
|
||||
if err := t.enf.EnforceErr(t.ctx.Value("claims"), rbacpolicy.ResourceExec, rbacpolicy.ActionCreate, t.appRBACName); err != nil {
|
||||
err = t.wsConn.WriteMessage(websocket.TextMessage, permissionDeniedMessage)
|
||||
if err != nil {
|
||||
log.Errorf("permission denied message err: %v", err)
|
||||
}
|
||||
return copy(p, EndOfTransmission), permissionDeniedErr
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// Read called in a loop from remotecommand as long as the process is running
|
||||
func (t *terminalSession) Read(p []byte) (int, error) {
|
||||
// check if token still valid
|
||||
@@ -135,6 +168,12 @@ func (t *terminalSession) Read(p []byte) (int, error) {
|
||||
return t.reconnect()
|
||||
}
|
||||
|
||||
// validate permissions
|
||||
code, err := t.validatePermissions(p)
|
||||
if err != nil {
|
||||
return code, err
|
||||
}
|
||||
|
||||
t.readLock.Lock()
|
||||
_, message, err := t.wsConn.ReadMessage()
|
||||
t.readLock.Unlock()
|
||||
|
||||
@@ -1,23 +1,65 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/util/assets"
|
||||
"github.com/argoproj/argo-cd/v2/util/rbac"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func reconnect(w http.ResponseWriter, r *http.Request) {
|
||||
func newTestTerminalSession(w http.ResponseWriter, r *http.Request) terminalSession {
|
||||
var upgrader = websocket.Upgrader{}
|
||||
c, err := upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
return
|
||||
return terminalSession{}
|
||||
}
|
||||
|
||||
ts := terminalSession{wsConn: c}
|
||||
return terminalSession{wsConn: c}
|
||||
}
|
||||
|
||||
func newEnforcer() *rbac.Enforcer {
|
||||
additionalConfig := make(map[string]string, 0)
|
||||
kubeclientset := fake.NewSimpleClientset(&v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
Name: "argocd-cm",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: additionalConfig,
|
||||
}, &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-secret",
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"admin.password": []byte("test"),
|
||||
"server.secretkey": []byte("test"),
|
||||
},
|
||||
})
|
||||
|
||||
enforcer := rbac.NewEnforcer(kubeclientset, testNamespace, common.ArgoCDRBACConfigMapName, nil)
|
||||
return enforcer
|
||||
}
|
||||
|
||||
func reconnect(w http.ResponseWriter, r *http.Request) {
|
||||
ts := newTestTerminalSession(w, r)
|
||||
_, _ = ts.reconnect()
|
||||
}
|
||||
|
||||
@@ -44,3 +86,71 @@ func TestReconnect(t *testing.T) {
|
||||
assert.Equal(t, message.Data, ReconnectMessage)
|
||||
|
||||
}
|
||||
|
||||
func TestValidateWithAdminPermissions(t *testing.T) {
|
||||
validate := func(w http.ResponseWriter, r *http.Request) {
|
||||
enf := newEnforcer()
|
||||
_ = enf.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enf.SetDefaultRole("role:admin")
|
||||
enf.SetClaimsEnforcerFunc(func(claims jwt.Claims, rvals ...interface{}) bool {
|
||||
return true
|
||||
})
|
||||
ts := newTestTerminalSession(w, r)
|
||||
ts.enf = enf
|
||||
ts.appRBACName = "test"
|
||||
// nolint:staticcheck
|
||||
ts.ctx = context.WithValue(context.Background(), "claims", &jwt.MapClaims{"groups": []string{"admin"}})
|
||||
_, err := ts.validatePermissions([]byte{})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
s := httptest.NewServer(http.HandlerFunc(validate))
|
||||
defer s.Close()
|
||||
|
||||
u := "ws" + strings.TrimPrefix(s.URL, "http")
|
||||
|
||||
// Connect to the server
|
||||
ws, _, err := websocket.DefaultDialer.Dial(u, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer ws.Close()
|
||||
}
|
||||
|
||||
func TestValidateWithoutPermissions(t *testing.T) {
|
||||
validate := func(w http.ResponseWriter, r *http.Request) {
|
||||
enf := newEnforcer()
|
||||
_ = enf.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enf.SetDefaultRole("role:test")
|
||||
enf.SetClaimsEnforcerFunc(func(claims jwt.Claims, rvals ...interface{}) bool {
|
||||
return false
|
||||
})
|
||||
ts := newTestTerminalSession(w, r)
|
||||
ts.enf = enf
|
||||
ts.appRBACName = "test"
|
||||
// nolint:staticcheck
|
||||
ts.ctx = context.WithValue(context.Background(), "claims", &jwt.MapClaims{"groups": []string{"test"}})
|
||||
_, err := ts.validatePermissions([]byte{})
|
||||
require.Error(t, err)
|
||||
assert.Equal(t, permissionDeniedErr.Error(), err.Error())
|
||||
}
|
||||
|
||||
s := httptest.NewServer(http.HandlerFunc(validate))
|
||||
defer s.Close()
|
||||
|
||||
u := "ws" + strings.TrimPrefix(s.URL, "http")
|
||||
|
||||
// Connect to the server
|
||||
ws, _, err := websocket.DefaultDialer.Dial(u, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
defer ws.Close()
|
||||
|
||||
_, p, _ := ws.ReadMessage()
|
||||
|
||||
var message TerminalMessage
|
||||
|
||||
err = json.Unmarshal(p, &message)
|
||||
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, "Permission denied", message.Data)
|
||||
}
|
||||
|
||||
@@ -187,15 +187,11 @@ func (s *Server) Create(ctx context.Context, q *cluster.ClusterCreateRequest) (*
|
||||
|
||||
// Get returns a cluster from a query
|
||||
func (s *Server) Get(ctx context.Context, q *cluster.ClusterQuery) (*appv1.Cluster, error) {
|
||||
c, err := s.getClusterWith403IfNotExist(ctx, q)
|
||||
c, err := s.getClusterAndVerifyAccess(ctx, q, rbacpolicy.ActionGet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionGet, CreateClusterRBACObject(c.Project, q.Server)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.toAPIResponse(c), nil
|
||||
}
|
||||
|
||||
@@ -207,6 +203,21 @@ func (s *Server) getClusterWith403IfNotExist(ctx context.Context, q *cluster.Clu
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (s *Server) getClusterAndVerifyAccess(ctx context.Context, q *cluster.ClusterQuery, action string) (*appv1.Cluster, error) {
|
||||
c, err := s.getClusterWith403IfNotExist(ctx, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify that user can do the specified action inside project where cluster is located
|
||||
if !s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceClusters, action, CreateClusterRBACObject(c.Project, c.Server)) {
|
||||
log.WithField("cluster", q.Server).Warnf("encountered permissions issue while processing request: %v", err)
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (s *Server) getCluster(ctx context.Context, q *cluster.ClusterQuery) (*appv1.Cluster, error) {
|
||||
if q.Id != nil {
|
||||
q.Server = ""
|
||||
@@ -278,20 +289,16 @@ var clusterFieldsByPath = map[string]func(updated *appv1.Cluster, existing *appv
|
||||
|
||||
// Update updates a cluster
|
||||
func (s *Server) Update(ctx context.Context, q *cluster.ClusterUpdateRequest) (*appv1.Cluster, error) {
|
||||
c, err := s.getClusterWith403IfNotExist(ctx, &cluster.ClusterQuery{
|
||||
c, err := s.getClusterAndVerifyAccess(ctx, &cluster.ClusterQuery{
|
||||
Server: q.Cluster.Server,
|
||||
Name: q.Cluster.Name,
|
||||
Id: q.Id,
|
||||
})
|
||||
}, rbacpolicy.ActionUpdate)
|
||||
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// verify that user can do update inside project where cluster is located
|
||||
if !s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, CreateClusterRBACObject(c.Project, c.Server)) {
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
|
||||
if len(q.UpdatedFields) == 0 || sets.NewString(q.UpdatedFields...).Has("project") {
|
||||
// verify that user can do update inside project where cluster will be located
|
||||
if !s.enf.Enforce(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, CreateClusterRBACObject(q.Cluster.Project, c.Server)) {
|
||||
@@ -341,7 +348,8 @@ func (s *Server) Delete(ctx context.Context, q *cluster.ClusterQuery) (*cluster.
|
||||
if q.Name != "" {
|
||||
servers, err := s.db.GetClusterServersByName(ctx, q.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
log.WithField("cluster", q.Name).Warnf("failed to get cluster servers by name: %v", err)
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
for _, server := range servers {
|
||||
if err := enforceAndDelete(s, ctx, server, c.Project); err != nil {
|
||||
@@ -359,7 +367,8 @@ func (s *Server) Delete(ctx context.Context, q *cluster.ClusterQuery) (*cluster.
|
||||
|
||||
func enforceAndDelete(s *Server, ctx context.Context, server, project string) error {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionDelete, CreateClusterRBACObject(project, server)); err != nil {
|
||||
return err
|
||||
log.WithField("cluster", server).Warnf("encountered permissions issue while processing request: %v", err)
|
||||
return common.PermissionDeniedAPIError
|
||||
}
|
||||
if err := s.db.DeleteCluster(ctx, server); err != nil {
|
||||
return err
|
||||
@@ -378,16 +387,19 @@ func (s *Server) RotateAuth(ctx context.Context, q *cluster.ClusterQuery) (*clus
|
||||
if q.Name != "" {
|
||||
servers, err = s.db.GetClusterServersByName(ctx, q.Name)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.NotFound, "failed to get cluster servers by name: %v", err)
|
||||
log.WithField("cluster", q.Name).Warnf("failed to get cluster servers by name: %v", err)
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
for _, server := range servers {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, CreateClusterRBACObject(clust.Project, server)); err != nil {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "encountered permissions issue while processing request: %v", err)
|
||||
log.WithField("cluster", server).Warnf("encountered permissions issue while processing request: %v", err)
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, CreateClusterRBACObject(clust.Project, q.Server)); err != nil {
|
||||
return nil, status.Errorf(codes.PermissionDenied, "encountered permissions issue while processing request: %v", err)
|
||||
log.WithField("cluster", q.Server).Warnf("encountered permissions issue while processing request: %v", err)
|
||||
return nil, common.PermissionDeniedAPIError
|
||||
}
|
||||
servers = append(servers, q.Server)
|
||||
}
|
||||
@@ -467,13 +479,10 @@ func (s *Server) toAPIResponse(clust *appv1.Cluster) *appv1.Cluster {
|
||||
|
||||
// InvalidateCache invalidates cluster cache
|
||||
func (s *Server) InvalidateCache(ctx context.Context, q *cluster.ClusterQuery) (*appv1.Cluster, error) {
|
||||
cls, err := s.getClusterWith403IfNotExist(ctx, q)
|
||||
cls, err := s.getClusterAndVerifyAccess(ctx, q, rbacpolicy.ActionUpdate)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceClusters, rbacpolicy.ActionUpdate, CreateClusterRBACObject(cls.Project, q.Server)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := v1.Now()
|
||||
cls.RefreshRequestedAt = &now
|
||||
cls, err = s.db.UpdateCluster(ctx, cls)
|
||||
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
|
||||
"github.com/argoproj/argo-cd/v2/util/assets"
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -51,6 +54,16 @@ func newNoopEnforcer() *rbac.Enforcer {
|
||||
return enf
|
||||
}
|
||||
|
||||
func newEnforcer() *rbac.Enforcer {
|
||||
enforcer := rbac.NewEnforcer(fake.NewSimpleClientset(test.NewFakeConfigMap()), test.FakeArgoCDNamespace, common.ArgoCDRBACConfigMapName, nil)
|
||||
_ = enforcer.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enforcer.SetDefaultRole("role:test")
|
||||
enforcer.SetClaimsEnforcerFunc(func(claims jwt.Claims, rvals ...interface{}) bool {
|
||||
return true
|
||||
})
|
||||
return enforcer
|
||||
}
|
||||
|
||||
func TestUpdateCluster_RejectInvalidParams(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -604,3 +617,152 @@ func TestListCluster(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetClusterAndVerifyAccess(t *testing.T) {
|
||||
t.Run("GetClusterAndVerifyAccess - No Cluster", func(t *testing.T) {
|
||||
db := &dbmocks.ArgoDB{}
|
||||
|
||||
mockCluster := v1alpha1.Cluster{
|
||||
Name: "test/ing",
|
||||
Server: "https://127.0.0.1",
|
||||
Namespaces: []string{"default", "kube-system"},
|
||||
}
|
||||
mockClusterList := v1alpha1.ClusterList{
|
||||
ListMeta: v1.ListMeta{},
|
||||
Items: []v1alpha1.Cluster{
|
||||
mockCluster,
|
||||
},
|
||||
}
|
||||
|
||||
db.On("ListClusters", mock.Anything).Return(&mockClusterList, nil)
|
||||
|
||||
server := NewServer(db, newNoopEnforcer(), newServerInMemoryCache(), &kubetest.MockKubectlCmd{})
|
||||
cluster, err := server.getClusterAndVerifyAccess(context.Background(), &clusterapi.ClusterQuery{
|
||||
Name: "test/not-exists",
|
||||
}, rbacpolicy.ActionGet)
|
||||
|
||||
assert.Nil(t, cluster)
|
||||
assert.ErrorIs(t, err, common.PermissionDeniedAPIError)
|
||||
})
|
||||
|
||||
t.Run("GetClusterAndVerifyAccess - Permissions Denied", func(t *testing.T) {
|
||||
db := &dbmocks.ArgoDB{}
|
||||
|
||||
mockCluster := v1alpha1.Cluster{
|
||||
Name: "test/ing",
|
||||
Server: "https://127.0.0.1",
|
||||
Namespaces: []string{"default", "kube-system"},
|
||||
}
|
||||
mockClusterList := v1alpha1.ClusterList{
|
||||
ListMeta: v1.ListMeta{},
|
||||
Items: []v1alpha1.Cluster{
|
||||
mockCluster,
|
||||
},
|
||||
}
|
||||
|
||||
db.On("ListClusters", mock.Anything).Return(&mockClusterList, nil)
|
||||
|
||||
server := NewServer(db, newEnforcer(), newServerInMemoryCache(), &kubetest.MockKubectlCmd{})
|
||||
cluster, err := server.getClusterAndVerifyAccess(context.Background(), &clusterapi.ClusterQuery{
|
||||
Name: "test/ing",
|
||||
}, rbacpolicy.ActionGet)
|
||||
|
||||
assert.Nil(t, cluster)
|
||||
assert.ErrorIs(t, err, common.PermissionDeniedAPIError)
|
||||
})
|
||||
}
|
||||
|
||||
func TestNoClusterEnumeration(t *testing.T) {
|
||||
db := &dbmocks.ArgoDB{}
|
||||
|
||||
mockCluster := v1alpha1.Cluster{
|
||||
Name: "test/ing",
|
||||
Server: "https://127.0.0.1",
|
||||
Namespaces: []string{"default", "kube-system"},
|
||||
}
|
||||
mockClusterList := v1alpha1.ClusterList{
|
||||
ListMeta: v1.ListMeta{},
|
||||
Items: []v1alpha1.Cluster{
|
||||
mockCluster,
|
||||
},
|
||||
}
|
||||
|
||||
db.On("ListClusters", mock.Anything).Return(&mockClusterList, nil)
|
||||
db.On("GetCluster", mock.Anything, mock.Anything).Return(&mockCluster, nil)
|
||||
|
||||
server := NewServer(db, newEnforcer(), newServerInMemoryCache(), &kubetest.MockKubectlCmd{})
|
||||
|
||||
t.Run("Get", func(t *testing.T) {
|
||||
_, err := server.Get(context.Background(), &clusterapi.ClusterQuery{
|
||||
Name: "cluster-not-exists",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
|
||||
_, err = server.Get(context.Background(), &clusterapi.ClusterQuery{
|
||||
Name: "test/ing",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
})
|
||||
|
||||
t.Run("Update", func(t *testing.T) {
|
||||
_, err := server.Update(context.Background(), &clusterapi.ClusterUpdateRequest{
|
||||
Cluster: &v1alpha1.Cluster{
|
||||
Name: "cluster-not-exists",
|
||||
},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
|
||||
_, err = server.Update(context.Background(), &clusterapi.ClusterUpdateRequest{
|
||||
Cluster: &v1alpha1.Cluster{
|
||||
Name: "test/ing",
|
||||
},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
})
|
||||
|
||||
t.Run("Delete", func(t *testing.T) {
|
||||
_, err := server.Delete(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.2",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
|
||||
_, err = server.Delete(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.1",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
})
|
||||
|
||||
t.Run("RotateAuth", func(t *testing.T) {
|
||||
_, err := server.RotateAuth(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.2",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
|
||||
_, err = server.RotateAuth(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.1",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
})
|
||||
|
||||
t.Run("InvalidateCache", func(t *testing.T) {
|
||||
_, err := server.InvalidateCache(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.2",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
|
||||
_, err = server.InvalidateCache(context.Background(), &clusterapi.ClusterQuery{
|
||||
Server: "https://127.0.0.1",
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, common.PermissionDeniedAPIError.Error(), err.Error(), "error message must be _only_ the permission error, to avoid leaking information about cluster existence")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1048,7 +1048,7 @@ func (a *ArgoCDServer) newHTTPServer(ctx context.Context, port int, grpcWebHandl
|
||||
|
||||
// Webhook handler for git events (Note: cache timeouts are hardcoded because API server does not write to cache and not really using them)
|
||||
argoDB := db.NewDB(a.Namespace, a.settingsMgr, a.KubeClientset)
|
||||
acdWebhookHandler := webhook.NewHandler(a.Namespace, a.ArgoCDServerOpts.ApplicationNamespaces, a.AppClientset, a.settings, a.settingsMgr, a.RepoServerCache, a.Cache, argoDB)
|
||||
acdWebhookHandler := webhook.NewHandler(a.Namespace, a.ArgoCDServerOpts.ApplicationNamespaces, a.AppClientset, a.settings, a.settingsMgr, a.RepoServerCache, a.Cache, argoDB, a.settingsMgr.GetMaxWebhookPayloadSize())
|
||||
|
||||
mux.HandleFunc("/api/webhook", acdWebhookHandler.Handler)
|
||||
|
||||
|
||||
@@ -109,7 +109,6 @@ func (s *Server) Get(ctx context.Context, q *settingspkg.SettingsQuery) (*settin
|
||||
UserLoginsDisabled: userLoginsDisabled,
|
||||
KustomizeVersions: kustomizeVersions,
|
||||
UiCssURL: argoCDSettings.UiCssURL,
|
||||
PasswordPattern: argoCDSettings.PasswordPattern,
|
||||
TrackingMethod: trackingMethod,
|
||||
ExecEnabled: argoCDSettings.ExecEnabled,
|
||||
AppsInAnyNamespaceEnabled: s.appsInAnyNamespaceEnabled,
|
||||
@@ -122,6 +121,9 @@ func (s *Server) Get(ctx context.Context, q *settingspkg.SettingsQuery) (*settin
|
||||
set.UiBannerPosition = argoCDSettings.UiBannerPosition
|
||||
set.ControllerNamespace = s.mgr.GetNamespace()
|
||||
}
|
||||
if sessionmgr.LoggedIn(ctx) {
|
||||
set.PasswordPattern = argoCDSettings.PasswordPattern
|
||||
}
|
||||
if argoCDSettings.DexConfig != "" {
|
||||
var cfg settingspkg.DexConfig
|
||||
err = yaml.Unmarshal([]byte(argoCDSettings.DexConfig), &cfg)
|
||||
|
||||
@@ -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:21.7.1@sha256:b9ccc4aca32eebf124e0ca0fd573dacffba2b9236987a1d4d2625ce3c162ecc8 as node
|
||||
|
||||
FROM docker.io/library/golang:1.21.9@sha256:7d0dcbe5807b1ad7272a598fbf9d7af15b5e2bed4fd6c4c2b5b3684df0b317dd as golang
|
||||
FROM docker.io/library/golang:1.21.10@sha256:16438a8e66c0c984f732e815ee5b7d715b8e33e81bac6d6a3750b1067744e7ca as golang
|
||||
|
||||
FROM docker.io/library/registry:2.8@sha256:fb9c9aef62af3955f6014613456551c92e88a67dcf1fc51f5f91bcbd1832813f as registry
|
||||
|
||||
|
||||
@@ -523,100 +523,6 @@ func TestSimpleListGeneratorGoTemplate(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestCreateApplicationDespiteParamsError(t *testing.T) {
|
||||
expectedErrorMessage := `failed to execute go template {{.cluster}}-guestbook: template: :1:2: executing "" at <.cluster>: map has no entry for key "cluster"`
|
||||
expectedConditionsParamsError := []v1alpha1.ApplicationSetCondition{
|
||||
{
|
||||
Type: v1alpha1.ApplicationSetConditionErrorOccurred,
|
||||
Status: v1alpha1.ApplicationSetConditionStatusTrue,
|
||||
Message: expectedErrorMessage,
|
||||
Reason: v1alpha1.ApplicationSetReasonRenderTemplateParamsError,
|
||||
},
|
||||
{
|
||||
Type: v1alpha1.ApplicationSetConditionParametersGenerated,
|
||||
Status: v1alpha1.ApplicationSetConditionStatusFalse,
|
||||
Message: expectedErrorMessage,
|
||||
Reason: v1alpha1.ApplicationSetReasonErrorOccurred,
|
||||
},
|
||||
{
|
||||
Type: v1alpha1.ApplicationSetConditionResourcesUpToDate,
|
||||
Status: v1alpha1.ApplicationSetConditionStatusFalse,
|
||||
Message: expectedErrorMessage,
|
||||
Reason: v1alpha1.ApplicationSetReasonRenderTemplateParamsError,
|
||||
},
|
||||
}
|
||||
expectedApp := argov1alpha1.Application{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: application.ApplicationKind,
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "my-cluster-guestbook",
|
||||
Namespace: fixture.TestNamespace(),
|
||||
Finalizers: []string{"resources-finalizer.argocd.argoproj.io"},
|
||||
},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
Source: &argov1alpha1.ApplicationSource{
|
||||
RepoURL: "https://github.com/argoproj/argocd-example-apps.git",
|
||||
TargetRevision: "HEAD",
|
||||
Path: "guestbook",
|
||||
},
|
||||
Destination: argov1alpha1.ApplicationDestination{
|
||||
Server: "https://kubernetes.default.svc",
|
||||
Namespace: "guestbook",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
Given(t).
|
||||
// Create a ListGenerator-based ApplicationSet
|
||||
When().Create(v1alpha1.ApplicationSet{ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "simple-list-generator",
|
||||
},
|
||||
Spec: v1alpha1.ApplicationSetSpec{
|
||||
GoTemplate: true,
|
||||
GoTemplateOptions: []string{"missingkey=error"},
|
||||
Template: v1alpha1.ApplicationSetTemplate{
|
||||
ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{.cluster}}-guestbook"},
|
||||
Spec: argov1alpha1.ApplicationSpec{
|
||||
Project: "default",
|
||||
Source: &argov1alpha1.ApplicationSource{
|
||||
RepoURL: "https://github.com/argoproj/argocd-example-apps.git",
|
||||
TargetRevision: "HEAD",
|
||||
Path: "guestbook",
|
||||
},
|
||||
Destination: argov1alpha1.ApplicationDestination{
|
||||
Server: "{{.url}}",
|
||||
Namespace: "guestbook",
|
||||
},
|
||||
},
|
||||
},
|
||||
Generators: []v1alpha1.ApplicationSetGenerator{
|
||||
{
|
||||
List: &v1alpha1.ListGenerator{
|
||||
Elements: []apiextensionsv1.JSON{
|
||||
{
|
||||
Raw: []byte(`{"cluster": "my-cluster","url": "https://kubernetes.default.svc"}`),
|
||||
},
|
||||
{
|
||||
Raw: []byte(`{"invalidCluster": "invalid-cluster","url": "https://kubernetes.default.svc"}`),
|
||||
}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}).Then().Expect(ApplicationsExist([]argov1alpha1.Application{expectedApp})).
|
||||
|
||||
// verify the ApplicationSet status conditions were set correctly
|
||||
Expect(ApplicationSetHasConditions("simple-list-generator", expectedConditionsParamsError)).
|
||||
|
||||
// Delete the ApplicationSet, and verify it deletes the Applications
|
||||
When().
|
||||
Delete().Then().Expect(ApplicationsDoNotExist([]argov1alpha1.Application{expectedApp}))
|
||||
|
||||
}
|
||||
|
||||
func TestRenderHelmValuesObject(t *testing.T) {
|
||||
|
||||
expectedApp := argov1alpha1.Application{
|
||||
|
||||
@@ -91,7 +91,7 @@ func TestClusterAddPermissionDenied(t *testing.T) {
|
||||
Create().
|
||||
Then().
|
||||
AndCLIOutput(func(output string, err error) {
|
||||
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, create"))
|
||||
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -256,7 +256,7 @@ func TestClusterDeleteDenied(t *testing.T) {
|
||||
DeleteByName().
|
||||
Then().
|
||||
AndCLIOutput(func(output string, err error) {
|
||||
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, delete"))
|
||||
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
|
||||
})
|
||||
|
||||
// Attempt to remove cluster creds by server
|
||||
@@ -270,7 +270,7 @@ func TestClusterDeleteDenied(t *testing.T) {
|
||||
DeleteByServer().
|
||||
Then().
|
||||
AndCLIOutput(func(output string, err error) {
|
||||
assert.True(t, strings.Contains(err.Error(), "PermissionDenied desc = permission denied: clusters, delete"))
|
||||
assert.Contains(t, err.Error(), "PermissionDenied desc = permission denied")
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -117,7 +117,7 @@
|
||||
"tslint-plugin-prettier": "^2.0.1",
|
||||
"tslint-react": "^5.0.0",
|
||||
"typescript": "^4.9.5",
|
||||
"webpack": "^5.84.1",
|
||||
"webpack": "^5.94.0",
|
||||
"webpack-cli": "^4.9.2",
|
||||
"webpack-dev-server": "^4.7.4",
|
||||
"yarn": "^1.22.21"
|
||||
|
||||
539
ui/yarn.lock
539
ui/yarn.lock
@@ -1432,16 +1432,35 @@
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/resolve-uri@3.1.0", "@jridgewell/resolve-uri@^3.0.3":
|
||||
"@jridgewell/gen-mapping@^0.3.5":
|
||||
version "0.3.5"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
|
||||
integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
|
||||
dependencies:
|
||||
"@jridgewell/set-array" "^1.2.1"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
"@jridgewell/trace-mapping" "^0.3.24"
|
||||
|
||||
"@jridgewell/resolve-uri@^3.0.3":
|
||||
version "3.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78"
|
||||
integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==
|
||||
|
||||
"@jridgewell/resolve-uri@^3.1.0":
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
|
||||
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
|
||||
|
||||
"@jridgewell/set-array@^1.0.1":
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72"
|
||||
integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==
|
||||
|
||||
"@jridgewell/set-array@^1.2.1":
|
||||
version "1.2.1"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
|
||||
integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
|
||||
|
||||
"@jridgewell/source-map@^0.3.2":
|
||||
version "0.3.2"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.2.tgz#f45351aaed4527a298512ec72f81040c998580fb"
|
||||
@@ -1450,11 +1469,24 @@
|
||||
"@jridgewell/gen-mapping" "^0.3.0"
|
||||
"@jridgewell/trace-mapping" "^0.3.9"
|
||||
|
||||
"@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10":
|
||||
"@jridgewell/source-map@^0.3.3":
|
||||
version "0.3.6"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a"
|
||||
integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==
|
||||
dependencies:
|
||||
"@jridgewell/gen-mapping" "^0.3.5"
|
||||
"@jridgewell/trace-mapping" "^0.3.25"
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.10":
|
||||
version "1.4.14"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24"
|
||||
integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==
|
||||
|
||||
"@jridgewell/sourcemap-codec@^1.4.14":
|
||||
version "1.5.0"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
|
||||
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
|
||||
|
||||
"@jridgewell/trace-mapping@0.3.9":
|
||||
version "0.3.9"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
|
||||
@@ -1471,13 +1503,13 @@
|
||||
"@jridgewell/resolve-uri" "^3.0.3"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.10"
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.17":
|
||||
version "0.3.18"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6"
|
||||
integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==
|
||||
"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25":
|
||||
version "0.3.25"
|
||||
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
|
||||
integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
|
||||
dependencies:
|
||||
"@jridgewell/resolve-uri" "3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "1.4.14"
|
||||
"@jridgewell/resolve-uri" "^3.1.0"
|
||||
"@jridgewell/sourcemap-codec" "^1.4.14"
|
||||
|
||||
"@jridgewell/trace-mapping@^0.3.9":
|
||||
version "0.3.14"
|
||||
@@ -1751,26 +1783,10 @@
|
||||
dependencies:
|
||||
deepmerge "*"
|
||||
|
||||
"@types/eslint-scope@^3.7.3":
|
||||
version "3.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224"
|
||||
integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g==
|
||||
dependencies:
|
||||
"@types/eslint" "*"
|
||||
"@types/estree" "*"
|
||||
|
||||
"@types/eslint@*":
|
||||
version "8.4.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.4.1.tgz#c48251553e8759db9e656de3efc846954ac32304"
|
||||
integrity sha512-GE44+DNEyxxh2Kc6ro/VkIj+9ma0pO0bwv9+uHSyBrikYOHr8zYcdPvnBOp1aw8s+CjRvuSx7CyWqRrNFQ59mA==
|
||||
dependencies:
|
||||
"@types/estree" "*"
|
||||
"@types/json-schema" "*"
|
||||
|
||||
"@types/estree@*", "@types/estree@^1.0.0":
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.1.tgz#aa22750962f3bf0e79d753d3cc067f010c95f194"
|
||||
integrity sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==
|
||||
"@types/estree@^1.0.5":
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
|
||||
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
|
||||
|
||||
"@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18":
|
||||
version "4.17.28"
|
||||
@@ -1871,16 +1887,16 @@
|
||||
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-3.12.1.tgz#5c6f4a1eabca84792fbd916f0cb40847f123c656"
|
||||
integrity sha512-SGGAhXLHDx+PK4YLNcNGa6goPf9XRWQNAUUbffkwVGGXIxmDKWyGGL4inzq2sPmExu431Ekb9aEMn9BkPqEYFA==
|
||||
|
||||
"@types/json-schema@*", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
||||
|
||||
"@types/json-schema@^7.0.5", "@types/json-schema@^7.0.7":
|
||||
version "7.0.8"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.8.tgz#edf1bf1dbf4e04413ca8e5b17b3b7d7d54b59818"
|
||||
integrity sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg==
|
||||
|
||||
"@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9":
|
||||
version "7.0.11"
|
||||
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3"
|
||||
integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==
|
||||
|
||||
"@types/lodash-es@^4.17.6":
|
||||
version "4.17.6"
|
||||
resolved "https://registry.yarnpkg.com/@types/lodash-es/-/lodash-es-4.17.6.tgz#c2ed4c8320ffa6f11b43eb89e9eaeec65966a0a0"
|
||||
@@ -2099,10 +2115,10 @@
|
||||
dependencies:
|
||||
"@types/yargs-parser" "*"
|
||||
|
||||
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
|
||||
integrity sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==
|
||||
"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb"
|
||||
integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==
|
||||
dependencies:
|
||||
"@webassemblyjs/helper-numbers" "1.11.6"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||
@@ -2117,10 +2133,10 @@
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768"
|
||||
integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==
|
||||
|
||||
"@webassemblyjs/helper-buffer@1.11.6":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz#b66d73c43e296fd5e88006f18524feb0f2c7c093"
|
||||
integrity sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==
|
||||
"@webassemblyjs/helper-buffer@1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6"
|
||||
integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==
|
||||
|
||||
"@webassemblyjs/helper-numbers@1.11.6":
|
||||
version "1.11.6"
|
||||
@@ -2136,15 +2152,15 @@
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9"
|
||||
integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==
|
||||
|
||||
"@webassemblyjs/helper-wasm-section@1.11.6":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz#ff97f3863c55ee7f580fd5c41a381e9def4aa577"
|
||||
integrity sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==
|
||||
"@webassemblyjs/helper-wasm-section@1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf"
|
||||
integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@webassemblyjs/helper-buffer" "1.12.1"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||
"@webassemblyjs/wasm-gen" "1.12.1"
|
||||
|
||||
"@webassemblyjs/ieee754@1.11.6":
|
||||
version "1.11.6"
|
||||
@@ -2165,59 +2181,59 @@
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a"
|
||||
integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==
|
||||
|
||||
"@webassemblyjs/wasm-edit@^1.11.5":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz#c72fa8220524c9b416249f3d94c2958dfe70ceab"
|
||||
integrity sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==
|
||||
"@webassemblyjs/wasm-edit@^1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b"
|
||||
integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@webassemblyjs/helper-buffer" "1.12.1"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||
"@webassemblyjs/helper-wasm-section" "1.11.6"
|
||||
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||
"@webassemblyjs/wasm-opt" "1.11.6"
|
||||
"@webassemblyjs/wasm-parser" "1.11.6"
|
||||
"@webassemblyjs/wast-printer" "1.11.6"
|
||||
"@webassemblyjs/helper-wasm-section" "1.12.1"
|
||||
"@webassemblyjs/wasm-gen" "1.12.1"
|
||||
"@webassemblyjs/wasm-opt" "1.12.1"
|
||||
"@webassemblyjs/wasm-parser" "1.12.1"
|
||||
"@webassemblyjs/wast-printer" "1.12.1"
|
||||
|
||||
"@webassemblyjs/wasm-gen@1.11.6":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz#fb5283e0e8b4551cc4e9c3c0d7184a65faf7c268"
|
||||
integrity sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==
|
||||
"@webassemblyjs/wasm-gen@1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547"
|
||||
integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||
"@webassemblyjs/ieee754" "1.11.6"
|
||||
"@webassemblyjs/leb128" "1.11.6"
|
||||
"@webassemblyjs/utf8" "1.11.6"
|
||||
|
||||
"@webassemblyjs/wasm-opt@1.11.6":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz#d9a22d651248422ca498b09aa3232a81041487c2"
|
||||
integrity sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==
|
||||
"@webassemblyjs/wasm-opt@1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5"
|
||||
integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/helper-buffer" "1.11.6"
|
||||
"@webassemblyjs/wasm-gen" "1.11.6"
|
||||
"@webassemblyjs/wasm-parser" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@webassemblyjs/helper-buffer" "1.12.1"
|
||||
"@webassemblyjs/wasm-gen" "1.12.1"
|
||||
"@webassemblyjs/wasm-parser" "1.12.1"
|
||||
|
||||
"@webassemblyjs/wasm-parser@1.11.6", "@webassemblyjs/wasm-parser@^1.11.5":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz#bb85378c527df824004812bbdb784eea539174a1"
|
||||
integrity sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==
|
||||
"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937"
|
||||
integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@webassemblyjs/helper-api-error" "1.11.6"
|
||||
"@webassemblyjs/helper-wasm-bytecode" "1.11.6"
|
||||
"@webassemblyjs/ieee754" "1.11.6"
|
||||
"@webassemblyjs/leb128" "1.11.6"
|
||||
"@webassemblyjs/utf8" "1.11.6"
|
||||
|
||||
"@webassemblyjs/wast-printer@1.11.6":
|
||||
version "1.11.6"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz#a7bf8dd7e362aeb1668ff43f35cb849f188eff20"
|
||||
integrity sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==
|
||||
"@webassemblyjs/wast-printer@1.12.1":
|
||||
version "1.12.1"
|
||||
resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac"
|
||||
integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==
|
||||
dependencies:
|
||||
"@webassemblyjs/ast" "1.11.6"
|
||||
"@webassemblyjs/ast" "1.12.1"
|
||||
"@xtuc/long" "4.2.2"
|
||||
|
||||
"@webpack-cli/configtest@^1.1.1":
|
||||
@@ -2268,10 +2284,10 @@ acorn-globals@^6.0.0:
|
||||
acorn "^7.1.1"
|
||||
acorn-walk "^7.1.1"
|
||||
|
||||
acorn-import-assertions@^1.9.0:
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac"
|
||||
integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==
|
||||
acorn-import-attributes@^1.9.5:
|
||||
version "1.9.5"
|
||||
resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef"
|
||||
integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==
|
||||
|
||||
acorn-walk@^7.1.1:
|
||||
version "7.2.0"
|
||||
@@ -2293,6 +2309,11 @@ acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.1:
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a"
|
||||
integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw==
|
||||
|
||||
acorn@^8.8.2:
|
||||
version "8.12.1"
|
||||
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248"
|
||||
integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==
|
||||
|
||||
add@^2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.yarnpkg.com/add/-/add-2.0.6.tgz#248f0a9f6e5a528ef2295dbeec30532130ae2235"
|
||||
@@ -2781,10 +2802,10 @@ binary-extensions@^2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d"
|
||||
integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==
|
||||
|
||||
body-parser@1.20.2:
|
||||
version "1.20.2"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd"
|
||||
integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==
|
||||
body-parser@1.20.3:
|
||||
version "1.20.3"
|
||||
resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6"
|
||||
integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==
|
||||
dependencies:
|
||||
bytes "3.1.2"
|
||||
content-type "~1.0.5"
|
||||
@@ -2794,7 +2815,7 @@ body-parser@1.20.2:
|
||||
http-errors "2.0.0"
|
||||
iconv-lite "0.4.24"
|
||||
on-finished "2.4.1"
|
||||
qs "6.11.0"
|
||||
qs "6.13.0"
|
||||
raw-body "2.5.2"
|
||||
type-is "~1.6.18"
|
||||
unpipe "1.0.0"
|
||||
@@ -2841,18 +2862,18 @@ braces@^2.3.1:
|
||||
to-regex "^3.0.1"
|
||||
|
||||
braces@^3.0.1, braces@^3.0.2, braces@~3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107"
|
||||
integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789"
|
||||
integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==
|
||||
dependencies:
|
||||
fill-range "^7.0.1"
|
||||
fill-range "^7.1.1"
|
||||
|
||||
browser-process-hrtime@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626"
|
||||
integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==
|
||||
|
||||
browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.6.0:
|
||||
browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^4.6.0:
|
||||
version "4.20.2"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.20.2.tgz#567b41508757ecd904dab4d1c646c612cd3d4f88"
|
||||
integrity sha512-CQOBCqp/9pDvDbx3xfMi+86pr4KXIf2FDkTTdeuYw8OxS9t898LA1Khq57gtufFILXpfgsSx5woNgsBgvGjpsA==
|
||||
@@ -2863,6 +2884,16 @@ browserslist@^4.14.5, browserslist@^4.16.6, browserslist@^4.17.5, browserslist@^
|
||||
node-releases "^2.0.2"
|
||||
picocolors "^1.0.0"
|
||||
|
||||
browserslist@^4.21.10:
|
||||
version "4.23.3"
|
||||
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800"
|
||||
integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==
|
||||
dependencies:
|
||||
caniuse-lite "^1.0.30001646"
|
||||
electron-to-chromium "^1.5.4"
|
||||
node-releases "^2.0.18"
|
||||
update-browserslist-db "^1.1.0"
|
||||
|
||||
bs-logger@0.x:
|
||||
version "0.2.6"
|
||||
resolved "https://registry.yarnpkg.com/bs-logger/-/bs-logger-0.2.6.tgz#eb7d365307a72cf974cc6cda76b68354ad336bd8"
|
||||
@@ -2956,6 +2987,17 @@ call-bind@^1.0.0, call-bind@^1.0.2:
|
||||
function-bind "^1.1.1"
|
||||
get-intrinsic "^1.0.2"
|
||||
|
||||
call-bind@^1.0.7:
|
||||
version "1.0.7"
|
||||
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
|
||||
integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
set-function-length "^1.2.1"
|
||||
|
||||
call-me-maybe@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b"
|
||||
@@ -2989,6 +3031,11 @@ caniuse-lite@^1.0.30001317:
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001319.tgz#eb4da4eb3ecdd409f7ba1907820061d56096e88f"
|
||||
integrity sha512-xjlIAFHucBRSMUo1kb5D4LYgcN1M45qdKP++lhqowDpwJwGkpIRTt5qQqnhxjj1vHcI7nrJxWhCC1ATrCEBTcw==
|
||||
|
||||
caniuse-lite@^1.0.30001646:
|
||||
version "1.0.30001662"
|
||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001662.tgz#3574b22dfec54a3f3b6787331da1040fe8e763ec"
|
||||
integrity sha512-sgMUVwLmGseH8ZIrm1d51UbrhqMCH3jvS7gF/M6byuHOnKyLOBL7W8yz5V02OHwgLGA36o/AFhWzzh4uc5aqTA==
|
||||
|
||||
capture-exit@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4"
|
||||
@@ -3592,6 +3639,15 @@ default-gateway@^6.0.3:
|
||||
dependencies:
|
||||
execa "^5.0.0"
|
||||
|
||||
define-data-property@^1.1.4:
|
||||
version "1.1.4"
|
||||
resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e"
|
||||
integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
es-errors "^1.3.0"
|
||||
gopd "^1.0.1"
|
||||
|
||||
define-lazy-prop@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f"
|
||||
@@ -3789,9 +3845,9 @@ domhandler@^4.0.0, domhandler@^4.2.0:
|
||||
domelementtype "^2.2.0"
|
||||
|
||||
dompurify@^2.2.8:
|
||||
version "2.3.6"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.3.6.tgz#2e019d7d7617aacac07cbbe3d88ae3ad354cf875"
|
||||
integrity sha512-OFP2u/3T1R5CEgWCEONuJ1a5+MFKnOYpkywpUSxv/dj1LeBT1erK+JwM7zK0ROy2BRhqVCf0LRw/kHqKuMkVGg==
|
||||
version "2.5.6"
|
||||
resolved "https://registry.yarnpkg.com/dompurify/-/dompurify-2.5.6.tgz#8402b501611eaa7fb3786072297fcbe2787f8592"
|
||||
integrity sha512-zUTaUBO8pY4+iJMPE1B9XlO2tXVYIcEA4SNGtvDELzTSCQO7RzH+j7S180BmhmJId78lqGU2z19vgVx2Sxs/PQ==
|
||||
|
||||
domutils@^2.5.2, domutils@^2.6.0:
|
||||
version "2.7.0"
|
||||
@@ -3820,6 +3876,11 @@ electron-to-chromium@^1.4.84:
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.89.tgz#33c06592812a17a7131873f4596579084ce33ff8"
|
||||
integrity sha512-z1Axg0Fu54fse8wN4fd+GAINdU5mJmLtcl6bqIcYyzNVGONcfHAeeJi88KYMQVKalhXlYuVPzKkFIU5VD0raUw==
|
||||
|
||||
electron-to-chromium@^1.5.4:
|
||||
version "1.5.27"
|
||||
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.27.tgz#5203ce5d6054857d84ba84d3681cbe59132ade78"
|
||||
integrity sha512-o37j1vZqCoEgBuWWXLHQgTN/KDKe7zwpiY5CPeq2RvUqOyJw9xnrULzZAEVQ5p4h+zjMk7hgtOoPdnLxr7m/jw==
|
||||
|
||||
emittery@^0.8.1:
|
||||
version "0.8.1"
|
||||
resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.8.1.tgz#bb23cc86d03b30aa75a7f734819dee2e1ba70860"
|
||||
@@ -3845,6 +3906,11 @@ encodeurl@~1.0.2:
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59"
|
||||
integrity sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==
|
||||
|
||||
encodeurl@~2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58"
|
||||
integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==
|
||||
|
||||
end-of-stream@^1.1.0:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43"
|
||||
@@ -3852,10 +3918,10 @@ end-of-stream@^1.1.0:
|
||||
dependencies:
|
||||
once "^1.4.0"
|
||||
|
||||
enhanced-resolve@^5.14.1:
|
||||
version "5.14.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3"
|
||||
integrity sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow==
|
||||
enhanced-resolve@^5.17.1:
|
||||
version "5.17.1"
|
||||
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15"
|
||||
integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.4"
|
||||
tapable "^2.2.0"
|
||||
@@ -3884,6 +3950,18 @@ error-stack-parser@^1.3.6:
|
||||
dependencies:
|
||||
stackframe "^0.3.1"
|
||||
|
||||
es-define-property@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845"
|
||||
integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==
|
||||
dependencies:
|
||||
get-intrinsic "^1.2.4"
|
||||
|
||||
es-errors@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f"
|
||||
integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==
|
||||
|
||||
es-module-lexer@^0.10.5:
|
||||
version "0.10.5"
|
||||
resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.10.5.tgz#06f76d51fa53b1f78e3bd8bb36dd275eda2fdd53"
|
||||
@@ -4168,6 +4246,11 @@ escalade@^3.1.1:
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40"
|
||||
integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==
|
||||
|
||||
escalade@^3.1.2:
|
||||
version "3.2.0"
|
||||
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
|
||||
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
|
||||
|
||||
escape-carriage@^1.3.0:
|
||||
version "1.3.0"
|
||||
resolved "https://registry.yarnpkg.com/escape-carriage/-/escape-carriage-1.3.0.tgz#71006b2d4da8cb6828686addafcb094239c742f3"
|
||||
@@ -4320,36 +4403,36 @@ expect@^27.5.1:
|
||||
jest-message-util "^27.5.1"
|
||||
|
||||
express@^4.17.1:
|
||||
version "4.19.2"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465"
|
||||
integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==
|
||||
version "4.20.0"
|
||||
resolved "https://registry.yarnpkg.com/express/-/express-4.20.0.tgz#f1d08e591fcec770c07be4767af8eb9bcfd67c48"
|
||||
integrity sha512-pLdae7I6QqShF5PnNTCVn4hI91Dx0Grkn2+IAsMTgMIKuQVte2dN9PeGSSAME2FR8anOhVA62QDIUaWVfEXVLw==
|
||||
dependencies:
|
||||
accepts "~1.3.8"
|
||||
array-flatten "1.1.1"
|
||||
body-parser "1.20.2"
|
||||
body-parser "1.20.3"
|
||||
content-disposition "0.5.4"
|
||||
content-type "~1.0.4"
|
||||
cookie "0.6.0"
|
||||
cookie-signature "1.0.6"
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
encodeurl "~1.0.2"
|
||||
encodeurl "~2.0.0"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
finalhandler "1.2.0"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
merge-descriptors "1.0.1"
|
||||
merge-descriptors "1.0.3"
|
||||
methods "~1.1.2"
|
||||
on-finished "2.4.1"
|
||||
parseurl "~1.3.3"
|
||||
path-to-regexp "0.1.7"
|
||||
path-to-regexp "0.1.10"
|
||||
proxy-addr "~2.0.7"
|
||||
qs "6.11.0"
|
||||
range-parser "~1.2.1"
|
||||
safe-buffer "5.2.1"
|
||||
send "0.18.0"
|
||||
serve-static "1.15.0"
|
||||
send "0.19.0"
|
||||
serve-static "1.16.0"
|
||||
setprototypeof "1.2.0"
|
||||
statuses "2.0.1"
|
||||
type-is "~1.6.18"
|
||||
@@ -4474,10 +4557,10 @@ fill-range@^4.0.0:
|
||||
repeat-string "^1.6.1"
|
||||
to-regex-range "^2.1.0"
|
||||
|
||||
fill-range@^7.0.1:
|
||||
version "7.0.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40"
|
||||
integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==
|
||||
fill-range@^7.1.1:
|
||||
version "7.1.1"
|
||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292"
|
||||
integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==
|
||||
dependencies:
|
||||
to-regex-range "^5.0.1"
|
||||
|
||||
@@ -4619,6 +4702,11 @@ function-bind@^1.1.1:
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
|
||||
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
|
||||
|
||||
function-bind@^1.1.2:
|
||||
version "1.1.2"
|
||||
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
|
||||
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
|
||||
|
||||
generic-names@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/generic-names/-/generic-names-1.0.3.tgz#2d786a121aee508876796939e8e3bff836c20917"
|
||||
@@ -4645,6 +4733,17 @@ get-intrinsic@^1.0.2:
|
||||
has "^1.0.3"
|
||||
has-symbols "^1.0.3"
|
||||
|
||||
get-intrinsic@^1.1.3, get-intrinsic@^1.2.4:
|
||||
version "1.2.4"
|
||||
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
|
||||
integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==
|
||||
dependencies:
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
has-proto "^1.0.1"
|
||||
has-symbols "^1.0.3"
|
||||
hasown "^2.0.0"
|
||||
|
||||
get-package-type@^0.1.0:
|
||||
version "0.1.0"
|
||||
resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a"
|
||||
@@ -4736,11 +4835,23 @@ globby@^11.0.1:
|
||||
merge2 "^1.3.0"
|
||||
slash "^3.0.0"
|
||||
|
||||
gopd@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
|
||||
integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==
|
||||
dependencies:
|
||||
get-intrinsic "^1.1.3"
|
||||
|
||||
graceful-fs@^4.1.2, graceful-fs@^4.2.4, graceful-fs@^4.2.6, graceful-fs@^4.2.9:
|
||||
version "4.2.9"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.9.tgz#041b05df45755e587a24942279b9d113146e1c96"
|
||||
integrity sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==
|
||||
|
||||
graceful-fs@^4.2.11:
|
||||
version "4.2.11"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3"
|
||||
integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==
|
||||
|
||||
graphlib@^2.1.8:
|
||||
version "2.1.8"
|
||||
resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.8.tgz#5761d414737870084c92ec7b5dbcb0592c9d35da"
|
||||
@@ -4780,6 +4891,18 @@ has-flag@^4.0.0:
|
||||
resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b"
|
||||
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
|
||||
|
||||
has-property-descriptors@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854"
|
||||
integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==
|
||||
dependencies:
|
||||
es-define-property "^1.0.0"
|
||||
|
||||
has-proto@^1.0.1:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd"
|
||||
integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==
|
||||
|
||||
has-symbols@^1.0.1, has-symbols@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423"
|
||||
@@ -4828,6 +4951,13 @@ has@^1.0.3:
|
||||
dependencies:
|
||||
function-bind "^1.1.1"
|
||||
|
||||
hasown@^2.0.0:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
|
||||
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
|
||||
dependencies:
|
||||
function-bind "^1.1.2"
|
||||
|
||||
he@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
|
||||
@@ -5346,7 +5476,7 @@ is-wsl@^2.2.0:
|
||||
isarray@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf"
|
||||
integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=
|
||||
integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==
|
||||
|
||||
isarray@1.0.0, isarray@~1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -6274,10 +6404,10 @@ memfs@^3.4.3:
|
||||
dependencies:
|
||||
fs-monkey "^1.0.4"
|
||||
|
||||
merge-descriptors@1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
|
||||
integrity sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==
|
||||
merge-descriptors@1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5"
|
||||
integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==
|
||||
|
||||
merge-stream@^2.0.0:
|
||||
version "2.0.0"
|
||||
@@ -6591,6 +6721,11 @@ node-readfiles@^0.2.0:
|
||||
dependencies:
|
||||
es6-promise "^3.2.1"
|
||||
|
||||
node-releases@^2.0.18:
|
||||
version "2.0.18"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
|
||||
integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
|
||||
|
||||
node-releases@^2.0.2:
|
||||
version "2.0.2"
|
||||
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.2.tgz#7139fe71e2f4f11b47d4d2986aaf8c48699e0c01"
|
||||
@@ -6704,6 +6839,11 @@ object-copy@^0.1.0:
|
||||
define-property "^0.2.5"
|
||||
kind-of "^3.0.3"
|
||||
|
||||
object-inspect@^1.13.1:
|
||||
version "1.13.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff"
|
||||
integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==
|
||||
|
||||
object-inspect@^1.9.0:
|
||||
version "1.12.2"
|
||||
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
|
||||
@@ -6957,15 +7097,15 @@ path-parse@^1.0.6, path-parse@^1.0.7:
|
||||
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
|
||||
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
|
||||
|
||||
path-to-regexp@0.1.7:
|
||||
version "0.1.7"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c"
|
||||
integrity sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==
|
||||
path-to-regexp@0.1.10:
|
||||
version "0.1.10"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b"
|
||||
integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==
|
||||
|
||||
path-to-regexp@^1.7.0:
|
||||
version "1.8.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a"
|
||||
integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==
|
||||
version "1.9.0"
|
||||
resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24"
|
||||
integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g==
|
||||
dependencies:
|
||||
isarray "0.0.1"
|
||||
|
||||
@@ -6992,6 +7132,11 @@ picocolors@^1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c"
|
||||
integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==
|
||||
|
||||
picocolors@^1.0.1:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59"
|
||||
integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==
|
||||
|
||||
picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972"
|
||||
@@ -7287,6 +7432,13 @@ qs@6.11.0, qs@^6.11.0:
|
||||
dependencies:
|
||||
side-channel "^1.0.4"
|
||||
|
||||
qs@6.13.0:
|
||||
version "6.13.0"
|
||||
resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906"
|
||||
integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==
|
||||
dependencies:
|
||||
side-channel "^1.0.6"
|
||||
|
||||
querystring@0.2.0:
|
||||
version "0.2.0"
|
||||
resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620"
|
||||
@@ -8384,7 +8536,7 @@ schema-utils@^2.7.1:
|
||||
ajv "^6.12.4"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
schema-utils@^3.1.1, schema-utils@^3.1.2:
|
||||
schema-utils@^3.1.1:
|
||||
version "3.1.2"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.2.tgz#36c10abca6f7577aeae136c804b0c741edeadc99"
|
||||
integrity sha512-pvjEHOgWc9OWA/f/DE3ohBWTD6EleVLf7iFUkoSwAxttdBhB9QUebQgxER2kWueOvRJXPHNnyrvvh9eZINB8Eg==
|
||||
@@ -8393,6 +8545,15 @@ schema-utils@^3.1.1, schema-utils@^3.1.2:
|
||||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
schema-utils@^3.2.0:
|
||||
version "3.3.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe"
|
||||
integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==
|
||||
dependencies:
|
||||
"@types/json-schema" "^7.0.8"
|
||||
ajv "^6.12.5"
|
||||
ajv-keywords "^3.5.2"
|
||||
|
||||
schema-utils@^4.0.0:
|
||||
version "4.0.0"
|
||||
resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7"
|
||||
@@ -8463,6 +8624,25 @@ send@0.18.0:
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
send@0.19.0:
|
||||
version "0.19.0"
|
||||
resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8"
|
||||
integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==
|
||||
dependencies:
|
||||
debug "2.6.9"
|
||||
depd "2.0.0"
|
||||
destroy "1.2.0"
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
etag "~1.8.1"
|
||||
fresh "0.5.2"
|
||||
http-errors "2.0.0"
|
||||
mime "1.6.0"
|
||||
ms "2.1.3"
|
||||
on-finished "2.4.1"
|
||||
range-parser "~1.2.1"
|
||||
statuses "2.0.1"
|
||||
|
||||
serialize-javascript@^5.0.1:
|
||||
version "5.0.1"
|
||||
resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4"
|
||||
@@ -8490,16 +8670,28 @@ serve-index@^1.9.1:
|
||||
mime-types "~2.1.17"
|
||||
parseurl "~1.3.2"
|
||||
|
||||
serve-static@1.15.0:
|
||||
version "1.15.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540"
|
||||
integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==
|
||||
serve-static@1.16.0:
|
||||
version "1.16.0"
|
||||
resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.0.tgz#2bf4ed49f8af311b519c46f272bf6ac3baf38a92"
|
||||
integrity sha512-pDLK8zwl2eKaYrs8mrPZBJua4hMplRWJ1tIFksVC3FtBEBnl8dxgeHtsaMS8DhS9i4fLObaon6ABoc4/hQGdPA==
|
||||
dependencies:
|
||||
encodeurl "~1.0.2"
|
||||
escape-html "~1.0.3"
|
||||
parseurl "~1.3.3"
|
||||
send "0.18.0"
|
||||
|
||||
set-function-length@^1.2.1:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449"
|
||||
integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==
|
||||
dependencies:
|
||||
define-data-property "^1.1.4"
|
||||
es-errors "^1.3.0"
|
||||
function-bind "^1.1.2"
|
||||
get-intrinsic "^1.2.4"
|
||||
gopd "^1.0.1"
|
||||
has-property-descriptors "^1.0.2"
|
||||
|
||||
set-value@^2.0.0, set-value@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
|
||||
@@ -8614,6 +8806,16 @@ side-channel@^1.0.4:
|
||||
get-intrinsic "^1.0.2"
|
||||
object-inspect "^1.9.0"
|
||||
|
||||
side-channel@^1.0.6:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
|
||||
integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==
|
||||
dependencies:
|
||||
call-bind "^1.0.7"
|
||||
es-errors "^1.3.0"
|
||||
get-intrinsic "^1.2.4"
|
||||
object-inspect "^1.13.1"
|
||||
|
||||
signal-exit@^3.0.0, signal-exit@^3.0.2:
|
||||
version "3.0.2"
|
||||
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
|
||||
@@ -9087,16 +9289,16 @@ terminal-link@^2.0.0:
|
||||
ansi-escapes "^4.2.1"
|
||||
supports-hyperlinks "^2.0.0"
|
||||
|
||||
terser-webpack-plugin@^5.3.7:
|
||||
version "5.3.9"
|
||||
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.9.tgz#832536999c51b46d468067f9e37662a3b96adfe1"
|
||||
integrity sha512-ZuXsqE07EcggTWQjXUj+Aot/OMcD0bMKGgF63f7UxYcu5/AJF53aIpK1YoP5xR9l6s/Hy2b+t1AM0bLNPRuhwA==
|
||||
terser-webpack-plugin@^5.3.10:
|
||||
version "5.3.10"
|
||||
resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199"
|
||||
integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "^0.3.17"
|
||||
"@jridgewell/trace-mapping" "^0.3.20"
|
||||
jest-worker "^27.4.5"
|
||||
schema-utils "^3.1.1"
|
||||
serialize-javascript "^6.0.1"
|
||||
terser "^5.16.8"
|
||||
terser "^5.26.0"
|
||||
|
||||
terser@^5.10.0:
|
||||
version "5.14.2"
|
||||
@@ -9108,13 +9310,13 @@ terser@^5.10.0:
|
||||
commander "^2.20.0"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
terser@^5.16.8:
|
||||
version "5.17.6"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.17.6.tgz#d810e75e1bb3350c799cd90ebefe19c9412c12de"
|
||||
integrity sha512-V8QHcs8YuyLkLHsJO5ucyff1ykrLVsR4dNnS//L5Y3NiSXpbK1J+WMVUs67eI0KTxs9JtHhgEQpXQVHlHI92DQ==
|
||||
terser@^5.26.0:
|
||||
version "5.33.0"
|
||||
resolved "https://registry.yarnpkg.com/terser/-/terser-5.33.0.tgz#8f9149538c7468ffcb1246cfec603c16720d2db1"
|
||||
integrity sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==
|
||||
dependencies:
|
||||
"@jridgewell/source-map" "^0.3.2"
|
||||
acorn "^8.5.0"
|
||||
"@jridgewell/source-map" "^0.3.3"
|
||||
acorn "^8.8.2"
|
||||
commander "^2.20.0"
|
||||
source-map-support "~0.5.20"
|
||||
|
||||
@@ -9460,6 +9662,14 @@ unset-value@^1.0.0:
|
||||
has-value "^0.3.1"
|
||||
isobject "^3.0.0"
|
||||
|
||||
update-browserslist-db@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e"
|
||||
integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==
|
||||
dependencies:
|
||||
escalade "^3.1.2"
|
||||
picocolors "^1.0.1"
|
||||
|
||||
uri-js@^4.2.2:
|
||||
version "4.2.2"
|
||||
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
|
||||
@@ -9589,10 +9799,10 @@ warning@^4.0.1, warning@^4.0.2:
|
||||
dependencies:
|
||||
loose-envify "^1.0.0"
|
||||
|
||||
watchpack@^2.4.0:
|
||||
version "2.4.0"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
|
||||
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
|
||||
watchpack@^2.4.1:
|
||||
version "2.4.2"
|
||||
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da"
|
||||
integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==
|
||||
dependencies:
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.1.2"
|
||||
@@ -9713,34 +9923,33 @@ webpack-sources@^3.2.3:
|
||||
resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde"
|
||||
integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==
|
||||
|
||||
webpack@^5.84.1:
|
||||
version "5.84.1"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.84.1.tgz#d4493acdeca46b26ffc99d86d784cabfeb925a15"
|
||||
integrity sha512-ZP4qaZ7vVn/K8WN/p990SGATmrL1qg4heP/MrVneczYtpDGJWlrgZv55vxaV2ul885Kz+25MP2kSXkPe3LZfmg==
|
||||
webpack@^5.94.0:
|
||||
version "5.94.0"
|
||||
resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f"
|
||||
integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==
|
||||
dependencies:
|
||||
"@types/eslint-scope" "^3.7.3"
|
||||
"@types/estree" "^1.0.0"
|
||||
"@webassemblyjs/ast" "^1.11.5"
|
||||
"@webassemblyjs/wasm-edit" "^1.11.5"
|
||||
"@webassemblyjs/wasm-parser" "^1.11.5"
|
||||
"@types/estree" "^1.0.5"
|
||||
"@webassemblyjs/ast" "^1.12.1"
|
||||
"@webassemblyjs/wasm-edit" "^1.12.1"
|
||||
"@webassemblyjs/wasm-parser" "^1.12.1"
|
||||
acorn "^8.7.1"
|
||||
acorn-import-assertions "^1.9.0"
|
||||
browserslist "^4.14.5"
|
||||
acorn-import-attributes "^1.9.5"
|
||||
browserslist "^4.21.10"
|
||||
chrome-trace-event "^1.0.2"
|
||||
enhanced-resolve "^5.14.1"
|
||||
enhanced-resolve "^5.17.1"
|
||||
es-module-lexer "^1.2.1"
|
||||
eslint-scope "5.1.1"
|
||||
events "^3.2.0"
|
||||
glob-to-regexp "^0.4.1"
|
||||
graceful-fs "^4.2.9"
|
||||
graceful-fs "^4.2.11"
|
||||
json-parse-even-better-errors "^2.3.1"
|
||||
loader-runner "^4.2.0"
|
||||
mime-types "^2.1.27"
|
||||
neo-async "^2.6.2"
|
||||
schema-utils "^3.1.2"
|
||||
schema-utils "^3.2.0"
|
||||
tapable "^2.1.1"
|
||||
terser-webpack-plugin "^5.3.7"
|
||||
watchpack "^2.4.0"
|
||||
terser-webpack-plugin "^5.3.10"
|
||||
watchpack "^2.4.1"
|
||||
webpack-sources "^3.2.3"
|
||||
|
||||
websocket-driver@>=0.5.1:
|
||||
|
||||
@@ -112,12 +112,12 @@ func GetAppRefreshPaths(app *v1alpha1.Application) []string {
|
||||
}
|
||||
|
||||
// AppFilesHaveChanged returns true if any of the changed files are under the given refresh paths
|
||||
// If refreshPaths is empty, it will always return true
|
||||
// If refreshPaths or changedFiles are empty, it will always return true
|
||||
func AppFilesHaveChanged(refreshPaths []string, changedFiles []string) bool {
|
||||
// empty slice means there was no changes to any files
|
||||
// so we should not refresh
|
||||
// an empty slice of changed files means that the payload didn't include a list
|
||||
// of changed files and we have to assume that a refresh is required
|
||||
if len(changedFiles) == 0 {
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
if len(refreshPaths) == 0 {
|
||||
|
||||
@@ -133,7 +133,7 @@ func Test_AppFilesHaveChanged(t *testing.T) {
|
||||
changeExpected bool
|
||||
}{
|
||||
{"default no path", &v1alpha1.Application{}, []string{"README.md"}, true},
|
||||
{"no files changed", getApp(".", "source/path"), []string{}, false},
|
||||
{"no files changed", getApp(".", "source/path"), []string{}, true},
|
||||
{"relative path - matching", getApp(".", "source/path"), []string{"source/path/my-deployment.yaml"}, true},
|
||||
{"relative path, multi source - matching #1", getMultiSourceApp(".", "source/path", "other/path"), []string{"source/path/my-deployment.yaml"}, true},
|
||||
{"relative path, multi source - matching #2", getMultiSourceApp(".", "other/path", "source/path"), []string{"source/path/my-deployment.yaml"}, true},
|
||||
|
||||
@@ -2,7 +2,6 @@ package argo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
@@ -46,7 +45,7 @@ const (
|
||||
EventReasonOperationCompleted = "OperationCompleted"
|
||||
)
|
||||
|
||||
func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, info EventInfo, message string, logFields map[string]interface{}) {
|
||||
func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, info EventInfo, message string, logFields map[string]string) {
|
||||
logCtx := log.WithFields(log.Fields{
|
||||
"type": info.Type,
|
||||
"reason": info.Reason,
|
||||
@@ -54,19 +53,6 @@ func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, i
|
||||
for field, val := range logFields {
|
||||
logCtx = logCtx.WithField(field, val)
|
||||
}
|
||||
logFieldStrings := make(map[string]string)
|
||||
for field, val := range logFields {
|
||||
if valStr, ok := val.(string); ok {
|
||||
logFieldStrings[field] = valStr
|
||||
continue
|
||||
}
|
||||
vJsonStr, err := json.Marshal(val)
|
||||
if err != nil {
|
||||
logCtx.Errorf("Unable to marshal audit event field %v: %v", field, err)
|
||||
continue
|
||||
}
|
||||
logFieldStrings[field] = string(vJsonStr)
|
||||
}
|
||||
|
||||
switch gvk.Kind {
|
||||
case application.ApplicationKind:
|
||||
@@ -80,7 +66,7 @@ func (l *AuditLogger) logEvent(objMeta ObjectRef, gvk schema.GroupVersionKind, i
|
||||
event := v1.Event{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: fmt.Sprintf("%v.%x", objMeta.Name, t.UnixNano()),
|
||||
Annotations: logFieldStrings,
|
||||
Annotations: logFields,
|
||||
},
|
||||
Source: v1.EventSource{
|
||||
Component: l.component,
|
||||
@@ -115,14 +101,13 @@ func (l *AuditLogger) LogAppEvent(app *v1alpha1.Application, info EventInfo, mes
|
||||
ResourceVersion: app.ObjectMeta.ResourceVersion,
|
||||
UID: app.ObjectMeta.UID,
|
||||
}
|
||||
fields := map[string]interface{}{
|
||||
fields := map[string]string{
|
||||
"dest-server": app.Spec.Destination.Server,
|
||||
"dest-namespace": app.Spec.Destination.Namespace,
|
||||
}
|
||||
if user != "" {
|
||||
fields["user"] = user
|
||||
}
|
||||
fields["spec"] = app.Spec
|
||||
l.logEvent(objectMeta, v1alpha1.ApplicationSchemaGroupVersionKind, info, message, fields)
|
||||
}
|
||||
|
||||
@@ -133,7 +118,7 @@ func (l *AuditLogger) LogAppSetEvent(app *v1alpha1.ApplicationSet, info EventInf
|
||||
ResourceVersion: app.ObjectMeta.ResourceVersion,
|
||||
UID: app.ObjectMeta.UID,
|
||||
}
|
||||
fields := make(map[string]interface{})
|
||||
fields := map[string]string{}
|
||||
if user != "" {
|
||||
fields["user"] = user
|
||||
}
|
||||
@@ -147,7 +132,7 @@ func (l *AuditLogger) LogResourceEvent(res *v1alpha1.ResourceNode, info EventInf
|
||||
ResourceVersion: res.ResourceRef.Version,
|
||||
UID: types.UID(res.ResourceRef.UID),
|
||||
}
|
||||
fields := make(map[string]interface{})
|
||||
fields := map[string]string{}
|
||||
if user != "" {
|
||||
fields["user"] = user
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"sigs.k8s.io/structured-merge-diff/v4/fieldpath"
|
||||
@@ -28,12 +29,15 @@ func Normalize(live, config *unstructured.Unstructured, trustedManagers []string
|
||||
|
||||
liveCopy := live.DeepCopy()
|
||||
configCopy := config.DeepCopy()
|
||||
normalized := false
|
||||
|
||||
results, err := newTypedResults(liveCopy, configCopy, pt)
|
||||
// error might happen if the resources are not parsable and so cannot be normalized
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error building typed results: %s", err)
|
||||
log.Debugf("error building typed results: %v", err)
|
||||
return liveCopy, configCopy, nil
|
||||
}
|
||||
|
||||
normalized := false
|
||||
for _, mf := range live.GetManagedFields() {
|
||||
if trustedManager(mf.Manager, trustedManagers) {
|
||||
err := normalize(mf, results)
|
||||
|
||||
@@ -143,6 +143,16 @@ func TestNormalize(t *testing.T) {
|
||||
assert.Equal(t, 1, len(vwcConfig.Webhooks))
|
||||
assert.Equal(t, "", string(vwcConfig.Webhooks[0].ClientConfig.CABundle))
|
||||
})
|
||||
t.Run("does not fail if object fails validation schema", func(t *testing.T) {
|
||||
desiredState := StrToUnstructured(testdata.DesiredDeploymentYaml)
|
||||
require.NoError(t, unstructured.SetNestedField(desiredState.Object, "spec", "hello", "world"))
|
||||
liveState := StrToUnstructured(testdata.LiveDeploymentWithManagedReplicaYaml)
|
||||
|
||||
pt := parser.Type("io.k8s.api.apps.v1.Deployment")
|
||||
|
||||
_, _, err := managedfields.Normalize(liveState, desiredState, []string{}, &pt)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
||||
func validateNestedFloat64(t *testing.T, expected float64, obj *unstructured.Unstructured, fields ...string) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package argo
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
@@ -21,6 +23,7 @@ const (
|
||||
|
||||
var WrongResourceTrackingFormat = fmt.Errorf("wrong resource tracking format, should be <application-name>:<group>/<kind>:<namespace>/<name>")
|
||||
var LabelMaxLength = 63
|
||||
var OkEndPattern = regexp.MustCompile("[a-zA-Z0-9]$")
|
||||
|
||||
// ResourceTracking defines methods which allow setup and retrieve tracking information to resource
|
||||
type ResourceTracking interface {
|
||||
@@ -155,6 +158,14 @@ func (rt *resourceTracking) SetAppInstance(un *unstructured.Unstructured, key, v
|
||||
}
|
||||
if len(val) > LabelMaxLength {
|
||||
val = val[:LabelMaxLength]
|
||||
// Prevent errors if the truncated name ends in a special character.
|
||||
// See https://github.com/argoproj/argo-cd/issues/18237.
|
||||
for !OkEndPattern.MatchString(val) {
|
||||
if len(val) <= 1 {
|
||||
return errors.New("failed to set app instance label: unable to truncate label to not end with a special character")
|
||||
}
|
||||
val = val[:len(val)-1]
|
||||
}
|
||||
}
|
||||
err = argokube.SetAppInstanceLabel(un, key, val)
|
||||
if err != nil {
|
||||
|
||||
@@ -62,6 +62,60 @@ func TestSetAppInstanceAnnotationAndLabel(t *testing.T) {
|
||||
assert.Equal(t, "my-app", app)
|
||||
}
|
||||
|
||||
func TestSetAppInstanceAnnotationAndLabelLongName(t *testing.T) {
|
||||
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
|
||||
assert.Nil(t, err)
|
||||
var obj unstructured.Unstructured
|
||||
err = yaml.Unmarshal(yamlBytes, &obj)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resourceTracking := NewResourceTracking()
|
||||
|
||||
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", "", TrackingMethodAnnotationAndLabel)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// the annotation should still work, so the name from GetAppName should not be truncated
|
||||
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel)
|
||||
assert.Equal(t, "my-app-with-an-extremely-long-name-that-is-over-sixty-three-characters", app)
|
||||
|
||||
// the label should be truncated to 63 characters
|
||||
assert.Equal(t, obj.GetLabels()[common.LabelKeyAppInstance], "my-app-with-an-extremely-long-name-that-is-over-sixty-three-cha")
|
||||
}
|
||||
|
||||
func TestSetAppInstanceAnnotationAndLabelLongNameBadEnding(t *testing.T) {
|
||||
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
|
||||
assert.Nil(t, err)
|
||||
var obj unstructured.Unstructured
|
||||
err = yaml.Unmarshal(yamlBytes, &obj)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resourceTracking := NewResourceTracking()
|
||||
|
||||
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", "", TrackingMethodAnnotationAndLabel)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// the annotation should still work, so the name from GetAppName should not be truncated
|
||||
app := resourceTracking.GetAppName(&obj, common.LabelKeyAppInstance, TrackingMethodAnnotationAndLabel)
|
||||
assert.Equal(t, "the-very-suspicious-name-with-precisely-sixty-three-characters-with-hyphen", app)
|
||||
|
||||
// the label should be truncated to 63 characters, AND the hyphen should be removed
|
||||
assert.Equal(t, obj.GetLabels()[common.LabelKeyAppInstance], "the-very-suspicious-name-with-precisely-sixty-three-characters")
|
||||
}
|
||||
|
||||
func TestSetAppInstanceAnnotationAndLabelOutOfBounds(t *testing.T) {
|
||||
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
|
||||
assert.Nil(t, err)
|
||||
var obj unstructured.Unstructured
|
||||
err = yaml.Unmarshal(yamlBytes, &obj)
|
||||
assert.Nil(t, err)
|
||||
|
||||
resourceTracking := NewResourceTracking()
|
||||
|
||||
err = resourceTracking.SetAppInstance(&obj, common.LabelKeyAppInstance, "----------------------------------------------------------------", "", TrackingMethodAnnotationAndLabel)
|
||||
// this should error because it can't truncate to a valid value
|
||||
assert.EqualError(t, err, "failed to set app instance label: unable to truncate label to not end with a special character")
|
||||
}
|
||||
|
||||
func TestSetAppInstanceAnnotationNotFound(t *testing.T) {
|
||||
yamlBytes, err := os.ReadFile("testdata/svc.yaml")
|
||||
assert.Nil(t, err)
|
||||
|
||||
@@ -431,6 +431,8 @@ const (
|
||||
settingsWebhookAzureDevOpsUsernameKey = "webhook.azuredevops.username"
|
||||
// settingsWebhookAzureDevOpsPasswordKey is the key for Azure DevOps webhook password
|
||||
settingsWebhookAzureDevOpsPasswordKey = "webhook.azuredevops.password"
|
||||
// settingsWebhookMaxPayloadSize is the key for the maximum payload size for webhooks in MB
|
||||
settingsWebhookMaxPayloadSizeMB = "webhook.maxPayloadSizeMB"
|
||||
// settingsApplicationInstanceLabelKey is the key to configure injected app instance label key
|
||||
settingsApplicationInstanceLabelKey = "application.instanceLabelKey"
|
||||
// settingsResourceTrackingMethodKey is the key to configure tracking method for application resources
|
||||
@@ -518,6 +520,11 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
// default max webhook payload size is 1GB
|
||||
defaultMaxWebhookPayloadSize = int64(1) * 1024 * 1024 * 1024
|
||||
)
|
||||
|
||||
// SettingsManager holds config info for a new manager with which to access Kubernetes ConfigMaps.
|
||||
type SettingsManager struct {
|
||||
ctx context.Context
|
||||
@@ -2221,3 +2228,22 @@ func (mgr *SettingsManager) GetResourceCustomLabels() ([]string, error) {
|
||||
}
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func (mgr *SettingsManager) GetMaxWebhookPayloadSize() int64 {
|
||||
argoCDCM, err := mgr.getConfigMap()
|
||||
if err != nil {
|
||||
return defaultMaxWebhookPayloadSize
|
||||
}
|
||||
|
||||
if argoCDCM.Data[settingsWebhookMaxPayloadSizeMB] == "" {
|
||||
return defaultMaxWebhookPayloadSize
|
||||
}
|
||||
|
||||
maxPayloadSizeMB, err := strconv.ParseInt(argoCDCM.Data[settingsWebhookMaxPayloadSizeMB], 10, 64)
|
||||
if err != nil {
|
||||
log.Warnf("Failed to parse '%s' key: %v", settingsWebhookMaxPayloadSizeMB, err)
|
||||
return defaultMaxWebhookPayloadSize
|
||||
}
|
||||
|
||||
return maxPayloadSizeMB * 1024 * 1024
|
||||
}
|
||||
|
||||
@@ -41,6 +41,8 @@ type settingsSource interface {
|
||||
// https://github.com/shadow-maint/shadow/blob/master/libmisc/chkname.c#L36
|
||||
const usernameRegex = `[a-zA-Z0-9_\.][a-zA-Z0-9_\.-]{0,30}[a-zA-Z0-9_\.\$-]?`
|
||||
|
||||
const payloadQueueSize = 50000
|
||||
|
||||
var (
|
||||
_ settingsSource = &settings.SettingsManager{}
|
||||
errBasicAuthVerificationFailed = errors.New("basic auth verification failed")
|
||||
@@ -61,9 +63,11 @@ type ArgoCDWebhookHandler struct {
|
||||
azuredevopsAuthHandler func(r *http.Request) error
|
||||
gogs *gogs.Webhook
|
||||
settingsSrc settingsSource
|
||||
queue chan interface{}
|
||||
maxWebhookPayloadSizeB int64
|
||||
}
|
||||
|
||||
func NewHandler(namespace string, applicationNamespaces []string, appClientset appclientset.Interface, set *settings.ArgoCDSettings, settingsSrc settingsSource, repoCache *cache.Cache, serverCache *servercache.Cache, argoDB db.ArgoDB) *ArgoCDWebhookHandler {
|
||||
func NewHandler(namespace string, applicationNamespaces []string, appClientset appclientset.Interface, set *settings.ArgoCDSettings, settingsSrc settingsSource, repoCache *cache.Cache, serverCache *servercache.Cache, argoDB db.ArgoDB, maxWebhookPayloadSizeB int64) *ArgoCDWebhookHandler {
|
||||
githubWebhook, err := github.New(github.Options.Secret(set.WebhookGitHubSecret))
|
||||
if err != nil {
|
||||
log.Warnf("Unable to init the GitHub webhook")
|
||||
@@ -113,6 +117,8 @@ func NewHandler(namespace string, applicationNamespaces []string, appClientset a
|
||||
repoCache: repoCache,
|
||||
serverCache: serverCache,
|
||||
db: argoDB,
|
||||
queue: make(chan interface{}, payloadQueueSize),
|
||||
maxWebhookPayloadSizeB: maxWebhookPayloadSizeB,
|
||||
}
|
||||
|
||||
return &acdWebhook
|
||||
@@ -388,6 +394,8 @@ func (a *ArgoCDWebhookHandler) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
var payload interface{}
|
||||
var err error
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, a.maxWebhookPayloadSizeB)
|
||||
|
||||
switch {
|
||||
case r.Header.Get("X-Vss-Activityid") != "":
|
||||
if err = a.azuredevopsAuthHandler(r); err != nil {
|
||||
@@ -430,6 +438,14 @@ func (a *ArgoCDWebhookHandler) Handler(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// If the error is due to a large payload, return a more user-friendly error message
|
||||
if err.Error() == "error parsing payload" {
|
||||
msg := fmt.Sprintf("Webhook processing failed: The payload is either too large or corrupted. Please check the payload size (must be under %v MB) and ensure it is valid JSON", a.maxWebhookPayloadSizeB/1024/1024)
|
||||
log.WithField(common.SecurityField, common.SecurityHigh).Warn(msg)
|
||||
http.Error(w, msg, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
log.Infof("Webhook processing failed: %s", err)
|
||||
status := http.StatusBadRequest
|
||||
if r.Method != http.MethodPost {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/require"
|
||||
"io"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
@@ -56,6 +57,11 @@ type reactorDef struct {
|
||||
}
|
||||
|
||||
func NewMockHandler(reactor *reactorDef, applicationNamespaces []string, objects ...runtime.Object) *ArgoCDWebhookHandler {
|
||||
defaultMaxPayloadSize := int64(1) * 1024 * 1024 * 1024
|
||||
return NewMockHandlerWithPayloadLimit(reactor, applicationNamespaces, defaultMaxPayloadSize, objects...)
|
||||
}
|
||||
|
||||
func NewMockHandlerWithPayloadLimit(reactor *reactorDef, applicationNamespaces []string, maxPayloadSize int64, objects ...runtime.Object) *ArgoCDWebhookHandler {
|
||||
appClientset := appclientset.NewSimpleClientset(objects...)
|
||||
if reactor != nil {
|
||||
defaultReactor := appClientset.ReactionChain[0]
|
||||
@@ -72,7 +78,7 @@ func NewMockHandler(reactor *reactorDef, applicationNamespaces []string, objects
|
||||
1*time.Minute,
|
||||
1*time.Minute,
|
||||
10*time.Second,
|
||||
), servercache.NewCache(appstate.NewCache(cacheClient, time.Minute), time.Minute, time.Minute, time.Minute), &mocks.ArgoDB{})
|
||||
), servercache.NewCache(appstate.NewCache(cacheClient, time.Minute), time.Minute, time.Minute, time.Minute), &mocks.ArgoDB{}, maxPayloadSize)
|
||||
}
|
||||
|
||||
func TestGitHubCommitEvent(t *testing.T) {
|
||||
@@ -392,8 +398,9 @@ func TestInvalidEvent(t *testing.T) {
|
||||
req.Header.Set("X-GitHub-Event", "push")
|
||||
w := httptest.NewRecorder()
|
||||
h.Handler(w, req)
|
||||
assert.Equal(t, w.Code, http.StatusBadRequest)
|
||||
expectedLogResult := "Webhook processing failed: error parsing payload"
|
||||
close(h.queue)
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
expectedLogResult := "Webhook processing failed: The payload is either too large or corrupted. Please check the payload size (must be under 1024 MB) and ensure it is valid JSON"
|
||||
assert.Equal(t, expectedLogResult, hook.LastEntry().Message)
|
||||
assert.Equal(t, expectedLogResult+"\n", w.Body.String())
|
||||
hook.Reset()
|
||||
@@ -604,3 +611,21 @@ func Test_getWebUrlRegex(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestGitHubCommitEventMaxPayloadSize(t *testing.T) {
|
||||
hook := test.NewGlobal()
|
||||
maxPayloadSize := int64(100)
|
||||
h := NewMockHandlerWithPayloadLimit(nil, []string{}, maxPayloadSize)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/webhook", nil)
|
||||
req.Header.Set("X-GitHub-Event", "push")
|
||||
eventJSON, err := os.ReadFile("testdata/github-commit-event.json")
|
||||
require.NoError(t, err)
|
||||
req.Body = io.NopCloser(bytes.NewReader(eventJSON))
|
||||
w := httptest.NewRecorder()
|
||||
h.Handler(w, req)
|
||||
close(h.queue)
|
||||
assert.Equal(t, http.StatusBadRequest, w.Code)
|
||||
expectedLogResult := "Webhook processing failed: The payload is either too large or corrupted. Please check the payload size (must be under 0 MB) and ensure it is valid JSON"
|
||||
assert.Equal(t, expectedLogResult, hook.LastEntry().Message)
|
||||
hook.Reset()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user