mirror of
https://github.com/argoproj/argo-cd.git
synced 2026-03-13 20:08:48 +01:00
Compare commits
52 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4803dfac1d | ||
|
|
5dbdaa4fe2 | ||
|
|
e13e887de8 | ||
|
|
b043629979 | ||
|
|
273a952e6c | ||
|
|
2600f52a66 | ||
|
|
2cefc00855 | ||
|
|
e25d3b5435 | ||
|
|
b921433112 | ||
|
|
96f63c3e2b | ||
|
|
d04dc9baed | ||
|
|
0ef556e0f5 | ||
|
|
d54361937b | ||
|
|
de6735c386 | ||
|
|
df2149bbac | ||
|
|
09529ee1ae | ||
|
|
5c51d5dae0 | ||
|
|
ec9b6f1689 | ||
|
|
b7d9f0071b | ||
|
|
2fdaf7a9ad | ||
|
|
5e64458c6b | ||
|
|
2475403af7 | ||
|
|
a1e14d48ab | ||
|
|
425d35c477 | ||
|
|
0d7c4cbe83 | ||
|
|
a408e299ff | ||
|
|
1acd1af8ef | ||
|
|
5679e4060e | ||
|
|
a346cf933e | ||
|
|
f249d530b5 | ||
|
|
46c1ef7a16 | ||
|
|
b4565fd7b2 | ||
|
|
a8a6fc8dda | ||
|
|
81024f8a89 | ||
|
|
f0201c3a99 | ||
|
|
d5c6608827 | ||
|
|
0564de77e6 | ||
|
|
e1eec8a9dc | ||
|
|
3d8d03f0a4 | ||
|
|
64f5c6aa85 | ||
|
|
f9e2fc9210 | ||
|
|
f9eac82928 | ||
|
|
bfbc19a583 | ||
|
|
d855831540 | ||
|
|
6536fd9fb4 | ||
|
|
053bfbe845 | ||
|
|
7b771061e1 | ||
|
|
f8c6bcba65 | ||
|
|
6e9b18ea4b | ||
|
|
7a72b6f2d2 | ||
|
|
51db9bdf79 | ||
|
|
b2c5f5b63c |
1
.github/workflows/ci-build.yaml
vendored
1
.github/workflows/ci-build.yaml
vendored
@@ -9,6 +9,7 @@ on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'master'
|
||||
- 'release-*'
|
||||
|
||||
env:
|
||||
# Golang version to use across CI steps
|
||||
|
||||
1
USERS.md
1
USERS.md
@@ -154,3 +154,4 @@ Currently, the following organizations are **officially** using Argo CD:
|
||||
1. [Beleza Na Web](https://www.belezanaweb.com.br/)
|
||||
1. [MariaDB](https://mariadb.com)
|
||||
1. [Lightricks](https://www.lightricks.com/)
|
||||
1. [Snapp](https://snapp.ir/)
|
||||
@@ -2661,6 +2661,16 @@
|
||||
"type": "string",
|
||||
"name": "revision",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "appName",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"name": "appProject",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -3960,6 +3970,9 @@
|
||||
"appName": {
|
||||
"type": "string"
|
||||
},
|
||||
"appProject": {
|
||||
"type": "string"
|
||||
},
|
||||
"source": {
|
||||
"$ref": "#/definitions/v1alpha1ApplicationSource"
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/utils/kube"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/sirupsen/logrus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
apierr "k8s.io/apimachinery/pkg/api/errors"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -88,7 +88,11 @@ func NewExportCommand() *cobra.Command {
|
||||
}
|
||||
applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{})
|
||||
if err != nil && !apierr.IsNotFound(err) {
|
||||
errors.CheckError(err)
|
||||
if apierr.IsForbidden(err) {
|
||||
log.Warn(err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
}
|
||||
if applicationSets != nil {
|
||||
for _, appSet := range applicationSets.Items {
|
||||
@@ -176,6 +180,17 @@ func NewImportCommand() *cobra.Command {
|
||||
for _, proj := range projects.Items {
|
||||
pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "AppProject", Name: proj.GetName()}] = proj
|
||||
}
|
||||
applicationSets, err := acdClients.applicationSets.List(context.Background(), v1.ListOptions{})
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
log.Warnf("argoproj.io/ApplicationSet: %v\n", err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
if applicationSets != nil {
|
||||
for _, appSet := range applicationSets.Items {
|
||||
pruneObjects[kube.ResourceKey{Group: "argoproj.io", Kind: "ApplicationSet", Name: appSet.GetName()}] = appSet
|
||||
}
|
||||
}
|
||||
|
||||
// Create or replace existing object
|
||||
backupObjects, err := kube.SplitYAML(input)
|
||||
@@ -199,22 +214,39 @@ func NewImportCommand() *cobra.Command {
|
||||
dynClient = acdClients.applicationSets
|
||||
}
|
||||
if !exists {
|
||||
isForbidden := false
|
||||
if !dryRun {
|
||||
_, err = dynClient.Create(context.Background(), bakObj, v1.CreateOptions{})
|
||||
errors.CheckError(err)
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
isForbidden = true
|
||||
log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
}
|
||||
fmt.Printf("%s/%s %s created%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
|
||||
if !isForbidden {
|
||||
fmt.Printf("%s/%s %s created%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
|
||||
}
|
||||
|
||||
} else if specsEqual(*bakObj, liveObj) {
|
||||
if verbose {
|
||||
fmt.Printf("%s/%s %s unchanged%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
|
||||
}
|
||||
} else {
|
||||
isForbidden := false
|
||||
if !dryRun {
|
||||
newLive := updateLive(bakObj, &liveObj)
|
||||
_, err = dynClient.Update(context.Background(), newLive, v1.UpdateOptions{})
|
||||
errors.CheckError(err)
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
isForbidden = true
|
||||
log.Warnf("%s/%s %s: %v", gvk.Group, gvk.Kind, bakObj.GetName(), err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
}
|
||||
if !isForbidden {
|
||||
fmt.Printf("%s/%s %s updated%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
|
||||
}
|
||||
fmt.Printf("%s/%s %s updated%s\n", gvk.Group, gvk.Kind, bakObj.GetName(), dryRunMsg)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -239,16 +271,24 @@ func NewImportCommand() *cobra.Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
case "ApplicationSet":
|
||||
dynClient = acdClients.applicationSets
|
||||
default:
|
||||
logrus.Fatalf("Unexpected kind '%s' in prune list", key.Kind)
|
||||
log.Fatalf("Unexpected kind '%s' in prune list", key.Kind)
|
||||
}
|
||||
isForbidden := false
|
||||
if !dryRun {
|
||||
err = dynClient.Delete(context.Background(), key.Name, v1.DeleteOptions{})
|
||||
if err != nil && !apierr.IsNotFound(err) {
|
||||
if apierr.IsForbidden(err) || apierr.IsNotFound(err) {
|
||||
isForbidden = true
|
||||
log.Warnf("%s/%s %s: %v\n", key.Group, key.Kind, key.Name, err)
|
||||
} else {
|
||||
errors.CheckError(err)
|
||||
}
|
||||
}
|
||||
fmt.Printf("%s/%s %s pruned%s\n", key.Group, key.Kind, key.Name, dryRunMsg)
|
||||
if !isForbidden {
|
||||
fmt.Printf("%s/%s %s pruned%s\n", key.Group, key.Kind, key.Name, dryRunMsg)
|
||||
}
|
||||
} else {
|
||||
fmt.Printf("%s/%s %s needs pruning\n", key.Group, key.Kind, key.Name)
|
||||
}
|
||||
@@ -304,6 +344,8 @@ func updateLive(bak, live *unstructured.Unstructured) *unstructured.Unstructured
|
||||
if _, ok := bak.Object["status"]; ok {
|
||||
newLive.Object["status"] = bak.Object["status"]
|
||||
}
|
||||
case "ApplicationSet":
|
||||
newLive.Object["spec"] = bak.Object["spec"]
|
||||
}
|
||||
return newLive
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
apiruntime "k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
@@ -355,8 +356,12 @@ func (ctrl *ApplicationController) getResourceTree(a *appv1.Application, managed
|
||||
},
|
||||
})
|
||||
} else {
|
||||
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, kube.GetResourceKey(live), func(child appv1.ResourceNode, appName string) {
|
||||
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, kube.GetResourceKey(live), func(child appv1.ResourceNode, appName string) bool {
|
||||
if !proj.IsResourcePermitted(schema.GroupKind{Group: child.ResourceRef.Group, Kind: child.ResourceRef.Kind}, child.Namespace, a.Spec.Destination) {
|
||||
return false
|
||||
}
|
||||
nodes = append(nodes, child)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -366,16 +371,18 @@ func (ctrl *ApplicationController) getResourceTree(a *appv1.Application, managed
|
||||
orphanedNodes := make([]appv1.ResourceNode, 0)
|
||||
for k := range orphanedNodesMap {
|
||||
if k.Namespace != "" && proj.IsGroupKindPermitted(k.GroupKind(), true) && !isKnownOrphanedResourceExclusion(k, proj) {
|
||||
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, k, func(child appv1.ResourceNode, appName string) {
|
||||
err := ctrl.stateCache.IterateHierarchy(a.Spec.Destination.Server, k, func(child appv1.ResourceNode, appName string) bool {
|
||||
belongToAnotherApp := false
|
||||
if appName != "" {
|
||||
if _, exists, err := ctrl.appInformer.GetIndexer().GetByKey(ctrl.namespace + "/" + appName); exists && err == nil {
|
||||
belongToAnotherApp = true
|
||||
}
|
||||
}
|
||||
if !belongToAnotherApp {
|
||||
orphanedNodes = append(orphanedNodes, child)
|
||||
if belongToAnotherApp || !proj.IsResourcePermitted(schema.GroupKind{Group: child.ResourceRef.Group, Kind: child.ResourceRef.Kind}, child.Namespace, a.Spec.Destination) {
|
||||
return false
|
||||
}
|
||||
orphanedNodes = append(orphanedNodes, child)
|
||||
return true
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -665,6 +672,18 @@ func (ctrl *ApplicationController) processAppOperationQueueItem() (processNext b
|
||||
}
|
||||
app := origApp.DeepCopy()
|
||||
|
||||
if app.Operation != nil {
|
||||
// If we get here, we are about process an operation but we cannot rely on informer since it might has stale data.
|
||||
// So always retrieve the latest version to ensure it is not stale to avoid unnecessary syncing.
|
||||
// We cannot rely on informer since applications might be updated by both application controller and api server.
|
||||
freshApp, err := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace).Get(context.Background(), app.ObjectMeta.Name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
log.Errorf("Failed to retrieve latest application state: %v", err)
|
||||
return
|
||||
}
|
||||
app = freshApp
|
||||
}
|
||||
|
||||
if app.Operation != nil {
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
} else if app.DeletionTimestamp != nil && app.CascadedDeletion() {
|
||||
@@ -1037,7 +1056,7 @@ func (ctrl *ApplicationController) processRequestedAppOperation(app *appv1.Appli
|
||||
}
|
||||
|
||||
ctrl.setOperationState(app, state)
|
||||
if state.Phase.Completed() && !app.Operation.Sync.DryRun {
|
||||
if state.Phase.Completed() && (app.Operation.Sync != nil && !app.Operation.Sync.DryRun) {
|
||||
// if we just completed an operation, force a refresh so that UI will report up-to-date
|
||||
// sync/health information
|
||||
if _, err := cache.MetaNamespaceKeyFunc(app); err == nil {
|
||||
@@ -1085,7 +1104,7 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
|
||||
}
|
||||
|
||||
appClient := ctrl.applicationClientset.ArgoprojV1alpha1().Applications(ctrl.namespace)
|
||||
patchedApp, err := appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
|
||||
_, err = appClient.Patch(context.Background(), app.Name, types.MergePatchType, patchJSON, metav1.PatchOptions{})
|
||||
if err != nil {
|
||||
// Stop retrying updating deleted application
|
||||
if apierr.IsNotFound(err) {
|
||||
@@ -1115,10 +1134,6 @@ func (ctrl *ApplicationController) setOperationState(app *appv1.Application, sta
|
||||
ctrl.auditLogger.LogAppEvent(app, eventInfo, strings.Join(messages, " "))
|
||||
ctrl.metricsServer.IncSync(app, state)
|
||||
}
|
||||
// write back to informer in order to avoid stale cache
|
||||
if err := ctrl.appInformer.GetStore().Update(patchedApp); err != nil {
|
||||
log.Warnf("Fails to update informer: %v", err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -1197,6 +1212,13 @@ func (ctrl *ApplicationController) processAppRefreshQueueItem() (processNext boo
|
||||
app.Status.Sync.Status = appv1.SyncStatusCodeUnknown
|
||||
app.Status.Health.Status = health.HealthStatusUnknown
|
||||
ctrl.persistAppStatus(origApp, &app.Status)
|
||||
|
||||
if err := ctrl.cache.SetAppResourcesTree(app.Name, &appv1.ApplicationTree{}); err != nil {
|
||||
log.Warnf("failed to set app resource tree: %v", err)
|
||||
}
|
||||
if err := ctrl.cache.SetAppManagedResources(app.Name, nil); err != nil {
|
||||
log.Warnf("failed to set app managed resources tree: %v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -135,12 +135,12 @@ func newFakeController(data *fakeData) *ApplicationController {
|
||||
mockStateCache.On("GetClusterCache", mock.Anything).Return(&clusterCacheMock, nil)
|
||||
mockStateCache.On("IterateHierarchy", mock.Anything, mock.Anything, mock.Anything).Run(func(args mock.Arguments) {
|
||||
key := args[1].(kube.ResourceKey)
|
||||
action := args[2].(func(child argoappv1.ResourceNode, appName string))
|
||||
action := args[2].(func(child argoappv1.ResourceNode, appName string) bool)
|
||||
appName := ""
|
||||
if res, ok := data.namespacedResources[key]; ok {
|
||||
appName = res.AppName
|
||||
}
|
||||
action(argoappv1.ResourceNode{ResourceRef: argoappv1.ResourceRef{Kind: key.Kind, Group: key.Group, Namespace: key.Namespace, Name: key.Name}}, appName)
|
||||
_ = action(argoappv1.ResourceNode{ResourceRef: argoappv1.ResourceRef{Kind: key.Kind, Group: key.Group, Namespace: key.Namespace, Name: key.Name}}, appName)
|
||||
}).Return(nil)
|
||||
return ctrl
|
||||
}
|
||||
@@ -1083,12 +1083,10 @@ func TestProcessRequestedAppOperation_FailedNoRetries(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1110,12 +1108,10 @@ func TestProcessRequestedAppOperation_InvalidDestination(t *testing.T) {
|
||||
fakeAppCs.Lock()
|
||||
defer fakeAppCs.Unlock()
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
}()
|
||||
|
||||
@@ -1138,12 +1134,10 @@ func TestProcessRequestedAppOperation_FailedHasRetries(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1183,12 +1177,10 @@ func TestProcessRequestedAppOperation_RunningPreviouslyFailed(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
@@ -1218,12 +1210,10 @@ func TestProcessRequestedAppOperation_HasRetriesTerminated(t *testing.T) {
|
||||
fakeAppCs := ctrl.applicationClientset.(*appclientset.Clientset)
|
||||
receivedPatch := map[string]interface{}{}
|
||||
fakeAppCs.PrependReactor("patch", "*", func(action kubetesting.Action) (handled bool, ret runtime.Object, err error) {
|
||||
patchedApp := &v1alpha1.Application{}
|
||||
if patchAction, ok := action.(kubetesting.PatchAction); ok {
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &receivedPatch))
|
||||
assert.NoError(t, json.Unmarshal(patchAction.GetPatch(), &patchedApp))
|
||||
}
|
||||
return true, patchedApp, nil
|
||||
return true, nil, nil
|
||||
})
|
||||
|
||||
ctrl.processRequestedAppOperation(app)
|
||||
|
||||
8
controller/cache/cache.go
vendored
8
controller/cache/cache.go
vendored
@@ -56,7 +56,7 @@ type LiveStateCache interface {
|
||||
// Returns synced cluster cache
|
||||
GetClusterCache(server string) (clustercache.ClusterCache, error)
|
||||
// Executes give callback against resource specified by the key and all its children
|
||||
IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string)) error
|
||||
IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string) bool) error
|
||||
// Returns state of live nodes which correspond for target nodes of specified application.
|
||||
GetManagedLiveObjs(a *appv1.Application, targetObjs []*unstructured.Unstructured) (map[kube.ResourceKey]*unstructured.Unstructured, error)
|
||||
// IterateResources iterates all resource stored in cache
|
||||
@@ -371,13 +371,13 @@ func (c *liveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool,
|
||||
return clusterInfo.IsNamespaced(gk)
|
||||
}
|
||||
|
||||
func (c *liveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string)) error {
|
||||
func (c *liveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(child appv1.ResourceNode, appName string) bool) error {
|
||||
clusterInfo, err := c.getSyncedCluster(server)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clusterInfo.IterateHierarchy(key, func(resource *clustercache.Resource, namespaceResources map[kube.ResourceKey]*clustercache.Resource) {
|
||||
action(asResourceNode(resource), getApp(resource, namespaceResources))
|
||||
clusterInfo.IterateHierarchy(key, func(resource *clustercache.Resource, namespaceResources map[kube.ResourceKey]*clustercache.Resource) bool {
|
||||
return action(asResourceNode(resource), getApp(resource, namespaceResources))
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
4
controller/cache/mocks/LiveStateCache.go
vendored
4
controller/cache/mocks/LiveStateCache.go
vendored
@@ -178,11 +178,11 @@ func (_m *LiveStateCache) IsNamespaced(server string, gk schema.GroupKind) (bool
|
||||
}
|
||||
|
||||
// IterateHierarchy provides a mock function with given fields: server, key, action
|
||||
func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(v1alpha1.ResourceNode, string)) error {
|
||||
func (_m *LiveStateCache) IterateHierarchy(server string, key kube.ResourceKey, action func(v1alpha1.ResourceNode, string) bool) error {
|
||||
ret := _m.Called(server, key, action)
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(string, kube.ResourceKey, func(v1alpha1.ResourceNode, string)) error); ok {
|
||||
if rf, ok := ret.Get(0).(func(string, kube.ResourceKey, func(v1alpha1.ResourceNode, string) bool) error); ok {
|
||||
r0 = rf(server, key, action)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
|
||||
@@ -152,6 +152,11 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
helmOptions, err := m.settingsMgr.GetHelmSettings()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ts.AddCheckpoint("build_options_ms")
|
||||
serverVersion, apiGroups, err := m.liveStateCache.GetVersionsInfo(app.Spec.Destination.Server)
|
||||
if err != nil {
|
||||
@@ -174,6 +179,7 @@ func (m *appStateManager) getRepoObjs(app *v1alpha1.Application, source v1alpha1
|
||||
ApiVersions: argo.APIGroupsToVersions(apiGroups),
|
||||
VerifySignature: verifySignature,
|
||||
HelmRepoCreds: permittedHelmCredentials,
|
||||
HelmOptions: helmOptions,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
|
||||
@@ -194,6 +194,10 @@ data:
|
||||
kustomize.version.v3.5.1: /custom-tools/kustomize_3_5_1
|
||||
kustomize.version.v3.5.4: /custom-tools/kustomize_3_5_4
|
||||
|
||||
# Comma delimited list of additional custom remote values file schemes (http are https are allowed by default).
|
||||
# Change to empty value if you want to disable remote values files altogether.
|
||||
helm.valuesFileSchemes: http, https
|
||||
|
||||
# The metadata.label key name where Argo CD injects the app name as a tracking label (optional).
|
||||
# Tracking labels are used to determine which resources need to be deleted when pruning.
|
||||
# If omitted, Argo CD injects the app name into the label: 'app.kubernetes.io/instance'
|
||||
|
||||
@@ -14,3 +14,5 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
|
||||
@@ -396,6 +396,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
```
|
||||
|
||||
!!! note
|
||||
|
||||
@@ -39,6 +39,48 @@ the three components (argocd-server, argocd-repo-server, argocd-application-cont
|
||||
API server can enforce the use of TLS 1.2 using the flag: `--tlsminversion 1.2`.
|
||||
Communication with Redis is performed over plain HTTP by default. TLS can be setup with command line arguments.
|
||||
|
||||
## Git & Helm Repositories
|
||||
|
||||
Git and helm repositories are managed by a stand-alone service, called the repo-server. The
|
||||
repo-server does not carry any Kubernetes privileges and does not store credentials to any services
|
||||
(including git). The repo-server is responsible for cloning repositories which have been permitted
|
||||
and trusted by Argo CD operators, and generating kubernetes manifests at a given path in the
|
||||
repository. For performance and bandwidth efficiency, the repo-server maintains local clones of
|
||||
these repositories so that subsequent commits to the repository are efficiently downloaded.
|
||||
|
||||
There are security considerations when configuring git repositories that Argo CD is permitted to
|
||||
deploy from. In short, gaining unauthorized write access to a git repository trusted by Argo CD
|
||||
will have serious security implications outlined below.
|
||||
|
||||
### Unauthorized Deployments
|
||||
|
||||
Since Argo CD deploys the Kubernetes resources defined in git, an attacker with access to a trusted
|
||||
git repo would be able to affect the Kubernetes resources which are deployed. For example, an
|
||||
attacker could update the deployment manifest deploy malicious container images to the environment,
|
||||
or delete resources in git causing them to be pruned in the live environment.
|
||||
|
||||
### Tool command invocation
|
||||
|
||||
In addition to raw YAML, Argo CD natively supports two popular Kubernetes config management tools,
|
||||
helm and kustomize. When rendering manifests, Argo CD executes these config management tools
|
||||
(i.e. `helm template`, `kustomize build`) to generate the manifests. It is possible that an attacker
|
||||
with write access to a trusted git repository may construct malicious helm charts or kustomizations
|
||||
that attempt to read files out-of-tree. This includes adjacent git repos, as well as files on the
|
||||
repo-server itself. Whether or not this is a risk to your organization depends on if the contents
|
||||
in the git repos are sensitive in nature. By default, the repo-server itself does not contain
|
||||
sensitive information, but might be configured with Config Management Plugins which do
|
||||
(e.g. decryption keys). If such plugins are used, extreme care must be taken to ensure the
|
||||
repository contents can be trusted at all times.
|
||||
|
||||
### Remote bases and helm chart dependencies
|
||||
|
||||
Argo CD's repository allow-list only restricts the initial repository which is cloned. However, both
|
||||
kustomize and helm contain features to reference and follow *additional* repositories
|
||||
(e.g. kustomize remote bases, helm chart dependencies), of which might not be in the repository
|
||||
allow-list. Argo CD operators must understand that users with write access to trusted git
|
||||
repositories could reference other remote git repositories containing Kubernetes resources not
|
||||
easily searchable or auditable in the configured git repositories.
|
||||
|
||||
## Sensitive Information
|
||||
|
||||
### Secrets
|
||||
|
||||
@@ -5,12 +5,16 @@
|
||||
- [Config Management Tools Integrations (proposal)](#config-management-tools-integrations-proposal)
|
||||
- [Argo CD Extensions (proposal)](#argo-cd-extensions-proposal)
|
||||
- [Project scoped repository and clusters (proposal)](#project-scoped-repository-and-clusters-proposal)
|
||||
- [Core Argo CD (proposal)](#core-argo-cd-aka-gitops-agent-proposal)
|
||||
- [v2.3 and beyond](#v23-and-beyond)
|
||||
- [Application Details Page Usability](#application-details-page-usability)
|
||||
- [Cluster Management User Interface](#cluster-management-user-interface)
|
||||
- [Input Forms UI Refresh](#input-forms-ui-refresh)
|
||||
- [Merge ApplicationSet controller into Argo CD](#merge-applicationset-controller-into-argo-cd)
|
||||
- [Merge Argo CD Notifications into Argo CD](#merge-argo-cd-notifications-into-argo-cd)
|
||||
- [Merge Argo CD Image Updater into Argo CD](#merge-argo-cd-image-updater-into-argo-cd)
|
||||
- [Compact Resources Tree](#compact-resources-tree)
|
||||
- [Multi-tenancy improvements](#multi-tenancy-improvements)
|
||||
- [GitOps Engine Enhancements](#gitops-engine-enhancements)
|
||||
- [Completed](#completed)
|
||||
- [✅ Core Argo CD (proposal)](#core-argo-cd-aka-gitops-agent-proposal)
|
||||
- [✅ Core Functionality Bug Fixes](#-core-functionality-bug-fixes)
|
||||
- [✅ Performance](#-performance)
|
||||
- [✅ ApplicationSet](#-applicationset)
|
||||
@@ -20,7 +24,6 @@
|
||||
- [✅ Automated Registry Monitoring](#-automated-registry-monitoring)
|
||||
- [✅ Projects Enhancements](#-projects-enhancements)
|
||||
|
||||
|
||||
## v2.2
|
||||
|
||||
### Config Management Tools Integrations ([proposal](https://github.com/argoproj/argo-cd/pull/5927))
|
||||
@@ -44,17 +47,33 @@ Instead of asking an administrator to change Argo CD settings end users can perf
|
||||
|
||||
## v2.3 and beyond
|
||||
|
||||
### Application Details Page Usability
|
||||
### Input Forms UI Refresh
|
||||
|
||||
Application details page has accumulated multiple usability and feature requests such as
|
||||
[Node view](https://github.com/argoproj/argo-cd/issues/1483),
|
||||
Network view ([1](https://github.com/argoproj/argo-cd/issues/2892), [2](https://github.com/argoproj/argo-cd/issues/2338))
|
||||
[etc](https://github.com/argoproj/argo-cd/issues/2199).
|
||||
Improved design of the input forms in Argo CD Web UI: https://www.figma.com/file/IIlsFqqmM5UhqMVul9fQNq/Argo-CD?node-id=0%3A1
|
||||
|
||||
### Cluster Management User Interface
|
||||
### Merge ApplicationSet controller into Argo CD
|
||||
|
||||
The ApplicationSet functionality is available in Argo CD out-of-the-box ([#7351](https://github.com/argoproj/argo-cd/issues/7351)).
|
||||
The Argo CD UI/CLI/API allows to manage ApplicationSet resources same as Argo CD Applications ([#7352](https://github.com/argoproj/argo-cd/issues/7352)).
|
||||
|
||||
### Merge Argo CD Notifications into Argo CD
|
||||
|
||||
The [Argo CD Notifications](https://github.com/argoproj-labs/argocd-notifications) should be merged into Argo CD and available out-of-the-box: [#7350](https://github.com/argoproj/argo-cd/issues/7350)
|
||||
|
||||
### Merge Argo CD Image Updater into Argo CD
|
||||
|
||||
The [Argo CD Image Updater](https://github.com/argoproj-labs/argocd-image-updater) should be merged into Argo CD and available out-of-the-box: [#7385](https://github.com/argoproj/argo-cd/issues/7385)
|
||||
|
||||
### Compact resources tree
|
||||
|
||||
An ability to collaps leaf resources tree to improve visualization of very large applications: [#7349](https://github.com/argoproj/argo-cd/issues/7349)
|
||||
|
||||
### Multi-tenancy improvements
|
||||
|
||||
The multi-tenancy improvements that allow end-users to create Argo CD applications using Kubernetes directly without accessing Argo CD API.
|
||||
* [Applications outside argocd namespace](https://github.com/argoproj/argo-cd/pull/6409)
|
||||
* [AppSource](https://github.com/argoproj-labs/appsource)
|
||||
|
||||
Argo CD has information about whole clusters, not just applications in it.
|
||||
We need to provide a user interface for cluster administrators that visualize cluster level resources.
|
||||
|
||||
### GitOps Engine Enhancements
|
||||
|
||||
@@ -109,7 +128,7 @@ to improve user experience.
|
||||
|
||||
To make Argo CD successful we need to build tools that enable Argo CD administrators to handle scalability and performance issues in a self-service model.
|
||||
|
||||
That includes more metrics, out of the box alerts and a cluster management user interface.
|
||||
That includes more metrics, out-of-the-box alerts and a cluster management user interface.
|
||||
|
||||
|
||||
### ✅ Argo CD Notifications
|
||||
|
||||
@@ -35,8 +35,8 @@ metadata:
|
||||
app.kubernetes.io/name: argocd-cm
|
||||
app.kubernetes.io/part-of: argocd
|
||||
data:
|
||||
kustomize.buildOptions: --load_restrictor LoadRestrictionsNone
|
||||
kustomize.buildOptions.v3.9.1: --output /tmp
|
||||
kustomize.buildOptions: --load-restrictor LoadRestrictionsNone
|
||||
kustomize.buildOptions.v4.4.0: --output /tmp
|
||||
```
|
||||
## Custom Kustomize versions
|
||||
|
||||
|
||||
4
go.mod
4
go.mod
@@ -7,8 +7,8 @@ require (
|
||||
github.com/TomOnTime/utfutil v0.0.0-20180511104225-09c41003ee1d
|
||||
github.com/alicebob/miniredis v2.5.0+incompatible
|
||||
github.com/alicebob/miniredis/v2 v2.14.2
|
||||
github.com/argoproj/gitops-engine v0.4.1
|
||||
github.com/argoproj/pkg v0.9.1
|
||||
github.com/argoproj/gitops-engine v0.4.3
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0
|
||||
github.com/bombsimon/logrusr v1.0.0
|
||||
github.com/bradleyfalzon/ghinstallation v1.1.1
|
||||
github.com/casbin/casbin v1.9.1
|
||||
|
||||
8
go.sum
8
go.sum
@@ -96,10 +96,10 @@ github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/argoproj/gitops-engine v0.4.1 h1:kBAAWVUBfnhD40sRIEr3XcUcPZHODOmwSXSpySmVWR0=
|
||||
github.com/argoproj/gitops-engine v0.4.1/go.mod h1:EdFe8qIOqsmbyxRhtIydU4BUeyZ4VTsY6R3XVQhU9LA=
|
||||
github.com/argoproj/pkg v0.9.1 h1:osfOS3QkzfRf+W43lbCZb0o0bzrBweQhL+U3rgEg+5M=
|
||||
github.com/argoproj/pkg v0.9.1/go.mod h1:ra+bQPmbVAoEL+gYSKesuigt4m49i3Qa3mE/xQcjCiA=
|
||||
github.com/argoproj/gitops-engine v0.4.3 h1:QLAnFVmPPL1F5hmqb/5rABOAW7sb/fERaeeFz78kbKE=
|
||||
github.com/argoproj/gitops-engine v0.4.3/go.mod h1:EdFe8qIOqsmbyxRhtIydU4BUeyZ4VTsY6R3XVQhU9LA=
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 h1:Cfp7rO/HpVxnwlRqJe0jHiBbZ77ZgXhB6HWlYD02Xdc=
|
||||
github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0/go.mod h1:ra+bQPmbVAoEL+gYSKesuigt4m49i3Qa3mE/xQcjCiA=
|
||||
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
|
||||
|
||||
@@ -31,6 +31,7 @@ $KUSTOMIZE version
|
||||
|
||||
cd ${SRCROOT}/manifests/base && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
cd ${SRCROOT}/manifests/ha/base && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
cd ${SRCROOT}/manifests/core-install && $KUSTOMIZE edit set image quay.io/argoproj/argocd=${IMAGE_NAMESPACE}/argocd:${IMAGE_TAG}
|
||||
|
||||
echo "${AUTOGENMSG}" > "${SRCROOT}/manifests/install.yaml"
|
||||
$KUSTOMIZE build "${SRCROOT}/manifests/cluster-install" >> "${SRCROOT}/manifests/install.yaml"
|
||||
|
||||
@@ -14,3 +14,5 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
@@ -5,7 +5,7 @@ kind: Kustomization
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.2
|
||||
newTag: v2.1.13
|
||||
resources:
|
||||
- ./application-controller
|
||||
- ./dex
|
||||
|
||||
@@ -98,6 +98,12 @@ spec:
|
||||
name: argocd-cmd-params-cm
|
||||
key: reposerver.default.cache.expiration
|
||||
optional: true
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
- containerPort: 8084
|
||||
@@ -134,6 +140,8 @@ spec:
|
||||
mountPath: /app/config/reposerver/tls
|
||||
- name: tmp
|
||||
mountPath: /tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- name: ssh-known-hosts
|
||||
configMap:
|
||||
@@ -148,6 +156,8 @@ spec:
|
||||
emptyDir: {}
|
||||
- name: tmp
|
||||
emptyDir: {}
|
||||
- name: helm-working-dir
|
||||
emptyDir: {}
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
secretName: argocd-repo-server-tls
|
||||
|
||||
@@ -2735,7 +2735,7 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
ssh_known_hosts: |-
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
@@ -2743,6 +2743,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
@@ -2982,7 +2984,13 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3021,6 +3029,8 @@ spec:
|
||||
name: argocd-repo-server-tls
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -3035,6 +3045,8 @@ spec:
|
||||
name: gpg-keyring
|
||||
- emptyDir: {}
|
||||
name: tmp
|
||||
- emptyDir: {}
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
items:
|
||||
@@ -3175,7 +3187,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:latest
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -7,4 +7,8 @@ resources:
|
||||
- ../base/config
|
||||
- ../base/application-controller
|
||||
- ../base/repo-server
|
||||
- ../base/redis
|
||||
- ../base/redis
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.13
|
||||
|
||||
@@ -11,7 +11,7 @@ patchesStrategicMerge:
|
||||
images:
|
||||
- name: quay.io/argoproj/argocd
|
||||
newName: quay.io/argoproj/argocd
|
||||
newTag: v2.1.2
|
||||
newTag: v2.1.13
|
||||
resources:
|
||||
- ../../base/application-controller
|
||||
- ../../base/dex
|
||||
|
||||
@@ -770,7 +770,7 @@ spec:
|
||||
topologyKey: kubernetes.io/hostname
|
||||
initContainers:
|
||||
- name: config-init
|
||||
image: haproxy:2.0.22-alpine
|
||||
image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
resources:
|
||||
{}
|
||||
@@ -790,7 +790,7 @@ spec:
|
||||
runAsUser: 1000
|
||||
containers:
|
||||
- name: haproxy
|
||||
image: haproxy:2.0.22-alpine
|
||||
image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -9,7 +9,7 @@ redis-ha:
|
||||
haproxy:
|
||||
enabled: true
|
||||
image:
|
||||
tag: 2.0.22-alpine
|
||||
tag: 2.0.25-alpine
|
||||
timeout:
|
||||
server: 6m
|
||||
client: 6m
|
||||
|
||||
@@ -3377,7 +3377,7 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
ssh_known_hosts: |-
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
@@ -3385,6 +3385,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
@@ -3684,7 +3686,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -3731,7 +3733,7 @@ spec:
|
||||
app.kubernetes.io/name: argocd-redis-ha-haproxy
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers:
|
||||
- image: haproxy:2.0.22-alpine
|
||||
- image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle: {}
|
||||
livenessProbe:
|
||||
@@ -3760,7 +3762,7 @@ spec:
|
||||
- /readonly/haproxy_init.sh
|
||||
command:
|
||||
- sh
|
||||
image: haproxy:2.0.22-alpine
|
||||
image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
volumeMounts:
|
||||
@@ -3895,7 +3897,13 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3934,6 +3942,8 @@ spec:
|
||||
name: argocd-repo-server-tls
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -3948,6 +3958,8 @@ spec:
|
||||
name: gpg-keyring
|
||||
- emptyDir: {}
|
||||
name: tmp
|
||||
- emptyDir: {}
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
items:
|
||||
@@ -4144,7 +4156,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -4340,7 +4352,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -764,7 +764,7 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
ssh_known_hosts: |-
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
@@ -772,6 +772,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
@@ -1071,7 +1073,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -1118,7 +1120,7 @@ spec:
|
||||
app.kubernetes.io/name: argocd-redis-ha-haproxy
|
||||
topologyKey: kubernetes.io/hostname
|
||||
containers:
|
||||
- image: haproxy:2.0.22-alpine
|
||||
- image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
lifecycle: {}
|
||||
livenessProbe:
|
||||
@@ -1147,7 +1149,7 @@ spec:
|
||||
- /readonly/haproxy_init.sh
|
||||
command:
|
||||
- sh
|
||||
image: haproxy:2.0.22-alpine
|
||||
image: haproxy:2.0.25-alpine
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: config-init
|
||||
volumeMounts:
|
||||
@@ -1282,7 +1284,13 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -1321,6 +1329,8 @@ spec:
|
||||
name: argocd-repo-server-tls
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -1335,6 +1345,8 @@ spec:
|
||||
name: gpg-keyring
|
||||
- emptyDir: {}
|
||||
name: tmp
|
||||
- emptyDir: {}
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
items:
|
||||
@@ -1531,7 +1543,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1727,7 +1739,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -2847,7 +2847,7 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
ssh_known_hosts: |-
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
@@ -2855,6 +2855,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
@@ -3049,7 +3051,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -3224,7 +3226,13 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -3263,6 +3271,8 @@ spec:
|
||||
name: argocd-repo-server-tls
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -3277,6 +3287,8 @@ spec:
|
||||
name: gpg-keyring
|
||||
- emptyDir: {}
|
||||
name: tmp
|
||||
- emptyDir: {}
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
items:
|
||||
@@ -3469,7 +3481,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -3659,7 +3671,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -234,7 +234,7 @@ metadata:
|
||||
---
|
||||
apiVersion: v1
|
||||
data:
|
||||
ssh_known_hosts: |
|
||||
ssh_known_hosts: |-
|
||||
bitbucket.org ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAubiN81eDcafrgMeLzaFPsw2kNvEcqTKl/VqLat/MaB33pZy0y3rJZtnqwR2qOOvbwKZYKiEO1O6VqNEBxKvJJelCq0dTXWT5pbO2gDXC6h6QDXCaHo6pOHGPUy+YBaGQRGuSusMEASYiWunYN0vCAI8QaXnWMXNMdFP3jHAJH0eDsoiGnLPBlBp4TNm6rYI74nMzgz3B9IikW4WVK+dc8KZJZWYjAuORU3jc1c/NPskD2ASinf8v3xnfXeukU0sJ5N6m5E8VLjObPEO+mN2t/FZTMZLiFqPWc/ALSqnMnnhwrNi2rbfg/rd/IpL8Le3pSBne8+seeFVBoGqzHM9yXw==
|
||||
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
|
||||
gitlab.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBFSMqzJeV9rUzU4kWitGjeR4PWSa29SPqJ1fVkhtj3Hw9xjLVXVYrU9QlYWrOLXBpQ6KWjbjTDTdDkoohFzgbEY=
|
||||
@@ -242,6 +242,8 @@ data:
|
||||
gitlab.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCsj2bNKTBSpIYDEGk9KxsGh3mySTRgMtXL583qmBpzeQ+jqCMRgBqB98u3z++J1sKlXHWfM9dyhSevkMwSbhoR8XIq/U0tCNyokEi/ueaBMCvbcTHhO7FcwzY92WK4Yt0aGROY5qX2UKSeOvuP4D6TPqKF1onrSzH9bx9XUf2lEdWT/ia1NEKjunUqu1xOB/StKDHMoX4/OKyIzuS0q/T1zOATthvasJFoPrAjkohTyaDUz2LN5JoH839hViyEG82yB+MjcFV5MU3N1l1QL3cVUCh93xSaua1N85qivl+siMkPGbO5xR/En4iEY6K2XPASUEMaieWVNTRCtJ4S8H+9
|
||||
ssh.dev.azure.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
vs-ssh.visualstudio.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC7Hr1oTWqNqOlzGJOfGJ4NakVyIzf1rXYd4d7wo6jBlkLvCA4odBlL0mDUyZ0/QUfTTqeu+tm22gOsv+VrVTMk6vwRU75gY/y9ut5Mb3bR5BV58dKXyq9A9UeB5Cakehn5Zgm6x1mKoVyf+FFn26iYqXJRgzIZZcZ5V6hrE0Qg39kZm4az48o0AUbf6Sp4SLdvnuMa2sVNwHBboS7EJkm57XQPVU3/QpyNLHbWDdzwtrlS+ez30S3AdYhLKEOxAG8weOnyrtLJAUen9mTkol8oII1edf7mWWbWVf0nBmly21+nZcmCTISQBtdcyPaEno7fFQMDD26/s0lfKob4Kw8H
|
||||
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
|
||||
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
@@ -436,7 +438,7 @@ spec:
|
||||
- -n
|
||||
- /usr/local/bin/argocd
|
||||
- /shared/argocd-dex
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
name: copyutil
|
||||
volumeMounts:
|
||||
@@ -611,7 +613,13 @@ spec:
|
||||
key: reposerver.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
- name: HELM_CACHE_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_CONFIG_HOME
|
||||
value: /helm-working-dir
|
||||
- name: HELM_DATA_HOME
|
||||
value: /helm-working-dir
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
failureThreshold: 3
|
||||
@@ -650,6 +658,8 @@ spec:
|
||||
name: argocd-repo-server-tls
|
||||
- mountPath: /tmp
|
||||
name: tmp
|
||||
- mountPath: /helm-working-dir
|
||||
name: helm-working-dir
|
||||
volumes:
|
||||
- configMap:
|
||||
name: argocd-ssh-known-hosts-cm
|
||||
@@ -664,6 +674,8 @@ spec:
|
||||
name: gpg-keyring
|
||||
- emptyDir: {}
|
||||
name: tmp
|
||||
- emptyDir: {}
|
||||
name: helm-working-dir
|
||||
- name: argocd-repo-server-tls
|
||||
secret:
|
||||
items:
|
||||
@@ -856,7 +868,7 @@ spec:
|
||||
key: server.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
@@ -1046,7 +1058,7 @@ spec:
|
||||
key: controller.default.cache.expiration
|
||||
name: argocd-cmd-params-cm
|
||||
optional: true
|
||||
image: quay.io/argoproj/argocd:v2.1.2
|
||||
image: quay.io/argoproj/argocd:v2.1.13
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
|
||||
@@ -39,6 +39,8 @@ const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
type RepoAppsQuery struct {
|
||||
Repo string `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
|
||||
Revision string `protobuf:"bytes,2,opt,name=revision,proto3" json:"revision,omitempty"`
|
||||
AppName string `protobuf:"bytes,3,opt,name=appName,proto3" json:"appName,omitempty"`
|
||||
AppProject string `protobuf:"bytes,4,opt,name=appProject,proto3" json:"appProject,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@@ -91,6 +93,20 @@ func (m *RepoAppsQuery) GetRevision() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAppsQuery) GetAppName() string {
|
||||
if m != nil {
|
||||
return m.AppName
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAppsQuery) GetAppProject() string {
|
||||
if m != nil {
|
||||
return m.AppProject
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// AppInfo contains application type and app file path
|
||||
type AppInfo struct {
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
@@ -151,6 +167,7 @@ func (m *AppInfo) GetPath() string {
|
||||
type RepoAppDetailsQuery struct {
|
||||
Source *v1alpha1.ApplicationSource `protobuf:"bytes,1,opt,name=source,proto3" json:"source,omitempty"`
|
||||
AppName string `protobuf:"bytes,2,opt,name=appName,proto3" json:"appName,omitempty"`
|
||||
AppProject string `protobuf:"bytes,3,opt,name=appProject,proto3" json:"appProject,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@@ -203,6 +220,13 @@ func (m *RepoAppDetailsQuery) GetAppName() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (m *RepoAppDetailsQuery) GetAppProject() string {
|
||||
if m != nil {
|
||||
return m.AppProject
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// RepoAppsResponse contains applications of specified repository
|
||||
type RepoAppsResponse struct {
|
||||
Items []*AppInfo `protobuf:"bytes,1,rep,name=items,proto3" json:"items,omitempty"`
|
||||
@@ -654,76 +678,77 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_8d38260443475705 = []byte{
|
||||
// 1093 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0x4f, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0xd7, 0x36, 0xa9, 0x9b, 0x4c, 0xfe, 0xd4, 0x9d, 0x84, 0xb2, 0xb8, 0x69, 0x1a, 0x4d, 0x4b,
|
||||
0x15, 0xa2, 0xb2, 0xdb, 0x18, 0x21, 0xaa, 0x22, 0x40, 0x69, 0x12, 0xb5, 0x11, 0x11, 0x81, 0xad,
|
||||
0xc2, 0x01, 0x81, 0xd0, 0x64, 0xfd, 0x62, 0x2f, 0x59, 0xef, 0x4c, 0x67, 0xc6, 0x0b, 0x56, 0xd5,
|
||||
0x0b, 0x27, 0x24, 0xb8, 0x20, 0x84, 0xd4, 0x1b, 0x07, 0x90, 0x38, 0xf0, 0x45, 0x38, 0x22, 0xf1,
|
||||
0x05, 0x50, 0xc4, 0xe7, 0x40, 0x68, 0x66, 0xd6, 0xbb, 0xeb, 0xc4, 0x76, 0x52, 0x11, 0x72, 0x9b,
|
||||
0xf9, 0xbd, 0x37, 0xef, 0xfd, 0xde, 0xcf, 0x6f, 0xde, 0x78, 0x11, 0x91, 0x20, 0x52, 0x10, 0xbe,
|
||||
0x00, 0xce, 0x64, 0xa4, 0x98, 0xe8, 0x96, 0x96, 0x1e, 0x17, 0x4c, 0x31, 0x8c, 0x0a, 0xa4, 0x36,
|
||||
0xdf, 0x64, 0x4d, 0x66, 0x60, 0x5f, 0xaf, 0xac, 0x47, 0x6d, 0xa1, 0xc9, 0x58, 0x33, 0x06, 0x9f,
|
||||
0xf2, 0xc8, 0xa7, 0x49, 0xc2, 0x14, 0x55, 0x11, 0x4b, 0x64, 0x66, 0x25, 0x07, 0xf7, 0xa4, 0x17,
|
||||
0x31, 0x63, 0x0d, 0x99, 0x00, 0x3f, 0x5d, 0xf5, 0x9b, 0x90, 0x80, 0xa0, 0x0a, 0x1a, 0x99, 0xcf,
|
||||
0x76, 0x33, 0x52, 0xad, 0xce, 0x9e, 0x17, 0xb2, 0xb6, 0x4f, 0x85, 0x49, 0xf1, 0x85, 0x59, 0xbc,
|
||||
0x1e, 0x36, 0xfc, 0xb4, 0xee, 0xf3, 0x83, 0xa6, 0x3e, 0x2f, 0x7d, 0xca, 0x79, 0x1c, 0x85, 0x26,
|
||||
0xbe, 0x9f, 0xae, 0xd2, 0x98, 0xb7, 0xe8, 0xf1, 0x68, 0x9b, 0x27, 0x44, 0x33, 0x05, 0x9d, 0x58,
|
||||
0x38, 0x79, 0x0f, 0xcd, 0x04, 0xc0, 0xd9, 0x1a, 0xe7, 0xf2, 0xa3, 0x0e, 0x88, 0x2e, 0xc6, 0x68,
|
||||
0x5c, 0x3b, 0xb9, 0xce, 0x92, 0xb3, 0x3c, 0x19, 0x98, 0x35, 0xae, 0xa1, 0x09, 0x01, 0x69, 0x24,
|
||||
0x23, 0x96, 0xb8, 0x17, 0x0c, 0x9e, 0xef, 0xc9, 0x2a, 0xba, 0xb4, 0xc6, 0xf9, 0x56, 0xb2, 0xcf,
|
||||
0xf4, 0x51, 0xd5, 0xe5, 0xd0, 0x3b, 0xaa, 0xd7, 0x1a, 0xe3, 0x54, 0xb5, 0xb2, 0x63, 0x66, 0x4d,
|
||||
0x9e, 0x3b, 0x68, 0x2e, 0x4b, 0xba, 0x01, 0x8a, 0x46, 0x71, 0x96, 0xba, 0x89, 0x2a, 0x92, 0x75,
|
||||
0x44, 0x68, 0x23, 0x4c, 0xd5, 0x77, 0xbc, 0xa2, 0x46, 0xaf, 0x57, 0xa3, 0x59, 0x7c, 0x1e, 0x36,
|
||||
0xbc, 0xb4, 0xee, 0xf1, 0x83, 0xa6, 0xa7, 0x15, 0xf3, 0x4a, 0x8a, 0x79, 0x3d, 0xc5, 0xbc, 0xb5,
|
||||
0x02, 0x7c, 0x6c, 0xc2, 0x06, 0x59, 0x78, 0xec, 0xa2, 0x4b, 0x94, 0xf3, 0x0f, 0x68, 0x1b, 0x32,
|
||||
0x5e, 0xbd, 0x2d, 0x79, 0x07, 0x55, 0x7b, 0x72, 0x04, 0x20, 0x39, 0x4b, 0x24, 0xe0, 0xd7, 0xd0,
|
||||
0xc5, 0x48, 0x41, 0x5b, 0xba, 0xce, 0xd2, 0xd8, 0xf2, 0x54, 0x7d, 0xce, 0x2b, 0x89, 0x98, 0x95,
|
||||
0x1e, 0x58, 0x0f, 0xb2, 0x8e, 0x26, 0xf5, 0xf1, 0xe1, 0x4a, 0x12, 0x34, 0xbd, 0xcf, 0x34, 0x15,
|
||||
0xd8, 0x17, 0x20, 0xad, 0x2c, 0x13, 0x41, 0x1f, 0x46, 0x7e, 0x1e, 0x47, 0x97, 0x0d, 0x89, 0x30,
|
||||
0x04, 0x39, 0xfa, 0x57, 0xe9, 0x48, 0x10, 0x49, 0x51, 0x46, 0xbe, 0xd7, 0x36, 0x4e, 0xa5, 0xfc,
|
||||
0x92, 0x89, 0x86, 0x3b, 0x66, 0x6d, 0xbd, 0x3d, 0xbe, 0x85, 0x66, 0xa4, 0x6c, 0x7d, 0x28, 0xa2,
|
||||
0x94, 0x2a, 0x78, 0x1f, 0xba, 0xee, 0xb8, 0x71, 0xe8, 0x07, 0x75, 0x84, 0x28, 0x91, 0x10, 0x76,
|
||||
0x04, 0xb8, 0x17, 0x0d, 0xcb, 0x7c, 0x8f, 0xef, 0xa0, 0x2b, 0x2a, 0x96, 0xeb, 0x71, 0x04, 0x89,
|
||||
0x5a, 0x07, 0xa1, 0x36, 0xa8, 0xa2, 0x6e, 0xc5, 0x44, 0x39, 0x6e, 0xc0, 0x2b, 0xa8, 0xda, 0x07,
|
||||
0xea, 0x94, 0x97, 0x8c, 0xf3, 0x31, 0x3c, 0x6f, 0xa1, 0xc9, 0xfe, 0x16, 0x32, 0x35, 0x22, 0x8b,
|
||||
0x99, 0xfa, 0x16, 0xd0, 0x24, 0x24, 0x74, 0x2f, 0x86, 0x9d, 0x30, 0x72, 0xa7, 0x0c, 0xbd, 0x02,
|
||||
0xc0, 0x77, 0xd1, 0x9c, 0xed, 0x9c, 0x35, 0xce, 0x4b, 0x75, 0x4e, 0x9b, 0x00, 0x83, 0x4c, 0x78,
|
||||
0x09, 0x4d, 0xe5, 0xf0, 0xd6, 0x86, 0x3b, 0xb3, 0xe4, 0x2c, 0x8f, 0x05, 0x65, 0x08, 0xdf, 0x43,
|
||||
0x2f, 0x17, 0xdb, 0x44, 0x2a, 0x1a, 0xc7, 0xa6, 0xb5, 0xb6, 0x36, 0xdc, 0x59, 0xe3, 0x3d, 0xcc,
|
||||
0x8c, 0xdf, 0x45, 0xb5, 0xdc, 0xb4, 0x99, 0x28, 0x10, 0x5c, 0x44, 0x12, 0x1e, 0x50, 0x09, 0xbb,
|
||||
0x22, 0x76, 0x2f, 0x1b, 0x52, 0x23, 0x3c, 0xf0, 0x3c, 0xba, 0xc8, 0x05, 0xfb, 0xaa, 0xeb, 0x56,
|
||||
0x8d, 0xab, 0xdd, 0x90, 0x59, 0x34, 0xad, 0x9b, 0xa4, 0xd7, 0xa5, 0xe4, 0x57, 0x07, 0x5d, 0xd1,
|
||||
0xc0, 0xba, 0x00, 0xaa, 0x20, 0x80, 0x27, 0x1d, 0x90, 0x0a, 0x7f, 0x5a, 0xea, 0x9b, 0xa9, 0xfa,
|
||||
0xa3, 0xff, 0x76, 0xa1, 0x82, 0xbc, 0xef, 0xb3, 0x0e, 0xbc, 0x8a, 0x2a, 0x1d, 0x2e, 0x41, 0xa8,
|
||||
0xac, 0x8f, 0xb3, 0x9d, 0xfe, 0x75, 0x42, 0x01, 0x0d, 0xb9, 0x93, 0xc4, 0x5d, 0xd3, 0x7e, 0x13,
|
||||
0x41, 0x01, 0x90, 0x27, 0x96, 0xe8, 0x2e, 0x6f, 0x9c, 0x17, 0xd1, 0xfa, 0x3f, 0xb3, 0x36, 0xa7,
|
||||
0x05, 0x1f, 0x83, 0x48, 0xa3, 0x10, 0xf0, 0x77, 0x0e, 0x1a, 0xdf, 0x8e, 0xa4, 0xc2, 0x2f, 0x95,
|
||||
0xaf, 0x74, 0x7e, 0x81, 0x6b, 0xdb, 0x67, 0xc5, 0x42, 0x27, 0x21, 0x37, 0xbe, 0xfe, 0xf3, 0xef,
|
||||
0x1f, 0x2e, 0x5c, 0xc5, 0xf3, 0xe6, 0x91, 0x48, 0x57, 0x8b, 0x59, 0x1c, 0x81, 0xfc, 0xe6, 0x82,
|
||||
0x83, 0xbf, 0x75, 0xd0, 0xd8, 0x43, 0x18, 0xca, 0xe6, 0xcc, 0x34, 0x21, 0x37, 0x0d, 0x93, 0xeb,
|
||||
0xf8, 0xda, 0x20, 0x26, 0xfe, 0x53, 0xbd, 0x7b, 0x86, 0x7f, 0x74, 0x50, 0x55, 0xf3, 0x0e, 0x4a,
|
||||
0xb6, 0xf3, 0x11, 0x6a, 0x61, 0x94, 0x50, 0xf8, 0x33, 0x34, 0x61, 0x69, 0xed, 0x0f, 0xa5, 0x53,
|
||||
0xed, 0x87, 0xf7, 0x25, 0x59, 0x36, 0x21, 0x09, 0x5e, 0x1a, 0x51, 0xb1, 0x2f, 0x74, 0xc8, 0xb6,
|
||||
0x0d, 0xaf, 0x1f, 0x00, 0xfc, 0xca, 0xd1, 0xf0, 0xf9, 0x2b, 0x59, 0x5b, 0x18, 0x64, 0xca, 0xef,
|
||||
0xe2, 0xa9, 0xd2, 0x51, 0x9d, 0xe2, 0x7b, 0x07, 0xcd, 0x3c, 0x04, 0x55, 0xbc, 0x84, 0xf8, 0xc6,
|
||||
0x80, 0xc8, 0xe5, 0x57, 0xb2, 0x46, 0x86, 0x3b, 0xe4, 0x04, 0xde, 0x36, 0x04, 0xde, 0x24, 0x77,
|
||||
0x07, 0x13, 0xb0, 0xcf, 0xa0, 0x89, 0xb3, 0x1b, 0x6c, 0x1b, 0x2a, 0x0d, 0x1b, 0xe1, 0xbe, 0xb3,
|
||||
0x82, 0x53, 0x43, 0xe9, 0x11, 0xc4, 0xed, 0xf5, 0x16, 0x15, 0x6a, 0xa8, 0xcc, 0x8b, 0x65, 0xb8,
|
||||
0x70, 0xcf, 0x49, 0x78, 0x86, 0xc4, 0x32, 0xbe, 0x3d, 0x4a, 0x85, 0x16, 0xc4, 0xed, 0xd0, 0xa6,
|
||||
0x79, 0xee, 0xa0, 0x8a, 0x9d, 0x5e, 0xf8, 0xfa, 0xd1, 0x8c, 0x7d, 0x53, 0xed, 0x0c, 0xaf, 0xc2,
|
||||
0xab, 0x86, 0xe3, 0x02, 0x19, 0xd8, 0x6b, 0xf7, 0xcd, 0xf0, 0xd0, 0x57, 0xf3, 0x27, 0x07, 0x55,
|
||||
0x7b, 0x14, 0x7a, 0x67, 0xcf, 0x8f, 0x24, 0x39, 0x99, 0x24, 0xfe, 0xc5, 0x41, 0x15, 0x3b, 0x51,
|
||||
0x8f, 0xf3, 0xea, 0x9b, 0xb4, 0x67, 0xc8, 0x6b, 0xd5, 0xfe, 0xc0, 0xb5, 0x11, 0x6d, 0x6e, 0xa8,
|
||||
0x3c, 0x2b, 0x84, 0xfc, 0xcd, 0x41, 0xd5, 0x1e, 0x9d, 0xe1, 0x42, 0xfe, 0x5f, 0x84, 0xbd, 0x17,
|
||||
0x23, 0x8c, 0x29, 0xaa, 0x6c, 0x40, 0x0c, 0x0a, 0x86, 0x5d, 0x01, 0xf7, 0x28, 0x9c, 0x37, 0xff,
|
||||
0x6d, 0x3b, 0x63, 0x57, 0x46, 0xcd, 0x58, 0x2d, 0x48, 0x0b, 0x55, 0x6d, 0x8a, 0x92, 0x1e, 0x2f,
|
||||
0x9c, 0xec, 0xe6, 0x29, 0x92, 0xe1, 0xa7, 0x68, 0xf6, 0x63, 0x1a, 0x47, 0x5a, 0x59, 0xfb, 0xcf,
|
||||
0x12, 0x5f, 0x3b, 0x36, 0x49, 0x8a, 0x7f, 0x9c, 0x23, 0xb2, 0xd5, 0x4d, 0xb6, 0x3b, 0xe4, 0xd6,
|
||||
0xa8, 0x7b, 0x9d, 0x66, 0xa9, 0xac, 0x92, 0x0f, 0x36, 0x7f, 0x3f, 0x5c, 0x74, 0xfe, 0x38, 0x5c,
|
||||
0x74, 0xfe, 0x3a, 0x5c, 0x74, 0x3e, 0x79, 0xeb, 0x74, 0x5f, 0x42, 0xa1, 0xf9, 0x6b, 0x58, 0xfa,
|
||||
0x66, 0xd9, 0xab, 0x98, 0x8f, 0x96, 0x37, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xa8, 0xce, 0xfa,
|
||||
0x47, 0xd3, 0x0d, 0x00, 0x00,
|
||||
// 1118 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xbc, 0x57, 0xcd, 0x6e, 0x1c, 0x45,
|
||||
0x10, 0xd6, 0xf8, 0x67, 0x6d, 0xb7, 0x7f, 0xb2, 0x69, 0x9b, 0x30, 0x6c, 0x1c, 0xc7, 0x9a, 0x84,
|
||||
0xc8, 0x58, 0x61, 0x26, 0x5e, 0x84, 0x88, 0x82, 0x40, 0x72, 0x6c, 0x2b, 0xb1, 0xb0, 0x70, 0x98,
|
||||
0xc8, 0x1c, 0x10, 0x08, 0xb5, 0x67, 0x6b, 0x77, 0x27, 0x9e, 0x9d, 0xee, 0x74, 0xf7, 0x0e, 0xac,
|
||||
0xa2, 0x5c, 0x38, 0x21, 0xc1, 0x05, 0x21, 0x24, 0x6e, 0x1c, 0x40, 0xe2, 0xc0, 0x0b, 0xf0, 0x08,
|
||||
0x1c, 0x91, 0x78, 0x01, 0x64, 0xf1, 0x1c, 0x08, 0x75, 0xf7, 0xec, 0xcc, 0xac, 0xf7, 0xc7, 0x8e,
|
||||
0x70, 0x7c, 0xeb, 0xfe, 0xaa, 0xb6, 0xea, 0xab, 0xaf, 0xab, 0xab, 0x77, 0x90, 0x23, 0x80, 0x27,
|
||||
0xc0, 0x3d, 0x0e, 0x8c, 0x8a, 0x50, 0x52, 0xde, 0x29, 0x2c, 0x5d, 0xc6, 0xa9, 0xa4, 0x18, 0xe5,
|
||||
0x48, 0x65, 0xa9, 0x41, 0x1b, 0x54, 0xc3, 0x9e, 0x5a, 0x19, 0x8f, 0xca, 0x72, 0x83, 0xd2, 0x46,
|
||||
0x04, 0x1e, 0x61, 0xa1, 0x47, 0xe2, 0x98, 0x4a, 0x22, 0x43, 0x1a, 0x8b, 0xd4, 0xea, 0x1c, 0xdd,
|
||||
0x15, 0x6e, 0x48, 0xb5, 0x35, 0xa0, 0x1c, 0xbc, 0x64, 0xc3, 0x6b, 0x40, 0x0c, 0x9c, 0x48, 0xa8,
|
||||
0xa5, 0x3e, 0x7b, 0x8d, 0x50, 0x36, 0xdb, 0x87, 0x6e, 0x40, 0x5b, 0x1e, 0xe1, 0x3a, 0xc5, 0x13,
|
||||
0xbd, 0x78, 0x33, 0xa8, 0x79, 0x49, 0xd5, 0x63, 0x47, 0x0d, 0xf5, 0x7b, 0xe1, 0x11, 0xc6, 0xa2,
|
||||
0x30, 0xd0, 0xf1, 0xbd, 0x64, 0x83, 0x44, 0xac, 0x49, 0xfa, 0xa3, 0xed, 0x9c, 0x12, 0x4d, 0x17,
|
||||
0x74, 0x6a, 0xe1, 0x4e, 0x07, 0xcd, 0xfb, 0xc0, 0xe8, 0x26, 0x63, 0xe2, 0xa3, 0x36, 0xf0, 0x0e,
|
||||
0xc6, 0x68, 0x42, 0x39, 0xd9, 0xd6, 0xaa, 0xb5, 0x36, 0xe3, 0xeb, 0x35, 0xae, 0xa0, 0x69, 0x0e,
|
||||
0x49, 0x28, 0x42, 0x1a, 0xdb, 0x63, 0x1a, 0xcf, 0xf6, 0xd8, 0x46, 0x53, 0x84, 0xb1, 0x0f, 0x49,
|
||||
0x0b, 0xec, 0x71, 0x6d, 0xea, 0x6e, 0xf1, 0x0a, 0x42, 0x84, 0xb1, 0x47, 0x9c, 0x3e, 0x81, 0x40,
|
||||
0xda, 0x13, 0xda, 0x58, 0x40, 0x9c, 0x0d, 0x34, 0xb5, 0xc9, 0xd8, 0x6e, 0x5c, 0xa7, 0x2a, 0xa9,
|
||||
0xec, 0x30, 0xe8, 0x26, 0x55, 0x6b, 0x85, 0x31, 0x22, 0x9b, 0x69, 0x42, 0xbd, 0x76, 0x7e, 0xb7,
|
||||
0xd0, 0x62, 0x4a, 0x77, 0x1b, 0x24, 0x09, 0xa3, 0x94, 0x74, 0x03, 0x95, 0x04, 0x6d, 0xf3, 0xc0,
|
||||
0x44, 0x98, 0xad, 0xee, 0xbb, 0xb9, 0x3a, 0x6e, 0x57, 0x1d, 0xbd, 0xf8, 0x3c, 0xa8, 0xb9, 0x49,
|
||||
0xd5, 0x65, 0x47, 0x0d, 0x57, 0x69, 0xed, 0x16, 0xb4, 0x76, 0xbb, 0x5a, 0xbb, 0x9b, 0x39, 0xf8,
|
||||
0x58, 0x87, 0xf5, 0xd3, 0xf0, 0xc5, 0x6a, 0xc7, 0x46, 0x55, 0x3b, 0xde, 0x57, 0xed, 0x7b, 0xa8,
|
||||
0xdc, 0x15, 0xda, 0x07, 0xc1, 0x68, 0x2c, 0x00, 0xbf, 0x81, 0x26, 0x43, 0x09, 0x2d, 0x61, 0x5b,
|
||||
0xab, 0xe3, 0x6b, 0xb3, 0xd5, 0x45, 0xb7, 0x70, 0x3c, 0xa9, 0x34, 0xbe, 0xf1, 0x70, 0xb6, 0xd0,
|
||||
0x8c, 0xfa, 0xf9, 0xf0, 0x33, 0x72, 0xd0, 0x5c, 0x9d, 0x2a, 0xaa, 0x50, 0xe7, 0x20, 0x8c, 0x6c,
|
||||
0xd3, 0x7e, 0x0f, 0xe6, 0xfc, 0x3c, 0x81, 0x2e, 0x69, 0x12, 0x41, 0x00, 0x62, 0xf4, 0x79, 0xb7,
|
||||
0x05, 0xf0, 0x38, 0x2f, 0x33, 0xdb, 0x2b, 0x1b, 0x23, 0x42, 0x7c, 0x41, 0x79, 0x2d, 0xad, 0x32,
|
||||
0xdb, 0xe3, 0x9b, 0x68, 0x5e, 0x88, 0xe6, 0x23, 0x1e, 0x26, 0x44, 0xc2, 0x07, 0xd0, 0x49, 0x0f,
|
||||
0xbd, 0x17, 0x54, 0x11, 0xc2, 0x58, 0x40, 0xd0, 0xe6, 0x60, 0x4f, 0x6a, 0x96, 0xd9, 0x1e, 0xdf,
|
||||
0x46, 0x97, 0x65, 0x24, 0xb6, 0xa2, 0x10, 0x62, 0xb9, 0x05, 0x5c, 0x6e, 0x13, 0x49, 0xec, 0x92,
|
||||
0x8e, 0xd2, 0x6f, 0xc0, 0xeb, 0xa8, 0xdc, 0x03, 0xaa, 0x94, 0x53, 0xda, 0xb9, 0x0f, 0xcf, 0x5a,
|
||||
0x6c, 0xa6, 0xb7, 0xc5, 0x74, 0x8d, 0xc8, 0x60, 0xba, 0xbe, 0x65, 0x34, 0x03, 0x31, 0x39, 0x8c,
|
||||
0x60, 0x3f, 0x08, 0xed, 0x59, 0x4d, 0x2f, 0x07, 0xf0, 0x1d, 0xb4, 0x68, 0x3a, 0x6b, 0x53, 0x9d,
|
||||
0x6c, 0x56, 0xe7, 0x9c, 0x0e, 0x30, 0xc8, 0x84, 0x57, 0xd1, 0x6c, 0x06, 0xef, 0x6e, 0xdb, 0xf3,
|
||||
0xab, 0xd6, 0xda, 0xb8, 0x5f, 0x84, 0xf0, 0x5d, 0xf4, 0x6a, 0xbe, 0x8d, 0x85, 0x24, 0x51, 0xa4,
|
||||
0x5b, 0x6f, 0x77, 0xdb, 0x5e, 0xd0, 0xde, 0xc3, 0xcc, 0xf8, 0x7d, 0x54, 0xc9, 0x4c, 0x3b, 0xb1,
|
||||
0x04, 0xce, 0x78, 0x28, 0xe0, 0x3e, 0x11, 0x70, 0xc0, 0x23, 0xfb, 0x92, 0x26, 0x35, 0xc2, 0x03,
|
||||
0x2f, 0xa1, 0x49, 0xc6, 0xe9, 0x97, 0x1d, 0xbb, 0xac, 0x5d, 0xcd, 0xc6, 0x59, 0x40, 0x73, 0xaa,
|
||||
0x49, 0xba, 0x5d, 0xea, 0xfc, 0x6a, 0xa1, 0xcb, 0x0a, 0xd8, 0xe2, 0x40, 0x24, 0xf8, 0xf0, 0xb4,
|
||||
0x0d, 0x42, 0xe2, 0x4f, 0x0b, 0x7d, 0x33, 0x5b, 0x7d, 0xf8, 0xff, 0x2e, 0x9c, 0x9f, 0xf5, 0x7d,
|
||||
0xda, 0x81, 0x57, 0x50, 0xa9, 0xcd, 0x04, 0x70, 0x99, 0xf6, 0x71, 0xba, 0x53, 0xa7, 0x13, 0x70,
|
||||
0xa8, 0x89, 0xfd, 0x38, 0xea, 0xe8, 0xf6, 0x9b, 0xf6, 0x73, 0xc0, 0x79, 0x6a, 0x88, 0x1e, 0xb0,
|
||||
0xda, 0x45, 0x11, 0xad, 0xfe, 0xbb, 0x60, 0x72, 0x1a, 0xf0, 0x31, 0xf0, 0x24, 0x0c, 0x00, 0x7f,
|
||||
0x6b, 0xa1, 0x89, 0xbd, 0x50, 0x48, 0xfc, 0x4a, 0xf1, 0x4a, 0x67, 0x17, 0xb8, 0xb2, 0x77, 0x5e,
|
||||
0x2c, 0x54, 0x12, 0xe7, 0xfa, 0x57, 0x7f, 0xfd, 0xf3, 0xfd, 0xd8, 0x15, 0xbc, 0xa4, 0x9f, 0x9f,
|
||||
0x64, 0x23, 0x9f, 0xf2, 0x21, 0x88, 0xaf, 0xc7, 0x2c, 0xfc, 0x8d, 0x85, 0xc6, 0x1f, 0xc0, 0x50,
|
||||
0x36, 0xe7, 0xa6, 0x89, 0x73, 0x43, 0x33, 0xb9, 0x86, 0xaf, 0x0e, 0x62, 0xe2, 0x3d, 0x53, 0xbb,
|
||||
0xe7, 0xf8, 0x07, 0x0b, 0x95, 0x15, 0x6f, 0xbf, 0x60, 0xbb, 0x18, 0xa1, 0x96, 0x47, 0x09, 0x85,
|
||||
0x3f, 0x43, 0xd3, 0x86, 0x56, 0x7d, 0x28, 0x9d, 0x72, 0x2f, 0x5c, 0x17, 0xce, 0x9a, 0x0e, 0xe9,
|
||||
0xe0, 0xd5, 0x11, 0x15, 0x7b, 0x5c, 0x85, 0x6c, 0x99, 0xf0, 0xea, 0x01, 0xc0, 0xaf, 0x9d, 0x0c,
|
||||
0x9f, 0xbd, 0xbf, 0x95, 0xe5, 0x41, 0xa6, 0xec, 0x2e, 0x9e, 0x29, 0x1d, 0x51, 0x29, 0xbe, 0xb3,
|
||||
0xd0, 0xfc, 0x03, 0x90, 0xf9, 0x4b, 0x89, 0xaf, 0x0f, 0x88, 0x5c, 0x7c, 0x45, 0x2b, 0xce, 0x70,
|
||||
0x87, 0x8c, 0xc0, 0xbb, 0x9a, 0xc0, 0xdb, 0xce, 0x9d, 0xc1, 0x04, 0xcc, 0x33, 0xa9, 0xe3, 0x1c,
|
||||
0xf8, 0x7b, 0x9a, 0x4a, 0xcd, 0x44, 0xb8, 0x67, 0xad, 0xe3, 0x44, 0x53, 0x7a, 0x08, 0x51, 0x6b,
|
||||
0xab, 0x49, 0xb8, 0x1c, 0x2a, 0xf3, 0x4a, 0x11, 0xce, 0xdd, 0x33, 0x12, 0xae, 0x26, 0xb1, 0x86,
|
||||
0x6f, 0x8d, 0x52, 0xa1, 0x09, 0x51, 0x2b, 0x30, 0x69, 0x7e, 0xb4, 0x50, 0xc9, 0x4c, 0x2f, 0x7c,
|
||||
0xed, 0x64, 0xc6, 0x9e, 0xa9, 0x76, 0x8e, 0x57, 0xe1, 0x75, 0xcd, 0x71, 0xd9, 0x19, 0xd8, 0x6b,
|
||||
0xf7, 0xf4, 0xf0, 0x50, 0x57, 0xf3, 0x27, 0x0b, 0x95, 0xbb, 0x14, 0xba, 0xbf, 0xbd, 0x38, 0x92,
|
||||
0xce, 0xe9, 0x24, 0xf1, 0x2f, 0x16, 0x2a, 0x99, 0x89, 0xda, 0xcf, 0xab, 0x67, 0xd2, 0x9e, 0x23,
|
||||
0xaf, 0x0d, 0x73, 0xc0, 0x95, 0x11, 0x6d, 0xae, 0xa9, 0x3c, 0xcf, 0x85, 0xfc, 0xcd, 0x42, 0xe5,
|
||||
0x2e, 0x9d, 0xe1, 0x42, 0xbe, 0x2c, 0xc2, 0xee, 0x8b, 0x11, 0xc6, 0x04, 0x95, 0xb6, 0x21, 0x02,
|
||||
0x09, 0xc3, 0xae, 0x80, 0x7d, 0x12, 0xce, 0x9a, 0xff, 0x96, 0x99, 0xb1, 0xeb, 0xa3, 0x66, 0xac,
|
||||
0x12, 0xa4, 0x89, 0xca, 0x26, 0x45, 0x41, 0x8f, 0x17, 0x4e, 0x76, 0xe3, 0x0c, 0xc9, 0xf0, 0x33,
|
||||
0xb4, 0xf0, 0x31, 0x89, 0x42, 0xa5, 0xac, 0xf9, 0x67, 0x89, 0xaf, 0xf6, 0x4d, 0x92, 0xfc, 0x1f,
|
||||
0xe7, 0x88, 0x6c, 0x55, 0x9d, 0xed, 0xb6, 0x73, 0x73, 0xd4, 0xbd, 0x4e, 0xd2, 0x54, 0x46, 0xc9,
|
||||
0xfb, 0x3b, 0x7f, 0x1c, 0xaf, 0x58, 0x7f, 0x1e, 0xaf, 0x58, 0x7f, 0x1f, 0xaf, 0x58, 0x9f, 0xbc,
|
||||
0x73, 0xb6, 0x6f, 0xac, 0x40, 0xff, 0x35, 0x2c, 0x7c, 0x0d, 0x1d, 0x96, 0xf4, 0xe7, 0xd0, 0x5b,
|
||||
0xff, 0x05, 0x00, 0x00, 0xff, 0xff, 0x6a, 0x9e, 0xe7, 0xda, 0x2d, 0x0e, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -1328,6 +1353,20 @@ func (m *RepoAppsQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.AppProject) > 0 {
|
||||
i -= len(m.AppProject)
|
||||
copy(dAtA[i:], m.AppProject)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppProject)))
|
||||
i--
|
||||
dAtA[i] = 0x22
|
||||
}
|
||||
if len(m.AppName) > 0 {
|
||||
i -= len(m.AppName)
|
||||
copy(dAtA[i:], m.AppName)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppName)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.Revision) > 0 {
|
||||
i -= len(m.Revision)
|
||||
copy(dAtA[i:], m.Revision)
|
||||
@@ -1410,6 +1449,13 @@ func (m *RepoAppDetailsQuery) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if len(m.AppProject) > 0 {
|
||||
i -= len(m.AppProject)
|
||||
copy(dAtA[i:], m.AppProject)
|
||||
i = encodeVarintRepository(dAtA, i, uint64(len(m.AppProject)))
|
||||
i--
|
||||
dAtA[i] = 0x1a
|
||||
}
|
||||
if len(m.AppName) > 0 {
|
||||
i -= len(m.AppName)
|
||||
copy(dAtA[i:], m.AppName)
|
||||
@@ -1803,6 +1849,14 @@ func (m *RepoAppsQuery) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AppName)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AppProject)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@@ -1843,6 +1897,10 @@ func (m *RepoAppDetailsQuery) Size() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
l = len(m.AppProject)
|
||||
if l > 0 {
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@@ -2103,6 +2161,70 @@ func (m *RepoAppsQuery) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
m.Revision = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AppName", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AppName = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 4:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AppProject", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AppProject = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
@@ -2337,6 +2459,38 @@ func (m *RepoAppDetailsQuery) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
m.AppName = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 3:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field AppProject", wireType)
|
||||
}
|
||||
var stringLen uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLen |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLen := int(stringLen)
|
||||
if intStringLen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + intStringLen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.AppProject = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
|
||||
@@ -27,6 +27,7 @@ API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/ap
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,Command,Args
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,Command,Command
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ExecProviderConfig,Args
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,HelmOptions,ValuesFileSchemes
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,HostInfo,ResourcesInfo
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,JWTTokens,Items
|
||||
API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,Operation,Info
|
||||
@@ -61,6 +62,7 @@ API rule violation: list_type_missing,github.com/argoproj/argo-cd/v2/pkg/apis/ap
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ApplicationSourceJsonnet,TLAs
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ClusterCacheInfo,APIsCount
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,ConnectionState,ModifiedAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,HelmOptions,ValuesFileSchemes
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,JWTToken,ExpiresAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,JWTToken,IssuedAt
|
||||
API rule violation: names_match,github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1,KustomizeOptions,BinaryPath
|
||||
|
||||
@@ -313,11 +313,15 @@ func (proj AppProject) IsGroupKindPermitted(gk schema.GroupKind, namespaced bool
|
||||
|
||||
// IsLiveResourcePermitted returns whether a live resource found in the cluster is permitted by an AppProject
|
||||
func (proj AppProject) IsLiveResourcePermitted(un *unstructured.Unstructured, server string) bool {
|
||||
if !proj.IsGroupKindPermitted(un.GroupVersionKind().GroupKind(), un.GetNamespace() != "") {
|
||||
return proj.IsResourcePermitted(un.GroupVersionKind().GroupKind(), un.GetNamespace(), ApplicationDestination{Server: server})
|
||||
}
|
||||
|
||||
func (proj AppProject) IsResourcePermitted(groupKind schema.GroupKind, namespace string, dest ApplicationDestination) bool {
|
||||
if !proj.IsGroupKindPermitted(groupKind, namespace != "") {
|
||||
return false
|
||||
}
|
||||
if un.GetNamespace() != "" {
|
||||
return proj.IsDestinationPermitted(ApplicationDestination{Server: server, Namespace: un.GetNamespace()})
|
||||
if namespace != "" {
|
||||
return proj.IsDestinationPermitted(ApplicationDestination{Server: dest.Server, Name: dest.Name, Namespace: namespace})
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -36,12 +36,12 @@ var (
|
||||
|
||||
func init() {
|
||||
if envQPS := os.Getenv(EnvK8sClientQPS); envQPS != "" {
|
||||
if qps, err := strconv.ParseFloat(envQPS, 32); err != nil {
|
||||
if qps, err := strconv.ParseFloat(envQPS, 32); err == nil {
|
||||
K8sClientConfigQPS = float32(qps)
|
||||
}
|
||||
}
|
||||
if envBurst := os.Getenv(EnvK8sClientBurst); envBurst != "" {
|
||||
if burst, err := strconv.Atoi(envBurst); err != nil {
|
||||
if burst, err := strconv.Atoi(envBurst); err == nil {
|
||||
K8sClientConfigBurst = burst
|
||||
}
|
||||
} else {
|
||||
@@ -49,7 +49,7 @@ func init() {
|
||||
}
|
||||
|
||||
if envMaxConn := os.Getenv(EnvK8sClientMaxIdleConnections); envMaxConn != "" {
|
||||
if maxConn, err := strconv.Atoi(envMaxConn); err != nil {
|
||||
if maxConn, err := strconv.Atoi(envMaxConn); err == nil {
|
||||
K8sMaxIdleConnections = maxConn
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -588,6 +588,11 @@ message HelmFileParameter {
|
||||
optional string path = 2;
|
||||
}
|
||||
|
||||
// HelmOptions holds helm options
|
||||
message HelmOptions {
|
||||
repeated string valuesFileSchemes = 1;
|
||||
}
|
||||
|
||||
// HelmParameter is a parameter that's passed to helm template during manifest generation
|
||||
message HelmParameter {
|
||||
// Name is the name of the Helm parameter
|
||||
|
||||
@@ -51,6 +51,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.GnuPGPublicKeyList": schema_pkg_apis_application_v1alpha1_GnuPGPublicKeyList(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HealthStatus": schema_pkg_apis_application_v1alpha1_HealthStatus(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmFileParameter": schema_pkg_apis_application_v1alpha1_HelmFileParameter(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmOptions": schema_pkg_apis_application_v1alpha1_HelmOptions(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HelmParameter": schema_pkg_apis_application_v1alpha1_HelmParameter(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostInfo": schema_pkg_apis_application_v1alpha1_HostInfo(ref),
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1.HostResourceInfo": schema_pkg_apis_application_v1alpha1_HostResourceInfo(ref),
|
||||
@@ -2052,6 +2053,34 @@ func schema_pkg_apis_application_v1alpha1_HelmFileParameter(ref common.Reference
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_application_v1alpha1_HelmOptions(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "HelmOptions holds helm options",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"ValuesFileSchemes": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"ValuesFileSchemes"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_application_v1alpha1_HelmParameter(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
||||
@@ -1997,6 +1997,11 @@ type ConfigManagementPlugin struct {
|
||||
Generate Command `json:"generate" protobuf:"bytes,3,name=generate"`
|
||||
}
|
||||
|
||||
// HelmOptions holds helm options
|
||||
type HelmOptions struct {
|
||||
ValuesFileSchemes []string `protobuf:"bytes,1,opt,name=valuesFileSchemes"`
|
||||
}
|
||||
|
||||
// KustomizeOptions are options for kustomize to use when building manifests
|
||||
type KustomizeOptions struct {
|
||||
// BuildOptions is a string of build parameters to use when calling `kustomize build`
|
||||
|
||||
@@ -1052,6 +1052,27 @@ func (in *HelmFileParameter) DeepCopy() *HelmFileParameter {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmOptions) DeepCopyInto(out *HelmOptions) {
|
||||
*out = *in
|
||||
if in.ValuesFileSchemes != nil {
|
||||
in, out := &in.ValuesFileSchemes, &out.ValuesFileSchemes
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HelmOptions.
|
||||
func (in *HelmOptions) DeepCopy() *HelmOptions {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(HelmOptions)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *HelmParameter) DeepCopyInto(out *HelmParameter) {
|
||||
*out = *in
|
||||
|
||||
15
reposerver/apiclient/repository.go
Normal file
15
reposerver/apiclient/repository.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package apiclient
|
||||
|
||||
func (q *ManifestRequest) GetValuesFileSchemes() []string {
|
||||
if q.HelmOptions == nil {
|
||||
return nil
|
||||
}
|
||||
return q.HelmOptions.ValuesFileSchemes
|
||||
}
|
||||
|
||||
func (q *RepoServerAppDetailsQuery) GetValuesFileSchemes() []string {
|
||||
if q.HelmOptions == nil {
|
||||
return nil
|
||||
}
|
||||
return q.HelmOptions.ValuesFileSchemes
|
||||
}
|
||||
@@ -50,6 +50,7 @@ type ManifestRequest struct {
|
||||
VerifySignature bool `protobuf:"varint,16,opt,name=verifySignature,proto3" json:"verifySignature,omitempty"`
|
||||
HelmRepoCreds []*v1alpha1.RepoCreds `protobuf:"bytes,17,rep,name=helmRepoCreds,proto3" json:"helmRepoCreds,omitempty"`
|
||||
NoRevisionCache bool `protobuf:"varint,18,opt,name=noRevisionCache,proto3" json:"noRevisionCache,omitempty"`
|
||||
HelmOptions *v1alpha1.HelmOptions `protobuf:"bytes,21,opt,name=helmOptions,proto3" json:"helmOptions,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@@ -193,6 +194,13 @@ func (m *ManifestRequest) GetNoRevisionCache() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *ManifestRequest) GetHelmOptions() *v1alpha1.HelmOptions {
|
||||
if m != nil {
|
||||
return m.HelmOptions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestRepositoryRequest is a query to test repository is valid or not and has valid access.
|
||||
type TestRepositoryRequest struct {
|
||||
Repo *v1alpha1.Repository `protobuf:"bytes,1,opt,name=repo,proto3" json:"repo,omitempty"`
|
||||
@@ -594,6 +602,8 @@ type RepoServerAppDetailsQuery struct {
|
||||
KustomizeOptions *v1alpha1.KustomizeOptions `protobuf:"bytes,4,opt,name=kustomizeOptions,proto3" json:"kustomizeOptions,omitempty"`
|
||||
AppName string `protobuf:"bytes,5,opt,name=appName,proto3" json:"appName,omitempty"`
|
||||
NoCache bool `protobuf:"varint,6,opt,name=noCache,proto3" json:"noCache,omitempty"`
|
||||
NoRevisionCache bool `protobuf:"varint,7,opt,name=noRevisionCache,proto3" json:"noRevisionCache,omitempty"`
|
||||
HelmOptions *v1alpha1.HelmOptions `protobuf:"bytes,10,opt,name=helmOptions,proto3" json:"helmOptions,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
@@ -674,6 +684,20 @@ func (m *RepoServerAppDetailsQuery) GetNoCache() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *RepoServerAppDetailsQuery) GetNoRevisionCache() bool {
|
||||
if m != nil {
|
||||
return m.NoRevisionCache
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *RepoServerAppDetailsQuery) GetHelmOptions() *v1alpha1.HelmOptions {
|
||||
if m != nil {
|
||||
return m.HelmOptions
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RepoAppDetailsResponse application details
|
||||
type RepoAppDetailsResponse struct {
|
||||
Type string `protobuf:"bytes,1,opt,name=type,proto3" json:"type,omitempty"`
|
||||
@@ -1359,94 +1383,96 @@ func init() {
|
||||
}
|
||||
|
||||
var fileDescriptor_dd8723cfcc820480 = []byte{
|
||||
// 1392 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x18, 0xcb, 0x6e, 0xdb, 0xc6,
|
||||
0xd6, 0x94, 0xe4, 0x87, 0x8e, 0x12, 0x5b, 0x9e, 0x3c, 0x2e, 0xaf, 0xae, 0x23, 0x38, 0x04, 0x6e,
|
||||
0xe0, 0x36, 0x0d, 0x85, 0x28, 0x41, 0x1b, 0x24, 0x40, 0x01, 0xd5, 0x49, 0x1c, 0xc0, 0x49, 0xec,
|
||||
0xd2, 0x69, 0x81, 0x16, 0x41, 0x83, 0x31, 0x75, 0x4c, 0x4d, 0x25, 0x91, 0x13, 0x92, 0x52, 0xe1,
|
||||
0x00, 0x5d, 0x16, 0x5d, 0x74, 0xdd, 0xfe, 0x4e, 0x57, 0x7d, 0x2c, 0xdb, 0x3f, 0x28, 0xf2, 0x09,
|
||||
0xfd, 0x82, 0x62, 0x86, 0xaf, 0x21, 0x45, 0xbb, 0x0b, 0x25, 0xce, 0xc6, 0x9e, 0x39, 0xef, 0x73,
|
||||
0xe6, 0xbc, 0x28, 0xb8, 0xe6, 0x23, 0xf7, 0x02, 0xf4, 0xa7, 0xe8, 0x77, 0xe4, 0x91, 0x85, 0x9e,
|
||||
0x7f, 0xac, 0x1c, 0x4d, 0xee, 0x7b, 0xa1, 0x47, 0x20, 0x83, 0xb4, 0x2e, 0x3a, 0x9e, 0xe3, 0x49,
|
||||
0x70, 0x47, 0x9c, 0x22, 0x8a, 0xd6, 0x86, 0xe3, 0x79, 0xce, 0x08, 0x3b, 0x94, 0xb3, 0x0e, 0x75,
|
||||
0x5d, 0x2f, 0xa4, 0x21, 0xf3, 0xdc, 0x20, 0xc6, 0x1a, 0xc3, 0x3b, 0x81, 0xc9, 0x3c, 0x89, 0xb5,
|
||||
0x3d, 0x1f, 0x3b, 0xd3, 0x9b, 0x1d, 0x07, 0x5d, 0xf4, 0x69, 0x88, 0xfd, 0x98, 0xe6, 0xb1, 0xc3,
|
||||
0xc2, 0xc1, 0xe4, 0xd0, 0xb4, 0xbd, 0x71, 0x87, 0xfa, 0x52, 0xc5, 0xd7, 0xf2, 0x70, 0xc3, 0xee,
|
||||
0x77, 0xa6, 0xdd, 0x0e, 0x1f, 0x3a, 0x82, 0x3f, 0xe8, 0x50, 0xce, 0x47, 0xcc, 0x96, 0xf2, 0x3b,
|
||||
0xd3, 0x9b, 0x74, 0xc4, 0x07, 0x74, 0x46, 0x9a, 0xf1, 0xe7, 0x32, 0xac, 0x3d, 0xa1, 0x2e, 0x3b,
|
||||
0xc2, 0x20, 0xb4, 0xf0, 0xe5, 0x04, 0x83, 0x90, 0x3c, 0x87, 0x9a, 0xf0, 0x43, 0xd7, 0x36, 0xb5,
|
||||
0xad, 0x46, 0xf7, 0x91, 0x99, 0x29, 0x34, 0x13, 0x85, 0xf2, 0xf0, 0xc2, 0xee, 0x9b, 0xd3, 0xae,
|
||||
0xc9, 0x87, 0x8e, 0x29, 0x14, 0x9a, 0x8a, 0x42, 0x33, 0x51, 0x68, 0x5a, 0x69, 0x44, 0x2c, 0x29,
|
||||
0x95, 0xb4, 0x60, 0xc5, 0xc7, 0x29, 0x0b, 0x98, 0xe7, 0xea, 0x95, 0x4d, 0x6d, 0xab, 0x6e, 0xa5,
|
||||
0x77, 0xa2, 0xc3, 0xb2, 0xeb, 0x6d, 0x53, 0x7b, 0x80, 0x7a, 0x75, 0x53, 0xdb, 0x5a, 0xb1, 0x92,
|
||||
0x2b, 0xd9, 0x84, 0x06, 0xe5, 0xfc, 0x31, 0x3d, 0xc4, 0xd1, 0x2e, 0x1e, 0xeb, 0x35, 0xc9, 0xa8,
|
||||
0x82, 0x04, 0x2f, 0xe5, 0xfc, 0x29, 0x1d, 0xa3, 0xbe, 0x28, 0xb1, 0xc9, 0x95, 0x6c, 0x40, 0xdd,
|
||||
0xa5, 0x63, 0x0c, 0x38, 0xb5, 0x51, 0x5f, 0x91, 0xb8, 0x0c, 0x40, 0xbe, 0x85, 0x75, 0xc5, 0xf0,
|
||||
0x03, 0x6f, 0xe2, 0xdb, 0xa8, 0x83, 0x74, 0x7d, 0x6f, 0x3e, 0xd7, 0x7b, 0x45, 0xb1, 0xd6, 0xac,
|
||||
0x26, 0xf2, 0x15, 0x2c, 0xca, 0xa4, 0xd1, 0x1b, 0x9b, 0xd5, 0x37, 0x1a, 0xed, 0x48, 0x2c, 0x71,
|
||||
0x61, 0x99, 0x8f, 0x26, 0x0e, 0x73, 0x03, 0xfd, 0x9c, 0xd4, 0xf0, 0x6c, 0x3e, 0x0d, 0xdb, 0x9e,
|
||||
0x7b, 0xc4, 0x9c, 0x27, 0xd4, 0xa5, 0x0e, 0x8e, 0xd1, 0x0d, 0xf7, 0xa5, 0x70, 0x2b, 0x51, 0x42,
|
||||
0x5e, 0x41, 0x73, 0x38, 0x09, 0x42, 0x6f, 0xcc, 0x5e, 0xe1, 0x1e, 0x97, 0xc9, 0xad, 0x9f, 0x97,
|
||||
0xd1, 0x7c, 0x3a, 0x9f, 0xe2, 0xdd, 0x82, 0x54, 0x6b, 0x46, 0x8f, 0x48, 0x92, 0xe1, 0xe4, 0x10,
|
||||
0x3f, 0x47, 0x5f, 0x66, 0xd7, 0x6a, 0x94, 0x24, 0x0a, 0x28, 0x4a, 0x23, 0x16, 0xdf, 0x02, 0x7d,
|
||||
0x6d, 0xb3, 0x1a, 0xa5, 0x51, 0x0a, 0x22, 0x5b, 0xb0, 0x36, 0x45, 0x9f, 0x1d, 0x1d, 0x1f, 0x30,
|
||||
0xc7, 0xa5, 0xe1, 0xc4, 0x47, 0xbd, 0x29, 0x53, 0xb1, 0x08, 0x26, 0x63, 0x38, 0x3f, 0xc0, 0xd1,
|
||||
0x58, 0x84, 0x7c, 0xdb, 0xc7, 0x7e, 0xa0, 0xaf, 0xcb, 0xf8, 0xee, 0xcc, 0xff, 0x82, 0x52, 0x9c,
|
||||
0x95, 0x97, 0x2e, 0x0c, 0x73, 0x3d, 0x2b, 0xae, 0x94, 0xa8, 0x46, 0x48, 0x64, 0x58, 0x01, 0x6c,
|
||||
0x4c, 0xe0, 0xd2, 0x33, 0x59, 0xce, 0x69, 0x2e, 0x9c, 0x45, 0x61, 0x1b, 0x8f, 0xe0, 0x72, 0x51,
|
||||
0x6d, 0xc0, 0x3d, 0x37, 0x40, 0x62, 0x02, 0x91, 0xc1, 0x63, 0xd8, 0xcf, 0xb0, 0xd2, 0x8a, 0x15,
|
||||
0xab, 0x04, 0x63, 0xfc, 0xaa, 0x41, 0x33, 0x6b, 0x4a, 0xb1, 0x90, 0x0d, 0xa8, 0x8f, 0x63, 0x58,
|
||||
0xa0, 0x6b, 0xf2, 0xe1, 0x32, 0x40, 0xbe, 0xc6, 0x2b, 0xc5, 0x1a, 0xbf, 0x0c, 0x4b, 0x51, 0xf7,
|
||||
0x96, 0x6d, 0xa5, 0x6e, 0xc5, 0xb7, 0x5c, 0x2f, 0xaa, 0x15, 0x7a, 0x51, 0x1b, 0x20, 0x90, 0x25,
|
||||
0xfa, 0xec, 0x98, 0xa3, 0xbe, 0x24, 0xb1, 0x0a, 0x84, 0x18, 0x70, 0x2e, 0xca, 0x08, 0x0b, 0x83,
|
||||
0xc9, 0x28, 0xd4, 0x97, 0x25, 0x45, 0x0e, 0x66, 0x78, 0xb0, 0xf6, 0x98, 0x09, 0x1f, 0x8e, 0x82,
|
||||
0xb3, 0x79, 0x83, 0x0f, 0xa1, 0x26, 0x94, 0x09, 0xc7, 0x0e, 0x7d, 0xea, 0xda, 0x03, 0x4c, 0x62,
|
||||
0x95, 0xde, 0x09, 0x81, 0x5a, 0x48, 0x9d, 0x40, 0xaf, 0x48, 0xb8, 0x3c, 0x1b, 0x3f, 0x68, 0x91,
|
||||
0xa5, 0x3d, 0xce, 0x83, 0x77, 0x3e, 0x06, 0x8c, 0x09, 0x2c, 0xf7, 0x38, 0x17, 0xf6, 0x90, 0x9b,
|
||||
0x50, 0xa3, 0x9c, 0x47, 0x4e, 0x34, 0xba, 0x57, 0x4c, 0x65, 0xe4, 0xc6, 0x24, 0xe2, 0x7f, 0xf0,
|
||||
0xc0, 0x0d, 0x85, 0x64, 0x41, 0xda, 0xfa, 0x08, 0xea, 0x29, 0x88, 0x34, 0xa1, 0x3a, 0xc4, 0x28,
|
||||
0xd7, 0xea, 0x96, 0x38, 0x92, 0x8b, 0xb0, 0x38, 0xa5, 0xa3, 0x49, 0x92, 0x25, 0xd1, 0xe5, 0x6e,
|
||||
0xe5, 0x8e, 0x66, 0xfc, 0x5d, 0x85, 0xff, 0x0a, 0x3b, 0x0f, 0x64, 0x72, 0xf4, 0x38, 0xbf, 0x8f,
|
||||
0x21, 0x65, 0xa3, 0xe0, 0xd3, 0x09, 0xfa, 0xc7, 0x6f, 0x39, 0x1c, 0x0e, 0x2c, 0x45, 0xb9, 0x25,
|
||||
0xcd, 0x7a, 0x0b, 0xa3, 0x27, 0x16, 0x9f, 0xcd, 0x9b, 0xea, 0xdb, 0x99, 0x37, 0x65, 0xfd, 0xbf,
|
||||
0x76, 0x46, 0xfd, 0xff, 0xe4, 0x15, 0x40, 0x59, 0x2c, 0x96, 0x72, 0x8b, 0x85, 0xf1, 0x7d, 0x05,
|
||||
0x2e, 0x0b, 0x2f, 0xb2, 0xe7, 0x4e, 0x3b, 0x8e, 0x28, 0x14, 0x51, 0xfb, 0x51, 0xf2, 0xc8, 0x33,
|
||||
0xb9, 0x0d, 0xcb, 0xc3, 0xc0, 0x73, 0x5d, 0x0c, 0xe3, 0x87, 0x6a, 0xa9, 0x29, 0xb9, 0x1b, 0xa1,
|
||||
0x7a, 0x9c, 0x1f, 0x70, 0xb4, 0xad, 0x84, 0x94, 0x5c, 0x87, 0x9a, 0x68, 0xe6, 0xb2, 0xfb, 0x34,
|
||||
0xba, 0xff, 0x51, 0x59, 0x1e, 0xe1, 0x68, 0x9c, 0xd0, 0x4b, 0x22, 0x72, 0x17, 0xea, 0xa9, 0x67,
|
||||
0x71, 0xe8, 0x36, 0x72, 0x4a, 0x12, 0x64, 0xc2, 0x96, 0x91, 0x0b, 0xde, 0x3e, 0xf3, 0xd1, 0x96,
|
||||
0x0d, 0x76, 0x71, 0x96, 0xf7, 0x7e, 0x82, 0x4c, 0x79, 0x53, 0x72, 0xe3, 0x17, 0x0d, 0xae, 0x66,
|
||||
0xe9, 0x9f, 0x8c, 0x94, 0x27, 0x18, 0xd2, 0x3e, 0x0d, 0xe9, 0xbb, 0x5f, 0x0e, 0xaf, 0xc1, 0xaa,
|
||||
0x3d, 0x40, 0x7b, 0x98, 0x0d, 0xe6, 0x68, 0x47, 0x2c, 0x40, 0x8d, 0xdf, 0x2a, 0xb0, 0x9a, 0x7f,
|
||||
0x08, 0xf1, 0x92, 0x62, 0x18, 0x24, 0x2f, 0x29, 0xce, 0x64, 0x1f, 0xce, 0xa1, 0x3b, 0x65, 0xbe,
|
||||
0xe7, 0x8a, 0x35, 0x26, 0xa9, 0x87, 0x0f, 0x4e, 0x7e, 0x4e, 0xf3, 0x81, 0x42, 0x1e, 0x35, 0x9c,
|
||||
0x9c, 0x04, 0xe2, 0x02, 0x70, 0xea, 0xd3, 0x31, 0x86, 0xe8, 0x8b, 0xa4, 0xaf, 0xbe, 0x81, 0xa4,
|
||||
0x8f, 0x2c, 0xd8, 0x4f, 0xc4, 0x5a, 0x8a, 0x86, 0xd6, 0x0b, 0x58, 0x9f, 0x31, 0xa9, 0xa4, 0xe1,
|
||||
0xdd, 0x56, 0x1b, 0x5e, 0xa3, 0xdb, 0x2e, 0xf1, 0x50, 0x11, 0xa3, 0x36, 0xc4, 0x9f, 0x2b, 0xd0,
|
||||
0x50, 0xf2, 0xb3, 0x34, 0x8c, 0x6d, 0x00, 0xc9, 0xf0, 0x90, 0x8d, 0x30, 0x0a, 0x62, 0xdd, 0x52,
|
||||
0x20, 0x64, 0x58, 0x12, 0x94, 0xdd, 0xf9, 0x82, 0x22, 0x4c, 0x2a, 0x8d, 0x88, 0x98, 0xf3, 0x52,
|
||||
0x75, 0x10, 0xd7, 0x7f, 0x7c, 0x23, 0xdf, 0xc0, 0xea, 0x11, 0x1b, 0xe1, 0x7e, 0x66, 0xc8, 0x92,
|
||||
0x34, 0x64, 0x6f, 0x7e, 0x43, 0x1e, 0xaa, 0x72, 0xad, 0x82, 0x1a, 0xe3, 0x7d, 0x68, 0x16, 0xcb,
|
||||
0x55, 0x18, 0xc9, 0xc6, 0xd4, 0x49, 0xa3, 0x15, 0xdf, 0x8c, 0x1f, 0x35, 0x20, 0xb3, 0xef, 0x71,
|
||||
0x52, 0xd0, 0x87, 0x77, 0x82, 0x64, 0xcf, 0x8d, 0x0a, 0x45, 0x81, 0x90, 0x5d, 0x68, 0xf4, 0x31,
|
||||
0x08, 0x99, 0x2b, 0x0d, 0x8e, 0x9b, 0xc8, 0x7b, 0xa7, 0x3f, 0xfc, 0xfd, 0x8c, 0xc1, 0x52, 0xb9,
|
||||
0x8d, 0xcf, 0xe0, 0xca, 0xa9, 0xd4, 0xca, 0x76, 0xa5, 0xe5, 0xb6, 0xab, 0x53, 0x77, 0x32, 0x83,
|
||||
0x40, 0xb3, 0xd8, 0x8d, 0x8c, 0x97, 0xb0, 0x2e, 0x62, 0xba, 0x3d, 0xa0, 0x7e, 0x78, 0x46, 0x1b,
|
||||
0xd3, 0x3d, 0xa8, 0xa7, 0x2a, 0x4b, 0x63, 0xdd, 0x82, 0x95, 0x69, 0xf2, 0xbd, 0x10, 0xad, 0x4c,
|
||||
0xe9, 0xdd, 0xe8, 0x01, 0x51, 0xed, 0x8d, 0xe7, 0xc6, 0x75, 0x58, 0x64, 0x21, 0x8e, 0x93, 0xa5,
|
||||
0xe5, 0x52, 0xb1, 0xdd, 0x4b, 0x72, 0x2b, 0xa2, 0xe9, 0x7e, 0xb7, 0x08, 0xeb, 0x59, 0xd7, 0x15,
|
||||
0x7f, 0x99, 0x8d, 0x64, 0x0f, 0x9a, 0x3b, 0xf1, 0x97, 0x7a, 0xb2, 0x08, 0x93, 0xff, 0xa9, 0x72,
|
||||
0x0a, 0xdf, 0xec, 0xad, 0x8d, 0x72, 0x64, 0x64, 0x91, 0xb1, 0x40, 0xbe, 0x80, 0xd5, 0xfc, 0x72,
|
||||
0x4e, 0xae, 0xaa, 0x1c, 0xa5, 0xdf, 0x0b, 0x2d, 0xe3, 0x34, 0x92, 0x54, 0xf4, 0x3d, 0x58, 0x49,
|
||||
0x96, 0xdc, 0xbc, 0x8d, 0x85, 0xd5, 0xb7, 0xd5, 0x54, 0x91, 0x02, 0x61, 0x2c, 0x90, 0x8f, 0x23,
|
||||
0x66, 0xb1, 0xb0, 0xcd, 0x32, 0x2b, 0xdb, 0x68, 0xeb, 0x42, 0xc9, 0xea, 0x67, 0x2c, 0x90, 0xe7,
|
||||
0x70, 0x7e, 0x47, 0x76, 0xe8, 0x78, 0x78, 0x93, 0xff, 0xe7, 0x95, 0x9c, 0xb0, 0xcd, 0xe5, 0x5d,
|
||||
0x2b, 0x9f, 0xff, 0xc6, 0x02, 0xf9, 0x49, 0x83, 0x0b, 0x3b, 0x18, 0x16, 0x67, 0x21, 0xb9, 0x51,
|
||||
0xae, 0xe4, 0x84, 0x99, 0xd9, 0x7a, 0x3a, 0x6f, 0xce, 0xe6, 0xc5, 0x1a, 0x0b, 0x64, 0x5f, 0xba,
|
||||
0x9d, 0xe5, 0x1e, 0xb9, 0x52, 0x9a, 0x64, 0x69, 0xf4, 0xda, 0x27, 0xa1, 0x13, 0x57, 0x3f, 0xe9,
|
||||
0xfd, 0xfe, 0xba, 0xad, 0xfd, 0xf1, 0xba, 0xad, 0xfd, 0xf5, 0xba, 0xad, 0x7d, 0x79, 0xeb, 0x5f,
|
||||
0x7e, 0x64, 0x52, 0x7e, 0x0f, 0xa3, 0x9c, 0xd9, 0x23, 0x86, 0x6e, 0x78, 0xb8, 0x24, 0x7f, 0x52,
|
||||
0xba, 0xf5, 0x4f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf6, 0x7e, 0x8e, 0xd3, 0x2e, 0x13, 0x00, 0x00,
|
||||
// 1417 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xc4, 0x58, 0x5b, 0x6f, 0x1b, 0x45,
|
||||
0x14, 0xce, 0x3a, 0x76, 0x62, 0x1f, 0xb7, 0x89, 0x33, 0xbd, 0xb0, 0x98, 0xd4, 0x4a, 0x57, 0xa2,
|
||||
0x0a, 0x94, 0xae, 0x55, 0xb7, 0x82, 0xaa, 0x95, 0x90, 0x4c, 0xda, 0xa6, 0x28, 0x6d, 0x13, 0x36,
|
||||
0x05, 0x09, 0x54, 0x51, 0x4d, 0xd6, 0x93, 0xf5, 0x60, 0x7b, 0x77, 0xba, 0xb3, 0x36, 0x4a, 0x25,
|
||||
0x1e, 0x11, 0x42, 0x3c, 0xc3, 0xcf, 0x81, 0x27, 0x2e, 0x8f, 0xfc, 0x04, 0x94, 0x5f, 0x82, 0x66,
|
||||
0xf6, 0x36, 0xbb, 0x5e, 0x07, 0x24, 0x37, 0xe9, 0x4b, 0x32, 0x73, 0xee, 0x73, 0xe6, 0xcc, 0x77,
|
||||
0x8e, 0x17, 0xae, 0xf9, 0x84, 0x79, 0x9c, 0xf8, 0x13, 0xe2, 0xb7, 0xe5, 0x92, 0x06, 0x9e, 0x7f,
|
||||
0xa4, 0x2c, 0x4d, 0xe6, 0x7b, 0x81, 0x87, 0x20, 0xa5, 0x34, 0x2f, 0x3a, 0x9e, 0xe3, 0x49, 0x72,
|
||||
0x5b, 0xac, 0x42, 0x89, 0xe6, 0xba, 0xe3, 0x79, 0xce, 0x90, 0xb4, 0x31, 0xa3, 0x6d, 0xec, 0xba,
|
||||
0x5e, 0x80, 0x03, 0xea, 0xb9, 0x3c, 0xe2, 0x1a, 0x83, 0x3b, 0xdc, 0xa4, 0x9e, 0xe4, 0xda, 0x9e,
|
||||
0x4f, 0xda, 0x93, 0x9b, 0x6d, 0x87, 0xb8, 0xc4, 0xc7, 0x01, 0xe9, 0x45, 0x32, 0x8f, 0x1d, 0x1a,
|
||||
0xf4, 0xc7, 0x07, 0xa6, 0xed, 0x8d, 0xda, 0xd8, 0x97, 0x2e, 0xbe, 0x91, 0x8b, 0x1b, 0x76, 0xaf,
|
||||
0x3d, 0xe9, 0xb4, 0xd9, 0xc0, 0x11, 0xfa, 0xbc, 0x8d, 0x19, 0x1b, 0x52, 0x5b, 0xda, 0x6f, 0x4f,
|
||||
0x6e, 0xe2, 0x21, 0xeb, 0xe3, 0x29, 0x6b, 0xc6, 0xaf, 0x55, 0x58, 0x7d, 0x82, 0x5d, 0x7a, 0x48,
|
||||
0x78, 0x60, 0x91, 0x97, 0x63, 0xc2, 0x03, 0xf4, 0x1c, 0xca, 0xe2, 0x1c, 0xba, 0xb6, 0xa1, 0x6d,
|
||||
0xd6, 0x3b, 0x8f, 0xcc, 0xd4, 0xa1, 0x19, 0x3b, 0x94, 0x8b, 0x17, 0x76, 0xcf, 0x9c, 0x74, 0x4c,
|
||||
0x36, 0x70, 0x4c, 0xe1, 0xd0, 0x54, 0x1c, 0x9a, 0xb1, 0x43, 0xd3, 0x4a, 0x32, 0x62, 0x49, 0xab,
|
||||
0xa8, 0x09, 0x55, 0x9f, 0x4c, 0x28, 0xa7, 0x9e, 0xab, 0x97, 0x36, 0xb4, 0xcd, 0x9a, 0x95, 0xec,
|
||||
0x91, 0x0e, 0xcb, 0xae, 0xb7, 0x85, 0xed, 0x3e, 0xd1, 0x17, 0x37, 0xb4, 0xcd, 0xaa, 0x15, 0x6f,
|
||||
0xd1, 0x06, 0xd4, 0x31, 0x63, 0x8f, 0xf1, 0x01, 0x19, 0xee, 0x90, 0x23, 0xbd, 0x2c, 0x15, 0x55,
|
||||
0x92, 0xd0, 0xc5, 0x8c, 0x3d, 0xc5, 0x23, 0xa2, 0x57, 0x24, 0x37, 0xde, 0xa2, 0x75, 0xa8, 0xb9,
|
||||
0x78, 0x44, 0x38, 0xc3, 0x36, 0xd1, 0xab, 0x92, 0x97, 0x12, 0xd0, 0x77, 0xb0, 0xa6, 0x04, 0xbe,
|
||||
0xef, 0x8d, 0x7d, 0x9b, 0xe8, 0x20, 0x8f, 0xbe, 0x3b, 0xdf, 0xd1, 0xbb, 0x79, 0xb3, 0xd6, 0xb4,
|
||||
0x27, 0xf4, 0x35, 0x54, 0x64, 0xd1, 0xe8, 0xf5, 0x8d, 0xc5, 0xd7, 0x9a, 0xed, 0xd0, 0x2c, 0x72,
|
||||
0x61, 0x99, 0x0d, 0xc7, 0x0e, 0x75, 0xb9, 0x7e, 0x4e, 0x7a, 0x78, 0x36, 0x9f, 0x87, 0x2d, 0xcf,
|
||||
0x3d, 0xa4, 0xce, 0x13, 0xec, 0x62, 0x87, 0x8c, 0x88, 0x1b, 0xec, 0x49, 0xe3, 0x56, 0xec, 0x04,
|
||||
0xbd, 0x82, 0xc6, 0x60, 0xcc, 0x03, 0x6f, 0x44, 0x5f, 0x91, 0x5d, 0x26, 0x8b, 0x5b, 0x3f, 0x2f,
|
||||
0xb3, 0xf9, 0x74, 0x3e, 0xc7, 0x3b, 0x39, 0xab, 0xd6, 0x94, 0x1f, 0x51, 0x24, 0x83, 0xf1, 0x01,
|
||||
0xf9, 0x82, 0xf8, 0xb2, 0xba, 0x56, 0xc2, 0x22, 0x51, 0x48, 0x61, 0x19, 0xd1, 0x68, 0xc7, 0xf5,
|
||||
0xd5, 0x8d, 0xc5, 0xb0, 0x8c, 0x12, 0x12, 0xda, 0x84, 0xd5, 0x09, 0xf1, 0xe9, 0xe1, 0xd1, 0x3e,
|
||||
0x75, 0x5c, 0x1c, 0x8c, 0x7d, 0xa2, 0x37, 0x64, 0x29, 0xe6, 0xc9, 0x68, 0x04, 0xe7, 0xfb, 0x64,
|
||||
0x38, 0x12, 0x29, 0xdf, 0xf2, 0x49, 0x8f, 0xeb, 0x6b, 0x32, 0xbf, 0xdb, 0xf3, 0xdf, 0xa0, 0x34,
|
||||
0x67, 0x65, 0xad, 0x8b, 0xc0, 0x5c, 0xcf, 0x8a, 0x5e, 0x4a, 0xf8, 0x46, 0x50, 0x18, 0x58, 0x8e,
|
||||
0x8c, 0x06, 0x50, 0x17, 0xaa, 0x71, 0xf6, 0x2f, 0xc9, 0xec, 0x7f, 0x3a, 0x5f, 0x58, 0x8f, 0x52,
|
||||
0x83, 0x96, 0x6a, 0xdd, 0x18, 0xc3, 0xa5, 0x67, 0x12, 0x3b, 0x92, 0xc2, 0x3b, 0x0b, 0x14, 0x31,
|
||||
0x1e, 0xc1, 0xe5, 0xbc, 0x5b, 0xce, 0x3c, 0x97, 0x13, 0x64, 0x02, 0x92, 0x37, 0x45, 0x49, 0x2f,
|
||||
0xe5, 0xca, 0x28, 0xaa, 0x56, 0x01, 0xc7, 0xf8, 0x43, 0x83, 0x46, 0x8a, 0x80, 0x91, 0x91, 0x75,
|
||||
0xa8, 0x8d, 0x22, 0x1a, 0xd7, 0x35, 0x59, 0x25, 0x29, 0x21, 0x0b, 0x28, 0xa5, 0x3c, 0xa0, 0x5c,
|
||||
0x86, 0xa5, 0xb0, 0x55, 0x48, 0x0c, 0xab, 0x59, 0xd1, 0x2e, 0x03, 0x7c, 0xe5, 0x1c, 0xf0, 0xb5,
|
||||
0x00, 0xb8, 0xc4, 0x83, 0x67, 0x47, 0x8c, 0xe8, 0x4b, 0x92, 0xab, 0x50, 0x90, 0x01, 0xe7, 0xc2,
|
||||
0xf2, 0xb3, 0x08, 0x1f, 0x0f, 0x03, 0x7d, 0x59, 0x4a, 0x64, 0x68, 0x86, 0x07, 0xab, 0x8f, 0xa9,
|
||||
0x38, 0xc3, 0x21, 0x3f, 0x9b, 0x3b, 0xf8, 0x10, 0xca, 0xc2, 0x99, 0x38, 0xd8, 0x81, 0x8f, 0x5d,
|
||||
0xbb, 0x4f, 0xe2, 0x5c, 0x25, 0x7b, 0x84, 0xa0, 0x1c, 0x60, 0x87, 0xeb, 0x25, 0x49, 0x97, 0x6b,
|
||||
0xe3, 0x27, 0x2d, 0x8c, 0xb4, 0xcb, 0x18, 0x7f, 0xe3, 0x3d, 0xc7, 0x18, 0xc3, 0x72, 0x97, 0x31,
|
||||
0x11, 0x0f, 0xba, 0x09, 0x65, 0xcc, 0x58, 0x78, 0x88, 0x7a, 0xe7, 0x8a, 0xa9, 0xf4, 0xf7, 0x48,
|
||||
0x44, 0xfc, 0xe7, 0x0f, 0xdc, 0x40, 0x58, 0x16, 0xa2, 0xcd, 0x8f, 0xa0, 0x96, 0x90, 0x50, 0x03,
|
||||
0x16, 0x07, 0x24, 0xac, 0xb5, 0x9a, 0x25, 0x96, 0xe8, 0x22, 0x54, 0x26, 0x78, 0x38, 0x8e, 0xab,
|
||||
0x24, 0xdc, 0xdc, 0x2d, 0xdd, 0xd1, 0x8c, 0x1f, 0x2b, 0xf0, 0xb6, 0x88, 0x73, 0x5f, 0x16, 0x47,
|
||||
0x97, 0xb1, 0xfb, 0x24, 0xc0, 0x74, 0xc8, 0x3f, 0x1b, 0x13, 0xff, 0xe8, 0x94, 0xd3, 0xe1, 0xc0,
|
||||
0x52, 0x58, 0x5b, 0x32, 0xac, 0x53, 0xe8, 0x73, 0x91, 0xf9, 0xb4, 0xb9, 0x2d, 0x9e, 0x4e, 0x73,
|
||||
0x2b, 0x6a, 0x36, 0xe5, 0x33, 0x6a, 0x36, 0xb3, 0xe7, 0x0d, 0x65, 0x8a, 0x59, 0xca, 0x4e, 0x31,
|
||||
0x05, 0x18, 0xbe, 0xfc, 0xbf, 0x30, 0x1c, 0x4e, 0x15, 0xc3, 0x7f, 0x28, 0xc1, 0x65, 0x91, 0xdc,
|
||||
0xb4, 0x0a, 0x13, 0x20, 0x14, 0xef, 0x57, 0x40, 0x52, 0x58, 0xd3, 0x72, 0x8d, 0x6e, 0xc3, 0xf2,
|
||||
0x80, 0x7b, 0xae, 0x4b, 0x82, 0xa8, 0x7e, 0x9a, 0xea, 0x4b, 0xd9, 0x09, 0x59, 0x5d, 0xc6, 0xf6,
|
||||
0x19, 0xb1, 0xad, 0x58, 0x14, 0x5d, 0x87, 0xb2, 0xf0, 0x29, 0x41, 0xb1, 0xde, 0x79, 0x4b, 0x55,
|
||||
0x11, 0x81, 0xc5, 0xf2, 0x52, 0x08, 0xdd, 0x85, 0x5a, 0x92, 0xf0, 0xe8, 0x46, 0xd7, 0x33, 0x4e,
|
||||
0x62, 0x66, 0xac, 0x96, 0x8a, 0x0b, 0xdd, 0x1e, 0xf5, 0x89, 0x2d, 0x71, 0xbf, 0x32, 0xad, 0x7b,
|
||||
0x3f, 0x66, 0x26, 0xba, 0x89, 0xb8, 0xf1, 0xbb, 0x06, 0x57, 0xd3, 0x57, 0x19, 0x5f, 0xc9, 0x13,
|
||||
0x12, 0xe0, 0x1e, 0x0e, 0xf0, 0x9b, 0x1f, 0x90, 0xaf, 0xc1, 0x8a, 0xdd, 0x27, 0xf6, 0x20, 0x1d,
|
||||
0x4e, 0xc2, 0x39, 0x39, 0x47, 0x35, 0xfe, 0x2c, 0xc1, 0x4a, 0xf6, 0x22, 0xc4, 0x4d, 0x8a, 0x1e,
|
||||
0x15, 0xdf, 0xa4, 0x58, 0xa3, 0x3d, 0x38, 0x47, 0xdc, 0x09, 0xf5, 0x3d, 0x57, 0x8c, 0x72, 0xf1,
|
||||
0x33, 0xfd, 0x60, 0xf6, 0x75, 0x9a, 0x0f, 0x14, 0xf1, 0x10, 0x07, 0x33, 0x16, 0x90, 0x0b, 0xc0,
|
||||
0xb0, 0x8f, 0x47, 0x24, 0x20, 0xbe, 0x78, 0x8b, 0x8b, 0xaf, 0xe1, 0x2d, 0x86, 0x11, 0xec, 0xc5,
|
||||
0x66, 0x2d, 0xc5, 0x43, 0xf3, 0x05, 0xac, 0x4d, 0x85, 0x54, 0x80, 0xc3, 0xb7, 0x55, 0x1c, 0xae,
|
||||
0x77, 0x5a, 0x05, 0x27, 0x54, 0xcc, 0xa8, 0x38, 0xfd, 0x5b, 0x09, 0xea, 0x4a, 0x7d, 0x16, 0xa6,
|
||||
0xb1, 0x05, 0x20, 0x15, 0x1e, 0xd2, 0x21, 0x09, 0x93, 0x58, 0xb3, 0x14, 0x0a, 0x1a, 0x14, 0x24,
|
||||
0x65, 0x67, 0xfe, 0xb7, 0x5c, 0x98, 0x11, 0x31, 0x7e, 0x48, 0xd7, 0x3c, 0x82, 0xa5, 0x68, 0x87,
|
||||
0xbe, 0x85, 0x95, 0x43, 0x3a, 0x24, 0x7b, 0x69, 0x20, 0x4b, 0x32, 0x90, 0xdd, 0xf9, 0x03, 0x79,
|
||||
0xa8, 0xda, 0xb5, 0x72, 0x6e, 0x8c, 0xf7, 0xa1, 0x91, 0x7f, 0xae, 0x22, 0x48, 0x3a, 0xc2, 0x4e,
|
||||
0x92, 0xad, 0x68, 0x67, 0xfc, 0xac, 0x01, 0x9a, 0xbe, 0x8f, 0x59, 0x49, 0x1f, 0xdc, 0xe1, 0xf1,
|
||||
0xac, 0x1f, 0x3e, 0x14, 0x85, 0x82, 0x76, 0xa0, 0xde, 0x23, 0x3c, 0xa0, 0xae, 0x0c, 0x38, 0x02,
|
||||
0x91, 0xf7, 0x4e, 0xbe, 0xf8, 0xfb, 0xa9, 0x82, 0xa5, 0x6a, 0x1b, 0x9f, 0xc3, 0x95, 0x13, 0xa5,
|
||||
0x95, 0xa1, 0x4f, 0xcb, 0x0c, 0x7d, 0x27, 0x8e, 0x8a, 0x06, 0x82, 0x46, 0x1e, 0x8d, 0x8c, 0x97,
|
||||
0xb0, 0x26, 0x72, 0xba, 0xd5, 0xc7, 0x7e, 0x70, 0x46, 0x83, 0xdc, 0x3d, 0xa8, 0x25, 0x2e, 0x0b,
|
||||
0x73, 0xdd, 0x84, 0xea, 0x24, 0xfe, 0xcd, 0x14, 0x4e, 0x72, 0xc9, 0xde, 0xe8, 0x02, 0x52, 0xe3,
|
||||
0x8d, 0xfa, 0xc6, 0x75, 0xa8, 0xd0, 0x80, 0x8c, 0xe2, 0x59, 0xea, 0x52, 0x1e, 0xee, 0xa5, 0xb8,
|
||||
0x15, 0xca, 0x74, 0xbe, 0xaf, 0xc0, 0x5a, 0x8a, 0xba, 0xe2, 0x2f, 0xb5, 0x09, 0xda, 0x85, 0xc6,
|
||||
0x76, 0xf4, 0xb5, 0x22, 0x9e, 0xcf, 0xd1, 0x3b, 0xaa, 0x9d, 0xdc, 0x77, 0x8b, 0xe6, 0x7a, 0x31,
|
||||
0x33, 0x8c, 0xc8, 0x58, 0x40, 0x5f, 0xc2, 0x4a, 0xf6, 0x37, 0x03, 0xba, 0xaa, 0x6a, 0x14, 0xfe,
|
||||
0x8c, 0x69, 0x1a, 0x27, 0x89, 0x24, 0xa6, 0xef, 0x41, 0x35, 0x9e, 0xbd, 0xb3, 0x31, 0xe6, 0x26,
|
||||
0xf2, 0x66, 0x43, 0x65, 0x0a, 0x86, 0xb1, 0x80, 0x3e, 0x0e, 0x95, 0xc5, 0x1c, 0x39, 0xad, 0xac,
|
||||
0x0c, 0xc9, 0xcd, 0x0b, 0x05, 0x13, 0xa9, 0xb1, 0x80, 0x9e, 0xc3, 0xf9, 0x6d, 0x89, 0xd0, 0x51,
|
||||
0xf3, 0x46, 0xef, 0x66, 0x9d, 0xcc, 0x18, 0x32, 0xb3, 0x47, 0x2b, 0xee, 0xff, 0xc6, 0x02, 0xfa,
|
||||
0x45, 0x83, 0x0b, 0xdb, 0x24, 0xc8, 0xf7, 0x42, 0x74, 0xa3, 0xd8, 0xc9, 0x8c, 0x9e, 0xd9, 0x7c,
|
||||
0x3a, 0x6f, 0xcd, 0x66, 0xcd, 0x1a, 0x0b, 0x68, 0x4f, 0x1e, 0x3b, 0xad, 0x3d, 0x74, 0xa5, 0xb0,
|
||||
0xc8, 0x92, 0xec, 0xb5, 0x66, 0xb1, 0xe3, 0xa3, 0x7e, 0xd2, 0xfd, 0xeb, 0xb8, 0xa5, 0xfd, 0x7d,
|
||||
0xdc, 0xd2, 0xfe, 0x39, 0x6e, 0x69, 0x5f, 0xdd, 0xfa, 0x8f, 0x0f, 0x6d, 0xca, 0x37, 0x41, 0xcc,
|
||||
0xa8, 0x3d, 0xa4, 0xc4, 0x0d, 0x0e, 0x96, 0xe4, 0x67, 0xb5, 0x5b, 0xff, 0x06, 0x00, 0x00, 0xff,
|
||||
0xff, 0x44, 0x52, 0x29, 0xd7, 0x32, 0x14, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -1783,6 +1809,20 @@ func (m *ManifestRequest) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if m.HelmOptions != nil {
|
||||
{
|
||||
size, err := m.HelmOptions.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintRepository(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x1
|
||||
i--
|
||||
dAtA[i] = 0xaa
|
||||
}
|
||||
if m.NoRevisionCache {
|
||||
i--
|
||||
if m.NoRevisionCache {
|
||||
@@ -2291,6 +2331,28 @@ func (m *RepoServerAppDetailsQuery) MarshalToSizedBuffer(dAtA []byte) (int, erro
|
||||
i -= len(m.XXX_unrecognized)
|
||||
copy(dAtA[i:], m.XXX_unrecognized)
|
||||
}
|
||||
if m.HelmOptions != nil {
|
||||
{
|
||||
size, err := m.HelmOptions.MarshalToSizedBuffer(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarintRepository(dAtA, i, uint64(size))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x52
|
||||
}
|
||||
if m.NoRevisionCache {
|
||||
i--
|
||||
if m.NoRevisionCache {
|
||||
dAtA[i] = 1
|
||||
} else {
|
||||
dAtA[i] = 0
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x38
|
||||
}
|
||||
if m.NoCache {
|
||||
i--
|
||||
if m.NoCache {
|
||||
@@ -3013,6 +3075,10 @@ func (m *ManifestRequest) Size() (n int) {
|
||||
if m.NoRevisionCache {
|
||||
n += 3
|
||||
}
|
||||
if m.HelmOptions != nil {
|
||||
l = m.HelmOptions.Size()
|
||||
n += 2 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@@ -3199,6 +3265,13 @@ func (m *RepoServerAppDetailsQuery) Size() (n int) {
|
||||
if m.NoCache {
|
||||
n += 2
|
||||
}
|
||||
if m.NoRevisionCache {
|
||||
n += 2
|
||||
}
|
||||
if m.HelmOptions != nil {
|
||||
l = m.HelmOptions.Size()
|
||||
n += 1 + l + sovRepository(uint64(l))
|
||||
}
|
||||
if m.XXX_unrecognized != nil {
|
||||
n += len(m.XXX_unrecognized)
|
||||
}
|
||||
@@ -3960,6 +4033,42 @@ func (m *ManifestRequest) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.NoRevisionCache = bool(v != 0)
|
||||
case 21:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field HelmOptions", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.HelmOptions == nil {
|
||||
m.HelmOptions = &v1alpha1.HelmOptions{}
|
||||
}
|
||||
if err := m.HelmOptions.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
@@ -5105,6 +5214,62 @@ func (m *RepoServerAppDetailsQuery) Unmarshal(dAtA []byte) error {
|
||||
}
|
||||
}
|
||||
m.NoCache = bool(v != 0)
|
||||
case 7:
|
||||
if wireType != 0 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field NoRevisionCache", wireType)
|
||||
}
|
||||
var v int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
v |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
m.NoRevisionCache = bool(v != 0)
|
||||
case 10:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field HelmOptions", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowRepository
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthRepository
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.HelmOptions == nil {
|
||||
m.HelmOptions = &v1alpha1.HelmOptions{}
|
||||
}
|
||||
if err := m.HelmOptions.Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipRepository(dAtA[iNdEx:])
|
||||
|
||||
@@ -24,6 +24,7 @@ import (
|
||||
jsonpatch "github.com/evanphx/json-patch"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/google/go-jsonnet"
|
||||
"github.com/google/uuid"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"golang.org/x/sync/semaphore"
|
||||
"google.golang.org/grpc/codes"
|
||||
@@ -46,10 +47,10 @@ import (
|
||||
"github.com/argoproj/argo-cd/v2/util/gpg"
|
||||
"github.com/argoproj/argo-cd/v2/util/helm"
|
||||
"github.com/argoproj/argo-cd/v2/util/io"
|
||||
pathutil "github.com/argoproj/argo-cd/v2/util/io/path"
|
||||
"github.com/argoproj/argo-cd/v2/util/ksonnet"
|
||||
argokube "github.com/argoproj/argo-cd/v2/util/kube"
|
||||
"github.com/argoproj/argo-cd/v2/util/kustomize"
|
||||
"github.com/argoproj/argo-cd/v2/util/security"
|
||||
"github.com/argoproj/argo-cd/v2/util/text"
|
||||
)
|
||||
|
||||
@@ -489,8 +490,9 @@ func getHelmDependencyRepos(appPath string) ([]*v1alpha1.Repository, error) {
|
||||
for _, r := range d.Dependencies {
|
||||
if u, err := url.Parse(r.Repository); err == nil && (u.Scheme == "https" || u.Scheme == "oci") {
|
||||
repo := &v1alpha1.Repository{
|
||||
Repo: r.Repository,
|
||||
Name: r.Repository,
|
||||
Repo: r.Repository,
|
||||
Name: r.Repository,
|
||||
EnableOCI: u.Scheme == "oci",
|
||||
}
|
||||
repos = append(repos, repo)
|
||||
}
|
||||
@@ -557,7 +559,7 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
|
||||
APIVersions: q.ApiVersions,
|
||||
Set: map[string]string{},
|
||||
SetString: map[string]string{},
|
||||
SetFile: map[string]string{},
|
||||
SetFile: map[string]pathutil.ResolvedFilePath{},
|
||||
}
|
||||
|
||||
appHelm := q.ApplicationSource.Helm
|
||||
@@ -571,46 +573,28 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
|
||||
}
|
||||
|
||||
for _, val := range appHelm.ValueFiles {
|
||||
// If val is not a URL, run it against the directory enforcer. If it is a URL, use it without checking
|
||||
if _, err := url.ParseRequestURI(val); err != nil {
|
||||
|
||||
// Ensure that the repo root provided is absolute
|
||||
absRepoPath, err := filepath.Abs(repoRoot)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the path to the file is relative, join it with the current working directory (appPath)
|
||||
path := val
|
||||
if !filepath.IsAbs(path) {
|
||||
absWorkDir, err := filepath.Abs(appPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
path = filepath.Join(absWorkDir, path)
|
||||
}
|
||||
|
||||
_, err = security.EnforceToCurrentRoot(absRepoPath, path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
templateOpts.Values = append(templateOpts.Values, val)
|
||||
}
|
||||
|
||||
if appHelm.Values != "" {
|
||||
file, err := ioutil.TempFile("", "values-*.yaml")
|
||||
// This will resolve val to an absolute path (or an URL)
|
||||
path, _, err := pathutil.ResolveFilePath(appPath, repoRoot, val, q.GetValuesFileSchemes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := file.Name()
|
||||
|
||||
templateOpts.Values = append(templateOpts.Values, path)
|
||||
}
|
||||
|
||||
if appHelm.Values != "" {
|
||||
rand, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p := path.Join(os.TempDir(), rand.String())
|
||||
defer func() { _ = os.RemoveAll(p) }()
|
||||
err = ioutil.WriteFile(p, []byte(appHelm.Values), 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer file.Close()
|
||||
templateOpts.Values = append(templateOpts.Values, p)
|
||||
templateOpts.Values = append(templateOpts.Values, pathutil.ResolvedFilePath(p))
|
||||
}
|
||||
|
||||
for _, p := range appHelm.Parameters {
|
||||
@@ -621,7 +605,11 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
|
||||
}
|
||||
}
|
||||
for _, p := range appHelm.FileParameters {
|
||||
templateOpts.SetFile[p.Name] = p.Path
|
||||
resolvedPath, _, err := pathutil.ResolveFilePath(appPath, repoRoot, env.Envsubst(p.Path), q.GetValuesFileSchemes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
templateOpts.SetFile[p.Name] = resolvedPath
|
||||
}
|
||||
}
|
||||
if templateOpts.Name == "" {
|
||||
@@ -633,9 +621,6 @@ func helmTemplate(appPath string, repoRoot string, env *v1alpha1.Env, q *apiclie
|
||||
for i, j := range templateOpts.SetString {
|
||||
templateOpts.SetString[i] = env.Envsubst(j)
|
||||
}
|
||||
for i, j := range templateOpts.SetFile {
|
||||
templateOpts.SetFile[i] = env.Envsubst(j)
|
||||
}
|
||||
|
||||
repos, err := getHelmDependencyRepos(appPath)
|
||||
if err != nil {
|
||||
@@ -1060,11 +1045,12 @@ func makeJsonnetVm(appPath string, repoRoot string, sourceJsonnet v1alpha1.Appli
|
||||
// Jsonnet Imports relative to the repository path
|
||||
jpaths := []string{appPath}
|
||||
for _, p := range sourceJsonnet.Libs {
|
||||
jpath := path.Join(repoRoot, p)
|
||||
if !strings.HasPrefix(jpath, repoRoot) {
|
||||
return nil, status.Errorf(codes.FailedPrecondition, "%s: referenced library points outside the repository", p)
|
||||
// the jsonnet library path is relative to the repository root, not application path
|
||||
jpath, _, err := pathutil.ResolveFilePath(repoRoot, repoRoot, p, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
jpaths = append(jpaths, jpath)
|
||||
jpaths = append(jpaths, string(jpath))
|
||||
}
|
||||
|
||||
vm.Importer(&jsonnet.FileImporter{
|
||||
@@ -1167,7 +1153,7 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
|
||||
return err
|
||||
}
|
||||
case v1alpha1.ApplicationSourceTypeHelm:
|
||||
if err := populateHelmAppDetails(res, ctx.appPath, q); err != nil {
|
||||
if err := populateHelmAppDetails(res, ctx.appPath, repoRoot, q); err != nil {
|
||||
return err
|
||||
}
|
||||
case v1alpha1.ApplicationSourceTypeKustomize:
|
||||
@@ -1179,7 +1165,7 @@ func (s *Service) GetAppDetails(ctx context.Context, q *apiclient.RepoServerAppD
|
||||
return nil
|
||||
}
|
||||
|
||||
settings := operationSettings{allowConcurrent: q.Source.AllowsConcurrentProcessing(), noCache: q.NoCache, noRevisionCache: q.NoCache}
|
||||
settings := operationSettings{allowConcurrent: q.Source.AllowsConcurrentProcessing(), noCache: q.NoCache, noRevisionCache: q.NoCache || q.NoRevisionCache}
|
||||
err := s.runRepoOperation(ctx, q.Source.TargetRevision, q.Repo, q.Source, false, cacheFn, operation, settings)
|
||||
|
||||
return res, err
|
||||
@@ -1229,15 +1215,19 @@ func populateKsonnetAppDetails(res *apiclient.RepoAppDetailsResponse, appPath st
|
||||
return nil
|
||||
}
|
||||
|
||||
func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath string, q *apiclient.RepoServerAppDetailsQuery) error {
|
||||
var valueFiles []string
|
||||
func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath string, repoRoot string, q *apiclient.RepoServerAppDetailsQuery) error {
|
||||
var selectedValueFiles []string
|
||||
|
||||
valueFiles, err := findHelmValueFilesInPath(appPath)
|
||||
if q.Source.Helm != nil {
|
||||
selectedValueFiles = q.Source.Helm.ValueFiles
|
||||
}
|
||||
|
||||
availableValueFiles, err := findHelmValueFilesInPath(appPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
res.Helm = &apiclient.HelmAppSpec{ValueFiles: valueFiles}
|
||||
res.Helm = &apiclient.HelmAppSpec{ValueFiles: availableValueFiles}
|
||||
var version string
|
||||
if q.Source.Helm != nil {
|
||||
if q.Source.Helm.Version != "" {
|
||||
@@ -1257,7 +1247,16 @@ func populateHelmAppDetails(res *apiclient.RepoAppDetailsResponse, appPath strin
|
||||
if err := loadFileIntoIfExists(filepath.Join(appPath, "values.yaml"), &res.Helm.Values); err != nil {
|
||||
return err
|
||||
}
|
||||
params, err := h.GetParameters(valueFiles)
|
||||
var resolvedSelectedValueFiles []pathutil.ResolvedFilePath
|
||||
// drop not allowed values files
|
||||
for _, file := range selectedValueFiles {
|
||||
if resolvedFile, _, err := pathutil.ResolveFilePath(appPath, repoRoot, file, q.GetValuesFileSchemes()); err == nil {
|
||||
resolvedSelectedValueFiles = append(resolvedSelectedValueFiles, resolvedFile)
|
||||
} else {
|
||||
log.Debugf("Values file %s is not allowed: %v", file, err)
|
||||
}
|
||||
}
|
||||
params, err := h.GetParameters(resolvedSelectedValueFiles)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ message ManifestRequest {
|
||||
bool verifySignature = 16;
|
||||
repeated github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.RepoCreds helmRepoCreds = 17;
|
||||
bool noRevisionCache = 18;
|
||||
github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.HelmOptions helmOptions = 21;
|
||||
}
|
||||
|
||||
// TestRepositoryRequest is a query to test repository is valid or not and has valid access.
|
||||
@@ -81,6 +82,8 @@ message RepoServerAppDetailsQuery {
|
||||
github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.KustomizeOptions kustomizeOptions = 4;
|
||||
string appName = 5;
|
||||
bool noCache = 6;
|
||||
bool noRevisionCache = 7;
|
||||
github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.HelmOptions helmOptions = 10;
|
||||
}
|
||||
|
||||
// RepoAppDetailsResponse application details
|
||||
|
||||
@@ -258,6 +258,25 @@ func TestGenerateJsonnetManifestInDir(t *testing.T) {
|
||||
assert.Equal(t, 2, len(res1.Manifests))
|
||||
}
|
||||
|
||||
func TestGenerateJsonnetLibOutside(t *testing.T) {
|
||||
service := newService(".")
|
||||
|
||||
q := apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: "./testdata/jsonnet",
|
||||
Directory: &argoappv1.ApplicationSourceDirectory{
|
||||
Jsonnet: argoappv1.ApplicationSourceJsonnet{
|
||||
Libs: []string{"../../../testdata/jsonnet/vendor"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := service.GenerateManifest(context.Background(), &q)
|
||||
require.Error(t, err)
|
||||
require.Contains(t, err.Error(), "value file '../../../testdata/jsonnet/vendor' resolved to outside repository root")
|
||||
}
|
||||
|
||||
func TestGenerateKsonnetManifest(t *testing.T) {
|
||||
service := newService("../..")
|
||||
|
||||
@@ -726,7 +745,37 @@ func TestHelmManifestFromChartRepoWithValueFileOutsideRepo(t *testing.T) {
|
||||
}
|
||||
request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true}
|
||||
_, err := service.GenerateManifest(context.Background(), request)
|
||||
assert.Error(t, err, "should be on or under current directory")
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
func TestHelmManifestFromChartRepoWithValueFileLinks(t *testing.T) {
|
||||
t.Run("Valid symlink", func(t *testing.T) {
|
||||
service := newService("../..")
|
||||
source := &argoappv1.ApplicationSource{
|
||||
Chart: "my-chart",
|
||||
TargetRevision: ">= 1.0.0",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"my-chart-link.yaml"},
|
||||
},
|
||||
}
|
||||
request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true}
|
||||
_, err := service.GenerateManifest(context.Background(), request)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Symlink pointing to outside", func(t *testing.T) {
|
||||
service := newService("../..")
|
||||
source := &argoappv1.ApplicationSource{
|
||||
Chart: "my-chart",
|
||||
TargetRevision: ">= 1.0.0",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"my-chart-outside-link.yaml"},
|
||||
},
|
||||
}
|
||||
request := &apiclient.ManifestRequest{Repo: &argoappv1.Repository{}, ApplicationSource: source, NoCache: true}
|
||||
_, err := service.GenerateManifest(context.Background(), request)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGenerateHelmWithURL(t *testing.T) {
|
||||
@@ -742,6 +791,7 @@ func TestGenerateHelmWithURL(t *testing.T) {
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"https"}},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
@@ -749,38 +799,108 @@ func TestGenerateHelmWithURL(t *testing.T) {
|
||||
// The requested value file (`../../../../../minio/values.yaml`) is outside the repo directory
|
||||
// (`~/go/src/github.com/argoproj/argo-cd`), so it is blocked
|
||||
func TestGenerateHelmWithValuesDirectoryTraversalOutsideRepo(t *testing.T) {
|
||||
service := newService("../..")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: "./util/helm/testdata/redis",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"../../../../../minio/values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
t.Run("Values file with relative path pointing outside repo root", func(t *testing.T) {
|
||||
service := newService("../..")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: "./util/helm/testdata/redis",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"../../../../../minio/values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
})
|
||||
assert.Error(t, err, "should be on or under current directory")
|
||||
|
||||
service = newService("./testdata/my-chart")
|
||||
_, err = service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"../my-chart-2/values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
t.Run("Values file with relative path pointing inside repo root", func(t *testing.T) {
|
||||
service := newService("./testdata/my-chart")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"../my-chart/my-chart-values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Values file with absolute path stays within repo root", func(t *testing.T) {
|
||||
service := newService("./testdata/my-chart")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"/my-chart-values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Values file with absolute path using back-references outside repo root", func(t *testing.T) {
|
||||
service := newService("./testdata/my-chart")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"/../../../my-chart-values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
})
|
||||
|
||||
t.Run("Remote values file from forbidden protocol", func(t *testing.T) {
|
||||
service := newService("./testdata/my-chart")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"file://../../../../my-chart-values.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "is not allowed")
|
||||
})
|
||||
|
||||
t.Run("Remote values file from custom allowed protocol", func(t *testing.T) {
|
||||
service := newService("./testdata/my-chart")
|
||||
_, err := service.GenerateManifest(context.Background(), &apiclient.ManifestRequest{
|
||||
Repo: &argoappv1.Repository{},
|
||||
AppName: "test",
|
||||
ApplicationSource: &argoappv1.ApplicationSource{
|
||||
Path: ".",
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"s3://my-bucket/my-chart-values.yaml"},
|
||||
},
|
||||
},
|
||||
HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"s3"}},
|
||||
})
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "s3://my-bucket/my-chart-values.yaml: no such file or directory")
|
||||
})
|
||||
assert.Error(t, err, "should be on or under current directory")
|
||||
}
|
||||
|
||||
// The requested file parameter (`/tmp/external-secret.txt`) is outside the app path
|
||||
// (`./util/helm/testdata/redis`), and outside the repo directory. It is used as a means
|
||||
// of providing direct content to a helm chart via a specific key.
|
||||
// File parameter should not allow traversal outside of the repository root
|
||||
func TestGenerateHelmWithAbsoluteFileParameter(t *testing.T) {
|
||||
service := newService("../..")
|
||||
|
||||
@@ -802,16 +922,14 @@ func TestGenerateHelmWithAbsoluteFileParameter(t *testing.T) {
|
||||
Helm: &argoappv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"values-production.yaml"},
|
||||
Values: `cluster: {slaveCount: 2}`,
|
||||
FileParameters: []argoappv1.HelmFileParameter{
|
||||
argoappv1.HelmFileParameter{
|
||||
Name: "passwordContent",
|
||||
Path: externalSecretPath,
|
||||
},
|
||||
},
|
||||
FileParameters: []argoappv1.HelmFileParameter{{
|
||||
Name: "passwordContent",
|
||||
Path: externalSecretPath,
|
||||
}},
|
||||
},
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
// The requested file parameter (`../external/external-secret.txt`) is outside the app path
|
||||
|
||||
1
reposerver/repository/testdata/my-chart/my-chart-link.yaml
vendored
Symbolic link
1
reposerver/repository/testdata/my-chart/my-chart-link.yaml
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
my-chart-values.yaml
|
||||
1
reposerver/repository/testdata/my-chart/my-chart-outside-link.yaml
vendored
Symbolic link
1
reposerver/repository/testdata/my-chart/my-chart-outside-link.yaml
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
../my-chart-2/my-chart-2-values.yaml
|
||||
@@ -229,6 +229,7 @@ func (s *Server) queryRepoServer(ctx context.Context, a *v1alpha1.Application, a
|
||||
repo *appv1.Repository,
|
||||
helmRepos []*appv1.Repository,
|
||||
helmCreds []*v1alpha1.RepoCreds,
|
||||
helmOptions *v1alpha1.HelmOptions,
|
||||
kustomizeOptions *v1alpha1.KustomizeOptions,
|
||||
) error) error {
|
||||
|
||||
@@ -270,11 +271,15 @@ func (s *Server) queryRepoServer(ctx context.Context, a *v1alpha1.Application, a
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
helmOptions, err := s.settingsMgr.GetHelmSettings()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
permittedHelmCredentials, err := argo.GetPermittedReposCredentials(proj, helmRepositoryCredentials)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return action(client, repo, permittedHelmRepos, permittedHelmCredentials, kustomizeOptions)
|
||||
return action(client, repo, permittedHelmRepos, permittedHelmCredentials, helmOptions, kustomizeOptions)
|
||||
}
|
||||
|
||||
// GetManifests returns application manifests
|
||||
@@ -289,7 +294,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
|
||||
|
||||
var manifestInfo *apiclient.ManifestResponse
|
||||
err = s.queryRepoServer(ctx, a, func(
|
||||
client apiclient.RepoServerServiceClient, repo *appv1.Repository, helmRepos []*appv1.Repository, helmCreds []*appv1.RepoCreds, kustomizeOptions *appv1.KustomizeOptions) error {
|
||||
client apiclient.RepoServerServiceClient, repo *appv1.Repository, helmRepos []*appv1.Repository, helmCreds []*appv1.RepoCreds, helmOptions *appv1.HelmOptions, kustomizeOptions *appv1.KustomizeOptions) error {
|
||||
revision := a.Spec.Source.TargetRevision
|
||||
if q.Revision != "" {
|
||||
revision = q.Revision
|
||||
@@ -331,6 +336,7 @@ func (s *Server) GetManifests(ctx context.Context, q *application.ApplicationMan
|
||||
KubeVersion: serverVersion,
|
||||
ApiVersions: argo.APIGroupsToVersions(apiGroups),
|
||||
HelmRepoCreds: helmCreds,
|
||||
HelmOptions: helmOptions,
|
||||
})
|
||||
return err
|
||||
})
|
||||
@@ -405,6 +411,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
|
||||
repo *appv1.Repository,
|
||||
helmRepos []*appv1.Repository,
|
||||
_ []*appv1.RepoCreds,
|
||||
helmOptions *appv1.HelmOptions,
|
||||
kustomizeOptions *appv1.KustomizeOptions,
|
||||
) error {
|
||||
_, err := client.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
|
||||
@@ -414,6 +421,7 @@ func (s *Server) Get(ctx context.Context, q *application.ApplicationQuery) (*app
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
Repos: helmRepos,
|
||||
NoCache: true,
|
||||
HelmOptions: helmOptions,
|
||||
})
|
||||
return err
|
||||
}); err != nil {
|
||||
@@ -470,6 +478,21 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *application.Applicat
|
||||
"involvedObject.namespace": a.Namespace,
|
||||
}).String()
|
||||
} else {
|
||||
tree, err := s.getAppResources(ctx, a)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
found := false
|
||||
for _, n := range append(tree.Nodes, tree.OrphanedNodes...) {
|
||||
if n.ResourceRef.UID == q.ResourceUID && n.ResourceRef.Name == q.ResourceName && n.ResourceRef.Namespace == q.ResourceNamespace {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "%s not found as part of application %s", q.ResourceName, *q.Name)
|
||||
}
|
||||
|
||||
namespace = q.ResourceNamespace
|
||||
var config *rest.Config
|
||||
config, err = s.getApplicationClusterConfig(ctx, a)
|
||||
@@ -486,7 +509,6 @@ func (s *Server) ListResourceEvents(ctx context.Context, q *application.Applicat
|
||||
"involvedObject.namespace": namespace,
|
||||
}).String()
|
||||
}
|
||||
|
||||
log.Infof("Querying for resource events with field selector: %s", fieldSelector)
|
||||
opts := metav1.ListOptions{FieldSelector: fieldSelector}
|
||||
return kubeClientset.CoreV1().Events(namespace).List(ctx, opts)
|
||||
@@ -848,7 +870,7 @@ func (s *Server) validateAndNormalizeApp(ctx context.Context, app *appv1.Applica
|
||||
|
||||
var conditions []appv1.ApplicationCondition
|
||||
if validate {
|
||||
conditions, err = argo.ValidateRepo(ctx, app, s.repoClientset, s.db, kustomizeOptions, plugins, s.kubectl, proj)
|
||||
conditions, err = argo.ValidateRepo(ctx, app, s.repoClientset, s.db, kustomizeOptions, plugins, s.kubectl, proj, s.settingsMgr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -912,7 +934,7 @@ func (s *Server) getAppResources(ctx context.Context, a *appv1.Application) (*ap
|
||||
return &tree, err
|
||||
}
|
||||
|
||||
func (s *Server) getAppResource(ctx context.Context, action string, q *application.ApplicationResourceRequest) (*appv1.ResourceNode, *rest.Config, *appv1.Application, error) {
|
||||
func (s *Server) getAppLiveResource(ctx context.Context, action string, q *application.ApplicationResourceRequest) (*appv1.ResourceNode, *rest.Config, *appv1.Application, error) {
|
||||
a, err := s.appLister.Get(*q.Name)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
@@ -927,7 +949,7 @@ func (s *Server) getAppResource(ctx context.Context, action string, q *applicati
|
||||
}
|
||||
|
||||
found := tree.FindNode(q.Group, q.Kind, q.Namespace, q.ResourceName)
|
||||
if found == nil {
|
||||
if found == nil || found.ResourceRef.UID == "" {
|
||||
return nil, nil, nil, status.Errorf(codes.InvalidArgument, "%s %s %s not found as part of application %s", q.Kind, q.Group, q.ResourceName, *q.Name)
|
||||
}
|
||||
config, err := s.getApplicationClusterConfig(ctx, a)
|
||||
@@ -938,7 +960,7 @@ func (s *Server) getAppResource(ctx context.Context, action string, q *applicati
|
||||
}
|
||||
|
||||
func (s *Server) GetResource(ctx context.Context, q *application.ApplicationResourceRequest) (*application.ApplicationResourceResponse, error) {
|
||||
res, config, _, err := s.getAppResource(ctx, rbacpolicy.ActionGet, q)
|
||||
res, config, _, err := s.getAppLiveResource(ctx, rbacpolicy.ActionGet, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -983,7 +1005,7 @@ func (s *Server) PatchResource(ctx context.Context, q *application.ApplicationRe
|
||||
Version: q.Version,
|
||||
Group: q.Group,
|
||||
}
|
||||
res, config, a, err := s.getAppResource(ctx, rbacpolicy.ActionUpdate, resourceRequest)
|
||||
res, config, a, err := s.getAppLiveResource(ctx, rbacpolicy.ActionUpdate, resourceRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1023,7 +1045,7 @@ func (s *Server) DeleteResource(ctx context.Context, q *application.ApplicationR
|
||||
Version: q.Version,
|
||||
Group: q.Group,
|
||||
}
|
||||
res, config, a, err := s.getAppResource(ctx, rbacpolicy.ActionDelete, resourceRequest)
|
||||
res, config, a, err := s.getAppLiveResource(ctx, rbacpolicy.ActionDelete, resourceRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1293,7 +1315,7 @@ func getSelectedPods(treeNodes []appv1.ResourceNode, q *application.ApplicationP
|
||||
var pods []appv1.ResourceNode
|
||||
isTheOneMap := make(map[string]bool)
|
||||
for _, treeNode := range treeNodes {
|
||||
if treeNode.Kind == kube.PodKind && treeNode.Group == "" {
|
||||
if treeNode.Kind == kube.PodKind && treeNode.Group == "" && treeNode.UID != "" {
|
||||
if isTheSelectedOne(&treeNode, q, treeNodes, isTheOneMap) {
|
||||
pods = append(pods, treeNode)
|
||||
}
|
||||
@@ -1603,7 +1625,7 @@ func (s *Server) logResourceEvent(res *appv1.ResourceNode, ctx context.Context,
|
||||
}
|
||||
|
||||
func (s *Server) ListResourceActions(ctx context.Context, q *application.ApplicationResourceRequest) (*application.ResourceActionsListResponse, error) {
|
||||
res, config, _, err := s.getAppResource(ctx, rbacpolicy.ActionGet, q)
|
||||
res, config, _, err := s.getAppLiveResource(ctx, rbacpolicy.ActionGet, q)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1654,7 +1676,7 @@ func (s *Server) RunResourceAction(ctx context.Context, q *application.ResourceA
|
||||
Group: q.Group,
|
||||
}
|
||||
actionRequest := fmt.Sprintf("%s/%s/%s/%s", rbacpolicy.ActionAction, q.Group, q.Kind, q.Action)
|
||||
res, config, a, err := s.getAppResource(ctx, actionRequest, resourceRequest)
|
||||
res, config, a, err := s.getAppLiveResource(ctx, actionRequest, resourceRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -10,11 +10,14 @@ import (
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
apierr "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
repositorypkg "github.com/argoproj/argo-cd/v2/pkg/apiclient/repository"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
applisters "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
|
||||
servercache "github.com/argoproj/argo-cd/v2/server/cache"
|
||||
"github.com/argoproj/argo-cd/v2/server/rbacpolicy"
|
||||
@@ -31,6 +34,8 @@ type Server struct {
|
||||
repoClientset apiclient.Clientset
|
||||
enf *rbac.Enforcer
|
||||
cache *servercache.Cache
|
||||
appLister applisters.ApplicationNamespaceLister
|
||||
projLister applisters.AppProjectNamespaceLister
|
||||
settings *settings.SettingsManager
|
||||
}
|
||||
|
||||
@@ -40,6 +45,8 @@ func NewServer(
|
||||
db db.ArgoDB,
|
||||
enf *rbac.Enforcer,
|
||||
cache *servercache.Cache,
|
||||
appLister applisters.ApplicationNamespaceLister,
|
||||
projLister applisters.AppProjectNamespaceLister,
|
||||
settings *settings.SettingsManager,
|
||||
) *Server {
|
||||
return &Server{
|
||||
@@ -47,10 +54,31 @@ func NewServer(
|
||||
repoClientset: repoClientset,
|
||||
enf: enf,
|
||||
cache: cache,
|
||||
appLister: appLister,
|
||||
projLister: projLister,
|
||||
settings: settings,
|
||||
}
|
||||
}
|
||||
|
||||
var (
|
||||
errPermissionDenied = status.Error(codes.PermissionDenied, "permission denied")
|
||||
)
|
||||
|
||||
func (s *Server) getRepo(ctx context.Context, url string) (*appsv1.Repository, error) {
|
||||
repo, err := s.db.GetRepository(ctx, url)
|
||||
if err != nil {
|
||||
return nil, errPermissionDenied
|
||||
}
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func createRBACObject(project string, repo string) string {
|
||||
if project != "" {
|
||||
return project + "/" + repo
|
||||
}
|
||||
return repo
|
||||
}
|
||||
|
||||
// Get the connection state for a given repository URL by connecting to the
|
||||
// repo and evaluate the results. Unless forceRefresh is set to true, the
|
||||
// result may be retrieved out of the cache.
|
||||
@@ -183,7 +211,8 @@ func (s *Server) ListRefs(ctx context.Context, q *repositorypkg.RepoQuery) (*api
|
||||
})
|
||||
}
|
||||
|
||||
// ListApps returns list of apps in the repo
|
||||
// ListApps performs discovery of a git repository for potential sources of applications. Used
|
||||
// as a convenience to the UI for auto-complete.
|
||||
func (s *Server) ListApps(ctx context.Context, q *repositorypkg.RepoAppsQuery) (*repositorypkg.RepoAppsResponse, error) {
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, q.Repo); err != nil {
|
||||
return nil, err
|
||||
@@ -193,6 +222,24 @@ func (s *Server) ListApps(ctx context.Context, q *repositorypkg.RepoAppsQuery) (
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims := ctx.Value("claims")
|
||||
if err := s.enf.EnforceErr(claims, rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, createRBACObject("", repo.Repo)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// This endpoint causes us to clone git repos & invoke config management tooling for the purposes
|
||||
// of app discovery. Only allow this to happen if user has privileges to create or update the
|
||||
// application which it wants to retrieve these details for.
|
||||
appRBACresource := fmt.Sprintf("%s/%s", q.AppProject, q.AppName)
|
||||
if !s.enf.Enforce(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionCreate, appRBACresource) &&
|
||||
!s.enf.Enforce(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionUpdate, appRBACresource) {
|
||||
return nil, errPermissionDenied
|
||||
}
|
||||
// Also ensure the repo is actually allowed in the project in question
|
||||
if err := s.isRepoPermittedInProject(q.Repo, q.AppProject); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Test the repo
|
||||
conn, repoClient, err := s.repoClientset.NewRepoServerClient()
|
||||
if err != nil {
|
||||
@@ -214,6 +261,9 @@ func (s *Server) ListApps(ctx context.Context, q *repositorypkg.RepoAppsQuery) (
|
||||
return &repositorypkg.RepoAppsResponse{Items: items}, nil
|
||||
}
|
||||
|
||||
// GetAppDetails shows parameter values to various config tools (e.g. helm/kustomize values)
|
||||
// This is used by UI for parameter form fields during app create & edit pages.
|
||||
// It is also used when showing history of parameters used in previous syncs in the app history.
|
||||
func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDetailsQuery) (*apiclient.RepoAppDetailsResponse, error) {
|
||||
if q.Source == nil {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "missing payload in request")
|
||||
@@ -221,10 +271,44 @@ func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDeta
|
||||
if err := s.enf.EnforceErr(ctx.Value("claims"), rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, q.Source.RepoURL); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
repo, err := s.db.GetRepository(ctx, q.Source.RepoURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
claims := ctx.Value("claims")
|
||||
if err := s.enf.EnforceErr(claims, rbacpolicy.ResourceRepositories, rbacpolicy.ActionGet, createRBACObject("", repo.Repo)); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
app, err := s.appLister.Get(q.AppName)
|
||||
appRBACObj := createRBACObject(q.AppProject, q.AppName)
|
||||
// ensure caller has read privileges to app
|
||||
if err := s.enf.EnforceErr(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionGet, appRBACObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if apierr.IsNotFound(err) {
|
||||
// app doesn't exist since it still is being formulated. verify they can create the app
|
||||
// before we reveal repo details
|
||||
if err := s.enf.EnforceErr(claims, rbacpolicy.ResourceApplications, rbacpolicy.ActionCreate, appRBACObj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// if we get here we are returning repo details of an existing app
|
||||
if q.AppProject != app.Spec.Project {
|
||||
return nil, errPermissionDenied
|
||||
}
|
||||
// verify caller is not making a request with arbitrary source values which were not in our history
|
||||
if !isSourceInHistory(app, *q.Source) {
|
||||
return nil, errPermissionDenied
|
||||
}
|
||||
}
|
||||
// Ensure the repo is actually allowed in the project in question
|
||||
if err := s.isRepoPermittedInProject(q.Source.RepoURL, q.AppProject); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conn, repoClient, err := s.repoClientset.NewRepoServerClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -242,11 +326,16 @@ func (s *Server) GetAppDetails(ctx context.Context, q *repositorypkg.RepoAppDeta
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
helmOptions, err := s.settings.GetHelmSettings()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return repoClient.GetAppDetails(ctx, &apiclient.RepoServerAppDetailsQuery{
|
||||
Repo: repo,
|
||||
Source: q.Source,
|
||||
Repos: helmRepos,
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
HelmOptions: helmOptions,
|
||||
AppName: q.AppName,
|
||||
})
|
||||
}
|
||||
@@ -427,3 +516,33 @@ func (s *Server) testRepo(ctx context.Context, repo *appsv1.Repository) error {
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *Server) isRepoPermittedInProject(repo string, projName string) error {
|
||||
proj, err := s.projLister.Get(projName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !proj.IsSourcePermitted(appsv1.ApplicationSource{RepoURL: repo}) {
|
||||
return status.Errorf(codes.PermissionDenied, "repository '%s' not permitted in project '%s'", repo, projName)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// isSourceInHistory checks if the supplied application source is either our current application
|
||||
// source, or was something which we synced to previously.
|
||||
func isSourceInHistory(app *v1alpha1.Application, source v1alpha1.ApplicationSource) bool {
|
||||
if source.Equals(app.Spec.Source) {
|
||||
return true
|
||||
}
|
||||
// Iterate history. When comparing items in our history, use the actual synced revision to
|
||||
// compare with the supplied source.targetRevision in the request. This is because
|
||||
// history[].source.targetRevision is ambiguous (e.g. HEAD), whereas
|
||||
// history[].revision will contain the explicit SHA
|
||||
for _, h := range app.Status.History {
|
||||
h.Source.TargetRevision = h.Revision
|
||||
if source.Equals(h.Source) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import "github.com/argoproj/argo-cd/v2/reposerver/repository/repository.proto";
|
||||
message RepoAppsQuery {
|
||||
string repo = 1;
|
||||
string revision = 2;
|
||||
string appName = 3;
|
||||
string appProject = 4;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +31,7 @@ message AppInfo {
|
||||
message RepoAppDetailsQuery {
|
||||
github.com.argoproj.argo_cd.v2.pkg.apis.application.v1alpha1.ApplicationSource source = 1;
|
||||
string appName = 2;
|
||||
string appProject = 3;
|
||||
}
|
||||
|
||||
// RepoAppsResponse contains applications of specified repository
|
||||
|
||||
562
server/repository/repository_test.go
Normal file
562
server/repository/repository_test.go
Normal file
@@ -0,0 +1,562 @@
|
||||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/dgrijalva/jwt-go/v4"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/common"
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apiclient/repository"
|
||||
appsv1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
fakeapps "github.com/argoproj/argo-cd/v2/pkg/client/clientset/versioned/fake"
|
||||
appinformer "github.com/argoproj/argo-cd/v2/pkg/client/informers/externalversions"
|
||||
applisters "github.com/argoproj/argo-cd/v2/pkg/client/listers/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/apiclient"
|
||||
"github.com/argoproj/argo-cd/v2/reposerver/apiclient/mocks"
|
||||
"github.com/argoproj/argo-cd/v2/server/cache"
|
||||
"github.com/argoproj/argo-cd/v2/util/assets"
|
||||
cacheutil "github.com/argoproj/argo-cd/v2/util/cache"
|
||||
appstatecache "github.com/argoproj/argo-cd/v2/util/cache/appstate"
|
||||
"github.com/argoproj/argo-cd/v2/util/db"
|
||||
dbmocks "github.com/argoproj/argo-cd/v2/util/db/mocks"
|
||||
"github.com/argoproj/argo-cd/v2/util/rbac"
|
||||
"github.com/argoproj/argo-cd/v2/util/settings"
|
||||
)
|
||||
|
||||
const testNamespace = "default"
|
||||
|
||||
var (
|
||||
argocdCM = corev1.ConfigMap{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Namespace: testNamespace,
|
||||
Name: "argocd-cm",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
}
|
||||
argocdSecret = corev1.Secret{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "argocd-secret",
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"admin.password": []byte("test"),
|
||||
"server.secretkey": []byte("test"),
|
||||
},
|
||||
}
|
||||
defaultProj = &appsv1.AppProject{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "AppProject",
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Spec: appsv1.AppProjectSpec{
|
||||
SourceRepos: []string{"*"},
|
||||
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
|
||||
},
|
||||
}
|
||||
|
||||
defaultProjNoSources = &appsv1.AppProject{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "AppProject",
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "default",
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Spec: appsv1.AppProjectSpec{
|
||||
SourceRepos: []string{},
|
||||
Destinations: []appsv1.ApplicationDestination{{Server: "*", Namespace: "*"}},
|
||||
},
|
||||
}
|
||||
|
||||
guestbookApp = &appsv1.Application{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "Application",
|
||||
APIVersion: "argoproj.io/v1alpha1",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "guestbook",
|
||||
Namespace: testNamespace,
|
||||
},
|
||||
Spec: appsv1.ApplicationSpec{
|
||||
Project: "default",
|
||||
Source: appsv1.ApplicationSource{
|
||||
RepoURL: "https://test",
|
||||
TargetRevision: "HEAD",
|
||||
Helm: &appsv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"values.yaml"},
|
||||
},
|
||||
},
|
||||
},
|
||||
Status: appsv1.ApplicationStatus{
|
||||
History: appsv1.RevisionHistories{
|
||||
{
|
||||
Revision: "abcdef123567",
|
||||
Source: appsv1.ApplicationSource{
|
||||
RepoURL: "https://test",
|
||||
TargetRevision: "HEAD",
|
||||
Helm: &appsv1.ApplicationSourceHelm{
|
||||
ValueFiles: []string{"values-old.yaml"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func newAppAndProjLister(objects ...runtime.Object) (applisters.ApplicationNamespaceLister, applisters.AppProjectNamespaceLister) {
|
||||
fakeAppsClientset := fakeapps.NewSimpleClientset(objects...)
|
||||
factory := appinformer.NewSharedInformerFactoryWithOptions(fakeAppsClientset, 0, appinformer.WithNamespace(""), appinformer.WithTweakListOptions(func(options *metav1.ListOptions) {}))
|
||||
projInformer := factory.Argoproj().V1alpha1().AppProjects()
|
||||
appsInformer := factory.Argoproj().V1alpha1().Applications()
|
||||
for _, obj := range objects {
|
||||
switch obj.(type) {
|
||||
case *appsv1.AppProject:
|
||||
_ = projInformer.Informer().GetStore().Add(obj)
|
||||
case *appsv1.Application:
|
||||
_ = appsInformer.Informer().GetStore().Add(obj)
|
||||
}
|
||||
}
|
||||
appLister := appsInformer.Lister().Applications(testNamespace)
|
||||
projLister := projInformer.Lister().AppProjects(testNamespace)
|
||||
return appLister, projLister
|
||||
}
|
||||
|
||||
func Test_createRBACObject(t *testing.T) {
|
||||
object := createRBACObject("test-prj", "test-repo")
|
||||
assert.Equal(t, "test-prj/test-repo", object)
|
||||
objectWithoutPrj := createRBACObject("", "test-repo")
|
||||
assert.Equal(t, "test-repo", objectWithoutPrj)
|
||||
}
|
||||
|
||||
func TestRepositoryServer(t *testing.T) {
|
||||
kubeclientset := fake.NewSimpleClientset(&argocdCM, &argocdSecret)
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, testNamespace)
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
argoDB := db.NewDB("default", settingsMgr, kubeclientset)
|
||||
|
||||
t.Run("Test_getRepo", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
|
||||
s := NewServer(&repoServerClientset, argoDB, enforcer, nil, appLister, projLister, settingsMgr)
|
||||
url := "https://test"
|
||||
repo, _ := s.getRepo(context.TODO(), url)
|
||||
assert.Equal(t, repo.Repo, url)
|
||||
})
|
||||
|
||||
t.Run("Test_validateAccess", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClient.On("TestRepository", mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
|
||||
s := NewServer(&repoServerClientset, argoDB, enforcer, nil, appLister, projLister, settingsMgr)
|
||||
url := "https://test"
|
||||
_, err := s.ValidateAccess(context.TODO(), &repository.RepoAccessQuery{
|
||||
Repo: url,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
})
|
||||
|
||||
t.Run("Test_Get", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClient.On("TestRepository", mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
db.On("RepositoryExists", context.TODO(), url).Return(true, nil)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
repo, err := s.Get(context.TODO(), &repository.RepoQuery{
|
||||
Repo: url,
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, repo.Repo, url)
|
||||
})
|
||||
|
||||
t.Run("Test_CreateRepositoryWithoutUpsert", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClient.On("TestRepository", mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), "test").Return(nil, errors.New("not found"))
|
||||
db.On("CreateRepository", context.TODO(), mock.Anything).Return(&apiclient.TestRepositoryResponse{}).Return(&appsv1.Repository{
|
||||
Repo: "repo",
|
||||
}, nil)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
repo, err := s.CreateRepository(context.TODO(), &repository.RepoCreateRequest{
|
||||
Repo: &appsv1.Repository{
|
||||
Repo: "test",
|
||||
Username: "test",
|
||||
},
|
||||
})
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, repo.Repo, "repo")
|
||||
})
|
||||
|
||||
t.Run("Test_CreateRepositoryWithUpsert", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClient.On("TestRepository", mock.Anything, mock.Anything).Return(&apiclient.TestRepositoryResponse{}, nil)
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), "test").Return(&appsv1.Repository{
|
||||
Repo: "test",
|
||||
Username: "test",
|
||||
}, nil)
|
||||
db.On("CreateRepository", context.TODO(), mock.Anything).Return(nil, status.Errorf(codes.AlreadyExists, "repository already exists"))
|
||||
db.On("UpdateRepository", context.TODO(), mock.Anything).Return(nil, nil)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
repo, err := s.CreateRepository(context.TODO(), &repository.RepoCreateRequest{
|
||||
Repo: &appsv1.Repository{
|
||||
Repo: "test",
|
||||
Username: "test",
|
||||
},
|
||||
Upsert: true,
|
||||
})
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, repo.Repo, "test")
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func TestRepositoryServerListApps(t *testing.T) {
|
||||
kubeclientset := fake.NewSimpleClientset(&argocdCM, &argocdSecret)
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, testNamespace)
|
||||
|
||||
t.Run("Test_WithoutAppCreateUpdatePrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
enforcer.SetDefaultRole("role:readonly")
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.ListApps(context.TODO(), &repository.RepoAppsQuery{
|
||||
Repo: "https://test",
|
||||
Revision: "HEAD",
|
||||
AppName: "foo",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Nil(t, resp)
|
||||
assert.Equal(t, err, errPermissionDenied)
|
||||
})
|
||||
|
||||
t.Run("Test_WithAppCreateUpdatePrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
enforcer.SetDefaultRole("role:admin")
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
repoServerClient.On("ListApps", context.TODO(), mock.Anything).Return(&apiclient.AppList{
|
||||
Apps: map[string]string{
|
||||
"path/to/dir": "Kustomize",
|
||||
},
|
||||
}, nil)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.ListApps(context.TODO(), &repository.RepoAppsQuery{
|
||||
Repo: "https://test",
|
||||
Revision: "HEAD",
|
||||
AppName: "foo",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, resp.Items, 1)
|
||||
assert.Equal(t, "path/to/dir", resp.Items[0].Path)
|
||||
assert.Equal(t, "Kustomize", resp.Items[0].Type)
|
||||
})
|
||||
|
||||
t.Run("Test_WithAppCreateUpdatePrivilegesRepoNotAllowed", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
enforcer.SetDefaultRole("role:admin")
|
||||
appLister, projLister := newAppAndProjLister(defaultProjNoSources)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
repoServerClient.On("ListApps", context.TODO(), mock.Anything).Return(&apiclient.AppList{
|
||||
Apps: map[string]string{
|
||||
"path/to/dir": "Kustomize",
|
||||
},
|
||||
}, nil)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.ListApps(context.TODO(), &repository.RepoAppsQuery{
|
||||
Repo: "https://test",
|
||||
Revision: "HEAD",
|
||||
AppName: "foo",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Nil(t, resp)
|
||||
assert.Error(t, err, "repository 'https://test' not permitted in project 'default'")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepositoryServerGetAppDetails(t *testing.T) {
|
||||
kubeclientset := fake.NewSimpleClientset(&argocdCM, &argocdSecret)
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), kubeclientset, testNamespace)
|
||||
|
||||
t.Run("Test_WithoutRepoReadPrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
enforcer.SetDefaultRole("")
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &appsv1.ApplicationSource{
|
||||
RepoURL: url,
|
||||
},
|
||||
AppName: "newapp",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Nil(t, resp)
|
||||
assert.Error(t, err, "rpc error: code = PermissionDenied desc = permission denied: repositories, get, https://test")
|
||||
})
|
||||
t.Run("Test_WithoutAppReadPrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
_ = enforcer.SetUserPolicy("p, role:readrepos, repositories, get, *, allow")
|
||||
enforcer.SetDefaultRole("role:readrepos")
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &appsv1.ApplicationSource{
|
||||
RepoURL: url,
|
||||
},
|
||||
AppName: "newapp",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Nil(t, resp)
|
||||
assert.Error(t, err, "rpc error: code = PermissionDenied desc = permission denied: applications, get, default/newapp")
|
||||
})
|
||||
t.Run("Test_WithoutCreatePrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
enforcer.SetDefaultRole("role:readonly")
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &appsv1.ApplicationSource{
|
||||
RepoURL: url,
|
||||
},
|
||||
AppName: "newapp",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Nil(t, resp)
|
||||
assert.Error(t, err, "rpc error: code = PermissionDenied desc = permission denied: applications, create, default/newapp")
|
||||
})
|
||||
t.Run("Test_WithCreatePrivileges", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("ListHelmRepositories", context.TODO(), mock.Anything).Return(nil, nil)
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
expectedResp := apiclient.RepoAppDetailsResponse{Type: "Directory"}
|
||||
repoServerClient.On("GetAppDetails", context.TODO(), mock.Anything).Return(&expectedResp, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &appsv1.ApplicationSource{
|
||||
RepoURL: url,
|
||||
},
|
||||
AppName: "newapp",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedResp, *resp)
|
||||
})
|
||||
t.Run("Test_RepoNotPermitted", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
expectedResp := apiclient.RepoAppDetailsResponse{Type: "Directory"}
|
||||
repoServerClient.On("GetAppDetails", context.TODO(), mock.Anything).Return(&expectedResp, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProjNoSources)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &appsv1.ApplicationSource{
|
||||
RepoURL: url,
|
||||
},
|
||||
AppName: "newapp",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Error(t, err, "repository 'https://test' not permitted in project 'default'")
|
||||
assert.Nil(t, resp)
|
||||
})
|
||||
t.Run("Test_ExistingApp", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("ListHelmRepositories", context.TODO(), mock.Anything).Return(nil, nil)
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
expectedResp := apiclient.RepoAppDetailsResponse{Type: "Directory"}
|
||||
repoServerClient.On("GetAppDetails", context.TODO(), mock.Anything).Return(&expectedResp, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj, guestbookApp)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &guestbookApp.Spec.Source,
|
||||
AppName: "guestbook",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedResp, *resp)
|
||||
})
|
||||
t.Run("Test_ExistingAppMismatchedProjectName", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj, guestbookApp)
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: &guestbookApp.Spec.Source,
|
||||
AppName: "guestbook",
|
||||
AppProject: "mismatch",
|
||||
})
|
||||
assert.Equal(t, errPermissionDenied, err)
|
||||
assert.Nil(t, resp)
|
||||
})
|
||||
t.Run("Test_ExistingAppSourceNotInHistory", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj, guestbookApp)
|
||||
differentSource := guestbookApp.Spec.Source.DeepCopy()
|
||||
differentSource.Helm.ValueFiles = []string{"/etc/passwd"}
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: differentSource,
|
||||
AppName: "guestbook",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.Equal(t, errPermissionDenied, err)
|
||||
assert.Nil(t, resp)
|
||||
})
|
||||
t.Run("Test_ExistingAppSourceInHistory", func(t *testing.T) {
|
||||
repoServerClient := mocks.RepoServerServiceClient{}
|
||||
repoServerClientset := mocks.Clientset{RepoServerServiceClient: &repoServerClient}
|
||||
enforcer := newEnforcer(kubeclientset)
|
||||
|
||||
url := "https://test"
|
||||
db := &dbmocks.ArgoDB{}
|
||||
db.On("GetRepository", context.TODO(), url).Return(&appsv1.Repository{Repo: url}, nil)
|
||||
db.On("ListHelmRepositories", context.TODO(), mock.Anything).Return(nil, nil)
|
||||
expectedResp := apiclient.RepoAppDetailsResponse{Type: "Directory"}
|
||||
repoServerClient.On("GetAppDetails", context.TODO(), mock.Anything).Return(&expectedResp, nil)
|
||||
appLister, projLister := newAppAndProjLister(defaultProj, guestbookApp)
|
||||
previousSource := guestbookApp.Status.History[0].Source.DeepCopy()
|
||||
previousSource.TargetRevision = guestbookApp.Status.History[0].Revision
|
||||
|
||||
s := NewServer(&repoServerClientset, db, enforcer, newFixtures().Cache, appLister, projLister, settingsMgr)
|
||||
resp, err := s.GetAppDetails(context.TODO(), &repository.RepoAppDetailsQuery{
|
||||
Source: previousSource,
|
||||
AppName: "guestbook",
|
||||
AppProject: "default",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, expectedResp, *resp)
|
||||
})
|
||||
}
|
||||
|
||||
type fixtures struct {
|
||||
*cache.Cache
|
||||
}
|
||||
|
||||
func newFixtures() *fixtures {
|
||||
return &fixtures{cache.NewCache(
|
||||
appstatecache.NewCache(
|
||||
cacheutil.NewCache(cacheutil.NewInMemoryCache(1*time.Hour)),
|
||||
1*time.Minute,
|
||||
),
|
||||
1*time.Minute,
|
||||
1*time.Minute,
|
||||
1*time.Minute,
|
||||
)}
|
||||
}
|
||||
|
||||
func newEnforcer(kubeclientset *fake.Clientset) *rbac.Enforcer {
|
||||
enforcer := rbac.NewEnforcer(kubeclientset, testNamespace, common.ArgoCDRBACConfigMapName, nil)
|
||||
_ = enforcer.SetBuiltinPolicy(assets.BuiltinPolicyCSV)
|
||||
enforcer.SetDefaultRole("role:admin")
|
||||
enforcer.SetClaimsEnforcerFunc(func(claims jwt.Claims, rvals ...interface{}) bool {
|
||||
return true
|
||||
})
|
||||
return enforcer
|
||||
}
|
||||
@@ -154,6 +154,7 @@ type ArgoCDServer struct {
|
||||
settingsMgr *settings_util.SettingsManager
|
||||
enf *rbac.Enforcer
|
||||
projInformer cache.SharedIndexInformer
|
||||
projLister applisters.AppProjectNamespaceLister
|
||||
policyEnforcer *rbacpolicy.RBACPolicyEnforcer
|
||||
appInformer cache.SharedIndexInformer
|
||||
appLister applisters.ApplicationNamespaceLister
|
||||
@@ -248,6 +249,7 @@ func NewServer(ctx context.Context, opts ArgoCDServerOpts) *ArgoCDServer {
|
||||
settingsMgr: settingsMgr,
|
||||
enf: enf,
|
||||
projInformer: projInformer,
|
||||
projLister: projLister,
|
||||
appInformer: appInformer,
|
||||
appLister: appLister,
|
||||
policyEnforcer: policyEnf,
|
||||
@@ -560,7 +562,7 @@ func (a *ArgoCDServer) newGRPCServer() *grpc.Server {
|
||||
db := db.NewDB(a.Namespace, a.settingsMgr, a.KubeClientset)
|
||||
kubectl := kubeutil.NewKubectl()
|
||||
clusterService := cluster.NewServer(db, a.enf, a.Cache, kubectl)
|
||||
repoService := repository.NewServer(a.RepoClientset, db, a.enf, a.Cache, a.settingsMgr)
|
||||
repoService := repository.NewServer(a.RepoClientset, db, a.enf, a.Cache, a.appLister, a.projLister, a.settingsMgr)
|
||||
repoCredsService := repocreds.NewServer(a.RepoClientset, db, a.enf, a.settingsMgr)
|
||||
var loginRateLimiter func() (io.Closer, error)
|
||||
if maxConcurrentLoginRequestsCount > 0 {
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
. "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
. "github.com/argoproj/argo-cd/v2/test/e2e/fixture"
|
||||
. "github.com/argoproj/argo-cd/v2/test/e2e/fixture/app"
|
||||
projectFixture "github.com/argoproj/argo-cd/v2/test/e2e/fixture/project"
|
||||
. "github.com/argoproj/argo-cd/v2/util/argo"
|
||||
. "github.com/argoproj/argo-cd/v2/util/errors"
|
||||
"github.com/argoproj/argo-cd/v2/util/io"
|
||||
@@ -621,7 +622,9 @@ func TestKsonnetApp(t *testing.T) {
|
||||
defer io.Close(closer)
|
||||
|
||||
details, err := client.GetAppDetails(context.Background(), &repositorypkg.RepoAppDetailsQuery{
|
||||
Source: &app.Spec.Source,
|
||||
AppName: app.Name,
|
||||
AppProject: app.Spec.Project,
|
||||
Source: &app.Spec.Source,
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
@@ -799,64 +802,125 @@ func TestSyncAsync(t *testing.T) {
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced))
|
||||
}
|
||||
|
||||
func TestPermissions(t *testing.T) {
|
||||
EnsureCleanState(t)
|
||||
appName := Name()
|
||||
_, err := RunCli("proj", "create", "test")
|
||||
assert.NoError(t, err)
|
||||
|
||||
// make sure app cannot be created without permissions in project
|
||||
_, err = RunCli("app", "create", appName, "--repo", RepoURL(RepoURLTypeFile),
|
||||
"--path", guestbookPath, "--project", "test", "--dest-server", KubernetesInternalAPIServerAddr, "--dest-namespace", DeploymentNamespace())
|
||||
assert.Error(t, err)
|
||||
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'test'", RepoURL(RepoURLTypeFile))
|
||||
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'test'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
|
||||
|
||||
assert.Contains(t, err.Error(), sourceError)
|
||||
assert.Contains(t, err.Error(), destinationError)
|
||||
|
||||
proj, err := AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Get(context.Background(), "test", metav1.GetOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
proj.Spec.Destinations = []ApplicationDestination{{Server: "*", Namespace: "*"}}
|
||||
proj.Spec.SourceRepos = []string{"*"}
|
||||
proj, err = AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Update(context.Background(), proj, metav1.UpdateOptions{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// make sure controller report permissions issues in conditions
|
||||
_, err = RunCli("app", "create", appName, "--repo", RepoURL(RepoURLTypeFile),
|
||||
"--path", guestbookPath, "--project", "test", "--dest-server", KubernetesInternalAPIServerAddr, "--dest-namespace", DeploymentNamespace())
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
err = AppClientset.ArgoprojV1alpha1().Applications(ArgoCDNamespace).Delete(context.Background(), appName, metav1.DeleteOptions{})
|
||||
assert.NoError(t, err)
|
||||
}()
|
||||
|
||||
proj.Spec.Destinations = []ApplicationDestination{}
|
||||
proj.Spec.SourceRepos = []string{}
|
||||
_, err = AppClientset.ArgoprojV1alpha1().AppProjects(ArgoCDNamespace).Update(context.Background(), proj, metav1.UpdateOptions{})
|
||||
assert.NoError(t, err)
|
||||
time.Sleep(1 * time.Second)
|
||||
closer, client, err := ArgoCDClientset.NewApplicationClient()
|
||||
assert.NoError(t, err)
|
||||
defer io.Close(closer)
|
||||
|
||||
refresh := string(RefreshTypeNormal)
|
||||
app, err := client.Get(context.Background(), &applicationpkg.ApplicationQuery{Name: &appName, Refresh: &refresh})
|
||||
assert.NoError(t, err)
|
||||
|
||||
destinationErrorExist := false
|
||||
sourceErrorExist := false
|
||||
for i := range app.Status.Conditions {
|
||||
if strings.Contains(app.Status.Conditions[i].Message, destinationError) {
|
||||
destinationErrorExist = true
|
||||
}
|
||||
if strings.Contains(app.Status.Conditions[i].Message, sourceError) {
|
||||
sourceErrorExist = true
|
||||
// assertResourceActions verifies if view/modify resource actions are successful/failing for given application
|
||||
func assertResourceActions(t *testing.T, appName string, successful bool) {
|
||||
assertError := func(err error, message string) {
|
||||
if successful {
|
||||
assert.NoError(t, err)
|
||||
} else {
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), message)
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.True(t, destinationErrorExist)
|
||||
assert.True(t, sourceErrorExist)
|
||||
|
||||
closer, cdClient := ArgoCDClientset.NewApplicationClientOrDie()
|
||||
defer io.Close(closer)
|
||||
|
||||
deploymentResource, err := KubeClientset.AppsV1().Deployments(DeploymentNamespace()).Get(context.Background(), "guestbook-ui", metav1.GetOptions{})
|
||||
require.NoError(t, err)
|
||||
|
||||
logs, err := cdClient.PodLogs(context.Background(), &applicationpkg.ApplicationPodLogsQuery{
|
||||
Group: pointer.StringPtr("apps"), Kind: pointer.StringPtr("Deployment"), Name: &appName, Namespace: DeploymentNamespace(),
|
||||
})
|
||||
require.NoError(t, err)
|
||||
_, err = logs.Recv()
|
||||
assertError(err, "EOF")
|
||||
|
||||
expectedError := fmt.Sprintf("Deployment apps guestbook-ui not found as part of application %s", appName)
|
||||
|
||||
_, err = cdClient.ListResourceEvents(context.Background(), &applicationpkg.ApplicationResourceEventsQuery{
|
||||
Name: &appName, ResourceName: "guestbook-ui", ResourceNamespace: DeploymentNamespace(), ResourceUID: string(deploymentResource.UID)})
|
||||
assertError(err, fmt.Sprintf("%s not found as part of application %s", "guestbook-ui", appName))
|
||||
|
||||
_, err = cdClient.GetResource(context.Background(), &applicationpkg.ApplicationResourceRequest{
|
||||
Name: &appName, ResourceName: "guestbook-ui", Namespace: DeploymentNamespace(), Version: "v1", Group: "apps", Kind: "Deployment"})
|
||||
assertError(err, expectedError)
|
||||
|
||||
_, err = cdClient.DeleteResource(context.Background(), &applicationpkg.ApplicationResourceDeleteRequest{
|
||||
Name: &appName, ResourceName: "guestbook-ui", Namespace: DeploymentNamespace(), Version: "v1", Group: "apps", Kind: "Deployment",
|
||||
})
|
||||
assertError(err, expectedError)
|
||||
|
||||
_, err = cdClient.RunResourceAction(context.Background(), &applicationpkg.ResourceActionRunRequest{
|
||||
Name: &appName, ResourceName: "guestbook-ui", Namespace: DeploymentNamespace(), Version: "v1", Group: "apps", Kind: "Deployment", Action: "restart",
|
||||
})
|
||||
assertError(err, expectedError)
|
||||
}
|
||||
|
||||
func TestPermissions(t *testing.T) {
|
||||
appCtx := Given(t)
|
||||
projName := "argo-project"
|
||||
projActions := projectFixture.
|
||||
Given(t).
|
||||
Name(projName).
|
||||
When().
|
||||
Create()
|
||||
|
||||
sourceError := fmt.Sprintf("application repo %s is not permitted in project 'argo-project'", RepoURL(RepoURLTypeFile))
|
||||
destinationError := fmt.Sprintf("application destination {%s %s} is not permitted in project 'argo-project'", KubernetesInternalAPIServerAddr, DeploymentNamespace())
|
||||
|
||||
appCtx.
|
||||
Path("guestbook-logs").
|
||||
Project(projName).
|
||||
When().
|
||||
IgnoreErrors().
|
||||
// ensure app is not created if project permissions are missing
|
||||
Create().
|
||||
Then().
|
||||
Expect(Error("", sourceError)).
|
||||
Expect(Error("", destinationError)).
|
||||
When().
|
||||
DoNotIgnoreErrors().
|
||||
// add missing permissions, create and sync app
|
||||
And(func() {
|
||||
projActions.AddDestination("*", "*")
|
||||
projActions.AddSource("*")
|
||||
}).
|
||||
Create().
|
||||
Sync().
|
||||
Then().
|
||||
// make sure application resource actiions are successful
|
||||
And(func(app *Application) {
|
||||
assertResourceActions(t, app.Name, true)
|
||||
}).
|
||||
When().
|
||||
// remove projet permissions and "refresh" app
|
||||
And(func() {
|
||||
projActions.UpdateProject(func(proj *AppProject) {
|
||||
proj.Spec.Destinations = nil
|
||||
proj.Spec.SourceRepos = nil
|
||||
})
|
||||
}).
|
||||
Refresh(RefreshTypeNormal).
|
||||
Then().
|
||||
// ensure app resource tree is empty when source/destination permissions are missing
|
||||
Expect(Condition(ApplicationConditionInvalidSpecError, destinationError)).
|
||||
Expect(Condition(ApplicationConditionInvalidSpecError, sourceError)).
|
||||
And(func(app *Application) {
|
||||
closer, cdClient := ArgoCDClientset.NewApplicationClientOrDie()
|
||||
defer io.Close(closer)
|
||||
tree, err := cdClient.ResourceTree(context.Background(), &applicationpkg.ResourcesQuery{ApplicationName: &app.Name})
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, tree.Nodes, 0)
|
||||
assert.Len(t, tree.OrphanedNodes, 0)
|
||||
}).
|
||||
When().
|
||||
// add missing permissions but deny management of Deployment kind
|
||||
And(func() {
|
||||
projActions.
|
||||
AddDestination("*", "*").
|
||||
AddSource("*").
|
||||
UpdateProject(func(proj *AppProject) {
|
||||
proj.Spec.NamespaceResourceBlacklist = []metav1.GroupKind{{Group: "*", Kind: "Deployment"}}
|
||||
})
|
||||
}).
|
||||
Refresh(RefreshTypeNormal).
|
||||
Then().
|
||||
// make sure application resource actiions are failing
|
||||
And(func(app *Application) {
|
||||
assertResourceActions(t, "test-permissions", false)
|
||||
})
|
||||
}
|
||||
|
||||
// make sure that if we deleted a resource from the app, it is not pruned if annotated with Prune=false
|
||||
|
||||
103
test/e2e/fixture/project/actions.go
Normal file
103
test/e2e/fixture/project/actions.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1"
|
||||
"github.com/argoproj/argo-cd/v2/test/e2e/fixture"
|
||||
)
|
||||
|
||||
// this implements the "when" part of given/when/then
|
||||
//
|
||||
// none of the func implement error checks, and that is complete intended, you should check for errors
|
||||
// using the Then()
|
||||
type Actions struct {
|
||||
context *Context
|
||||
lastOutput string
|
||||
lastError error
|
||||
ignoreErrors bool
|
||||
}
|
||||
|
||||
func (a *Actions) IgnoreErrors() *Actions {
|
||||
a.ignoreErrors = true
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) DoNotIgnoreErrors() *Actions {
|
||||
a.ignoreErrors = false
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) Create(args ...string) *Actions {
|
||||
args = a.prepareCreateArgs(args)
|
||||
|
||||
// are you adding new context values? if you only use them for this func, then use args instead
|
||||
a.runCli(args...)
|
||||
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) AddDestination(cluster string, namespace string) *Actions {
|
||||
a.runCli("proj", "add-destination", a.context.name, cluster, namespace)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) AddSource(repo string) *Actions {
|
||||
a.runCli("proj", "add-source", a.context.name, repo)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) UpdateProject(updater func(project *v1alpha1.AppProject)) *Actions {
|
||||
proj, err := fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Get(context.TODO(), a.context.name, v1.GetOptions{})
|
||||
require.NoError(a.context.t, err)
|
||||
updater(proj)
|
||||
_, err = fixture.AppClientset.ArgoprojV1alpha1().AppProjects(fixture.ArgoCDNamespace).Update(context.TODO(), proj, v1.UpdateOptions{})
|
||||
require.NoError(a.context.t, err)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) Name(name string) *Actions {
|
||||
a.context.name = name
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) prepareCreateArgs(args []string) []string {
|
||||
a.context.t.Helper()
|
||||
args = append([]string{
|
||||
"proj", "create", a.context.name,
|
||||
}, args...)
|
||||
|
||||
if a.context.destination != "" {
|
||||
args = append(args, "--dest", a.context.destination)
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
func (a *Actions) Delete() *Actions {
|
||||
a.context.t.Helper()
|
||||
a.runCli("proj", "delete", a.context.name)
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) And(block func()) *Actions {
|
||||
a.context.t.Helper()
|
||||
block()
|
||||
return a
|
||||
}
|
||||
|
||||
func (a *Actions) Then() *Consequences {
|
||||
a.context.t.Helper()
|
||||
return &Consequences{a.context, a}
|
||||
}
|
||||
|
||||
func (a *Actions) runCli(args ...string) {
|
||||
a.context.t.Helper()
|
||||
a.lastOutput, a.lastError = fixture.RunCli(args...)
|
||||
if !a.ignoreErrors {
|
||||
require.Empty(a.context.t, a.lastError)
|
||||
}
|
||||
}
|
||||
19
test/e2e/fixture/project/consequences.go
Normal file
19
test/e2e/fixture/project/consequences.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package project
|
||||
|
||||
// this implements the "then" part of given/when/then
|
||||
type Consequences struct {
|
||||
context *Context
|
||||
actions *Actions
|
||||
}
|
||||
|
||||
func (c *Consequences) Expect() *Consequences {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Consequences) Given() *Context {
|
||||
return c.context
|
||||
}
|
||||
|
||||
func (c *Consequences) When() *Actions {
|
||||
return c.actions
|
||||
}
|
||||
55
test/e2e/fixture/project/context.go
Normal file
55
test/e2e/fixture/project/context.go
Normal file
@@ -0,0 +1,55 @@
|
||||
package project
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/test/e2e/fixture"
|
||||
"github.com/argoproj/argo-cd/v2/util/env"
|
||||
)
|
||||
|
||||
// this implements the "given" part of given/when/then
|
||||
type Context struct {
|
||||
t *testing.T
|
||||
// seconds
|
||||
timeout int
|
||||
name string
|
||||
destination string
|
||||
}
|
||||
|
||||
func Given(t *testing.T) *Context {
|
||||
fixture.EnsureCleanState(t)
|
||||
return GivenWithSameState(t)
|
||||
}
|
||||
|
||||
func GivenWithSameState(t *testing.T) *Context {
|
||||
// ARGOCE_E2E_DEFAULT_TIMEOUT can be used to override the default timeout
|
||||
// for any context.
|
||||
timeout := env.ParseNumFromEnv("ARGOCD_E2E_DEFAULT_TIMEOUT", 10, 0, 180)
|
||||
return &Context{t: t, name: fixture.Name(), timeout: timeout}
|
||||
}
|
||||
|
||||
func (c *Context) GetName() string {
|
||||
return c.name
|
||||
}
|
||||
|
||||
func (c *Context) Name(name string) *Context {
|
||||
c.name = name
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Context) Destination(destination string) *Context {
|
||||
c.destination = destination
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Context) And(block func()) *Context {
|
||||
block()
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Context) When() *Actions {
|
||||
// in case any settings have changed, pause for 1s, not great, but fine
|
||||
time.Sleep(1 * time.Second)
|
||||
return &Actions{context: c}
|
||||
}
|
||||
@@ -549,24 +549,3 @@ func TestTemplatesHelmOCIWithDependencies(t *testing.T) {
|
||||
Expect(HealthIs(health.HealthStatusHealthy)).
|
||||
Expect(SyncStatusIs(SyncStatusCodeSynced))
|
||||
}
|
||||
|
||||
// This is for the scenario of application source is from Git repo which has a helm chart with helm OCI registry dependency.
|
||||
// When the application project only allows git repository, this app creation should fail.
|
||||
func TestRepoPermission(t *testing.T) {
|
||||
Given(t).
|
||||
And(func() {
|
||||
repoURL := fixture.RepoURL("")
|
||||
output := FailOnErr(RunCli("proj", "remove-source", "default", "*")).(string)
|
||||
assert.Empty(t, output)
|
||||
output = FailOnErr(RunCli("proj", "add-source", "default", repoURL)).(string)
|
||||
assert.Empty(t, output)
|
||||
}).
|
||||
PushChartToOCIRegistry("helm-values", "helm-values", "1.0.0").
|
||||
HelmOCIRepoAdded("myrepo").
|
||||
Path("helm-oci-with-dependencies").
|
||||
When().
|
||||
IgnoreErrors().
|
||||
Create().
|
||||
Then().
|
||||
Expect(Error("", "Unable to generate manifests"))
|
||||
}
|
||||
|
||||
@@ -279,7 +279,7 @@ export const ApplicationCreatePanel = (props: {
|
||||
load={async src =>
|
||||
(src.repoURL &&
|
||||
services.repos
|
||||
.apps(src.repoURL, src.revision)
|
||||
.apps(src.repoURL, src.revision, app.metadata.name, app.spec.project)
|
||||
.then(apps => Array.from(new Set(apps.map(item => item.path))).sort())
|
||||
.catch(() => new Array<string>())) ||
|
||||
new Array<string>()
|
||||
@@ -419,7 +419,7 @@ export const ApplicationCreatePanel = (props: {
|
||||
}}
|
||||
load={async src => {
|
||||
if (src.repoURL && src.targetRevision && (src.path || src.chart)) {
|
||||
return services.repos.appDetails(src, src.appName).catch(() => ({
|
||||
return services.repos.appDetails(src, src.appName, app.spec.project).catch(() => ({
|
||||
type: 'Directory',
|
||||
details: {}
|
||||
}));
|
||||
|
||||
@@ -80,7 +80,7 @@ export const ApplicationDeploymentHistory = ({
|
||||
/>
|
||||
<DataLoader
|
||||
input={{...recentDeployments[index].source, targetRevision: recentDeployments[index].revision, appName: app.metadata.name}}
|
||||
load={src => services.repos.appDetails(src, src.appName)}>
|
||||
load={src => services.repos.appDetails(src, src.appName, app.spec.project)}>
|
||||
{(details: models.RepoAppDetails) => (
|
||||
<div>
|
||||
<ApplicationParameters
|
||||
|
||||
@@ -2,6 +2,7 @@ import {DataLoader, Tab, Tabs} from 'argo-ui';
|
||||
import {useData} from 'argo-ui/v2';
|
||||
import * as React from 'react';
|
||||
import {EventsList, YamlEditor} from '../../../shared/components';
|
||||
import {ErrorBoundary} from '../../../shared/components/error-boundary/error-boundary';
|
||||
import {Context} from '../../../shared/context';
|
||||
import {Application, ApplicationTree, AppSourceType, Event, RepoAppDetails, ResourceNode, State, SyncStatuses} from '../../../shared/models';
|
||||
import {services} from '../../../shared/services';
|
||||
@@ -119,9 +120,9 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
title: 'More',
|
||||
key: 'extension',
|
||||
content: (
|
||||
<div>
|
||||
<ErrorBoundary message={`Something went wrong with Extension for ${state.kind}`}>
|
||||
<ExtensionComponent tree={tree} resource={state} />
|
||||
</div>
|
||||
</ErrorBoundary>
|
||||
)
|
||||
});
|
||||
}
|
||||
@@ -143,7 +144,7 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
key='appDetails'
|
||||
input={application}
|
||||
load={app =>
|
||||
services.repos.appDetails(app.spec.source, app.metadata.name).catch(() => ({
|
||||
services.repos.appDetails(app.spec.source, app.metadata.name, app.spec.project).catch(() => ({
|
||||
type: 'Directory' as AppSourceType,
|
||||
path: application.spec.source.path
|
||||
}))
|
||||
@@ -196,10 +197,16 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
return tabs;
|
||||
};
|
||||
|
||||
const [extension] = useData(() => services.extensions.loadResourceExtension(selectedNode?.group || '', selectedNode?.kind || ''), null, null, [
|
||||
selectedNode?.group,
|
||||
selectedNode?.kind
|
||||
]);
|
||||
const [extension, , error] = useData(
|
||||
async () => {
|
||||
if (selectedNode?.kind && selectedNode?.group) {
|
||||
return await services.extensions.loadResourceExtension(selectedNode?.group || '', selectedNode?.kind || '');
|
||||
}
|
||||
},
|
||||
null,
|
||||
null,
|
||||
[selectedNode]
|
||||
);
|
||||
|
||||
return (
|
||||
<div style={{width: '100%', height: '100%'}}>
|
||||
@@ -272,7 +279,7 @@ export const ResourceDetails = (props: ResourceDetailsProps) => {
|
||||
</div>
|
||||
<Tabs
|
||||
navTransparent={true}
|
||||
tabs={getResourceTabs(selectedNode, data.liveState, data.podState, data.events, extension?.component, [
|
||||
tabs={getResourceTabs(selectedNode, data.liveState, data.podState, data.events, error.state ? null : extension?.component, [
|
||||
{
|
||||
title: 'SUMMARY',
|
||||
icon: 'fa fa-file-alt',
|
||||
|
||||
@@ -40,6 +40,12 @@ test('getOperationType.Sync.Operation', () => {
|
||||
expect(state).toBe('Sync');
|
||||
});
|
||||
|
||||
test('getOperationType.DeleteAndRecentSync', () => {
|
||||
const state = getOperationType({metadata: {deletionTimestamp: '123'}, status: {operationState: {operation: {sync: {}}}}} as Application);
|
||||
|
||||
expect(state).toBe('Delete');
|
||||
});
|
||||
|
||||
test('getOperationType.Sync.Status', () => {
|
||||
const state = getOperationType({metadata: {}, status: {operationState: {operation: {sync: {}}}}} as Application);
|
||||
|
||||
|
||||
@@ -597,12 +597,12 @@ export const getAppOperationState = (app: appModels.Application): appModels.Oper
|
||||
|
||||
export function getOperationType(application: appModels.Application) {
|
||||
const operation = application.operation || (application.status && application.status.operationState && application.status.operationState.operation);
|
||||
if (application.metadata.deletionTimestamp && !application.operation) {
|
||||
return 'Delete';
|
||||
}
|
||||
if (operation && operation.sync) {
|
||||
return 'Sync';
|
||||
}
|
||||
if (application.metadata.deletionTimestamp) {
|
||||
return 'Delete';
|
||||
}
|
||||
return 'Unknown';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
import * as React from 'react';
|
||||
|
||||
export class ErrorBoundary extends React.Component<{message?: string}, {hasError: boolean}> {
|
||||
constructor(props: any) {
|
||||
super(props);
|
||||
this.state = {hasError: false};
|
||||
}
|
||||
|
||||
static getDerivedStateFromError(error: React.ErrorInfo) {
|
||||
return {hasError: true};
|
||||
}
|
||||
|
||||
render() {
|
||||
if (this.state.hasError) {
|
||||
return <h1>{this.props.message ? this.props.message : 'Something went wrong.'}</h1>;
|
||||
}
|
||||
|
||||
return this.props.children;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import {ApplicationTree, State} from '../models';
|
||||
|
||||
const extensions: {[key: string]: Extension} = {};
|
||||
const extensions: {resources: {[key: string]: Extension}} = {resources: {}};
|
||||
const cache = new Map<string, Promise<Extension>>();
|
||||
|
||||
export interface Extension {
|
||||
@@ -15,14 +15,14 @@ export interface ExtensionComponentProps {
|
||||
|
||||
export class ExtensionsService {
|
||||
public async loadResourceExtension(group: string, kind: string): Promise<Extension> {
|
||||
const key = `${group}-${kind}`;
|
||||
const key = `${group}/${kind}`;
|
||||
const res =
|
||||
cache.get(key) ||
|
||||
new Promise<Extension>((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = `extensions/${group}/${kind}/ui/extensions.js`;
|
||||
script.src = `extensions/resources/${group}/${kind}/ui/extensions.js`;
|
||||
script.onload = () => {
|
||||
const ext = extensions[key];
|
||||
const ext = extensions.resources[key];
|
||||
if (!ext) {
|
||||
reject(`Failed to load extension for ${group}/${kind}`);
|
||||
} else {
|
||||
|
||||
@@ -125,10 +125,12 @@ export class RepositoriesService {
|
||||
return requests.get(`/repositories/${encodeURIComponent(repo)}/refs`).then(res => res.body as models.RefsInfo);
|
||||
}
|
||||
|
||||
public apps(repo: string, revision: string): Promise<models.AppInfo[]> {
|
||||
public apps(repo: string, revision: string, appName: string, appProject: string): Promise<models.AppInfo[]> {
|
||||
return requests
|
||||
.get(`/repositories/${encodeURIComponent(repo)}/apps`)
|
||||
.query({revision})
|
||||
.query({appName})
|
||||
.query({appProject})
|
||||
.then(res => (res.body.items as models.AppInfo[]) || []);
|
||||
}
|
||||
|
||||
@@ -136,10 +138,10 @@ export class RepositoriesService {
|
||||
return requests.get(`/repositories/${encodeURIComponent(repo)}/helmcharts`).then(res => (res.body.items as models.HelmChart[]) || []);
|
||||
}
|
||||
|
||||
public appDetails(source: models.ApplicationSource, appName: string): Promise<models.RepoAppDetails> {
|
||||
public appDetails(source: models.ApplicationSource, appName: string, appProject: string): Promise<models.RepoAppDetails> {
|
||||
return requests
|
||||
.post(`/repositories/${encodeURIComponent(source.repoURL)}/appdetails`)
|
||||
.send({source, appName})
|
||||
.send({source, appName, appProject})
|
||||
.then(res => res.body as models.RepoAppDetails);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,6 +180,7 @@ func ValidateRepo(
|
||||
plugins []*argoappv1.ConfigManagementPlugin,
|
||||
kubectl kube.Kubectl,
|
||||
proj *argoappv1.AppProject,
|
||||
settingsMgr *settings.SettingsManager,
|
||||
) ([]argoappv1.ApplicationCondition, error) {
|
||||
spec := &app.Spec
|
||||
conditions := make([]argoappv1.ApplicationCondition, 0)
|
||||
@@ -218,6 +219,11 @@ func ValidateRepo(
|
||||
return conditions, nil
|
||||
}
|
||||
|
||||
helmOptions, err := settingsMgr.GetHelmSettings()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
helmRepos, err := db.ListHelmRepositories(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -240,6 +246,9 @@ func ValidateRepo(
|
||||
Source: &spec.Source,
|
||||
Repos: permittedHelmRepos,
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
// don't use case during application change to make sure to fetch latest git/helm revisions
|
||||
NoRevisionCache: true,
|
||||
HelmOptions: helmOptions,
|
||||
})
|
||||
if err != nil {
|
||||
conditions = append(conditions, argoappv1.ApplicationCondition{
|
||||
@@ -269,7 +278,17 @@ func ValidateRepo(
|
||||
return nil, err
|
||||
}
|
||||
conditions = append(conditions, verifyGenerateManifests(
|
||||
ctx, repo, permittedHelmRepos, app, repoClient, kustomizeOptions, plugins, cluster.ServerVersion, APIGroupsToVersions(apiGroups), permittedHelmCredentials)...)
|
||||
ctx,
|
||||
repo,
|
||||
permittedHelmRepos,
|
||||
helmOptions,
|
||||
app,
|
||||
repoClient,
|
||||
kustomizeOptions,
|
||||
plugins,
|
||||
cluster.ServerVersion,
|
||||
APIGroupsToVersions(apiGroups),
|
||||
permittedHelmCredentials)...)
|
||||
|
||||
return conditions, nil
|
||||
}
|
||||
@@ -389,18 +408,7 @@ func GetAppProject(spec *argoappv1.ApplicationSpec, projLister applicationsv1.Ap
|
||||
}
|
||||
|
||||
// verifyGenerateManifests verifies a repo path can generate manifests
|
||||
func verifyGenerateManifests(
|
||||
ctx context.Context,
|
||||
repoRes *argoappv1.Repository,
|
||||
helmRepos argoappv1.Repositories,
|
||||
app *argoappv1.Application,
|
||||
repoClient apiclient.RepoServerServiceClient,
|
||||
kustomizeOptions *argoappv1.KustomizeOptions,
|
||||
plugins []*argoappv1.ConfigManagementPlugin,
|
||||
kubeVersion string,
|
||||
apiVersions []string,
|
||||
repositoryCredentials []*argoappv1.RepoCreds,
|
||||
) []argoappv1.ApplicationCondition {
|
||||
func verifyGenerateManifests(ctx context.Context, repoRes *argoappv1.Repository, helmRepos argoappv1.Repositories, helmOptions *argoappv1.HelmOptions, app *argoappv1.Application, repoClient apiclient.RepoServerServiceClient, kustomizeOptions *argoappv1.KustomizeOptions, plugins []*argoappv1.ConfigManagementPlugin, kubeVersion string, apiVersions []string, repositoryCredentials []*argoappv1.RepoCreds) []argoappv1.ApplicationCondition {
|
||||
spec := &app.Spec
|
||||
var conditions []argoappv1.ApplicationCondition
|
||||
if spec.Destination.Server == "" {
|
||||
@@ -426,7 +434,9 @@ func verifyGenerateManifests(
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
KubeVersion: kubeVersion,
|
||||
ApiVersions: apiVersions,
|
||||
HelmOptions: helmOptions,
|
||||
HelmRepoCreds: repositoryCredentials,
|
||||
NoRevisionCache: true,
|
||||
}
|
||||
req.Repo.CopyCredentialsFromRepo(repoRes)
|
||||
req.Repo.CopySettingsFrom(repoRes)
|
||||
|
||||
@@ -250,6 +250,8 @@ func TestValidateRepo(t *testing.T) {
|
||||
Source: &app.Spec.Source,
|
||||
Repos: helmRepos,
|
||||
KustomizeOptions: kustomizeOptions,
|
||||
HelmOptions: &argoappv1.HelmOptions{ValuesFileSchemes: []string{"https", "http"}},
|
||||
NoRevisionCache: true,
|
||||
}).Return(&apiclient.RepoAppDetailsResponse{}, nil)
|
||||
|
||||
repo.Type = "git"
|
||||
@@ -275,7 +277,33 @@ func TestValidateRepo(t *testing.T) {
|
||||
return true
|
||||
})).Return(nil, nil)
|
||||
|
||||
conditions, err := ValidateRepo(context.Background(), app, repoClientSet, db, kustomizeOptions, nil, &kubetest.MockKubectlCmd{Version: kubeVersion, APIGroups: apiGroups}, proj)
|
||||
cm := corev1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "argocd-cm",
|
||||
Namespace: test.FakeArgoCDNamespace,
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string]string{
|
||||
"globalProjects": `
|
||||
- projectName: default-x
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: is-x
|
||||
operator: Exists
|
||||
- projectName: default-non-x
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: is-x
|
||||
operator: DoesNotExist
|
||||
`,
|
||||
},
|
||||
}
|
||||
kubeClient := fake.NewSimpleClientset(&cm)
|
||||
settingsMgr := settings.NewSettingsManager(context.Background(), kubeClient, test.FakeArgoCDNamespace)
|
||||
|
||||
conditions, err := ValidateRepo(context.Background(), app, repoClientSet, db, kustomizeOptions, nil, &kubetest.MockKubectlCmd{Version: kubeVersion, APIGroups: apiGroups}, proj, settingsMgr)
|
||||
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, conditions)
|
||||
|
||||
@@ -327,7 +327,6 @@ func TestNewFactory(t *testing.T) {
|
||||
defer addBinDirToPath.Close()
|
||||
closer := log.Debug()
|
||||
defer closer()
|
||||
|
||||
type args struct {
|
||||
url string
|
||||
insecureIgnoreHostKey bool
|
||||
@@ -337,7 +336,6 @@ func TestNewFactory(t *testing.T) {
|
||||
args args
|
||||
}{
|
||||
{"GitHub", args{url: "https://github.com/argoproj/argocd-example-apps"}},
|
||||
{"Azure", args{url: "https://jsuen0437@dev.azure.com/jsuen0437/jsuen/_git/jsuen"}},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
executil "github.com/argoproj/argo-cd/v2/util/exec"
|
||||
"github.com/argoproj/argo-cd/v2/util/io"
|
||||
pathutil "github.com/argoproj/argo-cd/v2/util/io/path"
|
||||
"github.com/argoproj/argo-cd/v2/util/proxy"
|
||||
)
|
||||
|
||||
@@ -280,8 +281,8 @@ type TemplateOpts struct {
|
||||
APIVersions []string
|
||||
Set map[string]string
|
||||
SetString map[string]string
|
||||
SetFile map[string]string
|
||||
Values []string
|
||||
SetFile map[string]pathutil.ResolvedFilePath
|
||||
Values []pathutil.ResolvedFilePath
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -316,10 +317,10 @@ func (c *Cmd) template(chartPath string, opts *TemplateOpts) (string, error) {
|
||||
args = append(args, "--set-string", key+"="+cleanSetParameters(val))
|
||||
}
|
||||
for key, val := range opts.SetFile {
|
||||
args = append(args, "--set-file", key+"="+cleanSetParameters(val))
|
||||
args = append(args, "--set-file", key+"="+cleanSetParameters(string(val)))
|
||||
}
|
||||
for _, val := range opts.Values {
|
||||
args = append(args, "--values", val)
|
||||
args = append(args, "--values", string(val))
|
||||
}
|
||||
for _, v := range opts.APIVersions {
|
||||
args = append(args, "--api-versions", v)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
|
||||
"github.com/argoproj/argo-cd/v2/util/config"
|
||||
executil "github.com/argoproj/argo-cd/v2/util/exec"
|
||||
pathutil "github.com/argoproj/argo-cd/v2/util/io/path"
|
||||
)
|
||||
|
||||
type HelmRepository struct {
|
||||
@@ -27,7 +28,7 @@ type Helm interface {
|
||||
// Template returns a list of unstructured objects from a `helm template` command
|
||||
Template(opts *TemplateOpts) (string, error)
|
||||
// GetParameters returns a list of chart parameters taking into account values in provided YAML files.
|
||||
GetParameters(valuesFiles []string) (map[string]string, error)
|
||||
GetParameters(valuesFiles []pathutil.ResolvedFilePath) (map[string]string, error)
|
||||
// DependencyBuild runs `helm dependency build` to download a chart's dependencies
|
||||
DependencyBuild() error
|
||||
// Init runs `helm init --client-only`
|
||||
@@ -128,13 +129,14 @@ func Version(shortForm bool) (string, error) {
|
||||
return strings.TrimSpace(version), nil
|
||||
}
|
||||
|
||||
func (h *helm) GetParameters(valuesFiles []string) (map[string]string, error) {
|
||||
func (h *helm) GetParameters(valuesFiles []pathutil.ResolvedFilePath) (map[string]string, error) {
|
||||
out, err := h.cmd.inspectValues(".")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
values := []string{out}
|
||||
for _, file := range valuesFiles {
|
||||
for i := range valuesFiles {
|
||||
file := string(valuesFiles[i])
|
||||
var fileValues []byte
|
||||
parsedURL, err := url.ParseRequestURI(file)
|
||||
if err == nil && (parsedURL.Scheme == "http" || parsedURL.Scheme == "https") {
|
||||
|
||||
@@ -5,8 +5,9 @@ import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/utils/kube"
|
||||
"github.com/argoproj/argo-cd/v2/util/io/path"
|
||||
|
||||
"github.com/argoproj/gitops-engine/pkg/utils/kube"
|
||||
"github.com/stretchr/testify/assert"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
@@ -56,7 +57,7 @@ func TestHelmTemplateValues(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
opts := TemplateOpts{
|
||||
Name: "test",
|
||||
Values: []string{"values-production.yaml"},
|
||||
Values: []path.ResolvedFilePath{"values-production.yaml"},
|
||||
}
|
||||
objs, err := template(h, &opts)
|
||||
assert.Nil(t, err)
|
||||
@@ -75,7 +76,7 @@ func TestHelmTemplateValues(t *testing.T) {
|
||||
func TestHelmGetParams(t *testing.T) {
|
||||
h, err := NewHelmApp("./testdata/redis", nil, false, "", "")
|
||||
assert.NoError(t, err)
|
||||
params, err := h.GetParameters([]string{})
|
||||
params, err := h.GetParameters(nil)
|
||||
assert.Nil(t, err)
|
||||
|
||||
slaveCountParam := params["cluster.slaveCount"]
|
||||
@@ -85,7 +86,7 @@ func TestHelmGetParams(t *testing.T) {
|
||||
func TestHelmGetParamsValueFiles(t *testing.T) {
|
||||
h, err := NewHelmApp("./testdata/redis", nil, false, "", "")
|
||||
assert.NoError(t, err)
|
||||
params, err := h.GetParameters([]string{"values-production.yaml"})
|
||||
params, err := h.GetParameters([]path.ResolvedFilePath{"values-production.yaml"})
|
||||
assert.Nil(t, err)
|
||||
|
||||
slaveCountParam := params["cluster.slaveCount"]
|
||||
@@ -95,7 +96,7 @@ func TestHelmGetParamsValueFiles(t *testing.T) {
|
||||
func TestHelmGetParamsValueFilesThatExist(t *testing.T) {
|
||||
h, err := NewHelmApp("./testdata/redis", nil, false, "", "")
|
||||
assert.NoError(t, err)
|
||||
params, err := h.GetParameters([]string{"values-missing.yaml", "values-production.yaml"})
|
||||
params, err := h.GetParameters([]path.ResolvedFilePath{"values-missing.yaml", "values-production.yaml"})
|
||||
assert.Nil(t, err)
|
||||
|
||||
slaveCountParam := params["cluster.slaveCount"]
|
||||
|
||||
158
util/io/path/resolved.go
Normal file
158
util/io/path/resolved.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// ResolvedFilePath represents a resolved file path and intended to prevent unintentional use of not verified file path.
|
||||
type ResolvedFilePath string
|
||||
|
||||
// resolveSymbolicLinkRecursive resolves the symlink path recursively to its
|
||||
// canonical path on the file system, with a maximum nesting level of maxDepth.
|
||||
// If path is not a symlink, returns the verbatim copy of path and err of nil.
|
||||
func resolveSymbolicLinkRecursive(path string, maxDepth int) (string, error) {
|
||||
resolved, err := os.Readlink(path)
|
||||
if err != nil {
|
||||
// path is not a symbolic link
|
||||
_, ok := err.(*os.PathError)
|
||||
if ok {
|
||||
return path, nil
|
||||
}
|
||||
// Other error has occured
|
||||
return "", err
|
||||
}
|
||||
|
||||
if maxDepth == 0 {
|
||||
return "", fmt.Errorf("maximum nesting level reached")
|
||||
}
|
||||
|
||||
// If we resolved to a relative symlink, make sure we use the absolute
|
||||
// path for further resolving
|
||||
if !strings.HasPrefix(resolved, "/") {
|
||||
basePath := filepath.Dir(path)
|
||||
resolved = filepath.Join(basePath, resolved)
|
||||
}
|
||||
|
||||
return resolveSymbolicLinkRecursive(resolved, maxDepth-1)
|
||||
}
|
||||
|
||||
// isURLSchemeAllowed returns true if the protocol scheme is in the list of
|
||||
// allowed URL schemes.
|
||||
func isURLSchemeAllowed(scheme string, allowed []string) bool {
|
||||
isAllowed := false
|
||||
if len(allowed) > 0 {
|
||||
for _, s := range allowed {
|
||||
if strings.EqualFold(scheme, s) {
|
||||
isAllowed = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Empty scheme means local file
|
||||
return isAllowed && scheme != ""
|
||||
}
|
||||
|
||||
// ResolveFilePath will inspect and resolve given file, and make sure that its final path is within the boundaries of
|
||||
// the path specified in repoRoot.
|
||||
//
|
||||
// appPath is the path we're operating in, e.g. where a Helm chart was unpacked
|
||||
// to. repoRoot is the path to the root of the repository.
|
||||
//
|
||||
// If either appPath or repoRoot is relative, it will be treated as relative
|
||||
// to the current working directory.
|
||||
//
|
||||
// valueFile is the path to a value file, relative to appPath. If valueFile is
|
||||
// specified as an absolute path (i.e. leading slash), it will be treated as
|
||||
// relative to the repoRoot. In case valueFile is a symlink in the extracted
|
||||
// chart, it will be resolved recursively and the decision of whether it is in
|
||||
// the boundary of repoRoot will be made using the final resolved path.
|
||||
// valueFile can also be a remote URL with a protocol scheme as prefix,
|
||||
// in which case the scheme must be included in the list of allowed schemes
|
||||
// specified by allowedURLSchemes.
|
||||
//
|
||||
// Will return an error if either valueFile is outside the boundaries of the
|
||||
// repoRoot, valueFile is an URL with a forbidden protocol scheme or if
|
||||
// valueFile is a recursive symlink nested too deep. May return errors for
|
||||
// other reasons as well.
|
||||
//
|
||||
// resolvedPath will hold the absolute, resolved path for valueFile on success
|
||||
// or set to the empty string on failure.
|
||||
//
|
||||
// isRemote will be set to true if valueFile is an URL using an allowed
|
||||
// protocol scheme, or to false if it resolved to a local file.
|
||||
func ResolveFilePath(appPath, repoRoot, valueFile string, allowedURLSchemes []string) (resolvedPath ResolvedFilePath, isRemote bool, err error) {
|
||||
// We do not provide the path in the error message, because it will be
|
||||
// returned to the user and could be used for information gathering.
|
||||
// Instead, we log the concrete error details.
|
||||
resolveFailure := func(path string, err error) error {
|
||||
log.Errorf("failed to resolve path '%s': %v", path, err)
|
||||
return fmt.Errorf("internal error: failed to resolve path. Check logs for more details")
|
||||
}
|
||||
|
||||
// A value file can be specified as an URL to a remote resource.
|
||||
// We only allow certain URL schemes for remote value files.
|
||||
url, err := url.Parse(valueFile)
|
||||
if err == nil {
|
||||
// If scheme is empty, it means we parsed a path only
|
||||
if url.Scheme != "" {
|
||||
if isURLSchemeAllowed(url.Scheme, allowedURLSchemes) {
|
||||
return ResolvedFilePath(valueFile), true, nil
|
||||
} else {
|
||||
return "", false, fmt.Errorf("the URL scheme '%s' is not allowed", url.Scheme)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure that our repository root is absolute
|
||||
absRepoPath, err := filepath.Abs(repoRoot)
|
||||
if err != nil {
|
||||
return "", false, resolveFailure(repoRoot, err)
|
||||
}
|
||||
|
||||
// If the path to the file is relative, join it with the current working directory (appPath)
|
||||
// Otherwise, join it with the repository's root
|
||||
path := valueFile
|
||||
if !filepath.IsAbs(path) {
|
||||
absWorkDir, err := filepath.Abs(appPath)
|
||||
if err != nil {
|
||||
return "", false, resolveFailure(repoRoot, err)
|
||||
}
|
||||
path = filepath.Join(absWorkDir, path)
|
||||
} else {
|
||||
path = filepath.Join(absRepoPath, path)
|
||||
}
|
||||
|
||||
// Ensure any symbolic link is resolved before we
|
||||
delinkedPath, err := resolveSymbolicLinkRecursive(path, 10)
|
||||
if err != nil {
|
||||
return "", false, resolveFailure(path, err)
|
||||
}
|
||||
path = delinkedPath
|
||||
|
||||
// Resolve the joined path to an absolute path
|
||||
path, err = filepath.Abs(path)
|
||||
if err != nil {
|
||||
return "", false, resolveFailure(path, err)
|
||||
}
|
||||
|
||||
// Ensure our root path has a trailing slash, otherwise the following check
|
||||
// would return true if root is /foo and path would be /foo2
|
||||
requiredRootPath := absRepoPath
|
||||
if !strings.HasSuffix(requiredRootPath, "/") {
|
||||
requiredRootPath += "/"
|
||||
}
|
||||
|
||||
// Make sure that the resolved path to values file is within the repository's root path
|
||||
if !strings.HasPrefix(path, requiredRootPath) {
|
||||
return "", false, fmt.Errorf("value file '%s' resolved to outside repository root", valueFile)
|
||||
}
|
||||
|
||||
return ResolvedFilePath(path), false, nil
|
||||
}
|
||||
181
util/io/path/resolved_test.go
Normal file
181
util/io/path/resolved_test.go
Normal file
@@ -0,0 +1,181 @@
|
||||
package path
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_resolveSymlinkRecursive(t *testing.T) {
|
||||
testsDir, err := filepath.Abs("./testdata")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
t.Run("Resolve non-symlink", func(t *testing.T) {
|
||||
r, err := resolveSymbolicLinkRecursive(testsDir+"/foo", 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testsDir+"/foo", r)
|
||||
})
|
||||
t.Run("Successfully resolve symlink", func(t *testing.T) {
|
||||
r, err := resolveSymbolicLinkRecursive(testsDir+"/bar", 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testsDir+"/foo", r)
|
||||
})
|
||||
t.Run("Do not allow symlink at all", func(t *testing.T) {
|
||||
r, err := resolveSymbolicLinkRecursive(testsDir+"/bar", 0)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "", r)
|
||||
})
|
||||
t.Run("Error because too nested symlink", func(t *testing.T) {
|
||||
r, err := resolveSymbolicLinkRecursive(testsDir+"/bam", 2)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "", r)
|
||||
})
|
||||
t.Run("No such file or directory", func(t *testing.T) {
|
||||
r, err := resolveSymbolicLinkRecursive(testsDir+"/foobar", 2)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testsDir+"/foobar", r)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_isURLSchemeAllowed(t *testing.T) {
|
||||
type testdata struct {
|
||||
name string
|
||||
scheme string
|
||||
allowed []string
|
||||
expected bool
|
||||
}
|
||||
var tts []testdata = []testdata{
|
||||
{
|
||||
name: "Allowed scheme matches",
|
||||
scheme: "http",
|
||||
allowed: []string{"http", "https"},
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "Allowed scheme matches only partially",
|
||||
scheme: "http",
|
||||
allowed: []string{"https"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Scheme is not allowed",
|
||||
scheme: "file",
|
||||
allowed: []string{"http", "https"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Empty scheme with valid allowances is forbidden",
|
||||
scheme: "",
|
||||
allowed: []string{"http", "https"},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Empty scheme with empty allowances is forbidden",
|
||||
scheme: "",
|
||||
allowed: []string{},
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "Some scheme with empty allowances is forbidden",
|
||||
scheme: "file",
|
||||
allowed: []string{},
|
||||
expected: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tts {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
r := isURLSchemeAllowed(tt.scheme, tt.allowed)
|
||||
assert.Equal(t, tt.expected, r)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
var allowedRemoteProtocols = []string{"http", "https"}
|
||||
|
||||
func Test_resolveFilePath(t *testing.T) {
|
||||
t.Run("Resolve normal relative path into absolute path", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", "baz/bim.yaml", allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "/foo/bar/baz/bim.yaml", string(p))
|
||||
})
|
||||
t.Run("Resolve normal relative path into absolute path", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", "baz/../../bim.yaml", allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "/foo/bim.yaml", string(p))
|
||||
})
|
||||
t.Run("Error on path resolving outside repository root", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", "baz/../../../bim.yaml", allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
t.Run("Return verbatim URL", func(t *testing.T) {
|
||||
url := "https://some.where/foo,yaml"
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", url, allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, remote)
|
||||
assert.Equal(t, url, string(p))
|
||||
})
|
||||
t.Run("URL scheme not allowed", func(t *testing.T) {
|
||||
url := "file:///some.where/foo,yaml"
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", url, allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
t.Run("Implicit URL by absolute path", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath("/foo/bar", "/foo", "/baz.yaml", allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "/foo/baz.yaml", string(p))
|
||||
})
|
||||
t.Run("Relative app path", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath(".", "/foo", "/baz.yaml", allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "/foo/baz.yaml", string(p))
|
||||
})
|
||||
t.Run("Relative repo path", func(t *testing.T) {
|
||||
c, err := os.Getwd()
|
||||
require.NoError(t, err)
|
||||
p, remote, err := ResolveFilePath(".", ".", "baz.yaml", allowedRemoteProtocols)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, c+"/baz.yaml", string(p))
|
||||
})
|
||||
t.Run("Overlapping root prefix without trailing slash", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath(".", "/foo", "../foo2/baz.yaml", allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
t.Run("Overlapping root prefix with trailing slash", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath(".", "/foo/", "../foo2/baz.yaml", allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
t.Run("Garbage input as values file", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath(".", "/foo/", "kfdj\\ks&&&321209.,---e32908923%$§!\"", allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
t.Run("NUL-byte path input as values file", func(t *testing.T) {
|
||||
p, remote, err := ResolveFilePath(".", "/foo/", "\000", allowedRemoteProtocols)
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), "outside repository root")
|
||||
assert.False(t, remote)
|
||||
assert.Equal(t, "", string(p))
|
||||
})
|
||||
}
|
||||
1
util/io/path/testdata/bam
vendored
Symbolic link
1
util/io/path/testdata/bam
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
baz
|
||||
1
util/io/path/testdata/bar
vendored
Symbolic link
1
util/io/path/testdata/bar
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
foo
|
||||
1
util/io/path/testdata/baz
vendored
Symbolic link
1
util/io/path/testdata/baz
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
bar
|
||||
1
util/io/path/testdata/foo
vendored
Normal file
1
util/io/path/testdata/foo
vendored
Normal file
@@ -0,0 +1 @@
|
||||
hello
|
||||
@@ -313,6 +313,8 @@ const (
|
||||
partOfArgoCDSelector = "app.kubernetes.io/part-of=argocd"
|
||||
// settingsPasswordPatternKey is the key to configure user password regular expression
|
||||
settingsPasswordPatternKey = "passwordPattern"
|
||||
// helmValuesFileSchemesKey is the key to configure the list of supported helm values file schemas
|
||||
helmValuesFileSchemesKey = "helm.valuesFileSchemes"
|
||||
)
|
||||
|
||||
// SettingsManager holds config info for a new manager with which to access Kubernetes ConfigMaps.
|
||||
@@ -712,6 +714,25 @@ func (mgr *SettingsManager) GetResourceCompareOptions() (ArgoCDDiffOptions, erro
|
||||
return diffOptions, nil
|
||||
}
|
||||
|
||||
// GetHelmSettings returns helm settings
|
||||
func (mgr *SettingsManager) GetHelmSettings() (*v1alpha1.HelmOptions, error) {
|
||||
argoCDCM, err := mgr.getConfigMap()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
helmOptions := &v1alpha1.HelmOptions{}
|
||||
if value, ok := argoCDCM.Data[helmValuesFileSchemesKey]; ok {
|
||||
for _, item := range strings.Split(value, ",") {
|
||||
if item := strings.TrimSpace(item); item != "" {
|
||||
helmOptions.ValuesFileSchemes = append(helmOptions.ValuesFileSchemes, item)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
helmOptions.ValuesFileSchemes = []string{"https", "http"}
|
||||
}
|
||||
return helmOptions, nil
|
||||
}
|
||||
|
||||
// GetKustomizeSettings loads the kustomize settings from argocd-cm ConfigMap
|
||||
func (mgr *SettingsManager) GetKustomizeSettings() (*KustomizeSettings, error) {
|
||||
argoCDCM, err := mgr.getConfigMap()
|
||||
|
||||
@@ -947,3 +947,72 @@ requestedIDTokenClaims: {"groups": {"essential": true}}`,
|
||||
oidcConfig := settings.OIDCConfig()
|
||||
assert.Equal(t, oidcConfig.ClientSecret, "deadbeef")
|
||||
}
|
||||
|
||||
func TestGetHelmSettings(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
data map[string]string
|
||||
expected []string
|
||||
}{{
|
||||
name: "Default",
|
||||
data: map[string]string{},
|
||||
expected: []string{"http", "https"},
|
||||
}, {
|
||||
name: "Configured Not Empty",
|
||||
data: map[string]string{
|
||||
"helm.valuesFileSchemes": "s3, git",
|
||||
},
|
||||
expected: []string{"s3", "git"},
|
||||
}, {
|
||||
name: "Configured Empty",
|
||||
data: map[string]string{
|
||||
"helm.valuesFileSchemes": "",
|
||||
},
|
||||
expected: nil,
|
||||
}}
|
||||
|
||||
for i := range testCases {
|
||||
tc := testCases[i]
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cm := &v1.ConfigMap{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDConfigMapName,
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: tc.data,
|
||||
}
|
||||
argocdSecret := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: common.ArgoCDSecretName,
|
||||
Namespace: "default",
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"admin.password": nil,
|
||||
"server.secretkey": nil,
|
||||
},
|
||||
}
|
||||
secret := &v1.Secret{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "acme",
|
||||
Namespace: "default",
|
||||
Labels: map[string]string{
|
||||
"app.kubernetes.io/part-of": "argocd",
|
||||
},
|
||||
},
|
||||
Data: map[string][]byte{
|
||||
"clientSecret": []byte("deadbeef"),
|
||||
},
|
||||
}
|
||||
kubeClient := fake.NewSimpleClientset(cm, secret, argocdSecret)
|
||||
settingsManager := NewSettingsManager(context.Background(), kubeClient, "default")
|
||||
|
||||
helmSettings, err := settingsManager.GetHelmSettings()
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.ElementsMatch(t, tc.expected, helmSettings.ValuesFileSchemes)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user