devops-stack-module-application
A DevOps Stack module to deploy a simple Application in Argo CD.
The module creates an Argo CD AppProject using the name given on declaration and then creates an Argo CD Application using the chart that is inside the path for the Git repository that is declared.
Inside that folder, the module expects an Helm chart with a folder structure similar to the following (as is standard practice):
application_folder ├── Chart.yaml ├── charts │ ├── dependency1.tar.gz │ └── dependency2.tar.gz ├── secrets.yaml ├── templates │ ├── template1.yaml │ ├── template2.yaml │ ├── template3.yaml │ └── _helpers.tpl └── values.yaml
By default, the created AppProject can only create an Application within a Namespace of the same name or within a Namespace declared on the module declaration. Besides that, the AppProject has the permission to create any kind of Kubernetes resources inside the destination cluster, but you can restrict the allowed resources if you need to.
Usage
This module can be declared by adding the following block on your Terraform configuration:
module "module_name" {
source = "git::https://github.com/camptocamp/devops-stack-module-application.git?ref=<RELEASE>"
name = "application-name"
argocd_namespace = local.argocd_namespace
source_repo = "https://address.com/owner/repository.git"
source_repo_path = "path/to/chart"
source_target_revision = "branch"
depends_on = [module.argocd]
}
A more complex declaration, that defines the Namespace and also the AppProject allowed resources, would look like this:
module "module_name" {
source = "git::https://github.com/camptocamp/devops-stack-module-application.git?ref=<RELEASE>"
name = "application-name"
argocd_namespace = local.argocd_namespace
source_repo = "https://address.com/owner/repository.git"
source_repo_path = "path/to/chart"
source_target_revision = "branch"
destination_namespace = "namespace"
project_cluster_resource_whitelist = [
{
group = "*"
kind = "Namespace"
},
]
project_namespace_resource_whitelist = [
{
group = "apps"
kind = "Deployment"
},
{
group = "*"
kind = "Service"
},
]
depends_on = [module.argocd]
}
Furthermore, you can customize the chart’s values.yaml
by adding an Helm configuration as an HCL structure:
module "module_name" {
source = "git::https://github.com/camptocamp/devops-stack-module-application.git?ref=<RELEASE>"
name = "application-name"
argocd_namespace = local.argocd_namespace
source_repo = "https://address.com/owner/repository.git"
source_repo_path = "path/to/chart"
source_target_revision = "branch"
helm_values = [{ # Note the curly brackets here
map = {
string = "string"
bool = true
}
sequence = [
{
key1 = "value1"
key2 = "value2"
},
{
key1 = "value1"
key2 = "value2"
},
]
sequence2 = [
"string1",
"string2"
]
}]
depends_on = [module.argocd]
}
Using a private repository
When your charts are stored inside a private repository, Argo CD needs to have the credentials necessary to have at least read access to the contents of the repository.
This module has 2 variables you can use for that, depending on the type of credentials you want to configure, either HTTPS or SSH.
SSH
You’ll need to pass a string containing a private SSH key in the variable source_credentials_ssh_key
(you can pass the value however you want, as long as it is a string) and the repository needs to be of the type git@address.com:owner/repository
.
Do not hardcode your SSH private key as the example below! Either create the SSH key using Terraform and pass the output directly or use SOPS to store and pass the key as a secret. |
module "module_name" {
source = "git::https://github.com/camptocamp/devops-stack-module-application.git?ref=<RELEASE>"
name = "application-name"
argocd_namespace = local.argocd_namespace
source_repo = "git@address.com:owner/repository"
source_repo_path = "path/to/chart"
source_target_revision = "branch"
source_credentials_ssh_key = "-----BEGIN OPENSSH PRIVATE KEY-----\nfoo\nbar\n-----END OPENSSH PRIVATE KEY-----"
depends_on = [module.argocd]
}
HTTPS
You’ll need to pass the username and password inside the variable source_credentials_https
and the repository needs to be of the type https://address.com/owner/repository
.
Do not hardcode your password the example below! It is recommended to pass the value as secret, either using SOPS or another provider. Another best practice would be to use a token you created on Github.com (or another provider) that has the least amount of access needed (in these use-case, Argo CD only needs read access). |
module "module_name" {
source = "git::https://github.com/camptocamp/devops-stack-module-application.git?ref=<RELEASE>"
name = "application-name"
argocd_namespace = local.argocd_namespace
source_repo = "https://address.com/owner/repository.git"
source_repo_path = "path/to/chart"
source_target_revision = "branch"
source_credentials_https = {
username = "your_username"
password = "your_token_password"
https_insecure = false
}
depends_on = [module.argocd]
}
Technical Reference
Resources
The following resources are used by this module:
-
argocd_application.this (resource)
-
argocd_project.this (resource)
-
argocd_repository.private_https_repo (resource)
-
argocd_repository.private_ssh_repo (resource)
-
null_resource.dependencies (resource)
-
null_resource.this (resource)
-
utils_deep_merge_yaml.values (data source)
Required Inputs
The following input variables are required:
argocd_namespace
Description: Namespace used by Argo CD where the Application and AppProject resources should be created.
Type: string
source_repo_path
Description: Path for the application’s chart in the source repository.
Type: string
Optional Inputs
The following input variables are optional (have default values):
app_autosync
Description: Automated sync options for the Argo CD Application resource.
Type:
object({
allow_empty = optional(bool)
prune = optional(bool)
self_heal = optional(bool)
})
Default:
{
"allow_empty": false,
"prune": true,
"self_heal": true
}
dependency_ids
Description: IDs of the other modules on which this module depends on.
Type: map(string)
Default: {}
destination_namespace
Description: Namespace where the application will be deployed. By default it is the same as the application’s name defined by var.name
. We use a ternary operator to conditionally define the Namespace only if it is defined on the module’s instantiation: namespace = var.destination_namespace == null ? var.name : var.destination_namespace
.
Type: string
Default: null
helm_values
Description: Helm values, passed as a list of HCL structures. These values are concatenated with the default ones and then passed to the application’s charts.
Type: any
Default: []
project_cluster_resource_whitelist
Description: Cluster-scoped resources allowed to be deployed in the Argo CD AppProject created by the module. The group
must be a Kubernetes API group such as core
or apps
and the kind
must be a Kubernetes Kinds/Object Schemas such as Namespace
or ClusterRole
(note that only resources like these ones are compatible with this setting, the other resources are only Namespace-scoped). You can see the API Groups here.
Type:
list(object({
group = string
kind = string
}))
Default:
[
{
"group": "*",
"kind": "*"
}
]
project_namespace_resource_whitelist
Description: Namespace-scoped resources allowed to be deployed in the Argo CD AppProject created by the module. The group
must be a Kubernetes API group such as core
or apps
and the kind
must be a Kubernetes Kinds/Object Schemas such as Pod
, ConfigMap
, DaemonSet
, Deployment
, etc. You can see the API Groups here.
Type:
list(object({
group = string
kind = string
}))
Default:
[
{
"group": "*",
"kind": "*"
}
]
source_credentials_https
Description: Credentials to connect to a private repository. Use this variable when connecting through HTTPS. You’ll need to provide the the username
and password
values. If the TLS certificate for the HTTPS connection is not issued by a qualified CA, you can set https_insecure
as true.
Type:
object({
username = string
password = string
https_insecure = bool
})
Default:
{
"https_insecure": false,
"password": null,
"username": null
}
source_credentials_ssh_key
Description: Credentials to connect to a private repository. Use this variable when connecting to a repository through SSH.
Type: string
Default: null
Outputs
The following outputs are exported:
id
Description: ID to pass other modules in order to refer to this module as a dependency.
Reference in table format
Show tables
= Requirements
Name | Version |
---|---|
>= 4 |
|
>= 1 |
= Providers
Name | Version |
---|---|
>= 4 |
|
n/a |
|
>= 1 |
= Resources
Name | Type |
---|---|
resource |
|
resource |
|
resource |
|
resource |
|
resource |
|
resource |
|
data source |
= Inputs
Name | Description | Type | Default | Required |
---|---|---|---|---|
Automated sync options for the Argo CD Application resource. |
|
|
no |
|
Namespace used by Argo CD where the Application and AppProject resources should be created. |
|
n/a |
yes |
|
IDs of the other modules on which this module depends on. |
|
|
no |
|
Namespace where the application will be deployed. By default it is the same as the application’s name defined by |
|
|
no |
|
Helm values, passed as a list of HCL structures. These values are concatenated with the default ones and then passed to the application’s charts. |
|
|
no |
|
Name to give the to the AppProject and Application. |
|
n/a |
yes |
|
Cluster-scoped resources allowed to be deployed in the Argo CD AppProject created by the module. The |
|
|
no |
|
Namespace-scoped resources allowed to be deployed in the Argo CD AppProject created by the module. The |
|
|
no |
|
Credentials to connect to a private repository. Use this variable when connecting through HTTPS. You’ll need to provide the the |
|
|
no |
|
Credentials to connect to a private repository. Use this variable when connecting to a repository through SSH. |
|
|
no |
|
Repository where to retrieve the application’s chart. |
|
n/a |
yes |
|
Path for the application’s chart in the source repository. |
|
n/a |
yes |
|
Git target revision for the application chart. |
|
n/a |
yes |
= Outputs
Name | Description |
---|---|
ID to pass other modules in order to refer to this module as a dependency. |