From 3eb0378d1373f66b8bde49c15e8b29aee722a5fa Mon Sep 17 00:00:00 2001 From: Anton Weiss Date: Thu, 23 Dec 2021 13:27:32 +0200 Subject: [PATCH] ArgoCD --- k8s/argocd.yaml | 3689 +++++++++++++++++++++++++ k8s/argocd_app.yaml | 21 + slides/images/argocd_architecture.png | Bin 0 -> 105604 bytes slides/images/argocdlogo.png | Bin 0 -> 22872 bytes slides/k8s/argocd.md | 447 +++ 5 files changed, 4157 insertions(+) create mode 100644 k8s/argocd.yaml create mode 100644 k8s/argocd_app.yaml create mode 100644 slides/images/argocd_architecture.png create mode 100644 slides/images/argocdlogo.png create mode 100644 slides/k8s/argocd.md diff --git a/k8s/argocd.yaml b/k8s/argocd.yaml new file mode 100644 index 00000000..25383f99 --- /dev/null +++ b/k8s/argocd.yaml @@ -0,0 +1,3689 @@ +# 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: + 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: 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: 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: 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: 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: + type: NodePort + ports: + - name: http + port: 80 + protocol: TCP + targetPort: 8080 + nodePort: 30006 + - name: https + port: 443 + protocol: TCP + targetPort: 8080 + nodePort: 30007 + selector: + app.kubernetes.io/name: argocd-server +--- +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.1 + 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: 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.1 + 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.1 + 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: 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.1 + 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-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 diff --git a/k8s/argocd_app.yaml b/k8s/argocd_app.yaml new file mode 100644 index 00000000..fb5baa4d --- /dev/null +++ b/k8s/argocd_app.yaml @@ -0,0 +1,21 @@ +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: worker +spec: + destination: + namespace: helmcoins + server: 'https://kubernetes.default.svc' + source: + path: generic-service + repoURL: 'https://github.com/antweiss/kubercoins.git' + targetRevision: helm + helm: + valueFiles: + - values.yaml + - ../values/worker.yaml + project: default + syncPolicy: + syncOptions: + - CreateNamespace=true + diff --git a/slides/images/argocd_architecture.png b/slides/images/argocd_architecture.png new file mode 100644 index 0000000000000000000000000000000000000000..d1e4dd422733d50740fed61de88f55e0edf44493 GIT binary patch literal 105604 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 literal 0 HcmV?d00001 diff --git a/slides/images/argocdlogo.png b/slides/images/argocdlogo.png new file mode 100644 index 0000000000000000000000000000000000000000..01ac93120fcf9252268083b87c8f3c3e64ca5c4d GIT binary patch literal 22872 zcmd2?Ra+cgv&G%r-Q8UWClDaG5AG6zySoi8K?V;JT!OpHkQaA?ySp8}e{nAQdAj?i zYgg~uRkc>F81=6T=qMy8P*70lN{X`IprD}9{&yiEe7@n1k4}Yx(x+6CmDciJIWtD| zCYx{e6zmG8lN$d*6`uSKpx_+)LdD66Je6X_)z$G3>g32Zg!dnJSXpC7LWKe1`szV8et zkP14l{eQkG%iKHnN?iNNnKZ?$o`{bu{{07NuSr#I9McU++>aL&)GSvNv_vy2d7yYL zS48(AlXf^%RANMET=4B z6AL*2KzGdp8f}f1?dH=>`CuY|GzxxMxbUZ59==kGCKV)S^9!0dbWFW_bc}g-MFn9K z{hp@Izz0Dhk`WV3zYDUY}(msN2T`~s@eY}QeeoW+P;&kj1HGz$YJuuu%ZFq_j#kia4?UfyahBBjPaA}YXsRm9w^;ziYj6q;UG1~h7-gw zv@6lwQcI`QPG;=>xS@L*tPvGv>`yS1Gz{t$V8|VnoaCPU`1Ce4R=WvZ6V0x;J30Z` z<%|yliXkfgl7?f1ajC$PrdgOvg!3$vJDM2bTvAiy})G1Dh|}+322WdS(uweiPkOScWh(J2D#3 z7g?ouS-SBvVfcl(mfin&O*YvR_8B8qH5?2v42Dsn(kXY9Z{0MCl48Tpv5=i8m^u$% z_-1&S>$;Z4InD&NF@&@(EHgVwreN{s5a)Fy=Y&_leZ;{Gx==Z5(6;yPbyoKnZV`bP zx~UzoB*xJ9epe5=tFP+dN8+WdNoOIWi%^#;^16<-;SEz0Fb@6_4w40lEZ{~KKsic% zYr6dHppp! zey6&{jf^-||a%Wf$QxJa==m_QK;TMYUd$-BP$cauzDSe$s* ztc5L7NZ9g!FQFtJcbzkkf>~Z^Eaql!X?yp+R&CFv7^uIDKZ&W_?eLJ-=?Eb3Frc73 znZx?mlJ8#({fdl;vo)oHsIZ=tsVg*l`7B+a~skw>}L-Vzq%{QVXWsz!e=|rSQb-x~zCmF6R$(vJjWRD)8;22XW zv)z|niN$a!77|M5ti^lTy0$zRRa(!?HuisPAm~C>RtF9bQDHW8=^a5QK|_@!97&+0 z5m(5s`zO2o4$I|ck763x#VhJhk)Xr*BSkkyh|1&}BHKt>StGG8ck8j9w2yx;1$mL; zMCIj2qR6^a3VyhZmX)BwYUha>?b$Sf45yc^p~2uiEm-`Z+nXtpEx`CQOkUrKJZTGD zC@h?XPglNBFU}4d4BnbO#Nfg}l=gIq$SX}igh~pQs!&Qkq!ot0O*%of!XR6_t)EJ{ z(*sLARWZ#TzylnLL0Q{j@oI8&>{MgAL1~esm7xkuj?9?>Y$pwke1l$tj7k&mF%tQ- zv#1TIY-B=hrNa&MR@GF@2M0N6{50V7`d}DdvX1f44Y=W*LxUg5>Xc$!hT+txzT}5p zU_!!?9jPrQY`Q1v`rvnlgW!Z8WNS_Jcj*fnMI}EOaeR9eZS4*(?_g2p2nsvm$CdE- zzPr#wm_+gR;#D#MW#;Y3l3)kqX_Vdns29GTzU65fP4uaX)ZSbslIs$@(vue5xFmdPKRj>^!KQ#9M`0iP*+Ju5K1O=- z10o8p6%6ey69j)>%FJl1_f$Fi)XGjD?oo(Lp++$+sx>REV2@nOJFA~PK-IEBI6Qx&q*SK?Sf7*m` zj=Gw&vd@ld1>_04wJGE7fh6 zy6CG3Fa*EkDS@Nnz+_0HK($XGOwnxw3O!2kkQE^DCfuVjFt zrmR6ubZ(g*`}k*S5qWMAxuF)<;E(^BYgNkg)(MMWCl@k z=9twjjJicTlCs{A;FwqwI@yRrRZtGRxqkN;T|vK#5y@)C>q4W<8=v?r0PEB;Z#*nY zYU?B(oxt`{TfuL!Fi6m3$yYbn_@8}Lfw6PvA-xVJ9y0|~iF1nz%kRsJ!Of)Fu-d3v z!*y5&X)0oY@QV4FzqRIUCIhmI`vfb2gDxf_)&QipF2yu-u-?rmqC-)28I&JWNzRgN zcM+?E3D=F6=g1vTf4)p!Ri60S1TmMlUvQsguy#dw$l$~VWw)At&(UcNFgn!E({W|s z*;%$KFn#v{&RjTZv)3J2S~;({LG{{Hf7y+4p5Yq5;?#nlO2ifZ{+>f|FnP5XQd*0M zjez8zLP&~4hOh(LdO1g>I%2#>sf!fP(vDjxQ7AGDhgp4k6(CuYp!J}Y1AJG6yerlL z0o6rRrhOu&NA61qutZMX7{lm=4oRKTOJQ84#EOH4W|(jv0go3djF(8)BqjoC^s(h3 zfZjY|_!h~YZ{G$^)Z=YUmDw%aP}r6_it0FzccNmoV|^)kj@8)ct~@=tDGHZz0!?Ij zHW06=kSILt;3$L$V4muTEDuA-03T1=8`k-r{Aold$vg&WyR6Gtn-bYrKZVD&auI}# zM!!7bQi&Uig%rck{R>g}#ZT12*9H@bsZqy-?N>ZVC37BmcE&xMzX0Q+=+yy*9OX$eZ~om z;_crAL<1q)L%UVXmP8zSp9V!+xlK%DY{~TO9)<){WB;VDkL(qZ5=-w z!O?CgzXrF$=rfPP_koIS6l?W5av&NcIsDTkHB8+fUu7^2gX)~(71LsbT#7ED!v44g zq~-Ps#U}oCc137^?vhB!(x!HXX@u8iGkIu?$cF923lEclF^bCkE+!9~2>g)`b&{9j z5Q{w@tjY+LeIg8GaWp2id>Ve7SQWtyZoOLI`E@TaIjG&XauIc^78p!~5M zMIcVS5D{7+F}@HMpL!LDG!JRLfOfX$((otEs^Of_H@;a^xgxT}WBroCzj#4C|1QXq zdmS&1t>c4`59s(1G0?Q*`@e_Vl#o>?V35#&J3h~P+MX$94Of;WubV0p5mdOi@i}h- zJ?&!@cltC6x!zv&Fh8tc$lB_V;ZY4(ACeb`JPpH-m~d;<@XQeh`&^XWAF_bfTXR4p6 zi}h49x`IWmB^&AE`U9mcc6zWr)Q4*7+%qu7!$6Tmmy}MW?-UuMBUZqNUAJfkx=3HbF$hb^=%Bqwj&>XQ`qTYrxY$ zt+nIX+W`+cMaTO~d~#zIwGeJTMq%`0r={CFflDLpQHcfCCR1;k*>7N}_mO*L(M4Od zc{lneNtyI=anf9eZ%en_H7mnr1aO=|MS3AL>~VsOtN7XnudqIz9ZV%q>(( z&qqjH5yBZ>^lPMg#m`}EAXZC#9eNa64FU3HT#pdsF~jQbeHX1yNw3xa(BG%|Ff?u} zB8P6`FuP!zHFz1nN*8?*#GUX?gp0A1y{^~FGvUNpA;^|k*CweHyR$E@RZLrxRkt%I z#!9;Cqk*Bi{6ICVQ8!vdDy64a|9)s#v66?{{HH+XEz?D2fRR&rpu+)tHN^-%YE}Rr zC5#ka)sz=*za135r|K4-PdpTgxX@|^cEOI9%BUM?K+CDJqv<7fMhc#Z;c9I!9AOnv z*>0)3%wfqw#S@S>q!4=c{oo8kt{PG_imCIemh{APAC5o*uSzMv~o zzZf!QmL+4_+?@1Y_d2BR-NV*ro1+kO4WUJpG0bUMwvK%Y>gDgJT~lbGaPQ~#6nD{JifJ0xS^=faMD)irP4tCENJ&-ZOA=D#Wv7`e{RI0&1wdMjT=b!Tky53bpcW#Hs(u7#VSq4*|pK5*dJyhx&^wQ>dzvx=EFY zUK1k%!Kf~fpk&FFdK46=H@5_Xk9ZFlU_2>wnxauZ@6LdRfklLi6fJ@pkaAd-RVPq@ zPS9h8qmzajgL^v9?R|Y+SMPX&Wn$&9+)keDO5`HWvF}2-CXPBTTKK6Bf*5+`uKbZG zu8n~omkaPS+}a{yc)35`(Fcy>;pYzj)gilLP@Whs6gaT34LHZBqful-4;#dSq8V=3 zkO28$A;T(o-vuimj6STPsn&|aX#2GQz6WS>S#oo^YAtm#PZeg#TwjT6q!%i8Q!#&x zVbkESVeIhTZ7^$*AqW4?A^0gr0}LUrBLOgL(n8CDhmfs?7;GO;@$1AyNF65_>(ymc zlMfL|zC>Ly7IO=o zs2A!(={RwaJrrnIJ=wn*x=7=~p$3)rjjC1=qF528;o}2#7&&1AE?X$Rnk#M(t1o=p z#-XnsIERTpVQCttM^>7CsXEAz@ZF(u`CT_Pmqqp@QsN6 zZ?&;-??|-pxXOr$ZvuRpcu)b4u7h!5YvWtYrp`x+r+>H^)z}( zRlxnNB$jYoITn1B$Jpolzz>GdP6#>JrTmoV+sX2 zW0g|c?hu%FydI*-MfDc(jtS&MIGLG5NN>fypGh0@^)%l~2eeDZL>szZpL2WuhuE!EqtwpFO?tE{D@y=~osm+N zDjf5BQ=LG~GQyQ!n_rxtNB-~^C^obin8_jOcwy@BmjkPvr53{P`M4N|^;AFuz6;jNG%HX)y05Bl@TQ^kxl*$ory-%_&hRiet1dSDb<_x<5s&l zDPkiVKn@c#tl4pq$u}BRTe8w{;Q)SrE249ja#Q)QwUyozXi*S(s(NHLSFqUlTZIa( zSLF+MIfQhYoAtzO5@Q+6U z%xQ+i2|0ivE$G@c3^ix{c&r=oAG<3O==a$z0I0zlh%nx@h>lu!h^$IrZHr2B!x6SH zLI@CM=87*5$xhV@XNa&?Yr-(*50&L4%K+93Z~9b9r9Jp|qB3X6YdiFdd{v=T{24(E zViAwfMi@4-1E-mJi}#oudMRwm^ZBcK z>h6ITzHcIN|zI#ty@(^>mf<t$D9G&i)GO;;LpV{I0Qa5B1%z%O~f#8 z2-G7Op9#u_fwZ9+EV70CZTKeRP4a7tcM`nc=kxZr+AWW1wg;WHZpp+^QkrhO1N1|# zZqFpaIPdSBEC74CTyX3tBKECA+8XWvB8K`hUe$Ybi03Na17*a?iT?Y5Fm$K>7tqir zojRBn-vj{`oer?LK0$&&-1i@o8g#+z7TQAg?KY3=?mu21xy0=OE2P0|PLTQ!Iv!;f zAHpnrVkW%rh$7&*O4>2IJ869|T*k-&20LkkKaLPZHq5!;1d$G{)K^rEOdQTwX~l-W+vx=lwU|G7gGNsPxK&|m za(2-jm-Yqt(&F+p`3){Z6TXs7)g6ALz-@nf25$*}DkO{o39^9gMG1ebpAGa9oXKwk4aX;@wt15D-q^B)>*@n1EHFkRT)%X&CyGns-2kZWRP2mL4G zD>ND;q=Haizg007RxK1&$b}3i<)b1uFks{~x{A52_5!h?Nglh1S`L|^8aeVRe1_@1 zt;t=q=ktpQgp#C1Fp%IDF6p5l`rcjfpvW;#%@-J|CUS?$QleCeWSlkjID)hOn0e{Fo3qI@?Yk!X;gk8p?8T=`*kVe#u$Ak2H>! z4Wt($JAtvg?HSlH@p8oD|B1qXl&ndL1pJAE@l9kJdjj#(3jL{8Dm4Ik{|7B{iy;TN zqrRr)jUtE*??fHer$Zswz8gEHDge_W=dfJ!rocJ*-h3A@kiM8ip2)Ekqe4dIFRqaE zLSlH{xrK}Sn*o9W*~EnV(m2T12`e_V#}T+7J|a?ySfvG?9O~ooH%s5-Cef8PyGro7 zTmrGLd5mV*iA=h`jC9sV}uX1t2e$_n0* z5UZDd{XzBuWp%Q&S!6UrOhXjwxDK^&DV7X2YTHZgef#&XFM<{ne07bpJ~pEjNpBVq zxd+mZgxKJf21AK!UBnB(zju+#-QS*!(_@YFd<2O*joa3e0w%h1(&zn%0R&HV5-^l4wZ#lYDxVUaR6pjp0es-M{lH%FG|z6QlKrG zREh_UqOXKMtGA@D>t*oOm5j<^X~#7$JiJ|f1H-;9MKH~&?C-`*4g2}8(6N}N8Rlo3 zFF*Y9Enmz;>^Pl2iwijnO`YQKb%|gvGnWg?`eKu2nx(J5kGjg|Pn^CVq;CZ}Jr({} zdA_Jiq`=ax7*z*{4B6AIS8|9{Y_vbL0v?H?P`@Dk+5HLgMcx-L8{gn77Twd-s4Lvv z#aK!ntWs}%o606%CFW->E_Kl(*TtfB%cHXilaG0>X4H1q2fO9{C@_FmVztU3r`jYW?{uzHbGQQjboy3Wi*rE!18$EgFzp^| z`rlv4Yy}1g3+ZgyGu0hZOWZ-lCuh#SJ`bobRR#^yE#sT?Acsn_ASF`PIWnN@`yQJo{r(nTi@8Rk07bn}nCyMO<-e65|a zn9g$?Cy5!p+)+#T9jl!G0Y${hU-C3fW|95&x`U7B_{3kAwQR{<^m<2GJ>LOz3d4w7 z{R`$wK7_D*BhplMkVb9{o#F+4sns00Uv|5zRUuz9>PZdcEcCc59T9qN<_;Blj8ac1=l8VNrB`W&>qf-NgN*VZ_$<>H3!_79X7TPxEO zJLf9YAWB&6Ws)6;I}z!ps#HrolPR-G`y=d4GJTtQx8G04;RaF8sB3JdoeVG|s8dX4 zKK$+8%CSwEiELTZIqaEEkiq0d++ECFwe(+#G32qY@kqSck?4Ln`q$W_XSp;9f`evS z}cq7T^K~* z$iBOi&1j;hLaz%oCq7~gl9R%J&rh|{>q1BKHFAlKvN0)&9yZ^gU%Y7-xF0M4%D>0X!YK`J5V}30(*%L4 z+yBEBBs+?<7eA2)yuu5NnK`}rh|FhQUrNw$OoaVc*wnd(Wfr6JL%%)(Zu&I_?F$^h z;Rjtdne}9QYrR_RuuE z;|XN}oa6Mj!&~GTF1Rs2oByakEte1SDB~9{$*vX4#+bK(SaIyp@zWy+@jvM^<=bZ? zfET6RP?X!{?k!=<{d89PuRZ{8*8nzWnwCz;-t4kb5a??#_lKLUzYBX-#ROI`I6{le zF1Vp$zA6nxdO3{oABHF#t~e8x?}UK4xDNab;7JVxkg$xb5t?Gr0Rt?BRc-Vqdp6P+ovgu$1>FH{)cC^r&*zty*hW+cLv=Y$Q*FS zru`Q#4HHS^JdzpyPD2p{?r7&VH&afxQT&U}#Q@c{!;)dZj{@YP7{G^wKMukT0--GY zz_iW5Ae*Ao1O^%J;r~qa-pCyn!pJy{s-yv9saF89lQNLIbGk z3akhqKKfDzDlk5tI<8Z(df=Xc+MNex)P^PSZ~>(N6%SEw7NwE92?OL$Hq}hNx8>Av zBOplaz_Q^&ci#pfNP+^$mV?Cq&sPRIlE4>DMGOej-xf@*kugqeFSfwf%LKiiyLSs8 zpLu?SPK1QhipVLJM+yf!5zkhqLfM}Kg1??*OFpoK&ZB(ovO}kUg_b9x+PCDP0=@`X zT>25LwZ>4*WRLbnLMxi~>SZA}3l|Wfa4GZISNqFlLSj6;&xOIrEs5`g>7wBEQ(EpBwWXg~o2<>z#EViioaigsaw<_jU?#$c z{0NRLKpuSyemL%DLx4Ag~iza&ZbJ+o0SPNC_HRsXb7l!dqkHvB9-eb zm7^xfjb0$|xDDopf(2Dq%%_Iab@HBD-ZSKNgzc~}b3{C6E=sL-I`r{4{Y%DRd->DN zO1zbYOQ)M)yph<60W&1K4%K3#nu}C}>Jr{AXcGLdVVugADc`L8G2XF^mI#{*YivA) zNhD79Z{lR6^P8wlF&s-vEU?>;L$A!5A#m*KlgBEzg!>SM<)u%R&i6tey{U!wIp;r} zIrXFMajB!?p(QFK0ujme6G%HT5q2!T-&G@beXKQ_hAlPP^%dB4yHIPLt_=fJXyd%;+x1TF+W9J^cVP;5 z-A@|Y!|G3s(}|Ro$Neoj)RJq0fZi8GD}@`9#_)7IB1;D-EE`2|2jGxxVFlMb+IIV8>lyR}u} zgvJ@FH`8550j=EPUh4$(+0fILzY96UN)x9W?on$Ioi77^ zpg6pjW;cfUVG?$++y&qlGYI85x-dTkHE3Fg`SYR^%KfQ{)@({@d*+tS*4vsNPj}(? zpPenpz{#~`ARlgGO%sD?2@zI1Uj{zjn^(~&WP0xIa&UW`KLK)idYrE(NFgbmxiK7E zR1A(J*Hf)-#D(GClit$v{{aAlI0~^5;$(%wkMs+x4WROW&J;G*=)ZNHoB}CgUv651 ze`g7B2@VRSs@NLcK;h|@24XmX5q{_*7T>D~15Yu~IY?N5gSbw@E27JhWi)8a_Kp$H zy7`G0`dlzKD0Sjpu|80cS?FI}?gLjxc7CtFO$a%iy;A^P@&L2ZIke%kHVI#Jk(?7m zjQN!2-(Qim(t~%J`Kf09_(HkRD&`A_eGuU-@|WZBH8BC=xR*wWg6qrsGt$1`*H(+u zYgd9D6{iqg;DqCZfFUI%egiKMtJYA8g;KpNU0MrYFDNfk{E8MlEU+FgE+HF0AM<43 z3-KZJj>k8fbqUVLZXD@9ex9%5r~&65F5Os;dzmyd0z!bA@w}vV&P>e4aeuZ>Lc?>{=-h)Twkil~>^2ch9lOA+I~OvT zKD0yslN*_gQ=H`HXU0a&IQ-Xg3kGrxZaOwkl%R&}}}Sg`p-F-h>a zQXHoa5{j?Wy2x`J3Z_cI@)A4ObeXsJd_>&SvtO`4p+aWlUPw)% z?3I*NeyAU+LqfU@hK^CiLJxq($*!#2*S6P~^eGqC( zx>VrDbsq*JlbWq7b@!YEXjBoiqsJWasMr{SmeKyM;~~x`-o*C&pU;ZyaJAncC()|2 zrOa3O7`=%}RtrgPo60PE;|%!gwZ~AVmqtuLxwgPUf0NVvJNI7S^Nc{cW{ z*$Nsv)IeQ{O+zrq?eBlb5z60Do2GKsHX}x4BwtuAoi~e~mz$Oy)lE$?o12?~^?HRe zPP4kYgl(<IC%8y^9W3`*PU(rbc_2oz%4`fhu3Y(WjRS3f72!) za9r^@I_tS57__B!+LQ5o6OhZ>u-UFSW@4b98@;=5HH&z!$aZgEnCk~Drqu9YjB8)P zJKVv?Vo=}5+lgr%a2v3cl84Sw?mGx9Uqe|ybV(x4p-bo1CqQ#B4}rIKfZ1cfr+m+I zJ-jsY-s(dP^Lsdud^lZyg+~ScSEjn9E)2mpKyV-R@`p!GcDagVbwSvZ2ridzB;AM)YlU@l-`=b=VBdB?|~P%&W) zV=-AUq(#V%v$|x6<7E#wRKy1I^k?mzDSdTH()G92ZGM~_u!kclh`plA&WAr&rR2u9 z`Zn3IiTSYR#~Ckrujg4|LH;-zp*A(apc1^lZ>=3IRxKC~x|9dSka} zW9i=R11VM$2p(IsU1(^k1_lNxHt#h&dXz?Zsjnrdk%gx}vBOS{B*d3+W#KRWO?RA| z=fj8g0w2!Rf}T*bruKJ(TY#o@4!UUbj(6o3Rp(|EpVi<)-So!v^BfTdm#dlAziYZ2 zD8n5ndGF(F-`AliZVN53FmE5C9hL`gK(l=pWo?#J``*c6OhLh4fJS_kCM)}S~hXITEhRj%iw!D0d z6;1Ae-^U=T@$b727tfUy_p=EVWV(Z3fs=AooA!wWf077@Rp@< zcAYl#ovmkaUxrb>Azfe3ZGWr#PbgQ45S`1~cubzHk~pQ}_q99Y@9VjQfhCh_DfHOZ z$j79nq1-?M<(iZd=wg^jR%?3r7;FfA?}Vu{}J7mHtrHd8mQ1V2`_$ zrQrHe@8FR8d0o>!pPpxY*x8UyzO|0jufp*8{>RL=E-q?cdMh-12Bo@qlP~9Z*P&pE zmr?X{pDOd#*VRuh=`o4+=4W%?%oVSfP!8RGE&AcW8|Ah-hDg3%C2`qL5_vujgqB?P z4#XijAwMfa2u~zz*l0Q)Yo_?VQSUGOdjHU4V=}lD z-Sv{xI34Qny8}a3BV0;qy&hBi=+L(0pwj{DxG6C&gof5ks+C_AOEWI3S=kPa&@LHu zVyr}M(K&6Xl=+9XZ_HXXsRnK$4fzf8om`VYHy0bJNyg5O*>R~3+C=YxM(pAB=JFkp zvJT}-^RuvQ!20pG!Z>FwxhQPjn)WS`d)b9?EX9fOalQ82A&---KL`01eqLL>(5^yc zIh_oiXmKkPP#rGp-SEovsrJF(p?&|xguB$hq{u-d>*1v0(d7*d|^4yPO z3?jv*I`E_tRsnYbpYgHc;IhylQH0zE`SQT=mY+ZnS;t_&^p?GnIfg-g&X`CBCg}-M z@J>3T`IiAoeQ3Em_DZFJW+sOZUo2vrH>l!rdyhk_^9D|Vt1+##-*i4`xtJ_BZbc8* zKU1KmTMHJQQ93XXHxqHY&G8GSG=KSE-1mD2@>lf{VJwXKnzJQ#yHv+a|L2HNOEP35 z7i&2G>&*MY9#NyTQuHY1n^sy020oWTR~}Y$7!jX71?=h#z9NLAMx4@GnZlrdygzEF z&&3I5?_8K$Jif2xNG6m|$ETygjeu4!Dy*4suMzp??E#&VE4A=AE=il!g|m+Yrx{u8 zIIISlAWsfvxWy8RwpH;dQSq?sGr4t-S;owGpFQ_?aVz48$!o~4@`<-K1=)KTFtADu z4D$~3`EQ;=;T0dgDCe!hK}{9djg;@$66SJC{WKW5?We`eUmn z<|?8SaEnp34Fq0x0q3i4TmElHOL+q}m^I}#r#KI2_r6CI8NhPy)nZoj$;z?d{TBi$ z4X0vz3i)ON*er*tTw1rx?UkR{bjSa`1bZf{!PAO2AZjR)ht0hw} z^_#x|!WOqdYM!R~jr3D~ZIRbHit1Xoyo>@ zx7(j{vvfEH1Y;IyE$De8z2o!VzGyZL;u6a$^9Z(qR4tY(wEp?S=W>J&wzxlr?Q#B_ zF=vsG;SjwCDYk?(IIr$MgpxD1kC5Rx8o>l<2*-eO-)=E&%#zYZZf8%PHy%eRq8m z5OQ0!ssM|y>Vg0&>sD8-0G-Cu=#gaApk+6&x_rKXe(aA0^LD6YH$&k z0-ELMZu_z2c|%4IV#D_pu89sQvQwABz2CU!DoxngnSwL)cBwKtYyV`Tw<-~?%XMxL zj>Rjgc<)N-&0HV4&41b8r;TQf(`UkGEyg2bzs#>R?q}sgQW&@7JlWV}q+4!mUJ8ud z{>0a@#ii2@4MAqe7@?|VYTHs~F{h|>>vCjW@djzJ4@f_r+lv1CUxO~9S_Y~*`zC5) zh%1Um9E#^J#c5%3S_iiobyH&lUftml7#**v##EmCb>@h4W6t!uLSw3<*UfW&09y?a zkFTxhicswUZ*`aigX`WU0z{)>{TbE+W=h`v=HCJ&cEahqr#YCuwEs#ZjAg9^KfMoe zFMr3Q_i>XLXiyrsCOE&l81(!#kPRAQ36Y}-%f1Sj%tt%tlng#k3^tP{kY?Y{H?y{! z)>fx?)S2&47bP=0nme?>=I-!0Ln{6xEuLt=&Gu6)eS6WG@sa9(OTGzS#gh9#1U}lc zxY@2@@|{dc&M&=MUwXTqERwU!=y*MucubA!4ri^{Mq{6H95?q(Q7OK6Z7ZtZ`WsPp z_p>-zzzol+R0M5*XX4Y;hL(vtMfys~3-K_1|=f{ae_L zvbi6z%xR+M#Gz=_*R@7?yql{gQZMUNjxT28E%(@=SY9_teI8o8VWb1c<==rO*rImudhpO;x!mt83V?vk})_V(Tr zY%jt~9dmI`CL1B4;PRw&OBzo<^arV%K2Ghx9Uarf&W7SwU*)do%@euf&Av4H&p6xa zV@nFo078~ivvme~K3ESu?fx@um@tFg%&!6Zy-rgp5i-IZLC3+fl&R0dCAdcOu(r8$ zzjbJlQsAQlyF^>+C>Yt`Vp?6OF)PmRZ1gvEn`N-st&`wJked`(1%AYYZ!~@H;c=4{ z$zqz_j0w+BprNqyWP~TGc#U7wE0Qq@8?hW-N%;hrZsLgy@O_>xYt;LbIk^x?j3l^B@qLx18HLBrAsCxlf# zAx{id*PhmGiT3`dF)X0#3y50X1S#Jsmxz00F6z-z1&#>-XHzK@Cp*5i7a~OqBjkI3 zcE`W9o{hUANZ;g=r*U6{+Wvjh-{i2w31T9zhk$B`(~#^WztC%D$VB>A;KHEd>5`qv zF+&?urb)TPV8}r(Vk6!;%v{tvW+LytRfqu^>>gU}Xi7}U#7{$YL#cN)D)nO^C3){r|>0O&Td1!S1XDz2?sQpXzLc8p+ zHl*ynur*j1aKT6qrfJHhv>Fx_%@Ycn;G&8Rh|QJ_U1`+D68(G=-)Xb|MS^`Sz#@MO zAM!XCpze9-np_JBZiKkSOZ`AQi;%KyQLNrn673zGYE8mMHYT=*%xd<3#YL_5_UXWrP*TL8Kl4Vsp(YUxOIcF0x@$w9gpU6686hlq3jnEo z|3}MYukNBHC3X&Qx(Eg3C3-Hc_wdZKD!borge8J#|IU6YDw1fx+8`u7$f2@tBN?ov ziu$2;j!N-XNN0i$sg{)s)I@*PPO2RVd#AS|n?YtNwBGHN0GA)G?r!N`jxaKbi8q?E zdY6)MP6U;~55g=lDJRWM`5qYX)29;NO}2eS{-2mU)otl0ica;Sn*0+ng&br9zX#pO zupvNlht2#(Mqh~=qTL$op}~+U&nSEOYg>bj&-sy?$chOzaajgQI})a@k?WKG9lx#u z|La|pB7>d^0mNnh0tJW`Gl`1A0VtB8dUx-K^VU0=5iy!$1cGf6~SXh@KQ03VzIudQq4S$MOoSa z?#u{)#rd(zCW3PB^-wMy(j;w~D%}N3rCOr(y^!m2iTvjg>25g^8;JC2kC#Cx6PjQQ zmdwVX`qS6hJs<&^bXTqzVM$3vb&Zy=Mt~AL0Frw|C1jf!==$logp$0vM$lsXFm@ep}rymD(*x z^wpf=z_Do$7;6vLjua(&ZDfkIXF6Jvn>SE{9sH8n)2<0%6xTL@<*9{WUz#x>;fGIB zJiu%%4qlA#vMvh#9sAmnqX!@c+_NPiuWeBf0I)nC!2|(;fx`TtN2i4MZ%J^_QtTm2 znam?Z&roZ?(5gWWn`$OUEn{!VHaRXEF1qIjXG*#a%=?g9G}4jAbH7#YkXEUvBBG?l7V z8a3=)^sh>#vLGp0BZixag#J(@RE!jIg}IDmLlbNJz@Z6dP1Gw+!-hKwm|uH{14bGF zM(Z=npt!-TSvs{)qtS=VyKqJ2E&%5R=nko^9z|CAxZPwk2B9uZNShn6u}26W)$=Km#~|KB6`V);cnT5meWK+KMW$| zks6aqCAk`t@aDP($eO68098Ct_vJfG5X3KJ8my%m(D=bKP-tV9}LJl$W*~tUqqV(O@}6@+Bgn&5;D?{#vIhLKl>c$7<(?f7_^vhk=0MgW8-= zLI;wAhVcO-6B<5!IaotNJ*u|d(?b3oul=4#XoV;#|1;ufu??n{V?~KR7i{)%q+bS` zVWPq&%f3$Nh|)FK9S9bssU;7u*|rgEE3V*PMp~?iQ1|8As(Kg5ThwVF&oUC`)iS1q+l ztUjpPErRXN$s91!04(sowK*TFH|`KSfNR8Cgwv?|svXh1i+#DI?c5PZn|)Da8!He6 zXP9_;5ulAORbxQx(uK>+TAFpRcvCIFsQh*pSXW-d0mJZ8^NC;?TFC+;bfV zj5GiY^aQKE64>XKy!2a}!m{u~uEyqPa)Z7Sa8aTkZ6Wk~BaUVh3TcK&Xj3F;V68v4 zPd96X-bhlFB3rolaomDezjFj>GT)nJfv-%#X0ZPZYtN+_Uz z8*#MT)_nPR!9<@7k5>#UK&2*^W*-W!I#+vAy+85bm0}Z}2X50JFt~>^;QpW|SaIl^ zqyPhF_-ZB2itMBnMbYUKB>A4tOmy4`ZX-r)DWE?WiL$3}XoAHyW-UR(**^3Ui`WyR zvI^wY({%+5>+(rpz4I!b+KmesnV{TvBb1T+Ap-`>h`8D{1q?`X zH-YoB=fV2W6#YCg1dP?wp|rAc&}r2mSok$Pf4FcmV3e$gS0wU1n~H2a6p5+;HOW5{ z3EdgFX(;F_R-rrBfS}D6~UrLW3a$;jiLAU5^Mj`bwW2} z6Usx8xLFfIFBb`|jSNk2m~*A#(;hSi6`o*E3@dA*qbFdrE}j6=JI{hY&=H*eX08GE zn-79*`6PYFP<+j$nc!Tz7y`xn*?Vd!%7@04*9RLW>jW5WPc38~VWLXURDlK7im+kI z{lTJSi;4aZM}&bYS|#gvL6TR9gt{Zk;4#&zHJ>q9&?vOnq4~Ady7k0h9>(I!A@8Bv z!D_P~8Rle{!MpKQu-|=cYQYR&>&`2|{qAGX*;Li@eu{PoP;>hvu5z?vmnSFXz6W)yb8yoGr|AW2I%%UBgQ>+ zf$+wQP(JTca4gp^JVH+pJ;H$s&x%t(a5jfj#|2HUe#3~6!xM=7tZ1UAa3mO1t%>q` zkme%}pX z!*+sd0tW)ok_@ola~*g-S_7T+rEIEtq$zd>Jilx%RL#8@92h3))C&XKDYAjfaVt-? zO`S$AEVSI#zxy|?yxao%GmZd*wB05PHrtudm(RdWE@}0qV~PH8+=9Vc6@e@)kP zrhCN|@WB=T4GZSX0-wJ~gdBn+%_TTBl{0!t=b1Wk)B*A+0(6Ew-L*zNVOOg#nOD~8lq`mnR4-_&(nMY#pmzw_HaR28Vn zGEN|LQRGY$T)5e+-XsN}fim*)ShXisFVt;*PgmiVYsDnke)C1}*FXFg4jeihw|NkT z3IWsC;C}xJmcd}ZW66Xg020mn2!$KWJHfT$3UE9!9Xy{r%Rs2x>x%oDYoB`#=KT3Q zpvxw*5K1q=X#DUwU1~%6f(6!z>?yZLBRSgyLT?cW<-A35p$R=jl;~3;q5i%d$7`(q zlz;~6K(IQoFp509CU3p2DNKB7m(0Bce)q%g!je0dLq|sk3}^vAbT*WOZ|8b&zx6OU zo|qd9S(vzLVh|*7A?I+{RbYSM7H~duJ9s{N8vNhpKxb<`Ku2J}muYEffq(qp|G~W% z{Yp3QBFteleEwR$lq!CnRakYJ00GZ=g2)mP!W-#Hatn|J}Z zS4`4X>4}~oi3l%?Q=+(($nM zmj7j;lb-VQ+T723WZ}q5)u)Ku45v>~v7FloAviYH6{~oa3b+xV)qxkfGW73~s{4wLT zVBvH+VaBYPFkbs-%OuH_^eT_t#VZ2|xMXDeRJd z?~F6xt+(HX&d$!1gN4uMgVhf|3@4m?5_>O`e|r{_uiJH#sZV4cVBI&{*yok1^AQFM zsmUF!TpdIrlWa-m84;~5H=m9bB>ASuraNJc2D*KXDFlsXUpF*Y6oYdA&AMhv@abK@ zXaZbv-j86!*l{p&%ozBOv(ADKKKLM|pyBuX;pw$&;neSb7e8fX6KNAUa$FM!+a)*LKkS%!P>yAMu1 z?KJk<2o|TEbOLO?{zBdP3+uhtL2GdVH2b?#=2;+EME5Lcoj~O4)*q62`ZSfct-yL* zj%2xAB$UPi4RZkN zNuIt%;+?bfNw*$uK2DV6<-@zAiAE&7eHBQ1|9F_T^d7us8!QJ~tSa z;HAZd7kKozad5$({sgbR{yNh}s09?2m6h=5V~@eP=bgvEX>;YbKD&;vwIP%FSNhf=3F zBRB?FwB(rN1$hOO3$u&?8m-5NJPo<;hxKi>gY_KH1T?%|&_ZpXth+lXu{Ho;9G>}a z_{|T#3nL@Ej7V<-fn)q}$H6at`AfLzmRlIdv31)vC@Ly~hQ>z5McD0jrsY8Isj8|9 z4jecDpRZpJtM0!aE}Jj`e(>WTGj9TaSJ=LZvbG z;*287!qp%WWyY6>Ej$b{qHQX$9wQKn*^|b|4-U2aH~|}5p{WZPonUr&fWG@gurSL2 zeKgU_*f;H8aNe1x_2M$d!~u^m5Fmi`Tcbw@vmS9kqPKT34*vI?A3%lPWM>axOaNuw zN@$^02JmWr{#8~Vdl-q)!J<--=nb0+?VR8=w74r@IYuDz%>w4S`+SHv*tWRE%b0A{ z0K?@6`J-nI0~ldX9GZXSM)LQsjlYjeDXk473Uw5r290q!T=m{dgCmVvG#-h;df$han!2*jT zzZNCsA0K~P!$n!?WMAahkKRJ)MIxcQ`c}DyGbpN%q25lgY<|~p;}Y=+|Ni8^!1qo$ z5k`*F9yE|-J^TBoLf*~)YYgrp5->h`7R)YRQhRjX>zfk^MBn3wvrL&1?9&z>@cAPu+r%!VBazUxBBA!aAqu*d zre-(Gqnn4Q_H5g=32e)+Fx-q&3{5KMU&g`&ywqBN24+RZjz0$G|K&U|-=3*|8a0a2 z)3W&;X!Z^@1nGd1RuAkdjmcMFD*wSvl5z&WX~W6WkXla`P4dFX9--k33QnBbU*lly z(*_M1{%&afCJ$_PPB!FFWCRUq*2Qq~FMh;AlhLYr7UNl3_U1qQ45}AgZj7u*pGsBy zFM5E3B|Occ4q1omos9R20T!jAq)gp(xb--G!-k=4Czf%dq-2SN?(55Ih@sRgc5}w3 zO2WY52WUOC8*D4DHtZC2u@Y=RoD!NV z`4!9qOjLsr{@g2MAMCA&nKJDZiLxWFK>6o}QU}k33};)L=fuI!zZD66PbAb8EsJun zeh`GHAE3>20IWLq#7M-`D4cx>+;aXoOjtEkB6M^p8*=(7C&J3V{|4$7PB5Tn5dj!? zPG%lpBC>EZQ*E}hELw~#2!z7gmjq({1;0&4k%^M+43Q{zi9~LQ_7p)vH0W&v7(*V9 z!)PrfU|n^i;W8!BKm#xM;}`z{&OQA*3^efak4})-M9KH~V~>Fg&ps1AnEV%zmrgXM zXAub)E3alAV7y)!VXguRaO@KsgV@BsuM`PgC>B^x5H9TO1)2&EMVu!AUfB7X-gkk|10taipGw#R={~dzGcTPG1 zF8bM-@YJQ}vk(LorG_IoqXEV}*Fh^e5Yxj5&o{+%DbBo!;Z^uBWhxTof453j-p7Iy zqL!bF63e1kqCHu5mRiANb_c~?-Y6BT^>tu>@;_k3g};W+uK6oe%nx!EhW0A@_QJUDMrbWH^#ct2 z95FLi-0ET8WDKq%*u#R*hjL8vPx(#Z7NOUWPso+%)dHb=qj?)B_CgY@%;JTn$P_GA zteTs_`uH3}l(-L8tAT_ldJ8yc2*Z`)IhR8I%!|P^`x2;{e>t?UROuwvXxN!9KoJQT z58eu`Rb@SZ5e`3a5EfQ4GZB^)6(~@*vo+TwXXYJp@ZvFU{q4z*4~!Iu{7Zq*HQ4Z^ z?;&EOXpsW@YaLLf_@EiHDXb@k49c2?X$Khn+x!JX7H4RoyxX3p|DGPecz8Or*4KhL z1Q?h)KU5!=)WlUU5V|@?lF#P1g4=+$-qdz%PO){OXrh8hs3#h5;DN(dfYr8kFe^4t zo?DjIfH5rB(hTPLp$Ay&2zJB5F`HqpF$z#PMM5_Sg#IhfM7dYNZE%)dto&Gz=n8?* zl4!b(AirUQf@&FBUs%Zj!+?MxKd}G`%NyaVa(g_UqEjHWK$PgbTtd&}C!gDp?MsP{ z5r}-gXreC)gf{o{HZYq~&OERGGvD;zW!3GeB5(_L)`TL|u z=x?$MEWE;$n@Zk>Nj^~^%H<-VpZA?6pDS6Q^7%)=wkQLvOYq6YFRQ-XMON^0Sd;;E zPu>Yz4>yC@A26^68fSpy&e_4$-81nM;%#!~&TE1vmYT+;rhsx@7XYm|zjPmU7@wlcyMH zzgt(_eDLsF@9{!0ZpN{;+a{b#=S?g~2r$Cl1_usJfg-$=xf5G0w_bcHKc(D^;ayyF z!Kk)r6X(ivvpj=2$YJ2H@{CI2K(Ta?`+Iv9(79P%ZPO>dB2UdYfuB}xx?Ahij32g5 zpO`1l8QhaEs>i{BK{cQV?<<{~1(xYqwXIVo{*9kjZn_(to^^v|dX`Px#07*qoM6N<$f`YJj6aWAK literal 0 HcmV?d00001 diff --git a/slides/k8s/argocd.md b/slides/k8s/argocd.md new file mode 100644 index 00000000..c3c9a648 --- /dev/null +++ b/slides/k8s/argocd.md @@ -0,0 +1,447 @@ +# GitOps with ArgoCD + +- Resources in our Kubernetes cluster can be described in YAML files + +- These YAML files can and should be stored in source control - specifically - Git + +- YAML manifests from Git can then be used to continuously update our cluster configuraition + +- When this process is automated - it is now called "GitOps" + +- The term was coined by Alexis Richardson of Weaveworks. + +- Many tools exist for GitOps automation + +- ArgoCD is one of the most popular ones due to its slick WebUI + +--- + +## ArgoCD overview + +![ArgoCD Logo](images/argocdlogo.png) +- We put our Kubernetes resources as YAML files (or Helm charts) in a git repository + +- ArgoCD polls that repository regularly + +- The resources described in git are created/updated automatically + +- Changes are made by updating the code in the repository + +--- +## ArgoCD - the Core Concepts + +- ArgoCD manages **Applications** by **syncing** their **live state** with their **target state** + +- **Application**: A group of Kubernetes resources as defined by a manifest. ArgoCD applies a Custom Resource Definition (CRD) to manage these. + +- **Application source type**: Which **Tool** is used to build the application. (e.g: Helm. Kustomize, Jsonnette) + +- **Target state**: The desired state of an **application**, as represented by files in a Git repository. +- **Live state**: The live state of that application. What pods etc are deployed, etc. + +- **Sync status**: Whether or not the live state matches the target state. Is the deployed application the same as Git says it should be? + +- **Sync**: The process of making an application move to its target state. E.g. by applying changes to a Kubernetes cluster. + +--- + +## Setting up ArgoCD + +- We have a YAML file that installs core ArgoCD components + +- Apply the yaml: + +```bash +kubectl create namespace argocd +kubectl apply ~/container.training/k8s/argocd.yaml +``` + +- This will create a new namespace, argocd, where Argo CD services and application resources will live. + +--- + +## Installing the ArgoCD CLI + +- ArgoCD features both a WebUI and a CLI + +- CLI can be used for automation and some of the configuration not currently available in the WebUI + +- Download the CLI: + +.exercise[ +```bash +VERSION=v2.2.1 +curl -sSL -o /usr/local/bin/argocd \ + https://github.com/argoproj/argo-cd/releases/download/$VERSION/argocd-linux-amd64 +chmod +x /usr/local/bin/argocd +``` +] +--- +## Logging in with the ArgoCD CLI + +Verify we can login to ArgoCD via CLI: + +```bash +argocd login --core +``` + +You should see "Context 'kubernetes' updated" + + + +- Note: argocd cli can talk to ArgoCD API server or to Kubernetes API + +In the `--core` mode it talks directly to Kubernetes + +- So ArgoCD has an API server! But what else is there? + +- Let's Look at ArgoCD Architecture! + +--- + +class: pic +## ArgoCD Architecture + +![ArgoCD Architecture](images/argocd_architecture.png) + +--- +## ArgoCD API Server + +The API server is a gRPC/REST server which exposes the API consumed by the Web UI, CLI, and CI/CD systems. It has the following responsibilities: + +- application management and status reporting + +- invoking of application operations (e.g. sync, rollback, user-defined actions) + +- repository and cluster credential management (stored as K8s secrets) + +- authentication and auth delegation to external identity providers + +- RBAC enforcement + +- listener/forwarder for Git webhook events +--- +## ArgoCD Repository Server + +The repository server is an internal service which maintains a local cache of the Git repository holding the application manifests. It is responsible for generating and returning the Kubernetes manifests when provided the following inputs: + +- repository URL + +- revision (commit, tag, branch) + +- application path + +- template specific settings: parameters, ksonnet environments, helm values.yaml + +--- + +## ArgoCD Application Controller + +The application controller is a Kubernetes controller which continuously monitors running applications and compares the current, live state against the desired target state (as specified in the repo). + +It detects *OutOfSync* application state and optionally takes corrective action. + +It is responsible for invoking any user-defined hooks for lifecycle events (*PreSync, Sync, PostSync*) + +--- +## Preparing a repository for ArgoCD + +- We need a repository with Kubernetes YAML files + +- Let's use **kubercoins**: https://github.com/otomato-gh/kubercoins + +- Fork it to your GitHub account + +- Create a new branch in your fork; e.g. `prod` + + (e.g. by adding a line in the README through the GitHub web UI) + +- This is the branch that we are going to use for deployment + +--- +## Start Managing an Application + +- An Application can be added to ArgoCD (and consequently - to our cluster) vi UI or CLI + +- Adding an Application via CLI: + +.exercise[ +```bash +argocd app create kubercoins \ +--repo https://github.com//kubercoins.git \ +--path . --revision prod \ +--dest-server https://kubernetes.default.svc \ +--dest-namespace kubercoins-prod +``` +Check what we did: +```bash +argocd app list +``` +The app is there and it is `OutOfSync`! +] +--- + +## Syncing the Application vi CLI + +- Let's sync kubercoins into our cluster + +.exercise[ +```bash + argocd app sync kubercoins +``` +] +-- + +We should recieve a failure: + +`Operation has completed with phase: Failed` + +And the culprit is: + +`Message: one or more objects failed to apply, reason: namespaces "kubercoins-prod" not found` + +We need to create a namespace! + +--- + +## Sync Options + +- Syncing is only trivial in theory + +- There are a lot of edge cases + +- Hence ArgoCD supports "Sync Options" + +- One of them is "CreateNamespace" + +- Some [others](https://argo-cd.readthedocs.io/en/stable/user-guide/sync-options/) are: `FailOnSharedResource`, `PruneLast`, `PrunePropagationPolicy` + +--- +## Let's edit the sync options of our app +.exercise[ +```bash +argocd app edit kubercoins +``` +Add this to the YAML opened in the console (root level): +```yaml +syncPolicy: + syncOptions: + - CreateNamespace=true +``` +Now retry sync: +```bash +argocd app sync kubercoins +``` +] + +Looks better now! + +--- + +## Managing Applications via the Web UI + +- ArgoCD is popular in large part due to it's browser-based UI + +- Let's see how to manage Applications in the UI + +- ArgoCD web dashboard should be available on your lab machine's port 30006 + +- Alternatively we can run it on port 8080 by executing: `argocd admin dasboard` + +.exercise[ + Open the ArgoCD Web UI +] + +--- + +## Let's add a Staging environment for our Application + +* Create a branch named "stage" in your **kubercoins** fork +* Back in ArgoCD UI - click "New application" + +| Field | Value | +|-------|-------| +| Application name: | `kubercoins-stg` | +| Project: | `default` | +| Sync policy: | `Manual` | +| Repository: | `https://github.com/${username}/kubercoins` | +| Revision: | `stage` | +| Path: | `.` | +| Cluster: | `https://kubernetes.default.svc` | +| Namespace: | `kubercoins-stg` | + +--- +## Sync Your Application from the UI + +* Click "Sync". + +* Click "Synchronize" in the Sliding panel. + +* Watch app status become Healthy and Synced + +--- +## Making Changes + +- Let's see what happens when we change our app + +- Change the image tag in worker-deployment.yaml to v0.3 (on the `stage` branch) + +- Line 18: +` - image: dockercoins/worker:v0.3` + +- In a few moments the `kubercoins-stg` application will show OutOfSync in both the UI and when running `argocd app list` + +.exercise[ + Check the application sync status: + ```bash + argocd app list + ``` +] + +--- + +## Automating the Sync for True CD + +- Syncing manually for every change isn't really doing CD + +- Argo allows us to automate the sync process + +- Note that this requires much more rigorous production testing and observability - in order to make sure that the changes we do in Git don't crash our app and the cluster as a whole. + +- Argo project provides a complementary Progressive Delivery controller - Argo Rollouts - that helps us make sure all our deployment roll out safely + +- But today we will just turn on automated sync for the staging namespace + +--- + +## Enable AutoSync + +- In Web UI - go to Applications -> kubercoins-stg -> App Details + +- Under Sync Policy - click on "ENABLE AUTO-SYNC" + +- The application goes into sync and the `worker` deployment gets stuck in `progressing` + +.exercise[ + Check the applicationn resource health: + ```bash + argocd app get kubercoins-stg -ojson | \ + jq ".status.resources[]| {name: .name} + .health" + ``` +] + +Worker deployment will show "Progressing" for a while until it's marked as "Degraded" + +Makes sense - there is no `v0.3` image for worker! + +--- + +## Rolling Back a Bad Deployment + +- Sometimes we deploy a bad version. + +- Or a non-existent one (as we just did with v0.3) + +- Depending on our rolling update strategy this can leave our application in a partially degraded state. + +- Let's see how to roll back a degraded sync. + +--- + +## Emergency Rollback + +- The purist way of rolling back would be doing it with GitOps (see next slide) + +- But sometimes we don't have time to go through the pipeline. We just need to get back to the previous version. + +- That's when we apply "emergency rollback" + +.exercise[ + +* On application details page - click "History And Rollback" +* Click "..." button in the last row +* Click "Rollback" + * Note that we'll have to disable auto-sync for that +* Click "Ok" in the modal panel +] +-- + +After a while the application goes back to healthy but OutOfSync + +--- +## GitOps Rollback + +- The correct way to roll back is rolling back the code in source control + +.exercise[ +```bash + git checkout stage + git revert HEAD + git push origin stage +``` +] +-- + +- Click on 'Refresh' on the application box in the UI + +- Watch the application go back to "Synced" + +--- + +## Working with Helm + +- ArgoCD supports different Kubernetes deployment tools: Kustomize, Jsonnnet, Ksonnet and of course **Helm** + +- Let's see what features ArgoCD offers for working with Helm Charts + +- In our `kubercoins` repo there's a branch called `helm` + +- It provides a generic helm chart found in the `generic-service` directory + +- And service-specific `values` files in the `values` directory. + +- We'll create an application for each of our services reusing the same helm chart. + +- We have an ArgoCD Application resource manifest ready at `~/container.training/k8s/argocd_app.yaml` + + +--- +## ArgoCD Application Resource + +```yaml +apiVersion: argoproj.io/v1alpha1 +kind: Application +metadata: + name: kc-worker +spec: + destination: + namespace: helmcoins + server: 'https://kubernetes.default.svc' + source: + path: generic-service + repoURL: 'https://github.com/antweiss/kubercoins.git' + targetRevision: helm + helm: + valueFiles: + - values.yaml + - ../values/worker.yaml +... + ``` + +--- + +## Create an Application for each Microservice + +.exercise[ + +```bash +kubectl apply -f ~/container.training/k8s/argocd_app.yaml +argocd app sync worker +``` + + +Change the ~/container.training/k8s/argocd_app.yaml to deploy `rng`, `hasher`, `redis` and `webui`. + +Apply the application resource for each. + +] \ No newline at end of file