From 131e8b4d314381e70c2da153160f869ec1e34401 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 20 Feb 2022 20:54:36 +0100 Subject: [PATCH 1/8] feat: opt-in gotemplate with sprig for application template render (#303) Signed-off-by: Vlad --- api/v1alpha1/applicationset_types.go | 13 +- api/v1alpha1/zz_generated.deepcopy.go | 20 + go.sum | 3 + .../crds/argoproj.io_applicationsets.yaml | 5 + manifests/install-with-argo-cd.yaml | 9897 +++++++++++++++++ manifests/install.yaml | 5 + pkg/controllers/applicationset_controller.go | 2 +- .../applicationset_controller_test.go | 2 +- pkg/utils/util.go | 76 +- pkg/utils/util_test.go | 128 +- 10 files changed, 10125 insertions(+), 26 deletions(-) create mode 100644 manifests/install-with-argo-cd.yaml diff --git a/api/v1alpha1/applicationset_types.go b/api/v1alpha1/applicationset_types.go index b6dc6bc1..168c2021 100644 --- a/api/v1alpha1/applicationset_types.go +++ b/api/v1alpha1/applicationset_types.go @@ -48,9 +48,10 @@ type ApplicationSet struct { // ApplicationSetSpec represents a class of application set state. type ApplicationSetSpec struct { - Generators []ApplicationSetGenerator `json:"generators"` - Template ApplicationSetTemplate `json:"template"` - SyncPolicy *ApplicationSetSyncPolicy `json:"syncPolicy,omitempty"` + Generators []ApplicationSetGenerator `json:"generators"` + Template ApplicationSetTemplate `json:"template"` + SyncPolicy *ApplicationSetSyncPolicy `json:"syncPolicy,omitempty"` + TemplateOptions *ApplicationSetTemplateOptions `json:"templateOptions,omitempty"` } // ApplicationSetSyncPolicy configures how generated Applications will relate to their @@ -60,6 +61,12 @@ type ApplicationSetSyncPolicy struct { PreserveResourcesOnDeletion bool `json:"preserveResourcesOnDeletion,omitempty"` } +// ApplicationSetTemplateOptions configures how template rendering behaves +type ApplicationSetTemplateOptions struct { + // GotemplateEnabled will switch to Go template rendering engine. + GotemplateEnabled bool `json:"gotemplateEnabled,omitempty"` +} + // ApplicationSetTemplate represents argocd ApplicationSpec type ApplicationSetTemplate struct { ApplicationSetTemplateMeta `json:"metadata"` diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 4248a934..3993100a 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -249,6 +249,11 @@ func (in *ApplicationSetSpec) DeepCopyInto(out *ApplicationSetSpec) { *out = new(ApplicationSetSyncPolicy) **out = **in } + if in.TemplateOptions != nil { + in, out := &in.TemplateOptions, &out.TemplateOptions + *out = new(ApplicationSetTemplateOptions) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSetSpec. @@ -349,6 +354,21 @@ func (in *ApplicationSetTemplateMeta) DeepCopy() *ApplicationSetTemplateMeta { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApplicationSetTemplateOptions) DeepCopyInto(out *ApplicationSetTemplateOptions) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSetTemplateOptions. +func (in *ApplicationSetTemplateOptions) DeepCopy() *ApplicationSetTemplateOptions { + if in == nil { + return nil + } + out := new(ApplicationSetTemplateOptions) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationSetTerminalGenerator) DeepCopyInto(out *ApplicationSetTerminalGenerator) { *out = *in diff --git a/go.sum b/go.sum index fd9a55b7..d764c3e6 100644 --- a/go.sum +++ b/go.sum @@ -842,6 +842,8 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -1023,6 +1025,7 @@ golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ= diff --git a/manifests/crds/argoproj.io_applicationsets.yaml b/manifests/crds/argoproj.io_applicationsets.yaml index 7eda3253..d730a11d 100644 --- a/manifests/crds/argoproj.io_applicationsets.yaml +++ b/manifests/crds/argoproj.io_applicationsets.yaml @@ -6458,6 +6458,11 @@ spec: - metadata - spec type: object + templateOptions: + properties: + gotemplateEnabled: + type: boolean + type: object required: - generators - template diff --git a/manifests/install-with-argo-cd.yaml b/manifests/install-with-argo-cd.yaml new file mode 100644 index 00000000..aec9a41b --- /dev/null +++ b/manifests/install-with-argo-cd.yaml @@ -0,0 +1,9897 @@ +# This is an auto-generated file. DO NOT EDIT +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + app.kubernetes.io/name: applications.argoproj.io + app.kubernetes.io/part-of: argocd + name: applications.argoproj.io +spec: + group: argoproj.io + names: + kind: Application + listKind: ApplicationList + plural: applications + shortNames: + - app + - apps + singular: application + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.sync.status + name: Sync Status + type: string + - jsonPath: .status.health.status + name: Health Status + type: string + - jsonPath: .status.sync.revision + name: Revision + priority: 10 + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Application is a definition of Application resource. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + operation: + description: Operation contains information about a requested or running operation + properties: + info: + description: Info is a list of informational items for this operation + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + initiatedBy: + description: InitiatedBy contains information about who initiated the operations + properties: + automated: + description: Automated is set to true if operation was initiated automatically by the application controller. + type: boolean + username: + description: Username contains the name of a user who started operation + type: string + type: object + retry: + description: Retry controls the strategy to apply if a sync fails + properties: + backoff: + description: Backoff controls how to backoff on subsequent retries of failed syncs + properties: + duration: + description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") + type: string + factor: + description: Factor is a factor to multiply the base duration after each failed retry + format: int64 + type: integer + maxDuration: + description: MaxDuration is the maximum amount of time allowed for the backoff strategy + type: string + type: object + limit: + description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. + format: int64 + type: integer + type: object + sync: + description: Sync contains parameters for the operation + properties: + dryRun: + description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync + type: boolean + manifests: + description: Manifests is an optional field that overrides sync source with a local directory for development + items: + type: string + type: array + prune: + description: Prune specifies to delete resources from the cluster that are no longer tracked in git + type: boolean + resources: + description: Resources describes which resources shall be part of the sync + items: + description: SyncOperationResource contains resources to sync. + properties: + group: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + type: array + revision: + description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. + type: string + source: + description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + syncOptions: + description: SyncOptions provide per-sync sync-options, e.g. Validate=false + items: + type: string + type: array + syncStrategy: + description: SyncStrategy describes how to perform the sync + properties: + apply: + description: Apply will perform a `kubectl apply` to perform the sync. + properties: + force: + description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. + type: boolean + type: object + hook: + description: Hook will submit any referenced resources to perform the sync. This is the default strategy + properties: + force: + description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. + type: boolean + type: object + type: object + type: object + type: object + spec: + description: ApplicationSpec represents desired application state. Contains link to repository with application definition and additional parameters link definition revision. + properties: + destination: + description: Destination is a reference to the target Kubernetes server and namespace + properties: + name: + description: Name is an alternate way of specifying the target cluster by its symbolic name + type: string + namespace: + description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace + type: string + server: + description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API + type: string + type: object + ignoreDifferences: + description: IgnoreDifferences is a list of resources and their fields which should be ignored during comparison + items: + description: ResourceIgnoreDifferences contains resource filter and list of json paths which should be ignored during comparison with live state. + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + description: Info contains a list of information (URLs, email addresses, and plain text) that relates to the application + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + description: Project is a reference to the project this application belongs to. The empty string means that application belongs to the 'default' project. + type: string + revisionHistoryLimit: + description: RevisionHistoryLimit limits the number of items kept in the application's revision history, which is used for informational purposes as well as for rollbacks to previous versions. This should only be changed in exceptional circumstances. Setting to zero will store no history. This will reduce storage used. Increasing will increase the space used to store the history, so we do not recommend increasing it. Default is 10. + format: int64 + type: integer + source: + description: Source is a reference to the location of the application's manifests or chart + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + syncPolicy: + description: SyncPolicy controls when and how a sync will be performed + properties: + automated: + description: Automated will keep an application synced to the target revision + properties: + allowEmpty: + description: 'AllowEmpty allows apps have zero live resources (default: false)' + type: boolean + prune: + description: 'Prune specifies whether to delete resources from the cluster that are not found in the sources anymore as part of automated sync (default: false)' + type: boolean + selfHeal: + description: 'SelfHeal specifes whether to revert resources back to their desired state upon modification in the cluster (default: false)' + type: boolean + type: object + retry: + description: Retry controls failed sync retry behavior + properties: + backoff: + description: Backoff controls how to backoff on subsequent retries of failed syncs + properties: + duration: + description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") + type: string + factor: + description: Factor is a factor to multiply the base duration after each failed retry + format: int64 + type: integer + maxDuration: + description: MaxDuration is the maximum amount of time allowed for the backoff strategy + type: string + type: object + limit: + description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. + format: int64 + type: integer + type: object + syncOptions: + description: Options allow you to specify whole app sync-options + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + status: + description: ApplicationStatus contains status information for the application + properties: + conditions: + description: Conditions is a list of currently observed application conditions + items: + description: ApplicationCondition contains details about an application condition, which is usally an error or warning + properties: + lastTransitionTime: + description: LastTransitionTime is the time the condition was last observed + format: date-time + type: string + message: + description: Message contains human-readable message indicating details about condition + type: string + type: + description: Type is an application condition type + type: string + required: + - message + - type + type: object + type: array + health: + description: Health contains information about the application's current health status + properties: + message: + description: Message is a human-readable informational message describing the health status + type: string + status: + description: Status holds the status code of the application or resource + type: string + type: object + history: + description: History contains information about the application's sync history + items: + description: RevisionHistory contains history information about a previous sync + properties: + deployStartedAt: + description: DeployStartedAt holds the time the sync operation started + format: date-time + type: string + deployedAt: + description: DeployedAt holds the time the sync operation completed + format: date-time + type: string + id: + description: ID is an auto incrementing identifier of the RevisionHistory + format: int64 + type: integer + revision: + description: Revision holds the revision the sync was performed against + type: string + source: + description: Source is a reference to the application source used for the sync operation + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + required: + - deployedAt + - id + - revision + type: object + type: array + observedAt: + description: 'ObservedAt indicates when the application state was updated without querying latest git state Deprecated: controller no longer updates ObservedAt field' + format: date-time + type: string + operationState: + description: OperationState contains information about any ongoing operations, such as a sync + properties: + finishedAt: + description: FinishedAt contains time of operation completion + format: date-time + type: string + message: + description: Message holds any pertinent messages when attempting to perform operation (typically errors). + type: string + operation: + description: Operation is the original requested operation + properties: + info: + description: Info is a list of informational items for this operation + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + initiatedBy: + description: InitiatedBy contains information about who initiated the operations + properties: + automated: + description: Automated is set to true if operation was initiated automatically by the application controller. + type: boolean + username: + description: Username contains the name of a user who started operation + type: string + type: object + retry: + description: Retry controls the strategy to apply if a sync fails + properties: + backoff: + description: Backoff controls how to backoff on subsequent retries of failed syncs + properties: + duration: + description: Duration is the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") + type: string + factor: + description: Factor is a factor to multiply the base duration after each failed retry + format: int64 + type: integer + maxDuration: + description: MaxDuration is the maximum amount of time allowed for the backoff strategy + type: string + type: object + limit: + description: Limit is the maximum number of attempts for retrying a failed sync. If set to 0, no retries will be performed. + format: int64 + type: integer + type: object + sync: + description: Sync contains parameters for the operation + properties: + dryRun: + description: DryRun specifies to perform a `kubectl apply --dry-run` without actually performing the sync + type: boolean + manifests: + description: Manifests is an optional field that overrides sync source with a local directory for development + items: + type: string + type: array + prune: + description: Prune specifies to delete resources from the cluster that are no longer tracked in git + type: boolean + resources: + description: Resources describes which resources shall be part of the sync + items: + description: SyncOperationResource contains resources to sync. + properties: + group: + type: string + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + - name + type: object + type: array + revision: + description: Revision is the revision (Git) or chart version (Helm) which to sync the application to If omitted, will use the revision specified in app spec. + type: string + source: + description: Source overrides the source definition set in the application. This is typically set in a Rollback operation and is nil during a Sync operation + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + syncOptions: + description: SyncOptions provide per-sync sync-options, e.g. Validate=false + items: + type: string + type: array + syncStrategy: + description: SyncStrategy describes how to perform the sync + properties: + apply: + description: Apply will perform a `kubectl apply` to perform the sync. + properties: + force: + description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. + type: boolean + type: object + hook: + description: Hook will submit any referenced resources to perform the sync. This is the default strategy + properties: + force: + description: Force indicates whether or not to supply the --force flag to `kubectl apply`. The --force flag deletes and re-create the resource, when PATCH encounters conflict and has retried for 5 times. + type: boolean + type: object + type: object + type: object + type: object + phase: + description: Phase is the current phase of the operation + type: string + retryCount: + description: RetryCount contains time of operation retries + format: int64 + type: integer + startedAt: + description: StartedAt contains time of operation start + format: date-time + type: string + syncResult: + description: SyncResult is the result of a Sync operation + properties: + resources: + description: Resources contains a list of sync result items for each individual resource in a sync operation + items: + description: ResourceResult holds the operation result details of a specific resource + properties: + group: + description: Group specifies the API group of the resource + type: string + hookPhase: + description: HookPhase contains the state of any operation associated with this resource OR hook This can also contain values for non-hook resources. + type: string + hookType: + description: HookType specifies the type of the hook. Empty for non-hook resources + type: string + kind: + description: Kind specifies the API kind of the resource + type: string + message: + description: Message contains an informational or error message for the last sync OR operation + type: string + name: + description: Name specifies the name of the resource + type: string + namespace: + description: Namespace specifies the target namespace of the resource + type: string + status: + description: Status holds the final result of the sync. Will be empty if the resources is yet to be applied/pruned and is always zero-value for hooks + type: string + syncPhase: + description: SyncPhase indicates the particular phase of the sync that this result was acquired in + type: string + version: + description: Version specifies the API version of the resource + type: string + required: + - group + - kind + - name + - namespace + - version + type: object + type: array + revision: + description: Revision holds the revision this sync operation was performed to + type: string + source: + description: Source records the application source information of the sync, used for comparing auto-sync + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + required: + - revision + type: object + required: + - operation + - phase + - startedAt + type: object + reconciledAt: + description: ReconciledAt indicates when the application state was reconciled using the latest git version + format: date-time + type: string + resources: + description: Resources is a list of Kubernetes resources managed by this application + items: + description: 'ResourceStatus holds the current sync and health status of a resource TODO: describe members of this type' + properties: + group: + type: string + health: + description: HealthStatus contains information about the currently observed health state of an application or resource + properties: + message: + description: Message is a human-readable informational message describing the health status + type: string + status: + description: Status holds the status code of the application or resource + type: string + type: object + hook: + type: boolean + kind: + type: string + name: + type: string + namespace: + type: string + requiresPruning: + type: boolean + status: + description: SyncStatusCode is a type which represents possible comparison results + type: string + version: + type: string + type: object + type: array + sourceType: + description: SourceType specifies the type of this application + type: string + summary: + description: Summary contains a list of URLs and container images used by this application + properties: + externalURLs: + description: ExternalURLs holds all external URLs of application child resources. + items: + type: string + type: array + images: + description: Images holds all images of application child resources. + items: + type: string + type: array + type: object + sync: + description: Sync contains information about the application's current sync status + properties: + comparedTo: + description: ComparedTo contains information about what has been compared + properties: + destination: + description: Destination is a reference to the application's destination used for comparison + properties: + name: + description: Name is an alternate way of specifying the target cluster by its symbolic name + type: string + namespace: + description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace + type: string + server: + description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API + type: string + type: object + source: + description: Source is a reference to the application's source used for comparison + properties: + chart: + description: Chart is a Helm chart name, and must be specified for applications sourced from a Helm repo. + type: string + directory: + description: Directory holds path/directory specific options + properties: + exclude: + description: Exclude contains a glob pattern to match paths against that should be explicitly excluded from being used during manifest generation + type: string + include: + description: Include contains a glob pattern to match paths against that should be explicitly included during manifest generation + type: string + jsonnet: + description: Jsonnet holds options specific to Jsonnet + properties: + extVars: + description: ExtVars is a list of Jsonnet External Variables + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + description: Additional library search dirs + items: + type: string + type: array + tlas: + description: TLAS is a list of Jsonnet Top-level Arguments + items: + description: JsonnetVar represents a variable to be passed to jsonnet during manifest generation + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + description: Recurse specifies whether to scan a directory recursively for manifests + type: boolean + type: object + helm: + description: Helm holds helm specific options + properties: + fileParameters: + description: FileParameters are file parameters to the helm template + items: + description: HelmFileParameter is a file parameter that's passed to helm template during manifest generation + properties: + name: + description: Name is the name of the Helm parameter + type: string + path: + description: Path is the path to the file containing the values for the Helm parameter + type: string + type: object + type: array + parameters: + description: Parameters is a list of Helm parameters which are passed to the helm template command upon manifest generation + items: + description: HelmParameter is a parameter that's passed to helm template during manifest generation + properties: + forceString: + description: ForceString determines whether to tell Helm to interpret booleans and numbers as strings + type: boolean + name: + description: Name is the name of the Helm parameter + type: string + value: + description: Value is the value for the Helm parameter + type: string + type: object + type: array + passCredentials: + description: PassCredentials pass credentials to all domains (Helm's --pass-credentials) + type: boolean + releaseName: + description: ReleaseName is the Helm release name to use. If omitted it will use the application name + type: string + valueFiles: + description: ValuesFiles is a list of Helm value files to use when generating a template + items: + type: string + type: array + values: + description: Values specifies Helm values to be passed to helm template, typically defined as a block + type: string + version: + description: Version is the Helm version to use for templating (either "2" or "3") + type: string + type: object + ksonnet: + description: Ksonnet holds ksonnet specific options + properties: + environment: + description: Environment is a ksonnet application environment name + type: string + parameters: + description: Parameters are a list of ksonnet component parameter override values + items: + description: KsonnetParameter is a ksonnet component parameter + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + description: Kustomize holds kustomize specific options + properties: + commonAnnotations: + additionalProperties: + type: string + description: CommonAnnotations is a list of additional annotations to add to rendered manifests + type: object + commonLabels: + additionalProperties: + type: string + description: CommonLabels is a list of additional labels to add to rendered manifests + type: object + forceCommonAnnotations: + description: ForceCommonAnnotations specifies whether to force applying common annotations to resources for Kustomize apps + type: boolean + forceCommonLabels: + description: ForceCommonLabels specifies whether to force applying common labels to resources for Kustomize apps + type: boolean + images: + description: Images is a list of Kustomize image override specifications + items: + description: KustomizeImage represents a Kustomize image definition in the format [old_image_name=]: + type: string + type: array + namePrefix: + description: NamePrefix is a prefix appended to resources for Kustomize apps + type: string + nameSuffix: + description: NameSuffix is a suffix appended to resources for Kustomize apps + type: string + version: + description: Version controls which version of Kustomize to use for rendering manifests + type: string + type: object + path: + description: Path is a directory path within the Git repository, and is only valid for applications sourced from Git. + type: string + plugin: + description: ConfigManagementPlugin holds config management plugin specific options + properties: + env: + description: Env is a list of environment variable entries + items: + description: EnvEntry represents an entry in the application's environment + properties: + name: + description: Name is the name of the variable, usually expressed in uppercase + type: string + value: + description: Value is the value of the variable + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + description: RepoURL is the URL to the repository (Git or Helm) that contains the application manifests + type: string + targetRevision: + description: TargetRevision defines the revision of the source to sync the application to. In case of Git, this can be commit, tag, or branch. If omitted, will equal to HEAD. In case of Helm, this is a semver tag for the Chart's version. + type: string + required: + - repoURL + type: object + required: + - destination + - source + type: object + revision: + description: Revision contains information about the revision the comparison has been performed to + type: string + status: + description: Status is the sync state of the comparison + type: string + required: + - status + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: {} +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.3.0 + creationTimestamp: null + name: applicationsets.argoproj.io +spec: + group: argoproj.io + names: + kind: ApplicationSet + listKind: ApplicationSetList + plural: applicationsets + shortNames: + - appset + - appsets + singular: applicationset + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + properties: + apiVersion: + type: string + kind: + type: string + metadata: + type: object + spec: + properties: + generators: + items: + properties: + clusterDecisionResource: + properties: + configMapRef: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + name: + type: string + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + required: + - configMapRef + type: object + clusters: + properties: + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + type: object + git: + properties: + directories: + items: + properties: + exclude: + type: boolean + path: + type: string + required: + - path + type: object + type: array + files: + items: + properties: + path: + type: string + required: + - path + type: object + type: array + repoURL: + type: string + requeueAfterSeconds: + format: int64 + type: integer + revision: + type: string + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - repoURL + - revision + type: object + list: + properties: + elements: + items: + x-kubernetes-preserve-unknown-fields: true + type: array + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - elements + type: object + matrix: + properties: + generators: + items: + properties: + clusterDecisionResource: + properties: + configMapRef: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + name: + type: string + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + required: + - configMapRef + type: object + clusters: + properties: + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + type: object + git: + properties: + directories: + items: + properties: + exclude: + type: boolean + path: + type: string + required: + - path + type: object + type: array + files: + items: + properties: + path: + type: string + required: + - path + type: object + type: array + repoURL: + type: string + requeueAfterSeconds: + format: int64 + type: integer + revision: + type: string + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - repoURL + - revision + type: object + list: + properties: + elements: + items: + x-kubernetes-preserve-unknown-fields: true + type: array + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - elements + type: object + matrix: + x-kubernetes-preserve-unknown-fields: true + merge: + x-kubernetes-preserve-unknown-fields: true + pullRequest: + properties: + github: + properties: + api: + type: string + labels: + items: + type: string + type: array + owner: + type: string + repo: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - owner + - repo + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + scmProvider: + properties: + cloneProtocol: + type: string + filters: + items: + properties: + branchMatch: + type: string + labelMatch: + type: string + pathsExist: + items: + type: string + type: array + repositoryMatch: + type: string + type: object + type: array + github: + properties: + allBranches: + type: boolean + api: + type: string + organization: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - organization + type: object + gitlab: + properties: + allBranches: + type: boolean + api: + type: string + group: + type: string + includeSubgroups: + type: boolean + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - group + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + type: object + type: array + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - generators + type: object + merge: + properties: + generators: + items: + properties: + clusterDecisionResource: + properties: + configMapRef: + type: string + labelSelector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + name: + type: string + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + required: + - configMapRef + type: object + clusters: + properties: + selector: + properties: + matchExpressions: + items: + properties: + key: + type: string + operator: + type: string + values: + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + type: object + type: object + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + values: + additionalProperties: + type: string + type: object + type: object + git: + properties: + directories: + items: + properties: + exclude: + type: boolean + path: + type: string + required: + - path + type: object + type: array + files: + items: + properties: + path: + type: string + required: + - path + type: object + type: array + repoURL: + type: string + requeueAfterSeconds: + format: int64 + type: integer + revision: + type: string + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - repoURL + - revision + type: object + list: + properties: + elements: + items: + x-kubernetes-preserve-unknown-fields: true + type: array + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - elements + type: object + matrix: + x-kubernetes-preserve-unknown-fields: true + merge: + x-kubernetes-preserve-unknown-fields: true + pullRequest: + properties: + github: + properties: + api: + type: string + labels: + items: + type: string + type: array + owner: + type: string + repo: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - owner + - repo + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + scmProvider: + properties: + cloneProtocol: + type: string + filters: + items: + properties: + branchMatch: + type: string + labelMatch: + type: string + pathsExist: + items: + type: string + type: array + repositoryMatch: + type: string + type: object + type: array + github: + properties: + allBranches: + type: boolean + api: + type: string + organization: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - organization + type: object + gitlab: + properties: + allBranches: + type: boolean + api: + type: string + group: + type: string + includeSubgroups: + type: boolean + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - group + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + type: object + type: array + mergeKeys: + items: + type: string + type: array + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + required: + - generators + - mergeKeys + type: object + pullRequest: + properties: + github: + properties: + api: + type: string + labels: + items: + type: string + type: array + owner: + type: string + repo: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - owner + - repo + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + scmProvider: + properties: + cloneProtocol: + type: string + filters: + items: + properties: + branchMatch: + type: string + labelMatch: + type: string + pathsExist: + items: + type: string + type: array + repositoryMatch: + type: string + type: object + type: array + github: + properties: + allBranches: + type: boolean + api: + type: string + organization: + type: string + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - organization + type: object + gitlab: + properties: + allBranches: + type: boolean + api: + type: string + group: + type: string + includeSubgroups: + type: boolean + tokenRef: + properties: + key: + type: string + secretName: + type: string + required: + - key + - secretName + type: object + required: + - group + type: object + requeueAfterSeconds: + format: int64 + type: integer + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + type: object + type: object + type: array + syncPolicy: + properties: + preserveResourcesOnDeletion: + type: boolean + type: object + template: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + finalizers: + items: + type: string + type: array + labels: + additionalProperties: + type: string + type: object + name: + type: string + namespace: + type: string + type: object + spec: + properties: + destination: + properties: + name: + type: string + namespace: + type: string + server: + type: string + type: object + ignoreDifferences: + items: + properties: + group: + type: string + jqPathExpressions: + items: + type: string + type: array + jsonPointers: + items: + type: string + type: array + kind: + type: string + name: + type: string + namespace: + type: string + required: + - kind + type: object + type: array + info: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + project: + type: string + revisionHistoryLimit: + format: int64 + type: integer + source: + properties: + chart: + type: string + directory: + properties: + exclude: + type: string + include: + type: string + jsonnet: + properties: + extVars: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + libs: + items: + type: string + type: array + tlas: + items: + properties: + code: + type: boolean + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + recurse: + type: boolean + type: object + helm: + properties: + fileParameters: + items: + properties: + name: + type: string + path: + type: string + type: object + type: array + parameters: + items: + properties: + forceString: + type: boolean + name: + type: string + value: + type: string + type: object + type: array + passCredentials: + type: boolean + releaseName: + type: string + valueFiles: + items: + type: string + type: array + values: + type: string + version: + type: string + type: object + ksonnet: + properties: + environment: + type: string + parameters: + items: + properties: + component: + type: string + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + type: object + kustomize: + properties: + commonAnnotations: + additionalProperties: + type: string + type: object + commonLabels: + additionalProperties: + type: string + type: object + forceCommonAnnotations: + type: boolean + forceCommonLabels: + type: boolean + images: + items: + type: string + type: array + namePrefix: + type: string + nameSuffix: + type: string + version: + type: string + type: object + path: + type: string + plugin: + properties: + env: + items: + properties: + name: + type: string + value: + type: string + required: + - name + - value + type: object + type: array + name: + type: string + type: object + repoURL: + type: string + targetRevision: + type: string + required: + - repoURL + type: object + syncPolicy: + properties: + automated: + properties: + allowEmpty: + type: boolean + prune: + type: boolean + selfHeal: + type: boolean + type: object + retry: + properties: + backoff: + properties: + duration: + type: string + factor: + format: int64 + type: integer + maxDuration: + type: string + type: object + limit: + format: int64 + type: integer + type: object + syncOptions: + items: + type: string + type: array + type: object + required: + - destination + - project + - source + type: object + required: + - metadata + - spec + type: object + templateOptions: + properties: + gotemplateEnabled: + type: boolean + type: object + required: + - generators + - template + type: object + status: + properties: + conditions: + items: + properties: + lastTransitionTime: + format: date-time + type: string + message: + type: string + reason: + type: string + status: + type: string + type: + type: string + required: + - message + - reason + - status + - type + type: object + type: array + type: object + required: + - metadata + - spec + type: object + served: true + storage: true + subresources: + status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + labels: + app.kubernetes.io/name: appprojects.argoproj.io + app.kubernetes.io/part-of: argocd + name: appprojects.argoproj.io +spec: + group: argoproj.io + names: + kind: AppProject + listKind: AppProjectList + plural: appprojects + shortNames: + - appproj + - appprojs + singular: appproject + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: 'AppProject provides a logical grouping of applications, providing controls for: * where the apps may deploy to (cluster whitelist) * what may be deployed (repository whitelist, resource whitelist/blacklist) * who can access these applications (roles, OIDC group claims bindings) * and what they can do (RBAC policies) * automation access to these roles (JWT tokens)' + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation of an object. Servers should convert recognized schemas to the latest internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this object represents. Servers may infer this from the endpoint the client submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: AppProjectSpec is the specification of an AppProject + properties: + clusterResourceBlacklist: + description: ClusterResourceBlacklist contains list of blacklisted cluster level resources + items: + description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types + properties: + group: + type: string + kind: + type: string + required: + - group + - kind + type: object + type: array + clusterResourceWhitelist: + description: ClusterResourceWhitelist contains list of whitelisted cluster level resources + items: + description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types + properties: + group: + type: string + kind: + type: string + required: + - group + - kind + type: object + type: array + description: + description: Description contains optional project description + type: string + destinations: + description: Destinations contains list of destinations available for deployment + items: + description: ApplicationDestination holds information about the application's destination + properties: + name: + description: Name is an alternate way of specifying the target cluster by its symbolic name + type: string + namespace: + description: Namespace specifies the target namespace for the application's resources. The namespace will only be set for namespace-scoped resources that have not set a value for .metadata.namespace + type: string + server: + description: Server specifies the URL of the target cluster and must be set to the Kubernetes control plane API + type: string + type: object + type: array + namespaceResourceBlacklist: + description: NamespaceResourceBlacklist contains list of blacklisted namespace level resources + items: + description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types + properties: + group: + type: string + kind: + type: string + required: + - group + - kind + type: object + type: array + namespaceResourceWhitelist: + description: NamespaceResourceWhitelist contains list of whitelisted namespace level resources + items: + description: GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types + properties: + group: + type: string + kind: + type: string + required: + - group + - kind + type: object + type: array + orphanedResources: + description: OrphanedResources specifies if controller should monitor orphaned resources of apps in this project + properties: + ignore: + description: Ignore contains a list of resources that are to be excluded from orphaned resources monitoring + items: + description: OrphanedResourceKey is a reference to a resource to be ignored from + properties: + group: + type: string + kind: + type: string + name: + type: string + type: object + type: array + warn: + description: Warn indicates if warning condition should be created for apps which have orphaned resources + type: boolean + type: object + roles: + description: Roles are user defined RBAC roles associated with this project + items: + description: ProjectRole represents a role that has access to a project + properties: + description: + description: Description is a description of the role + type: string + groups: + description: Groups are a list of OIDC group claims bound to this role + items: + type: string + type: array + jwtTokens: + description: JWTTokens are a list of generated JWT tokens bound to this role + items: + description: JWTToken holds the issuedAt and expiresAt values of a token + properties: + exp: + format: int64 + type: integer + iat: + format: int64 + type: integer + id: + type: string + required: + - iat + type: object + type: array + name: + description: Name is a name for this role + type: string + policies: + description: Policies Stores a list of casbin formatted strings that define access policies for the role in the project + items: + type: string + type: array + required: + - name + type: object + type: array + signatureKeys: + description: SignatureKeys contains a list of PGP key IDs that commits in Git must be signed with in order to be allowed for sync + items: + description: SignatureKey is the specification of a key required to verify commit signatures with + properties: + keyID: + description: The ID of the key in hexadecimal notation + type: string + required: + - keyID + type: object + type: array + sourceRepos: + description: SourceRepos contains list of repository URLs which can be used for deployment + items: + type: string + type: array + syncWindows: + description: SyncWindows controls when syncs can be run for apps in this project + items: + description: SyncWindow contains the kind, time, duration and attributes that are used to assign the syncWindows to apps + properties: + applications: + description: Applications contains a list of applications that the window will apply to + items: + type: string + type: array + clusters: + description: Clusters contains a list of clusters that the window will apply to + items: + type: string + type: array + duration: + description: Duration is the amount of time the sync window will be open + type: string + kind: + description: Kind defines if the window allows or blocks syncs + type: string + manualSync: + description: ManualSync enables manual syncs when they would otherwise be blocked + type: boolean + namespaces: + description: Namespaces contains a list of namespaces that the window will apply to + items: + type: string + type: array + schedule: + description: Schedule is the time the window will begin, specified in cron format + type: string + timeZone: + description: TimeZone of the sync that will be applied to the schedule + type: string + type: object + type: array + type: object + status: + description: AppProjectStatus contains status information for AppProject CRs + properties: + jwtTokensByRole: + additionalProperties: + description: JWTTokens represents a list of JWT tokens + properties: + items: + items: + description: JWTToken holds the issuedAt and expiresAt values of a token + properties: + exp: + format: int64 + type: integer + iat: + format: int64 + type: integer + id: + type: string + required: + - iat + type: object + type: array + type: object + description: JWTTokensByRole contains a list of JWT tokens issued for a given role + type: object + type: object + required: + - metadata + - spec + type: object + served: true + storage: true +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: argocd-applicationset-controller + app.kubernetes.io/part-of: argocd-applicationset + name: argocd-applicationset-controller +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: dex-server + app.kubernetes.io/name: argocd-dex-server + app.kubernetes.io/part-of: argocd + name: argocd-dex-server +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: redis + app.kubernetes.io/name: argocd-redis + app.kubernetes.io/part-of: argocd + name: argocd-redis +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +rules: +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - argoproj.io + resources: + - applications + - appprojects + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: argocd-applicationset-controller + app.kubernetes.io/part-of: argocd-applicationset + name: argocd-applicationset-controller +rules: +- apiGroups: + - argoproj.io + resources: + - applications + - appprojects + - applicationsets + - applicationsets/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - argoproj.io + resources: + - applicationsets/status + verbs: + - get + - patch + - update +- apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - list + - patch + - watch +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch +- apiGroups: + - apps + - extensions + resources: + - deployments + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: dex-server + app.kubernetes.io/name: argocd-dex-server + app.kubernetes.io/part-of: argocd + name: argocd-dex-server +rules: +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +rules: +- apiGroups: + - "" + resources: + - secrets + - configmaps + verbs: + - create + - get + - list + - watch + - update + - patch + - delete +- apiGroups: + - argoproj.io + resources: + - applications + - appprojects + verbs: + - create + - get + - list + - watch + - update + - delete + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - create + - list +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - '*' +- nonResourceURLs: + - '*' + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +rules: +- apiGroups: + - '*' + resources: + - '*' + verbs: + - delete + - get + - patch +- apiGroups: + - "" + resources: + - events + verbs: + - list +- apiGroups: + - "" + resources: + - pods + - pods/log + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argocd-application-controller +subjects: +- kind: ServiceAccount + name: argocd-application-controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: argocd-applicationset-controller + app.kubernetes.io/part-of: argocd-applicationset + name: argocd-applicationset-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argocd-applicationset-controller +subjects: +- kind: ServiceAccount + name: argocd-applicationset-controller +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: dex-server + app.kubernetes.io/name: argocd-dex-server + app.kubernetes.io/part-of: argocd + name: argocd-dex-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argocd-dex-server +subjects: +- kind: ServiceAccount + name: argocd-dex-server +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: redis + app.kubernetes.io/name: argocd-redis + app.kubernetes.io/part-of: argocd + name: argocd-redis +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argocd-redis +subjects: +- kind: ServiceAccount + name: argocd-redis +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: argocd-server +subjects: +- kind: ServiceAccount + name: argocd-server +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argocd-application-controller +subjects: +- kind: ServiceAccount + name: argocd-application-controller + namespace: argocd +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: argocd-server +subjects: +- kind: ServiceAccount + name: argocd-server + namespace: argocd +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-cm + app.kubernetes.io/part-of: argocd + name: argocd-cm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-cmd-params-cm + app.kubernetes.io/part-of: argocd + name: argocd-cmd-params-cm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-gpg-keys-cm + app.kubernetes.io/part-of: argocd + name: argocd-gpg-keys-cm +--- +apiVersion: v1 +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-rbac-cm + app.kubernetes.io/part-of: argocd + name: argocd-rbac-cm +--- +apiVersion: v1 +data: + 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= + gitlab.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAfuCHKVTjquxvt6CM6tdG4SLp1Btn/nOeHHE5UOzRdf + 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: + app.kubernetes.io/name: argocd-ssh-known-hosts-cm + app.kubernetes.io/part-of: argocd + name: argocd-ssh-known-hosts-cm +--- +apiVersion: v1 +data: null +kind: ConfigMap +metadata: + labels: + app.kubernetes.io/name: argocd-tls-certs-cm + app.kubernetes.io/part-of: argocd + name: argocd-tls-certs-cm +--- +apiVersion: v1 +kind: Secret +metadata: + labels: + app.kubernetes.io/name: argocd-secret + app.kubernetes.io/part-of: argocd + name: argocd-secret +type: Opaque +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: argocd-applicationset-controller + app.kubernetes.io/part-of: argocd-applicationset + name: argocd-applicationset-controller +spec: + ports: + - name: webhook + port: 7000 + protocol: TCP + targetPort: webhook + selector: + app.kubernetes.io/name: argocd-applicationset-controller +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: dex-server + app.kubernetes.io/name: argocd-dex-server + app.kubernetes.io/part-of: argocd + name: argocd-dex-server +spec: + ports: + - name: http + port: 5556 + protocol: TCP + targetPort: 5556 + - name: grpc + port: 5557 + protocol: TCP + targetPort: 5557 + - name: metrics + port: 5558 + protocol: TCP + targetPort: 5558 + selector: + app.kubernetes.io/name: argocd-dex-server +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: metrics + app.kubernetes.io/name: argocd-metrics + app.kubernetes.io/part-of: argocd + name: argocd-metrics +spec: + ports: + - name: metrics + port: 8082 + protocol: TCP + targetPort: 8082 + selector: + app.kubernetes.io/name: argocd-application-controller +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: redis + app.kubernetes.io/name: argocd-redis + app.kubernetes.io/part-of: argocd + name: argocd-redis +spec: + ports: + - name: tcp-redis + port: 6379 + targetPort: 6379 + selector: + app.kubernetes.io/name: argocd-redis +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: repo-server + app.kubernetes.io/name: argocd-repo-server + app.kubernetes.io/part-of: argocd + name: argocd-repo-server +spec: + ports: + - name: server + port: 8081 + protocol: TCP + targetPort: 8081 + - name: metrics + port: 8084 + protocol: TCP + targetPort: 8084 + selector: + app.kubernetes.io/name: argocd-repo-server +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +spec: + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 8080 + - name: https + port: 443 + protocol: TCP + targetPort: 8080 + selector: + app.kubernetes.io/name: argocd-server +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server-metrics + app.kubernetes.io/part-of: argocd + name: argocd-server-metrics +spec: + ports: + - name: metrics + port: 8083 + protocol: TCP + targetPort: 8083 + selector: + app.kubernetes.io/name: argocd-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: controller + app.kubernetes.io/name: argocd-applicationset-controller + app.kubernetes.io/part-of: argocd-applicationset + name: argocd-applicationset-controller +spec: + selector: + matchLabels: + app.kubernetes.io/name: argocd-applicationset-controller + template: + metadata: + labels: + app.kubernetes.io/name: argocd-applicationset-controller + spec: + containers: + - command: + - entrypoint.sh + - applicationset-controller + env: + - name: NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + image: quay.io/argoproj/argocd-applicationset:latest + imagePullPolicy: Always + name: argocd-applicationset-controller + ports: + - containerPort: 7000 + name: webhook + volumeMounts: + - mountPath: /app/config/ssh + name: ssh-known-hosts + - mountPath: /app/config/tls + name: tls-certs + - mountPath: /app/config/gpg/source + name: gpg-keys + - mountPath: /app/config/gpg/keys + name: gpg-keyring + serviceAccountName: argocd-applicationset-controller + volumes: + - configMap: + name: argocd-ssh-known-hosts-cm + name: ssh-known-hosts + - configMap: + name: argocd-tls-certs-cm + name: tls-certs + - configMap: + name: argocd-gpg-keys-cm + name: gpg-keys + - emptyDir: {} + name: gpg-keyring +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: dex-server + app.kubernetes.io/name: argocd-dex-server + app.kubernetes.io/part-of: argocd + name: argocd-dex-server +spec: + selector: + matchLabels: + app.kubernetes.io/name: argocd-dex-server + template: + metadata: + labels: + app.kubernetes.io/name: argocd-dex-server + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + containers: + - command: + - /shared/argocd-dex + - rundex + image: ghcr.io/dexidp/dex:v2.30.0 + imagePullPolicy: Always + name: dex + ports: + - containerPort: 5556 + - containerPort: 5557 + - containerPort: 5558 + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /shared + name: static-files + - mountPath: /tmp + name: dexconfig + initContainers: + - command: + - cp + - -n + - /usr/local/bin/argocd + - /shared/argocd-dex + image: quay.io/argoproj/argocd:v2.2.0 + imagePullPolicy: Always + name: copyutil + volumeMounts: + - mountPath: /shared + name: static-files + - mountPath: /tmp + name: dexconfig + serviceAccountName: argocd-dex-server + volumes: + - emptyDir: {} + name: static-files + - emptyDir: {} + name: dexconfig +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: redis + app.kubernetes.io/name: argocd-redis + app.kubernetes.io/part-of: argocd + name: argocd-redis +spec: + selector: + matchLabels: + app.kubernetes.io/name: argocd-redis + template: + metadata: + labels: + app.kubernetes.io/name: argocd-redis + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/name: argocd-redis + topologyKey: kubernetes.io/hostname + weight: 100 + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + containers: + - args: + - --save + - "" + - --appendonly + - "no" + image: redis:6.2.4-alpine + imagePullPolicy: Always + name: redis + ports: + - containerPort: 6379 + securityContext: + runAsNonRoot: true + runAsUser: 999 + serviceAccountName: argocd-redis +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: repo-server + app.kubernetes.io/name: argocd-repo-server + app.kubernetes.io/part-of: argocd + name: argocd-repo-server +spec: + selector: + matchLabels: + app.kubernetes.io/name: argocd-repo-server + template: + metadata: + labels: + app.kubernetes.io/name: argocd-repo-server + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/name: argocd-repo-server + topologyKey: kubernetes.io/hostname + weight: 100 + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + automountServiceAccountToken: false + containers: + - command: + - entrypoint.sh + - argocd-repo-server + - --redis + - argocd-redis:6379 + env: + - name: ARGOCD_RECONCILIATION_TIMEOUT + valueFrom: + configMapKeyRef: + key: timeout.reconciliation + name: argocd-cm + optional: true + - name: ARGOCD_REPO_SERVER_LOGFORMAT + valueFrom: + configMapKeyRef: + key: reposerver.log.format + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_REPO_SERVER_LOGLEVEL + valueFrom: + configMapKeyRef: + key: reposerver.log.level + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_REPO_SERVER_PARALLELISM_LIMIT + valueFrom: + configMapKeyRef: + key: reposerver.parallelism.limit + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_REPO_SERVER_DISABLE_TLS + valueFrom: + configMapKeyRef: + key: reposerver.disable.tls + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_MIN_VERSION + valueFrom: + configMapKeyRef: + key: reposerver.tls.minversion + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_MAX_VERSION + valueFrom: + configMapKeyRef: + key: reposerver.tls.maxversion + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_CIPHERS + valueFrom: + configMapKeyRef: + key: reposerver.tls.ciphers + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_REPO_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: reposerver.repo.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: REDIS_SERVER + valueFrom: + configMapKeyRef: + key: redis.server + name: argocd-cmd-params-cm + optional: true + - name: REDISDB + valueFrom: + configMapKeyRef: + key: redis.db + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_DEFAULT_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: reposerver.default.cache.expiration + name: argocd-cmd-params-cm + 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 + image: quay.io/argoproj/argocd:v2.2.0 + imagePullPolicy: Always + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz?full=true + port: 8084 + initialDelaySeconds: 30 + periodSeconds: 5 + name: argocd-repo-server + ports: + - containerPort: 8081 + - containerPort: 8084 + readinessProbe: + httpGet: + path: /healthz + port: 8084 + initialDelaySeconds: 5 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /app/config/ssh + name: ssh-known-hosts + - mountPath: /app/config/tls + name: tls-certs + - mountPath: /app/config/gpg/source + name: gpg-keys + - mountPath: /app/config/gpg/keys + name: gpg-keyring + - mountPath: /app/config/reposerver/tls + name: argocd-repo-server-tls + - mountPath: /tmp + name: tmp + - mountPath: /helm-working-dir + name: helm-working-dir + - mountPath: /home/argocd/cmp-server/plugins + name: plugins + initContainers: + - command: + - cp + - -n + - /usr/local/bin/argocd + - /var/run/argocd/argocd-cmp-server + image: quay.io/argoproj/argocd:v2.2.0 + name: copyutil + volumeMounts: + - mountPath: /var/run/argocd + name: var-files + volumes: + - configMap: + name: argocd-ssh-known-hosts-cm + name: ssh-known-hosts + - configMap: + name: argocd-tls-certs-cm + name: tls-certs + - configMap: + name: argocd-gpg-keys-cm + name: gpg-keys + - emptyDir: {} + name: gpg-keyring + - emptyDir: {} + name: tmp + - emptyDir: {} + name: helm-working-dir + - name: argocd-repo-server-tls + secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + optional: true + secretName: argocd-repo-server-tls + - emptyDir: {} + name: var-files + - emptyDir: {} + name: plugins +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/component: server + app.kubernetes.io/name: argocd-server + app.kubernetes.io/part-of: argocd + name: argocd-server +spec: + selector: + matchLabels: + app.kubernetes.io/name: argocd-server + template: + metadata: + labels: + app.kubernetes.io/name: argocd-server + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/name: argocd-server + topologyKey: kubernetes.io/hostname + weight: 100 + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + containers: + - command: + - argocd-server + env: + - name: ARGOCD_SERVER_INSECURE + valueFrom: + configMapKeyRef: + key: server.insecure + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_BASEHREF + valueFrom: + configMapKeyRef: + key: server.basehref + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_ROOTPATH + valueFrom: + configMapKeyRef: + key: server.rootpath + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_LOGFORMAT + valueFrom: + configMapKeyRef: + key: server.log.format + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_REPO_SERVER_LOGLEVEL + valueFrom: + configMapKeyRef: + key: server.log.level + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_REPO_SERVER + valueFrom: + configMapKeyRef: + key: repo.server + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_DEX_SERVER + valueFrom: + configMapKeyRef: + key: server.dex.server + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_DISABLE_AUTH + valueFrom: + configMapKeyRef: + key: server.disable.auth + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_ENABLE_GZIP + valueFrom: + configMapKeyRef: + key: server.enable.gzip + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_REPO_SERVER_TIMEOUT_SECONDS + valueFrom: + configMapKeyRef: + key: server.repo.server.timeout.seconds + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_X_FRAME_OPTIONS + valueFrom: + configMapKeyRef: + key: server.x.frame.options + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_REPO_SERVER_PLAINTEXT + valueFrom: + configMapKeyRef: + key: server.repo.server.plaintext + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_REPO_SERVER_STRICT_TLS + valueFrom: + configMapKeyRef: + key: server.repo.server.strict.tls + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_MIN_VERSION + valueFrom: + configMapKeyRef: + key: server.tls.minversion + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_MAX_VERSION + valueFrom: + configMapKeyRef: + key: server.tls.maxversion + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_TLS_CIPHERS + valueFrom: + configMapKeyRef: + key: server.tls.ciphers + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_CONNECTION_STATUS_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: server.connection.status.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_OIDC_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: server.oidc.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_LOGIN_ATTEMPTS_EXPIRATION + valueFrom: + configMapKeyRef: + key: server.login.attempts.expiration + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_SERVER_STATIC_ASSETS + valueFrom: + configMapKeyRef: + key: server.staticassets + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APP_STATE_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: server.app.state.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: REDIS_SERVER + valueFrom: + configMapKeyRef: + key: redis.server + name: argocd-cmd-params-cm + optional: true + - name: REDISDB + valueFrom: + configMapKeyRef: + key: redis.db + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_DEFAULT_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: server.default.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_MAX_COOKIE_NUMBER + valueFrom: + configMapKeyRef: + key: server.http.cookie.maxnumber + name: argocd-cmd-params-cm + optional: true + image: quay.io/argoproj/argocd:v2.2.0 + imagePullPolicy: Always + livenessProbe: + httpGet: + path: /healthz?full=true + port: 8080 + initialDelaySeconds: 3 + periodSeconds: 30 + name: argocd-server + ports: + - containerPort: 8080 + - containerPort: 8083 + readinessProbe: + httpGet: + path: /healthz + port: 8080 + initialDelaySeconds: 3 + periodSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /app/config/ssh + name: ssh-known-hosts + - mountPath: /app/config/tls + name: tls-certs + - mountPath: /app/config/server/tls + name: argocd-repo-server-tls + - mountPath: /home/argocd + name: plugins-home + - mountPath: /tmp + name: tmp + serviceAccountName: argocd-server + volumes: + - emptyDir: {} + name: plugins-home + - emptyDir: {} + name: tmp + - emptyDir: {} + name: static-files + - configMap: + name: argocd-ssh-known-hosts-cm + name: ssh-known-hosts + - configMap: + name: argocd-tls-certs-cm + name: tls-certs + - name: argocd-repo-server-tls + secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + optional: true + secretName: argocd-repo-server-tls +--- +apiVersion: apps/v1 +kind: StatefulSet +metadata: + labels: + app.kubernetes.io/component: application-controller + app.kubernetes.io/name: argocd-application-controller + app.kubernetes.io/part-of: argocd + name: argocd-application-controller +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: argocd-application-controller + serviceName: argocd-application-controller + template: + metadata: + labels: + app.kubernetes.io/name: argocd-application-controller + spec: + affinity: + podAntiAffinity: + preferredDuringSchedulingIgnoredDuringExecution: + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/name: argocd-application-controller + topologyKey: kubernetes.io/hostname + weight: 100 + - podAffinityTerm: + labelSelector: + matchLabels: + app.kubernetes.io/part-of: argocd + topologyKey: kubernetes.io/hostname + weight: 5 + containers: + - command: + - argocd-application-controller + env: + - name: ARGOCD_RECONCILIATION_TIMEOUT + valueFrom: + configMapKeyRef: + key: timeout.reconciliation + name: argocd-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER + valueFrom: + configMapKeyRef: + key: repo.server + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_TIMEOUT_SECONDS + valueFrom: + configMapKeyRef: + key: controller.repo.server.timeout.seconds + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_STATUS_PROCESSORS + valueFrom: + configMapKeyRef: + key: controller.status.processors + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_OPERATION_PROCESSORS + valueFrom: + configMapKeyRef: + key: controller.operation.processors + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_LOGFORMAT + valueFrom: + configMapKeyRef: + key: controller.log.format + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_LOGLEVEL + valueFrom: + configMapKeyRef: + key: controller.log.level + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_METRICS_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: controller.metrics.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_SELF_HEAL_TIMEOUT_SECONDS + valueFrom: + configMapKeyRef: + key: controller.self.heal.timeout.seconds + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_PLAINTEXT + valueFrom: + configMapKeyRef: + key: controller.repo.server.plaintext + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APPLICATION_CONTROLLER_REPO_SERVER_STRICT_TLS + valueFrom: + configMapKeyRef: + key: controller.repo.server.strict.tls + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_APP_STATE_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: controller.app.state.cache.expiration + name: argocd-cmd-params-cm + optional: true + - name: REDIS_SERVER + valueFrom: + configMapKeyRef: + key: redis.server + name: argocd-cmd-params-cm + optional: true + - name: REDISDB + valueFrom: + configMapKeyRef: + key: redis.db + name: argocd-cmd-params-cm + optional: true + - name: ARGOCD_DEFAULT_CACHE_EXPIRATION + valueFrom: + configMapKeyRef: + key: controller.default.cache.expiration + name: argocd-cmd-params-cm + optional: true + image: quay.io/argoproj/argocd:v2.2.0 + imagePullPolicy: Always + livenessProbe: + httpGet: + path: /healthz + port: 8082 + initialDelaySeconds: 5 + periodSeconds: 10 + name: argocd-application-controller + ports: + - containerPort: 8082 + readinessProbe: + httpGet: + path: /healthz + port: 8082 + initialDelaySeconds: 5 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - all + readOnlyRootFilesystem: true + runAsNonRoot: true + volumeMounts: + - mountPath: /app/config/controller/tls + name: argocd-repo-server-tls + - mountPath: /home/argocd + name: argocd-home + workingDir: /home/argocd + serviceAccountName: argocd-application-controller + volumes: + - emptyDir: {} + name: argocd-home + - name: argocd-repo-server-tls + secret: + items: + - key: tls.crt + path: tls.crt + - key: tls.key + path: tls.key + - key: ca.crt + path: ca.crt + optional: true + secretName: argocd-repo-server-tls +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: argocd-application-controller-network-policy +spec: + ingress: + - from: + - namespaceSelector: {} + ports: + - port: 8082 + podSelector: + matchLabels: + app.kubernetes.io/name: argocd-application-controller + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: argocd-dex-server-network-policy +spec: + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-server + ports: + - port: 5556 + protocol: TCP + - port: 5557 + protocol: TCP + - from: + - namespaceSelector: {} + ports: + - port: 5558 + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: argocd-dex-server + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: argocd-redis-network-policy +spec: + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-server + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-repo-server + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-application-controller + ports: + - port: 6379 + protocol: TCP + podSelector: + matchLabels: + app.kubernetes.io/name: argocd-redis + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: argocd-repo-server-network-policy +spec: + ingress: + - from: + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-server + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-application-controller + - podSelector: + matchLabels: + app.kubernetes.io/name: argocd-notifications-controller + ports: + - port: 8081 + protocol: TCP + - from: + - namespaceSelector: {} + ports: + - port: 8084 + podSelector: + matchLabels: + app.kubernetes.io/name: argocd-repo-server + policyTypes: + - Ingress +--- +apiVersion: networking.k8s.io/v1 +kind: NetworkPolicy +metadata: + name: argocd-server-network-policy +spec: + ingress: + - {} + podSelector: + matchLabels: + app.kubernetes.io/name: argocd-server + policyTypes: + - Ingress diff --git a/manifests/install.yaml b/manifests/install.yaml index fec1e96d..635db7f4 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -6457,6 +6457,11 @@ spec: - metadata - spec type: object + templateOptions: + properties: + gotemplateEnabled: + type: boolean + type: object required: - generators - template diff --git a/pkg/controllers/applicationset_controller.go b/pkg/controllers/applicationset_controller.go index 13f33378..b86ec54d 100644 --- a/pkg/controllers/applicationset_controller.go +++ b/pkg/controllers/applicationset_controller.go @@ -444,7 +444,7 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argop tmplApplication := getTempApplication(a.Template) for _, p := range a.Params { - app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, p) + app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, applicationSetInfo.Spec.TemplateOptions, p) if err != nil { log.WithError(err).WithField("params", a.Params).WithField("generator", requestedGenerator). Error("error generating application from params") diff --git a/pkg/controllers/applicationset_controller_test.go b/pkg/controllers/applicationset_controller_test.go index 69c45637..f831423e 100644 --- a/pkg/controllers/applicationset_controller_test.go +++ b/pkg/controllers/applicationset_controller_test.go @@ -59,7 +59,7 @@ func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appl return args.Get(0).(time.Duration) } -func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) { +func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) { args := r.Called(tmpl, params) if args.Error(1) != nil { diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 1436cb23..9ef3edb8 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -1,6 +1,7 @@ package utils import ( + "bytes" "encoding/json" "fmt" "io" @@ -8,21 +9,24 @@ import ( "sort" "strconv" "strings" + "text/template" + "github.com/Masterminds/sprig/v3" argoprojiov1alpha1 "github.com/argoproj/applicationset/api/v1alpha1" argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" log "github.com/sirupsen/logrus" "github.com/valyala/fasttemplate" + "gopkg.in/yaml.v3" ) type Renderer interface { - RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) + RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) } type Render struct { } -func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) { +func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) { if tmpl == nil { return nil, fmt.Errorf("application template is empty ") } @@ -31,21 +35,47 @@ func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy return tmpl, nil } - tmplBytes, err := json.Marshal(tmpl) - if err != nil { - return nil, err - } + var replacedTmpl argov1alpha1.Application + var replacedTmplStr string - fstTmpl := fasttemplate.New(string(tmplBytes), "{{", "}}") - replacedTmplStr, err := r.replace(fstTmpl, params, true) - if err != nil { - return nil, err - } + if templateOptions == nil || !templateOptions.GotemplateEnabled { + tmplBytes, err := json.Marshal(tmpl) + if err != nil { + return nil, err + } - var replacedTmpl argov1alpha1.Application - err = json.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) - if err != nil { - return nil, err + fstTmpl := fasttemplate.New(string(tmplBytes), "{{", "}}") + replacedTmplStr, err = r.replaceWithFastTemplate(fstTmpl, params, true) + if err != nil { + return nil, err + } + + err = json.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) + if err != nil { + return nil, err + } + } else { + + // as opposed to json, yaml escapes double quote sign with only one slash and hence allow to use {{ "string" }} scalar variables for various use-cases + tmplBytes, err := yaml.Marshal(tmpl) + if err != nil { + return nil, err + } + + // missingkey=zero - replace unmatched variables with "" + goTemplate, err := template.New("argocd-app").Option("missingkey=zero").Funcs(sprig.TxtFuncMap()).Parse(string(tmplBytes)) + if err != nil { + return nil, err + } + replacedTmplStr, err = r.replaceWithGoTemplate(goTemplate, params) + if err != nil { + return nil, err + } + + err = yaml.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) + if err != nil { + return nil, err + } } // Add the 'resources-finalizer' finalizer if: @@ -62,10 +92,10 @@ func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy return &replacedTmpl, nil } -// Replace executes basic string substitution of a template with replacement values. +// replaceWithFastTemplate executes basic string substitution of a template with replacement values. // 'allowUnresolved' indicates whether or not it is acceptable to have unresolved variables // remaining in the substituted template. -func (r *Render) replace(fstTmpl *fasttemplate.Template, replaceMap map[string]string, allowUnresolved bool) (string, error) { +func (r *Render) replaceWithFastTemplate(fstTmpl *fasttemplate.Template, replaceMap map[string]string, allowUnresolved bool) (string, error) { var unresolvedErr error replacedTmpl := fstTmpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { @@ -93,6 +123,18 @@ func (r *Render) replace(fstTmpl *fasttemplate.Template, replaceMap map[string]s return replacedTmpl, nil } +// replaceWithGoTemplate applies a parsed Go template to replacement values +func (r *Render) replaceWithGoTemplate(goTemplate *template.Template, replaceMap map[string]string) (string, error) { + var tplString bytes.Buffer + + err := goTemplate.Execute(&tplString, replaceMap) + if err != nil { + return "", err + } + + return tplString.String(), nil +} + // Log a warning if there are unrecognized generators func CheckInvalidGenerators(applicationSetInfo *argoprojiov1alpha1.ApplicationSet) { hasInvalidGenerators, invalidGenerators := invalidGenerators(applicationSetInfo) diff --git a/pkg/utils/util_test.go b/pkg/utils/util_test.go index d56b25c7..f171e012 100644 --- a/pkg/utils/util_test.go +++ b/pkg/utils/util_test.go @@ -12,8 +12,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -func TestRenderTemplateParams(t *testing.T) { - +func composeApplicationFieldsFuncMap() map[string]func(app *argov1alpha1.Application) *string { // Believe it or not, this is actually less complex than the equivalent solution using reflection fieldMap := map[string]func(app *argov1alpha1.Application) *string{} fieldMap["Path"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.Path } @@ -27,6 +26,13 @@ func TestRenderTemplateParams(t *testing.T) { fieldMap["Project"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Project } + return fieldMap +} + +func TestRenderTemplateParams(t *testing.T) { + + fieldMap := composeApplicationFieldsFuncMap() + emptyApplication := &argov1alpha1.Application{ Spec: argov1alpha1.ApplicationSpec{ Source: argov1alpha1.ApplicationSource{ @@ -153,7 +159,7 @@ func TestRenderTemplateParams(t *testing.T) { // Render the cloned application, into a new application render := Render{} - newApplication, err := render.RenderTemplateParams(application, nil, test.params) + newApplication, err := render.RenderTemplateParams(application, nil, nil, test.params) // Retrieve the value of the target field from the newApplication, then verify that // the target field has been templated into the expected value @@ -261,7 +267,7 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) { // Render the cloned application, into a new application render := Render{} - res, err := render.RenderTemplateParams(application, c.syncPolicy, params) + res, err := render.RenderTemplateParams(application, c.syncPolicy, nil, params) assert.Nil(t, err) assert.ElementsMatch(t, res.Finalizers, c.expectedFinalizers) @@ -272,6 +278,120 @@ func TestRenderTemplateParamsFinalizers(t *testing.T) { } +func TestRenderGoTemplateParams(t *testing.T) { + + fieldMap := composeApplicationFieldsFuncMap() + + emptyApplication := &argov1alpha1.Application{ + Spec: argov1alpha1.ApplicationSpec{ + Source: argov1alpha1.ApplicationSource{ + Path: "", + RepoURL: "", + TargetRevision: "", + Chart: "", + }, + Destination: argov1alpha1.ApplicationDestination{ + Server: "", + Namespace: "", + Name: "", + }, + Project: "", + }, + } + + tests := []struct { + name string + fieldVal string + templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions + params map[string]string + expectedVal string + }{ + { + name: "simple substitution", + fieldVal: "{{.one}}", + expectedVal: "two", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "one": "two", + }, + }, + { + name: "simple substitution with whitespace", + fieldVal: "{{ .one }}", + expectedVal: "two", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "one": "two", + }, + }, + { + name: "multiple on a line", + fieldVal: "{{.one}}{{.one}}", + expectedVal: "twotwo", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "one": "two", + }, + }, + { + name: "multiple different on a line", + fieldVal: "{{.one}}{{.three}}", + expectedVal: "twofour", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "one": "two", + "three": "four", + }, + }, + { + name: "sprig functions are avilable", + fieldVal: "{{upper .one}}{{default \"four\" .three}}", + expectedVal: "TWOfour", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "one": "two", + }, + }, + } + + for _, test := range tests { + + t.Run(test.name, func(t *testing.T) { + + for fieldName, getPtrFunc := range fieldMap { + + // Clone the template application + application := emptyApplication.DeepCopy() + + // Set the value of the target field, to the test value + *getPtrFunc(application) = test.fieldVal + + // Render the cloned application, into a new application + render := Render{} + newApplication, err := render.RenderTemplateParams(application, nil, test.templateOptions, test.params) + + // Retrieve the value of the target field from the newApplication, then verify that + // the target field has been templated into the expected value + actualValue := *getPtrFunc(newApplication) + assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue) + assert.NoError(t, err) + + } + }) + } + +} + func TestCheckInvalidGenerators(t *testing.T) { scheme := runtime.NewScheme() From a8029cde2e5d99da98ec355024cf8be940273db9 Mon Sep 17 00:00:00 2001 From: Vlad Date: Sun, 20 Feb 2022 23:58:36 +0100 Subject: [PATCH 2/8] remove redundant autogenerated record Signed-off-by: Vlad --- api/v1alpha1/zz_generated.deepcopy.go | 1 - 1 file changed, 1 deletion(-) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 3993100a..8d1a6ab3 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,4 +1,3 @@ -//go:build !ignore_autogenerated // +build !ignore_autogenerated /* From 43bcad4ccbc07d91990c43deabc1faa7778d3589 Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 23 Feb 2022 00:22:11 +0100 Subject: [PATCH 3/8] getting rid of yet another YAML package Signed-off-by: Vlad --- pkg/utils/util.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 9ef3edb8..40d021b7 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -16,7 +16,7 @@ import ( argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" log "github.com/sirupsen/logrus" "github.com/valyala/fasttemplate" - "gopkg.in/yaml.v3" + "sigs.k8s.io/yaml" ) type Renderer interface { From c3e67ddbe23aa35c48f7218c457ad82099d41b1c Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 23 Feb 2022 00:30:03 +0100 Subject: [PATCH 4/8] test Signed-off-by: Vlad --- dsf | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 dsf diff --git a/dsf b/dsf new file mode 100644 index 00000000..e69de29b From c4dbe49588aa1f41a3b324ef50b96479acdaccbd Mon Sep 17 00:00:00 2001 From: Vlad Date: Wed, 23 Feb 2022 00:30:33 +0100 Subject: [PATCH 5/8] test Signed-off-by: Vlad --- 2 | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 2 diff --git a/2 b/2 new file mode 100644 index 00000000..e69de29b From 10f45ac54833514c81d2b4b6ae56297f106eedbd Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 25 Feb 2022 15:30:31 +0100 Subject: [PATCH 6/8] Output applicaiton structure is immutable Signed-off-by: Vlad --- pkg/utils/util_test.go | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/pkg/utils/util_test.go b/pkg/utils/util_test.go index f171e012..05fd562f 100644 --- a/pkg/utils/util_test.go +++ b/pkg/utils/util_test.go @@ -353,7 +353,7 @@ func TestRenderGoTemplateParams(t *testing.T) { }, { name: "sprig functions are avilable", - fieldVal: "{{upper .one}}{{default \"four\" .three}}", + fieldVal: `{{upper .one}}{{default "four" .three}}`, expectedVal: "TWOfour", templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ GotemplateEnabled: true, @@ -362,6 +362,17 @@ func TestRenderGoTemplateParams(t *testing.T) { "one": "two", }, }, + { + name: "the output application structure is imutable", + fieldVal: "{{ .yamlPiece }}\n\tsomeother: element", + expectedVal: "targetRevision: my-other-branch\n\tsomeother: element", + templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ + GotemplateEnabled: true, + }, + params: map[string]string{ + "yamlPiece": "targetRevision: my-other-branch", + }, + }, } for _, test := range tests { From ffe08d3f64b57b73838dc20dc4eb0e2ab6568377 Mon Sep 17 00:00:00 2001 From: Vlad Date: Fri, 25 Feb 2022 17:30:26 +0100 Subject: [PATCH 7/8] removing junk files Signed-off-by: Vlad --- 2 | 0 dsf | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 2 delete mode 100644 dsf diff --git a/2 b/2 deleted file mode 100644 index e69de29b..00000000 diff --git a/dsf b/dsf deleted file mode 100644 index e69de29b..00000000 From ff41793407d5ada205716c7ab44c8917f8243b7f Mon Sep 17 00:00:00 2001 From: Vlad Date: Sat, 12 Mar 2022 17:46:37 +0100 Subject: [PATCH 8/8] Implementation with two types of templates Signed-off-by: Vlad --- api/v1alpha1/applicationset_types.go | 13 +- api/v1alpha1/zz_generated.deepcopy.go | 32 +- go.mod | 7 + go.sum | 11 + .../crds/argoproj.io_applicationsets.yaml | 8 +- manifests/install.yaml | 8 +- pkg/controllers/applicationset_controller.go | 10 +- .../applicationset_controller_test.go | 34 +- pkg/generators/generator_spec_processor.go | 13 +- pkg/generators/matrix.go | 2 +- pkg/generators/merge.go | 2 +- pkg/utils/templating.go | 199 +++++++++ pkg/utils/templating_test.go | 402 ++++++++++++++++++ pkg/utils/util.go | 125 ------ pkg/utils/util_test.go | 391 ----------------- .../e2e/applicationset/applicationset_test.go | 14 +- test/e2e/applicationset/cluster_e2e_test.go | 8 +- test/e2e/applicationset/crl_e2e_test.go | 8 +- test/e2e/applicationset/matrix_e2e_test.go | 4 +- test/e2e/applicationset/merge_e2e_test.go | 4 +- 20 files changed, 696 insertions(+), 599 deletions(-) create mode 100644 pkg/utils/templating.go create mode 100644 pkg/utils/templating_test.go diff --git a/api/v1alpha1/applicationset_types.go b/api/v1alpha1/applicationset_types.go index 168c2021..886a7ba7 100644 --- a/api/v1alpha1/applicationset_types.go +++ b/api/v1alpha1/applicationset_types.go @@ -49,9 +49,9 @@ type ApplicationSet struct { // ApplicationSetSpec represents a class of application set state. type ApplicationSetSpec struct { Generators []ApplicationSetGenerator `json:"generators"` - Template ApplicationSetTemplate `json:"template"` + Template *ApplicationSetTemplate `json:"template,omitempty"` + UntypedTemplate *ApplicationSetUntypedTemplate `json:"untypedTemplate,omitempty"` SyncPolicy *ApplicationSetSyncPolicy `json:"syncPolicy,omitempty"` - TemplateOptions *ApplicationSetTemplateOptions `json:"templateOptions,omitempty"` } // ApplicationSetSyncPolicy configures how generated Applications will relate to their @@ -61,18 +61,15 @@ type ApplicationSetSyncPolicy struct { PreserveResourcesOnDeletion bool `json:"preserveResourcesOnDeletion,omitempty"` } -// ApplicationSetTemplateOptions configures how template rendering behaves -type ApplicationSetTemplateOptions struct { - // GotemplateEnabled will switch to Go template rendering engine. - GotemplateEnabled bool `json:"gotemplateEnabled,omitempty"` -} - // ApplicationSetTemplate represents argocd ApplicationSpec type ApplicationSetTemplate struct { ApplicationSetTemplateMeta `json:"metadata"` Spec v1alpha1.ApplicationSpec `json:"spec"` } +// ApplicationSetUntypedTemplate represents argocd ApplicationSpec without type check +type ApplicationSetUntypedTemplate string + // ApplicationSetTemplateMeta represents the Argo CD application fields that may // be used for Applications generated from the ApplicationSet (based on metav1.ObjectMeta) type ApplicationSetTemplateMeta struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8d1a6ab3..fab02ff9 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1,3 +1,4 @@ +//go:build !ignore_autogenerated // +build !ignore_autogenerated /* @@ -242,17 +243,21 @@ func (in *ApplicationSetSpec) DeepCopyInto(out *ApplicationSetSpec) { (*in)[i].DeepCopyInto(&(*out)[i]) } } - in.Template.DeepCopyInto(&out.Template) + if in.Template != nil { + in, out := &in.Template, &out.Template + *out = new(ApplicationSetTemplate) + (*in).DeepCopyInto(*out) + } + if in.UntypedTemplate != nil { + in, out := &in.UntypedTemplate, &out.UntypedTemplate + *out = new(ApplicationSetUntypedTemplate) + **out = **in + } if in.SyncPolicy != nil { in, out := &in.SyncPolicy, &out.SyncPolicy *out = new(ApplicationSetSyncPolicy) **out = **in } - if in.TemplateOptions != nil { - in, out := &in.TemplateOptions, &out.TemplateOptions - *out = new(ApplicationSetTemplateOptions) - **out = **in - } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSetSpec. @@ -353,21 +358,6 @@ func (in *ApplicationSetTemplateMeta) DeepCopy() *ApplicationSetTemplateMeta { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ApplicationSetTemplateOptions) DeepCopyInto(out *ApplicationSetTemplateOptions) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApplicationSetTemplateOptions. -func (in *ApplicationSetTemplateOptions) DeepCopy() *ApplicationSetTemplateOptions { - if in == nil { - return nil - } - out := new(ApplicationSetTemplateOptions) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ApplicationSetTerminalGenerator) DeepCopyInto(out *ApplicationSetTerminalGenerator) { *out = *in diff --git a/go.mod b/go.mod index 736375c1..ea63c3ef 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/argoproj/applicationset go 1.17 require ( + github.com/Masterminds/sprig/v3 v3.2.2 github.com/argoproj/argo-cd/v2 v2.3.0-rc5.0.20220225234205-31676e2aea6f github.com/argoproj/gitops-engine v0.6.0 github.com/argoproj/pkg v0.11.1-0.20211203175135-36c59d8fafe0 @@ -29,6 +30,7 @@ require ( cloud.google.com/go v0.81.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect + github.com/Masterminds/goutils v1.1.1 // indirect github.com/Masterminds/semver/v3 v3.1.1 // indirect github.com/PuerkitoBio/purell v1.1.1 // indirect github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect @@ -76,6 +78,7 @@ require ( github.com/grpc-ecosystem/grpc-gateway v1.16.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.1 // indirect github.com/hashicorp/go-retryablehttp v0.7.0 // indirect + github.com/huandu/xstrings v1.3.1 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jonboulle/clockwork v0.2.2 // indirect @@ -87,8 +90,10 @@ require ( github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect github.com/mailru/easyjson v0.7.6 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mitchellh/copystructure v1.0.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.0 // indirect + github.com/mitchellh/reflectwalk v1.0.0 // indirect github.com/moby/spdystream v0.2.0 // indirect github.com/moby/term v0.0.0-20210610120745-9d4ed1856297 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect @@ -107,6 +112,8 @@ require ( github.com/robfig/cron v1.2.0 // indirect github.com/russross/blackfriday v1.5.2 // indirect github.com/sergi/go-diff v1.1.0 // indirect + github.com/shopspring/decimal v1.2.0 // indirect + github.com/spf13/cast v1.3.1 // indirect github.com/spf13/cobra v1.2.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/stretchr/objx v0.2.0 // indirect diff --git a/go.sum b/go.sum index d764c3e6..b488d5e0 100644 --- a/go.sum +++ b/go.sum @@ -65,11 +65,16 @@ github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd h1:sjQovDkwrZp8u+gxLtPgKGjk5hCxuy2hrRejBTA9xFU= github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd/go.mod h1:64YHyfSL2R96J44Nlwm39UHepQbyR5q10x7iYa1ks2E= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60= github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o= +github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8= +github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= github.com/Microsoft/go-winio v0.4.15/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.17/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Microsoft/hcsshim v0.8.22/go.mod h1:91uVCVzvX2QD16sMCenoxxXo6L1wJnLMX2PSufFMtF0= @@ -537,12 +542,15 @@ github.com/heketi/tests v0.0.0-20151005000721-f3775cbcefd6/go.mod h1:xGMAM8JLi7U github.com/howeyc/gopass v0.0.0-20170109162249-bf9dde6d0d2c/go.mod h1:lADxMC39cJJqL93Duh1xhAs4I2Zs8mKS89XWXFGp9cs= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.1 h1:4jgBlKK6tLKFvO8u5pmYjG91cqytmDCDvGh7ECVFfFs= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/improbable-eng/grpc-web v0.0.0-20181111100011-16092bd1d58a/go.mod h1:6hRR09jOEG81ADP5wCQju1z71g6OL4eEvELdran/3cs= @@ -661,6 +669,7 @@ github.com/minio/minio-go/v7 v7.0.2/go.mod h1:dJ80Mv2HeGkYLH1sqS/ksz07ON6csH3S6J github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMKeZ+mmkFQ= github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= @@ -673,6 +682,7 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY= github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/moby/ipvs v1.0.1/go.mod h1:2pngiyseZbIKXNv7hsKj3O9UEz30c53MT9005gt2hxQ= github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= @@ -868,6 +878,7 @@ github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= diff --git a/manifests/crds/argoproj.io_applicationsets.yaml b/manifests/crds/argoproj.io_applicationsets.yaml index d730a11d..74aec7fb 100644 --- a/manifests/crds/argoproj.io_applicationsets.yaml +++ b/manifests/crds/argoproj.io_applicationsets.yaml @@ -6458,14 +6458,10 @@ spec: - metadata - spec type: object - templateOptions: - properties: - gotemplateEnabled: - type: boolean - type: object + untypedTemplate: + type: string required: - generators - - template type: object status: properties: diff --git a/manifests/install.yaml b/manifests/install.yaml index 635db7f4..1a44c57e 100644 --- a/manifests/install.yaml +++ b/manifests/install.yaml @@ -6457,14 +6457,10 @@ spec: - metadata - spec type: object - templateOptions: - properties: - gotemplateEnabled: - type: boolean - type: object + untypedTemplate: + type: string required: - generators - - template type: object status: properties: diff --git a/pkg/controllers/applicationset_controller.go b/pkg/controllers/applicationset_controller.go index b86ec54d..bf8f62a1 100644 --- a/pkg/controllers/applicationset_controller.go +++ b/pkg/controllers/applicationset_controller.go @@ -428,6 +428,14 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argop var firstError error var applicationSetReason argoprojiov1alpha1.ApplicationSetReasonType + if (applicationSetInfo.Spec.Template == nil && applicationSetInfo.Spec.UntypedTemplate == nil) || + (applicationSetInfo.Spec.Template != nil && applicationSetInfo.Spec.UntypedTemplate != nil) { + firstError = fmt.Errorf("application set spec should have either template or untypedTemplate defined") + applicationSetReason = argoprojiov1alpha1.ApplicationSetReasonErrorOccurred + + return res, applicationSetReason, firstError + } + for _, requestedGenerator := range applicationSetInfo.Spec.Generators { t, err := generators.Transform(requestedGenerator, r.Generators, applicationSetInfo.Spec.Template, &applicationSetInfo) if err != nil { @@ -444,7 +452,7 @@ func (r *ApplicationSetReconciler) generateApplications(applicationSetInfo argop tmplApplication := getTempApplication(a.Template) for _, p := range a.Params { - app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.SyncPolicy, applicationSetInfo.Spec.TemplateOptions, p) + app, err := r.Renderer.RenderTemplateParams(tmplApplication, applicationSetInfo.Spec.UntypedTemplate, applicationSetInfo.Spec.SyncPolicy, p) if err != nil { log.WithError(err).WithField("params", a.Params).WithField("generator", requestedGenerator). Error("error generating application from params") diff --git a/pkg/controllers/applicationset_controller_test.go b/pkg/controllers/applicationset_controller_test.go index f831423e..9efbddec 100644 --- a/pkg/controllers/applicationset_controller_test.go +++ b/pkg/controllers/applicationset_controller_test.go @@ -59,7 +59,7 @@ func (g *generatorMock) GetRequeueAfter(appSetGenerator *argoprojiov1alpha1.Appl return args.Get(0).(time.Duration) } -func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) { +func (r *rendererMock) RenderTemplateParams(tmpl *argov1alpha1.Application, untypedTemplate *argoprojiov1alpha1.ApplicationSetUntypedTemplate, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) { args := r.Called(tmpl, params) if args.Error(1) != nil { @@ -187,7 +187,7 @@ func TestExtractApplications(t *testing.T) { }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator}, - Template: cc.template, + Template: &cc.template, }, }) @@ -300,7 +300,7 @@ func TestMergeTemplateApplications(t *testing.T) { }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ Generators: []argoprojiov1alpha1.ApplicationSetGenerator{generator}, - Template: cc.template, + Template: &cc.template, }, }, ) @@ -370,7 +370,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -428,7 +428,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -486,7 +486,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -548,7 +548,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -608,7 +608,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -680,7 +680,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", Source: argov1alpha1.ApplicationSource{Path: "path", TargetRevision: "revision", RepoURL: "repoURL"}, @@ -760,7 +760,7 @@ func TestCreateOrUpdateInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -900,7 +900,7 @@ func TestRemoveFinalizerOnInvalidDestination_FinalizerTypes(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -1060,7 +1060,7 @@ func TestRemoveFinalizerOnInvalidDestination_DestinationTypes(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -1186,7 +1186,7 @@ func TestCreateApplications(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -1243,7 +1243,7 @@ func TestCreateApplications(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -1355,7 +1355,7 @@ func TestDeleteInCluster(t *testing.T) { Namespace: "namespace", }, Spec: argoprojiov1alpha1.ApplicationSetSpec{ - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ Spec: argov1alpha1.ApplicationSpec{ Project: "project", }, @@ -1797,7 +1797,7 @@ func TestReconcilerValidationErrorBehaviour(t *testing.T) { }, }, }, - Template: argoprojiov1alpha1.ApplicationSetTemplate{ + Template: &argoprojiov1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: argoprojiov1alpha1.ApplicationSetTemplateMeta{ Name: "{{cluster}}", Namespace: "argocd", @@ -1883,7 +1883,7 @@ func TestSetApplicationSetStatusCondition(t *testing.T) { }}, }}, }, - Template: argoprojiov1alpha1.ApplicationSetTemplate{}, + Template: &argoprojiov1alpha1.ApplicationSetTemplate{}, }, } diff --git a/pkg/generators/generator_spec_processor.go b/pkg/generators/generator_spec_processor.go index 84786ba1..17963488 100644 --- a/pkg/generators/generator_spec_processor.go +++ b/pkg/generators/generator_spec_processor.go @@ -32,7 +32,7 @@ type TransformResult struct { } //Transform a spec generator to list of paramSets and a template -func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, allGenerators map[string]Generator, baseTemplate argoprojiov1alpha1.ApplicationSetTemplate, appSet *argoprojiov1alpha1.ApplicationSet) ([]TransformResult, error) { +func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, allGenerators map[string]Generator, baseTemplate *argoprojiov1alpha1.ApplicationSetTemplate, appSet *argoprojiov1alpha1.ApplicationSet) ([]TransformResult, error) { res := []TransformResult{} var firstError error @@ -50,6 +50,7 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al } params, err := g.GenerateParams(&requestedGenerator, appSet) + if err != nil { log.WithError(err).WithField("generator", g). Error("error generating params") @@ -70,13 +71,19 @@ func Transform(requestedGenerator argoprojiov1alpha1.ApplicationSetGenerator, al } -func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetTemplate argoprojiov1alpha1.ApplicationSetTemplate) (argoprojiov1alpha1.ApplicationSetTemplate, error) { +func mergeGeneratorTemplate(g Generator, requestedGenerator *argoprojiov1alpha1.ApplicationSetGenerator, applicationSetTemplate *argoprojiov1alpha1.ApplicationSetTemplate) (argoprojiov1alpha1.ApplicationSetTemplate, error) { // Make a copy of the value from `GetTemplate()` before merge, rather than copying directly into // the provided parameter (which will touch the original resource object returned by client-go) dest := g.GetTemplate(requestedGenerator).DeepCopy() - err := mergo.Merge(dest, applicationSetTemplate) + var err error + + if applicationSetTemplate != nil { + err = mergo.Merge(dest, applicationSetTemplate) + } else { + log.Warn("generator template won't be applied when standard application template is not used") + } return *dest, err } diff --git a/pkg/generators/matrix.go b/pkg/generators/matrix.go index b6deedc6..a583a753 100644 --- a/pkg/generators/matrix.go +++ b/pkg/generators/matrix.go @@ -103,7 +103,7 @@ func (m *MatrixGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.Appli Merge: mergeGenerator, }, m.supportedGenerators, - argoprojiov1alpha1.ApplicationSetTemplate{}, + &argoprojiov1alpha1.ApplicationSetTemplate{}, appSet) if err != nil { diff --git a/pkg/generators/merge.go b/pkg/generators/merge.go index 73fe1412..b2d2ac60 100644 --- a/pkg/generators/merge.go +++ b/pkg/generators/merge.go @@ -162,7 +162,7 @@ func (m *MergeGenerator) getParams(appSetBaseGenerator argoprojiov1alpha1.Applic Merge: mergeGenerator, }, m.supportedGenerators, - argoprojiov1alpha1.ApplicationSetTemplate{}, + &argoprojiov1alpha1.ApplicationSetTemplate{}, appSet) if err != nil { diff --git a/pkg/utils/templating.go b/pkg/utils/templating.go new file mode 100644 index 00000000..f4feacef --- /dev/null +++ b/pkg/utils/templating.go @@ -0,0 +1,199 @@ +package utils + +import ( + "bytes" + "encoding/json" + "fmt" + "io" + + argoprojiov1alpha1 "github.com/argoproj/applicationset/api/v1alpha1" + argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + "github.com/valyala/fasttemplate" + + "strconv" + "strings" + "text/template" + + "github.com/Masterminds/sprig/v3" + "sigs.k8s.io/yaml" +) + +type Renderer interface { + RenderTemplateParams(tmpl *argov1alpha1.Application, untypedTemplate *argoprojiov1alpha1.ApplicationSetUntypedTemplate, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) +} + +type Render struct { +} + +func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, untypedTemplate *argoprojiov1alpha1.ApplicationSetUntypedTemplate, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, params map[string]string) (*argov1alpha1.Application, error) { + if tmpl == nil { + return nil, fmt.Errorf("application template is empty ") + } + + if len(params) == 0 { + return tmpl, nil + } + + var replacedTmpl argov1alpha1.Application + var replacedTmplStr string + + if untypedTemplate == nil { + // interpolates the `${expression}` first and simple `{reference}` right after + + tmplBytes, err := json.Marshal(tmpl) + if err != nil { + return nil, err + } + + replacedTmplStr, err = renderWithFastTemplateAndGoTemplate(string(tmplBytes), params) + if err != nil { + return nil, err + } + + replacedTmplStr = renderWithFastTemplate(replacedTmplStr, params) + if err != nil { + return nil, err + } + + err = json.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) + if err != nil { + return nil, err + } + } else { + replacedTmplStr, err := renderWithGoTemplate(string(*untypedTemplate), params) + if err != nil { + return nil, err + } + + // UnmarshalStrict to fail early and raise the fact that template + // result produced not what is expected + err = yaml.UnmarshalStrict([]byte(replacedTmplStr), &replacedTmpl) + if err != nil { + return nil, err + } + } + + // Add the 'resources-finalizer' finalizer if: + // The template application doesn't have any finalizers, and: + // a) there is no syncPolicy, or + // b) there IS a syncPolicy, but preserveResourcesOnDeletion is set to false + // See TestRenderTemplateParamsFinalizers in util_test.go for test-based definition of behaviour + if (syncPolicy == nil || !syncPolicy.PreserveResourcesOnDeletion) && + (replacedTmpl.ObjectMeta.Finalizers == nil || len(replacedTmpl.ObjectMeta.Finalizers) == 0) { + + replacedTmpl.ObjectMeta.Finalizers = []string{"resources-finalizer.argocd.argoproj.io"} + } + + return &replacedTmpl, nil +} + +// renderWithGoTemplate executes gotemplate with sprig functions against the raw (untyped) template +func renderWithGoTemplate(rawTemplate string, data map[string]string) (string, error) { + goTemplate, err := template.New("").Option("missingkey=zero").Funcs(createFuncMap()).Parse(rawTemplate) + + if err != nil { + return "", err + } + var tplString bytes.Buffer + + err = goTemplate.Execute(&tplString, data) + if err != nil { + return "", err + } + + return tplString.String(), nil +} + +// renderWithFastTemplateAndGoTemplate executes string substitution with the result of gotemplate run +// for every token found +func renderWithFastTemplateAndGoTemplate(rawTemplate string, data map[string]string) (string, error) { + + fstTmpl := fasttemplate.New(rawTemplate, "${{", "}}") + + replacedTmplStr, err := fstTmpl.ExecuteFuncStringWithErr(func(w io.Writer, tag string) (int, error) { + + trimmedTag := strings.TrimSpace(tag) + // json control characters here are double escaped, what was a double quote " becomes \" when + // unmarshalled to ApplicationSet and then \\\" when marshaled to json + // this becomes a problem with gotemplate trying to parse the token, so unquote the string + unquotedTag, err := strconv.Unquote(`"` + trimmedTag + `"`) + + if err != nil { + return 0, err + } + + // wrapping back in {{}} for gotemplate to identify the expression + gotemplateTag := fmt.Sprintf("{{%s}}", unquotedTag) + + goTemplate, err := template.New("").Option("missingkey=zero").Funcs(createFuncMap()).Parse(gotemplateTag) + if err != nil { + return 0, err + } + + var tplString bytes.Buffer + + err = goTemplate.Execute(&tplString, data) + + if err != nil { + return 0, err + } + + // The following escapes any special characters (e.g. newlines, tabs, etc...) + // in preparation for substitution + replacement := strconv.Quote(tplString.String()) + replacement = replacement[1 : len(replacement)-1] + return w.Write([]byte(replacement)) + }) + + if err != nil { + return "", err + } + + return replacedTmplStr, nil +} + +// replaceWithFastTemplate executes basic string substitution of a template with replacement values. +func renderWithFastTemplate(rawTemplate string, data map[string]string) string { + + fstTmpl := fasttemplate.New(rawTemplate, "{{", "}}") + + replacedTmplStr := fstTmpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { + + trimmedTag := strings.TrimSpace(tag) + + replacement, ok := data[trimmedTag] + if len(trimmedTag) == 0 || !ok { + return w.Write([]byte(fmt.Sprintf("{{%s}}", tag))) + } + // The following escapes any special characters (e.g. newlines, tabs, etc...) + // in preparation for substitution + replacement = strconv.Quote(replacement) + replacement = replacement[1 : len(replacement)-1] + return w.Write([]byte(replacement)) + }) + + return replacedTmplStr + +} + +func ToYaml(v interface{}) (string, error) { + data, err := yaml.Marshal(v) + if err != nil { + return "", err + } + return string(data), nil +} + +func createFuncMap() template.FuncMap { + funcMap := sprig.TxtFuncMap() + + extraFuncMap := template.FuncMap{ + "toYaml": ToYaml, + } + + for name, f := range extraFuncMap { + funcMap[name] = f + } + + return funcMap +} diff --git a/pkg/utils/templating_test.go b/pkg/utils/templating_test.go new file mode 100644 index 00000000..745155ee --- /dev/null +++ b/pkg/utils/templating_test.go @@ -0,0 +1,402 @@ +package utils + +import ( + "testing" + + argoprojiov1alpha1 "github.com/argoproj/applicationset/api/v1alpha1" + argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/stretchr/testify/assert" + // "sigs.k8s.io/yaml" +) + +func composeApplicationFieldsFuncMap() map[string]func(app *argov1alpha1.Application) *string { + // Believe it or not, this is actually less complex than the equivalent solution using reflection + fieldMap := map[string]func(app *argov1alpha1.Application) *string{} + fieldMap["Path"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.Path } + fieldMap["RepoURL"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.RepoURL } + fieldMap["TargetRevision"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.TargetRevision } + fieldMap["Chart"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.Chart } + + fieldMap["Server"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Server } + fieldMap["Namespace"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Namespace } + fieldMap["Name"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Name } + + fieldMap["Project"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Project } + + return fieldMap +} + +func TestRenderTemplateParamsWithFasttemplate(t *testing.T) { + + fieldMap := composeApplicationFieldsFuncMap() + + emptyApplication := &argov1alpha1.Application{ + Spec: argov1alpha1.ApplicationSpec{ + Source: argov1alpha1.ApplicationSource{ + Path: "", + RepoURL: "", + TargetRevision: "", + Chart: "", + }, + Destination: argov1alpha1.ApplicationDestination{ + Server: "", + Namespace: "", + Name: "", + }, + Project: "", + }, + } + + tests := []struct { + name string + fieldVal string + params map[string]string + expectedVal string + }{ + { + name: "simple substitution", + fieldVal: "{{one}}", + expectedVal: "two", + params: map[string]string{ + "one": "two", + }, + }, + { + name: "simple substitution with whitespace", + fieldVal: "{{ one }}", + expectedVal: "two", + params: map[string]string{ + "one": "two", + }, + }, + + { + name: "template characters but not in a template", + fieldVal: "}} {{", + expectedVal: "}} {{", + params: map[string]string{ + "one": "two", + }, + }, + + { + name: "nested template", + fieldVal: "{{ }}", + expectedVal: "{{ }}", + params: map[string]string{ + "one": "{{ }}", + }, + }, + { + name: "field with whitespace", + fieldVal: "{{ }}", + expectedVal: "{{ }}", + params: map[string]string{ + " ": "two", + "": "three", + }, + }, + + { + name: "template contains itself, containing itself", + fieldVal: "{{one}}", + expectedVal: "{{one}}", + params: map[string]string{ + "{{one}}": "{{one}}", + }, + }, + + { + name: "template contains itself, containing something else", + fieldVal: "{{one}}", + expectedVal: "{{one}}", + params: map[string]string{ + "{{one}}": "{{two}}", + }, + }, + + { + name: "templates are case sensitive", + fieldVal: "{{ONE}}", + expectedVal: "{{ONE}}", + params: map[string]string{ + "{{one}}": "two", + }, + }, + { + name: "multiple on a line", + fieldVal: "{{one}}{{one}}", + expectedVal: "twotwo", + params: map[string]string{ + "one": "two", + }, + }, + { + name: "multiple different on a line", + fieldVal: "{{one}}{{three}}", + expectedVal: "twofour", + params: map[string]string{ + "one": "two", + "three": "four", + }, + }, + { + name: "gotemplate expressions are supported", + fieldVal: "${{.one}} ${{.three}}", + expectedVal: "two four", + params: map[string]string{ + "one": "two", + "three": "four", + }, + }, + { + name: "sprig functions are avilable", + fieldVal: `${{upper .one}} ${{default "four" .three}}`, + expectedVal: "TWO four", + params: map[string]string{ + "one": "two", + }, + }, + { + name: "mix of gotemplate expressions and fasttemplate", + fieldVal: `{{one}} ${{default "four" .three}}`, + expectedVal: "two four", + params: map[string]string{ + "one": "two", + }, + }, + } + + for _, test := range tests { + + t.Run(test.name, func(t *testing.T) { + + for fieldName, getPtrFunc := range fieldMap { + + // Clone the template application + application := emptyApplication.DeepCopy() + + // Set the value of the target field, to the test value + *getPtrFunc(application) = test.fieldVal + + // Render the cloned application, into a new application + render := Render{} + newApplication, err := render.RenderTemplateParams(application, nil, nil, test.params) + + // Retrieve the value of the target field from the newApplication, then verify that + // the target field has been templated into the expected value + actualValue := *getPtrFunc(newApplication) + assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue) + assert.NoError(t, err) + + } + }) + } + +} + +func TestRenderTemplateParamsWithGotemplate(t *testing.T) { + + tests := []struct { + name string + input argoprojiov1alpha1.ApplicationSetUntypedTemplate + params map[string]string + expectedApp argov1alpha1.Application + }{ + { + name: "advanced gotemplate with sprig", + input: ` +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: 'app.{{ default .cluster .DoesNotExist }}' + labels: + {{ range $key, $val := . }} + {{ if (hasPrefix "appLables." $key ) }} + {{ $key | replace "appLables." "" }}: {{ $val }} + {{ end }} + {{ end }} +spec: + project: default + revisionHistoryLimit: {{ atoi .revisionHistoryLimit }} + source: + repoURL: https://github.com/argoproj-labs/applicationset.git + targetRevision: HEAD + path: examples/list-generator/guestbook/engineering-{{ .cluster }} + {{ toYaml (fromJson .sourceRendererConf) | nindent 4 }} + destination: + server: https://kubernetes.default.svc + namespace: {{ if (eq .cluster "dev") }}dev-namespace{{ else }}other-namespace{{ end }} + syncPolicy: + automated: + selfHeal: {{ eq .autosyncSelfHeal "true" }}`, + + params: map[string]string{ + "cluster": "dev", + "appLables.label1": "label1", + "appLables.label2": "label2", + "revisionHistoryLimit": "0", + "sourceRendererConf": "{\"plugin\": {\"name\": \"kustomized-helm\"} }", + "autosyncSelfHeal": "true", + }, + expectedApp: argov1alpha1.Application{ + TypeMeta: metav1.TypeMeta{ + Kind: "Application", + APIVersion: "argoproj.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "app.dev", + Finalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + Labels: map[string]string{ + "label1": "label1", + "label2": "label2", + }, + }, + Spec: argov1alpha1.ApplicationSpec{ + Source: argov1alpha1.ApplicationSource{ + Path: "examples/list-generator/guestbook/engineering-dev", + RepoURL: "https://github.com/argoproj-labs/applicationset.git", + TargetRevision: "HEAD", + Chart: "", + Plugin: &argov1alpha1.ApplicationSourcePlugin{ + Name: "kustomized-helm", + }, + }, + Destination: argov1alpha1.ApplicationDestination{ + Server: "https://kubernetes.default.svc", + Namespace: "dev-namespace", + Name: "", + }, + SyncPolicy: &argov1alpha1.SyncPolicy{ + Automated: &argov1alpha1.SyncPolicyAutomated{ + SelfHeal: true, + }, + }, + Project: "default", + RevisionHistoryLimit: new(int64), + }, + }, + }, + } + + for _, test := range tests { + + t.Run(test.name, func(t *testing.T) { + + render := Render{} + + newApplication, err := render.RenderTemplateParams(&argov1alpha1.Application{}, &test.input, nil, test.params) + + assert.NoError(t, err) + assert.Equal(t, *newApplication, test.expectedApp, "Expected: '%s' value: '%s'", *newApplication, test.expectedApp) + }) + } + +} + +func TestRenderTemplateParamsFinalizers(t *testing.T) { + + emptyApplication := &argov1alpha1.Application{ + Spec: argov1alpha1.ApplicationSpec{ + Source: argov1alpha1.ApplicationSource{ + Path: "", + RepoURL: "", + TargetRevision: "", + Chart: "", + }, + Destination: argov1alpha1.ApplicationDestination{ + Server: "", + Namespace: "", + Name: "", + }, + Project: "", + }, + } + + for _, c := range []struct { + testName string + syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy + existingFinalizers []string + expectedFinalizers []string + }{ + { + testName: "existing finalizer should be preserved", + existingFinalizers: []string{"existing-finalizer"}, + syncPolicy: nil, + expectedFinalizers: []string{"existing-finalizer"}, + }, + { + testName: "background finalizer should be preserved", + existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + syncPolicy: nil, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + }, + + { + testName: "empty finalizer and empty sync should use standard finalizer", + existingFinalizers: nil, + syncPolicy: nil, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + }, + + { + testName: "standard finalizer should be preserved", + existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + syncPolicy: nil, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + }, + { + testName: "empty array finalizers should use standard finalizer", + existingFinalizers: []string{}, + syncPolicy: nil, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + }, + { + testName: "non-nil sync policy should use standard finalizer", + existingFinalizers: nil, + syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{}, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, + }, + { + testName: "preserveResourcesOnDeletion should not have a finalizer", + existingFinalizers: nil, + syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{ + PreserveResourcesOnDeletion: true, + }, + expectedFinalizers: nil, + }, + { + testName: "user-specified finalizer should overwrite preserveResourcesOnDeletion", + existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{ + PreserveResourcesOnDeletion: true, + }, + expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, + }, + } { + + t.Run(c.testName, func(t *testing.T) { + + // Clone the template application + application := emptyApplication.DeepCopy() + application.Finalizers = c.existingFinalizers + + params := map[string]string{ + "one": "two", + } + + // Render the cloned application, into a new application + render := Render{} + + res, err := render.RenderTemplateParams(application, nil, c.syncPolicy, params) + assert.Nil(t, err) + + assert.ElementsMatch(t, res.Finalizers, c.expectedFinalizers) + + }) + + } + +} diff --git a/pkg/utils/util.go b/pkg/utils/util.go index 40d021b7..22887877 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -1,140 +1,15 @@ package utils import ( - "bytes" "encoding/json" - "fmt" - "io" "reflect" "sort" - "strconv" "strings" - "text/template" - "github.com/Masterminds/sprig/v3" argoprojiov1alpha1 "github.com/argoproj/applicationset/api/v1alpha1" - argov1alpha1 "github.com/argoproj/argo-cd/v2/pkg/apis/application/v1alpha1" log "github.com/sirupsen/logrus" - "github.com/valyala/fasttemplate" - "sigs.k8s.io/yaml" ) -type Renderer interface { - RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) -} - -type Render struct { -} - -func (r *Render) RenderTemplateParams(tmpl *argov1alpha1.Application, syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy, templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions, params map[string]string) (*argov1alpha1.Application, error) { - if tmpl == nil { - return nil, fmt.Errorf("application template is empty ") - } - - if len(params) == 0 { - return tmpl, nil - } - - var replacedTmpl argov1alpha1.Application - var replacedTmplStr string - - if templateOptions == nil || !templateOptions.GotemplateEnabled { - tmplBytes, err := json.Marshal(tmpl) - if err != nil { - return nil, err - } - - fstTmpl := fasttemplate.New(string(tmplBytes), "{{", "}}") - replacedTmplStr, err = r.replaceWithFastTemplate(fstTmpl, params, true) - if err != nil { - return nil, err - } - - err = json.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) - if err != nil { - return nil, err - } - } else { - - // as opposed to json, yaml escapes double quote sign with only one slash and hence allow to use {{ "string" }} scalar variables for various use-cases - tmplBytes, err := yaml.Marshal(tmpl) - if err != nil { - return nil, err - } - - // missingkey=zero - replace unmatched variables with "" - goTemplate, err := template.New("argocd-app").Option("missingkey=zero").Funcs(sprig.TxtFuncMap()).Parse(string(tmplBytes)) - if err != nil { - return nil, err - } - replacedTmplStr, err = r.replaceWithGoTemplate(goTemplate, params) - if err != nil { - return nil, err - } - - err = yaml.Unmarshal([]byte(replacedTmplStr), &replacedTmpl) - if err != nil { - return nil, err - } - } - - // Add the 'resources-finalizer' finalizer if: - // The template application doesn't have any finalizers, and: - // a) there is no syncPolicy, or - // b) there IS a syncPolicy, but preserveResourcesOnDeletion is set to false - // See TestRenderTemplateParamsFinalizers in util_test.go for test-based definition of behaviour - if (syncPolicy == nil || !syncPolicy.PreserveResourcesOnDeletion) && - (replacedTmpl.ObjectMeta.Finalizers == nil || len(replacedTmpl.ObjectMeta.Finalizers) == 0) { - - replacedTmpl.ObjectMeta.Finalizers = []string{"resources-finalizer.argocd.argoproj.io"} - } - - return &replacedTmpl, nil -} - -// replaceWithFastTemplate executes basic string substitution of a template with replacement values. -// 'allowUnresolved' indicates whether or not it is acceptable to have unresolved variables -// remaining in the substituted template. -func (r *Render) replaceWithFastTemplate(fstTmpl *fasttemplate.Template, replaceMap map[string]string, allowUnresolved bool) (string, error) { - var unresolvedErr error - replacedTmpl := fstTmpl.ExecuteFuncString(func(w io.Writer, tag string) (int, error) { - - trimmedTag := strings.TrimSpace(tag) - - replacement, ok := replaceMap[trimmedTag] - if len(trimmedTag) == 0 || !ok { - if allowUnresolved { - // just write the same string back - return w.Write([]byte(fmt.Sprintf("{{%s}}", tag))) - } - unresolvedErr = fmt.Errorf("failed to resolve {{%s}}", tag) - return 0, nil - } - // The following escapes any special characters (e.g. newlines, tabs, etc...) - // in preparation for substitution - replacement = strconv.Quote(replacement) - replacement = replacement[1 : len(replacement)-1] - return w.Write([]byte(replacement)) - }) - if unresolvedErr != nil { - return "", unresolvedErr - } - - return replacedTmpl, nil -} - -// replaceWithGoTemplate applies a parsed Go template to replacement values -func (r *Render) replaceWithGoTemplate(goTemplate *template.Template, replaceMap map[string]string) (string, error) { - var tplString bytes.Buffer - - err := goTemplate.Execute(&tplString, replaceMap) - if err != nil { - return "", err - } - - return tplString.String(), nil -} - // Log a warning if there are unrecognized generators func CheckInvalidGenerators(applicationSetInfo *argoprojiov1alpha1.ApplicationSet) { hasInvalidGenerators, invalidGenerators := invalidGenerators(applicationSetInfo) diff --git a/pkg/utils/util_test.go b/pkg/utils/util_test.go index 05fd562f..8829a9cc 100644 --- a/pkg/utils/util_test.go +++ b/pkg/utils/util_test.go @@ -12,397 +12,6 @@ import ( "k8s.io/apimachinery/pkg/runtime" ) -func composeApplicationFieldsFuncMap() map[string]func(app *argov1alpha1.Application) *string { - // Believe it or not, this is actually less complex than the equivalent solution using reflection - fieldMap := map[string]func(app *argov1alpha1.Application) *string{} - fieldMap["Path"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.Path } - fieldMap["RepoURL"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.RepoURL } - fieldMap["TargetRevision"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.TargetRevision } - fieldMap["Chart"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Source.Chart } - - fieldMap["Server"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Server } - fieldMap["Namespace"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Namespace } - fieldMap["Name"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Destination.Name } - - fieldMap["Project"] = func(app *argov1alpha1.Application) *string { return &app.Spec.Project } - - return fieldMap -} - -func TestRenderTemplateParams(t *testing.T) { - - fieldMap := composeApplicationFieldsFuncMap() - - emptyApplication := &argov1alpha1.Application{ - Spec: argov1alpha1.ApplicationSpec{ - Source: argov1alpha1.ApplicationSource{ - Path: "", - RepoURL: "", - TargetRevision: "", - Chart: "", - }, - Destination: argov1alpha1.ApplicationDestination{ - Server: "", - Namespace: "", - Name: "", - }, - Project: "", - }, - } - - tests := []struct { - name string - fieldVal string - params map[string]string - expectedVal string - }{ - { - name: "simple substitution", - fieldVal: "{{one}}", - expectedVal: "two", - params: map[string]string{ - "one": "two", - }, - }, - { - name: "simple substitution with whitespace", - fieldVal: "{{ one }}", - expectedVal: "two", - params: map[string]string{ - "one": "two", - }, - }, - - { - name: "template characters but not in a template", - fieldVal: "}} {{", - expectedVal: "}} {{", - params: map[string]string{ - "one": "two", - }, - }, - - { - name: "nested template", - fieldVal: "{{ }}", - expectedVal: "{{ }}", - params: map[string]string{ - "one": "{{ }}", - }, - }, - { - name: "field with whitespace", - fieldVal: "{{ }}", - expectedVal: "{{ }}", - params: map[string]string{ - " ": "two", - "": "three", - }, - }, - - { - name: "template contains itself, containing itself", - fieldVal: "{{one}}", - expectedVal: "{{one}}", - params: map[string]string{ - "{{one}}": "{{one}}", - }, - }, - - { - name: "template contains itself, containing something else", - fieldVal: "{{one}}", - expectedVal: "{{one}}", - params: map[string]string{ - "{{one}}": "{{two}}", - }, - }, - - { - name: "templates are case sensitive", - fieldVal: "{{ONE}}", - expectedVal: "{{ONE}}", - params: map[string]string{ - "{{one}}": "two", - }, - }, - { - name: "multiple on a line", - fieldVal: "{{one}}{{one}}", - expectedVal: "twotwo", - params: map[string]string{ - "one": "two", - }, - }, - { - name: "multiple different on a line", - fieldVal: "{{one}}{{three}}", - expectedVal: "twofour", - params: map[string]string{ - "one": "two", - "three": "four", - }, - }, - } - - for _, test := range tests { - - t.Run(test.name, func(t *testing.T) { - - for fieldName, getPtrFunc := range fieldMap { - - // Clone the template application - application := emptyApplication.DeepCopy() - - // Set the value of the target field, to the test value - *getPtrFunc(application) = test.fieldVal - - // Render the cloned application, into a new application - render := Render{} - newApplication, err := render.RenderTemplateParams(application, nil, nil, test.params) - - // Retrieve the value of the target field from the newApplication, then verify that - // the target field has been templated into the expected value - actualValue := *getPtrFunc(newApplication) - assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue) - assert.NoError(t, err) - - } - }) - } - -} - -func TestRenderTemplateParamsFinalizers(t *testing.T) { - - emptyApplication := &argov1alpha1.Application{ - Spec: argov1alpha1.ApplicationSpec{ - Source: argov1alpha1.ApplicationSource{ - Path: "", - RepoURL: "", - TargetRevision: "", - Chart: "", - }, - Destination: argov1alpha1.ApplicationDestination{ - Server: "", - Namespace: "", - Name: "", - }, - Project: "", - }, - } - - for _, c := range []struct { - testName string - syncPolicy *argoprojiov1alpha1.ApplicationSetSyncPolicy - existingFinalizers []string - expectedFinalizers []string - }{ - { - testName: "existing finalizer should be preserved", - existingFinalizers: []string{"existing-finalizer"}, - syncPolicy: nil, - expectedFinalizers: []string{"existing-finalizer"}, - }, - { - testName: "background finalizer should be preserved", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, - syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, - }, - - { - testName: "empty finalizer and empty sync should use standard finalizer", - existingFinalizers: nil, - syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, - }, - - { - testName: "standard finalizer should be preserved", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, - syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, - }, - { - testName: "empty array finalizers should use standard finalizer", - existingFinalizers: []string{}, - syncPolicy: nil, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, - }, - { - testName: "non-nil sync policy should use standard finalizer", - existingFinalizers: nil, - syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{}, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io"}, - }, - { - testName: "preserveResourcesOnDeletion should not have a finalizer", - existingFinalizers: nil, - syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{ - PreserveResourcesOnDeletion: true, - }, - expectedFinalizers: nil, - }, - { - testName: "user-specified finalizer should overwrite preserveResourcesOnDeletion", - existingFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, - syncPolicy: &argoprojiov1alpha1.ApplicationSetSyncPolicy{ - PreserveResourcesOnDeletion: true, - }, - expectedFinalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, - }, - } { - - t.Run(c.testName, func(t *testing.T) { - - // Clone the template application - application := emptyApplication.DeepCopy() - application.Finalizers = c.existingFinalizers - - params := map[string]string{ - "one": "two", - } - - // Render the cloned application, into a new application - render := Render{} - - res, err := render.RenderTemplateParams(application, c.syncPolicy, nil, params) - assert.Nil(t, err) - - assert.ElementsMatch(t, res.Finalizers, c.expectedFinalizers) - - }) - - } - -} - -func TestRenderGoTemplateParams(t *testing.T) { - - fieldMap := composeApplicationFieldsFuncMap() - - emptyApplication := &argov1alpha1.Application{ - Spec: argov1alpha1.ApplicationSpec{ - Source: argov1alpha1.ApplicationSource{ - Path: "", - RepoURL: "", - TargetRevision: "", - Chart: "", - }, - Destination: argov1alpha1.ApplicationDestination{ - Server: "", - Namespace: "", - Name: "", - }, - Project: "", - }, - } - - tests := []struct { - name string - fieldVal string - templateOptions *argoprojiov1alpha1.ApplicationSetTemplateOptions - params map[string]string - expectedVal string - }{ - { - name: "simple substitution", - fieldVal: "{{.one}}", - expectedVal: "two", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "one": "two", - }, - }, - { - name: "simple substitution with whitespace", - fieldVal: "{{ .one }}", - expectedVal: "two", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "one": "two", - }, - }, - { - name: "multiple on a line", - fieldVal: "{{.one}}{{.one}}", - expectedVal: "twotwo", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "one": "two", - }, - }, - { - name: "multiple different on a line", - fieldVal: "{{.one}}{{.three}}", - expectedVal: "twofour", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "one": "two", - "three": "four", - }, - }, - { - name: "sprig functions are avilable", - fieldVal: `{{upper .one}}{{default "four" .three}}`, - expectedVal: "TWOfour", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "one": "two", - }, - }, - { - name: "the output application structure is imutable", - fieldVal: "{{ .yamlPiece }}\n\tsomeother: element", - expectedVal: "targetRevision: my-other-branch\n\tsomeother: element", - templateOptions: &argoprojiov1alpha1.ApplicationSetTemplateOptions{ - GotemplateEnabled: true, - }, - params: map[string]string{ - "yamlPiece": "targetRevision: my-other-branch", - }, - }, - } - - for _, test := range tests { - - t.Run(test.name, func(t *testing.T) { - - for fieldName, getPtrFunc := range fieldMap { - - // Clone the template application - application := emptyApplication.DeepCopy() - - // Set the value of the target field, to the test value - *getPtrFunc(application) = test.fieldVal - - // Render the cloned application, into a new application - render := Render{} - newApplication, err := render.RenderTemplateParams(application, nil, test.templateOptions, test.params) - - // Retrieve the value of the target field from the newApplication, then verify that - // the target field has been templated into the expected value - actualValue := *getPtrFunc(newApplication) - assert.Equal(t, test.expectedVal, actualValue, "Field '%s' had an unexpected value. expected: '%s' value: '%s'", fieldName, test.expectedVal, actualValue) - assert.NoError(t, err) - - } - }) - } - -} - func TestCheckInvalidGenerators(t *testing.T) { scheme := runtime.NewScheme() diff --git a/test/e2e/applicationset/applicationset_test.go b/test/e2e/applicationset/applicationset_test.go index 0e50691e..576dd92d 100644 --- a/test/e2e/applicationset/applicationset_test.go +++ b/test/e2e/applicationset/applicationset_test.go @@ -71,7 +71,7 @@ func TestSimpleListGenerator(t *testing.T) { Name: "simple-list-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{cluster}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -172,7 +172,7 @@ func TestSimpleGitDirectoryGenerator(t *testing.T) { Name: "simple-git-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{path.basename}}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -281,7 +281,7 @@ func TestSimpleGitFilesGenerator(t *testing.T) { Name: "simple-git-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{cluster.name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -357,7 +357,7 @@ func TestSimpleGitFilesPreserveResourcesOnDeletion(t *testing.T) { Name: "simple-git-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{cluster.name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -442,7 +442,7 @@ func TestSimpleSCMProviderGenerator(t *testing.T) { Name: "simple-scm-provider-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{ repository }}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -506,7 +506,7 @@ func TestCustomApplicationFinalizers(t *testing.T) { Name: "simple-list-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{ Name: "{{cluster}}-guestbook", Finalizers: []string{"resources-finalizer.argocd.argoproj.io/background"}, @@ -580,7 +580,7 @@ func TestSimplePullRequestGenerator(t *testing.T) { Name: "simple-pull-request-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "guestbook-{{ number }}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/applicationset/cluster_e2e_test.go b/test/e2e/applicationset/cluster_e2e_test.go index f5128950..cb099139 100644 --- a/test/e2e/applicationset/cluster_e2e_test.go +++ b/test/e2e/applicationset/cluster_e2e_test.go @@ -47,7 +47,7 @@ func TestSimpleClusterGenerator(t *testing.T) { Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -172,7 +172,7 @@ func TestClusterGeneratorWithLocalCluster(t *testing.T) { Name: "in-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -263,7 +263,7 @@ func TestSimpleClusterGeneratorAddingCluster(t *testing.T) { Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -346,7 +346,7 @@ func TestSimpleClusterGeneratorDeletingCluster(t *testing.T) { Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/applicationset/crl_e2e_test.go b/test/e2e/applicationset/crl_e2e_test.go index 7e6c18fc..33b5d1e4 100644 --- a/test/e2e/applicationset/crl_e2e_test.go +++ b/test/e2e/applicationset/crl_e2e_test.go @@ -60,7 +60,7 @@ func TestSimpleClusterDecisionResourceGenerator(t *testing.T) { Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -171,7 +171,7 @@ func TestSimpleClusterDecisionResourceGeneratorAddingCluster(t *testing.T) { Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -267,7 +267,7 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterSecret(t *testing. Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -371,7 +371,7 @@ func TestSimpleClusterDecisionResourceGeneratorDeletingClusterFromResource(t *te Name: "simple-cluster-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-guestbook"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/applicationset/matrix_e2e_test.go b/test/e2e/applicationset/matrix_e2e_test.go index be5d8bb2..6dd1188a 100644 --- a/test/e2e/applicationset/matrix_e2e_test.go +++ b/test/e2e/applicationset/matrix_e2e_test.go @@ -59,7 +59,7 @@ func TestListMatrixGenerator(t *testing.T) { Name: "matrix-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{values.name}}-{{path.basename}}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -185,7 +185,7 @@ func TestClusterMatrixGenerator(t *testing.T) { Name: "matrix-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-{{path.basename}}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", diff --git a/test/e2e/applicationset/merge_e2e_test.go b/test/e2e/applicationset/merge_e2e_test.go index 4ed34544..39f90669 100644 --- a/test/e2e/applicationset/merge_e2e_test.go +++ b/test/e2e/applicationset/merge_e2e_test.go @@ -55,7 +55,7 @@ func TestListMergeGenerator(t *testing.T) { Name: "merge-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{path.basename}}-{{name-suffix}}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default", @@ -182,7 +182,7 @@ func TestClusterMergeGenerator(t *testing.T) { Name: "merge-generator", }, Spec: v1alpha1.ApplicationSetSpec{ - Template: v1alpha1.ApplicationSetTemplate{ + Template: &v1alpha1.ApplicationSetTemplate{ ApplicationSetTemplateMeta: v1alpha1.ApplicationSetTemplateMeta{Name: "{{name}}-{{path.basename}}-{{values.name-suffix}}"}, Spec: argov1alpha1.ApplicationSpec{ Project: "default",