__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
CLI tool for performing GitOps operations
NAME:
gitpos - GitOps CLI
USAGE:
gitpos [global options] command [command options] [arguments...]
COMMANDS:
secrets, s GitOps managed secrets
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--root-dir value root directory of the git repository [$GITOPS_ROOT_DIR]
--kubeconfig value, -k value kubeconfig file to use for connecting to the Kubernetes cluster [$KUBECONFIG, $GITOPS_KUBECONFIG]
--verbose, -v debug output (default: false) [$GITOPS_VERBOSE]
--very-verbose, --vv trace output (default: false) [$GITOPS_VERY_VERBOSE]
--cleartext print secrets in cleartext to the console (default: false) [$GITOPS_CLEARTEXT]
--print print secrets to the console (default: false) [$GITOPS_PRINT]
--help, -h show help
NOTE: It is expected, that the cluster's KUBECONFIG is already set up. Alternatively, the --kubeconfig
flag can be used.
gitops secrets plan kubernetes
Or in short
gitops s p k8s
Example output:
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
GitOps CLI computed the following changes for your cluster:
-------------------------------------------------------
default/my-config-map : add
+ data.loremIpsum: **************************************************
+ data.someConfigMapKey: **************
---
default/implicit-name : unchanged
---
default/my-secret-name : unchanged
---
default/database-credentials : change
~ data.bar: ** => **
-------------------------------------------------------
use gitops secrets apply kubernetes to apply these changes to your cluster
NOTE: It is expected, that the cluster's KUBECONFIG is already set up. Alternatively, the --kubeconfig
flag can be used.
gitops secrets apply kubernetes
Or in short
gitops s a k8s
The user will be prompted to confirm the changes before they are applied to the cluster. The prompt can be bypassed by using the --auto-approve
flag.
Example output:
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
GitOps CLI computed the following changes for your cluster:
-------------------------------------------------------
default/my-config-map : add
+ data.someConfigMapKey: **************
+ data.loremIpsum: **************************************************
---
default/implicit-name : unchanged
---
default/my-secret-name : unchanged
---
default/database-credentials : change
~ data.bar: ** => *****
-------------------------------------------------------
GitOps CLI will apply these changes to your Kubernetes cluster.
Only 'yes' will be accepted to approve.
Apply changes above: yes
GitOps CLI will now execute the changes for your cluster:
-------------------------------------------------------
default / my-config-map created
default / database-credentials updated
-------------------------------------------------------
All changes applied.
Redacted secrets (*********
) can be displayed in cleartext by using the --cleartext
flag.
To print all loaded secrets to the console, use the --print
flag.
Install using homebrew:
brew tap mxcd/gitops
brew install gitops
The GitOps CLI can handle secrets in a GitOps way. Either by injecting them directly as K8s secrets or by sending them to a vault instance for safekeeping. Either way, the secrets are stored in a Git repository and secured using SOPS.
Secrets are stored in any directory of your git repository. The GitOps CLI will pick
up any file that ends with *.gitops.secret.enc.y[a]ml
except for values.gitops.secret.enc.y[a]ml
(see Secrets Templating)
The secret files must be encrypted using SOPS.
NOTE: Secrets MUST NEVER be committed into version control unencrypted.
Therefore, it is very much encouraged to add the following lines to your .gitignore
file:
*.secret.yaml
*.secret.yml
*.secret.env
Make sure to follow a strict naming convention for your secret files, in order to keep them matching those patterns.
The secrets files must follow the following format:
# target of the secret
targetType: < k8s | vault >
# name of the secret
name: <my-secret-name>
# optional namespace of the secret (default: default)
namespace: <my-namespace>
# type of the secret (default: Opaque)
# only for k8s secrets: ConfigMap or any of the following: https://kubernetes.io/docs/concepts/configuration/secret/#secret-types
type: < ConfigMap | Opaque | ... >
# data of the secret as kv pairs
data:
<key1>: <value1>
<key2>: <value2>
# targetType of the secret
targetType: k8s
# name of the secret
name: my-secret-name
# optional namespace of the secret (default: default)
namespace: my-namespace
# type of the secret (default: Opaque)
type: Opaque
# data of the secret as kv pairs
data:
key: value
If the name is not given in the file, the name will be inferred from the filename. The file extension .gitops.secret.enc.y[a]ml
will be removed.
my-secret-name.gitops.secret.enc.yaml
# will be applied as
name: my-secret-name
This implies, that the filename must be a valid K8s secret name.
NOTE: Vault secrets are still WIP
# target of the secret
targetType: vault
# name of the secret - will be used as path in vault
name: /my/secret/name
# data of the secret as kv pairs
data:
key: value
It is possible to use Go templates in the secret files. The values will originate from sops-encrypted values.gitops.secret.enc.y[a]ml
files.
Values files can be located anywhere in the repository. The GitOps CLI will pick up all files that are located on the direct path towards the respective secret file.
Values files closer to the secret file will have higher precedence. Any object structure is allowed to be used in a values file.
Example:
# /foo/bar/dev/values.gitops.secret.enc.yaml
environment: dev
database:
host: localhost
port: 5432
user: postgres
password: postgres
# /foo/bar/dev/values.gitops.secret.enc.yaml
targetType: k8s
# name of the secret - will be used as path in vault
name: my-service
namespace: "{{ .Values.environment }}"
data:
application.properties: |-
service.environment={{ .Values.environment }}
spring.datasource.url=jdbc:postgresql://{{ .Values.database.host }}:{{ .Values.database.port }}/mydb
spring.datasource.username={{ .Values.database.user }}
spring.datasource.password={{ .Values.database.password }}
NOTE that the template string ({{ .Values.someValue }}
) must be enclosed in quotes for sops to work properly. In the above example, the entire application.properties
data value is considered as a string and thus does not need further quoting.
It is possible to address multiple clusters with a single GitOps repository.
To add a new cluster to the GitOps state use
gitops clusters add <cluster-name> <kubeconfig-path>
The kubeconfig file can either be a plain text file or a sops-encrypted file. If the file is encrypted, it must adhere to the following naming convention to be decrypted properly:
*.kubeconfig.secret.enc.ya?ml
To inspect the currently configured clusters use
gitops clusters list
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
dev => kubeconfigs/dev.kubeconfig.secret.enc.yml
int => kubeconfigs/int.kubeconfig.secret.enc.yml
prod => kubeconfigs/prod.kubeconfig.secret.enc.yml
To remove a cluster from the GitOps state use
gitops clusters remove <cluster-name>
To check connectivity with the configured clusters use
gitops clusters test
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
Cluster: __default (v1.25.3) Connected: true
Cluster: dev (v1.24.8) Connected: true
Cluster: int (v1.24.8) Connected: true
Cluster: prod (v1.24.8) Connected: true
A secret can be configured to be applied to a specific cluster using the target
attribute in the secret file. The default value is the __default
cluster which is inferred from the KUBECONFIG
environment variable or the default kubeconfig file. The target
attribute can also be set using a templating variable so that all secrets under a certain directory will be applied to a specific cluster.
# /foo/bar/dev/values.gitops.secret.enc.yaml
target: dev
# /foo/bar/dev/myservice/service.gitops.secret.enc.yaml
targetType: k8s
target: "{{ .Values.target }}" # will be replaced with "dev"
name: my-service
data:
key: value
By default, secrets will be applied to all configured clusters. This can be limited by giving the cluster as an argument:
gitops secrets plan kubernetes dev
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
Limiting to cluster dev
[Loading local secrets] 100% |██████████████████████████████████████████████████| (63/63)
No changes to apply.
It is possible to restrict the secrets input to a specific directory to speed up loading and decryption of secrets. This can be done by providing the --dir
flag:
gitops secrets --dir application/dev plan kubernetes
__ _ __
\ \ ____ _(_) /_____ ____ _____
\ \ / __ `/ / __/ __ \/ __ \/ ___/
/ / / /_/ / / /_/ /_/ / /_/ (__ )
/_/ \__, /_/\__/\____/ .___/____/
/____/ /_/
Limiting to directory applications/dev
[Loading local secrets] 100% |██████████████████████████████████████████████████| (1/1)
No changes to apply.
NOTE that the directory path must be relative to the repository root and that only forward slashes (/
) are supported.
Please make sure to follow conventional commits when committing to this repository.
To make one's life easier, a pre-commit config is provided that can be installed with the following command:
pre-commit install --hook-type commit-msg