Skip to content

Commit

Permalink
feat: Git write-back of parameters (#133)
Browse files Browse the repository at this point in the history
* feat: Initial support for persisting changes in Git

Signed-off-by: jannfis <jann@mistrust.net>

* Fix unit test

Signed-off-by: jannfis <jann@mistrust.net>

* Fix up some stuff

Signed-off-by: jannfis <jann@mistrust.net>

* More tests and fix mocks

Signed-off-by: jannfis <jann@mistrust.net>

* Spellings

* Spellings

* Spellings

* Fix lint

Signed-off-by: jannfis <jann@mistrust.net>

* Disable GPG tests

* Typo

* Exclude ext code from tests
  • Loading branch information
jannfis committed Dec 20, 2020
1 parent 69fbb79 commit 4a7c10b
Show file tree
Hide file tree
Showing 17 changed files with 2,853 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .github/actions/spelling/allow.txt
Expand Up @@ -169,19 +169,23 @@ rlt
roadmap
rolebinding
rolebindings
rsa
RUnlock
semver
serviceaccount
Setenv
SHAs
sirupsen
someparam
somepassword
someuser
somevalue
sortmode
spf
Sprintf
src
SRCROOT
ssh
stderr
stdout
stretchr
Expand Down Expand Up @@ -221,6 +225,7 @@ Warnf
webkit
webroot
WORKDIR
workflow
workflows
www
yaml
Expand Down
1 change: 1 addition & 0 deletions .github/actions/spelling/excludes.txt
@@ -1,6 +1,7 @@
^\.github/
^go\.(?:sum|mod)$
\/mocks\/
^ext/
^hack\/
ignore$
\.png$
Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-tests.yaml
Expand Up @@ -70,6 +70,8 @@ jobs:
with:
go-version: '1.14.4'
- name: Run tests
env:
GNUPG_DISABLED: true
run: |
make test
- name: Upload code coverage information to codecov.io
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -48,7 +48,7 @@ mod-vendor:

.PHONY: test
test:
go test -coverprofile coverage.out `go list ./... | egrep -v '(test|mocks)'`
go test -coverprofile coverage.out `go list ./... | egrep -v '(test|mocks|ext/)'`

.PHONY: prereq
prereq:
Expand Down
168 changes: 168 additions & 0 deletions docs/configuration/applications.md
@@ -1,5 +1,7 @@
# Application configuration

## Marking an application for being updateable

In order for Argo CD Image Updater to know which applications it should inspect
for updating the workloads' container images, the corresponding Kubernetes
resource needs to be correctly annotated. Argo CD Image Updater will inspect
Expand Down Expand Up @@ -45,3 +47,169 @@ spec:
repoURL: https://github.com/argocd-example-apps/argocd-example-apps
targetRevision: HEAD
```

## Configuring the write-back method

The Argo CD Image Updater supports two distinct methods on how to update images
of an application:

* *imperative*, via Argo CD API
* *declarative*, by pushing changes to a Git repository

Depending on your setup and requirements, you can chose the write-back method
per Application, but not per image. As a rule of thumb, if you are managing
`Application` in Git (i.e. in an *app-of-apps* setup), you most likely want
to chose the Git write-back method.

The write-back method is configured via an annotation on the `Application`
resource:

```yaml
argocd-image-updater.argoproj.io/write-back-method: <method>
```

Where `<method>` must be one of `argocd` (imperative) or `git` (declarative).

The default used by Argo CD Image Updater is `argocd`.

### Using the Argo CD API write-back method

When using the Argo CD API to write back changes, Argo CD Image Updater will
perform a similar action as `argocd app set --parameter ...` to instruct
Argo CD to re-render the manifests using those parameters.

This method is pseudo-persistent. If you delete the `Application` resource
from the cluster and re-create it, changes made by Image Updater will be gone.
The same is true if you manage your `Application` resources using Git, and
the version stored in Git is synced over the resource in the cluster. This
method is most suitable for Applications also created imperatively, i.e.
using the Web UI or CLI.

This method is the default and requires no further configuration.

### Using the Git write-back method

!!!warning "Compatibility with Argo CD"
The Git write-back method requires a feature in Argo CD that is not yet
GA and will be released with Argo CD v1.9.

The `git` write-back method uses Git to permanently store its parameter
overrides along with the Application's resource manifests. This will enable
persistent storage of the parameters in Git.

By default, Argo CD Image Updater will store the parameter in a file named
`.argocd-source-<appName>.yaml` in the path used by the Application to source
its manifests from. This will allow Argo CD to pick up parameters in this
file, when rendering manifests for the Application named `<appName>`. Using
this approach will also minimize the possibility of merge conflicts, as long
as no other party in your CI will modify this file.

!!!note "A note on the application's target revision"
Due to the nature of how Git write-back works, your application really
should track a *branch* instead of a revision. If you track `HEAD`, a tag
or a certain revision with your application, you **must** override the
branch in an annotation (see below). But in order for Argo CD to pick up
the change after Image Updater has committed & pushed the change, you
really want to set it up so it tracks a branch.

To use the Git write-back method, annotate your `Application` with the right
write-back method:

```yaml
argocd-image-updater.argoproj.io/write-back-method: git
```

In order to better decide whether this method is suitable for your use-case,
this is the workflow how Argo CD Image Updater performs change to Git:

* Fetch the remote repository from location specified by `.spec.source.repoURL`
in the Argo CD Application manifest, using credentials specified as annotation
(see below)
* Check-out the target branch on the local copy. The target branch is either
taken from an annotation (see below), or if no annotation is set, taken from
`.spec.source.targetRevision` in the Application manifest
* Create or update `.argocd-source-<appName>.yaml` in the local repository
* Commit the changed file to the local repository
* Push the commit to the remote repository, using credentials specified as
annotation (see below)

The important pieces to this workflow are:

* Credentials configured in Argo CD will not be re-used, you have to supply a
dedicated set of credentials

* Write-back is a commit to the tracking branch of the Application. Currently,
Image Updater does not support creating a new branch or creating pull or
merge requests

* If `.spec.source.targetRevision` does not reference a *branch*, you will have
to specify the branch to use manually (see below)

#### General configuration

Configuration for the Git write-back method comes from two sources:

* The Argo CD `Application` manifest is used to define the repository and the
path where the `.argocd-source-<appName>.yaml` should be written to. These
are defined in `.spec.source.repoURL` and `.spec.source.path` fields,
respectively. Additionally, `.spec.source.targetRevision` is used to define
the branch to commit and push the changes to. The branch to use can be
overridden by an annotation, see below.

* A set of annotations on the `Application` manifest, see below

#### Specifying Git credentials

In order for Argo CD Image Updater to be able to push any changes back to your
Git repository (e.g. hosted on GitHub, GitLab or elsewhere), you will need to
configure credentials that have write access to your remote upstream repository.
Argo CD Image Updater will **not** re-use the credentials you have configured
in Argo CD for accessing the repository.

Credentials must be stored in a Kubernetes secret, which needs to be accessible
by the Argo CD Image Updater's Service Account. The secret can be configured
using the `argocd-image-updater.argoproj.io/git-credentials` annotation, whose
value must be in format `namespace/secret-name`, for example to use a secret
named `git-creds` in the namespace `argocd-image-updater`, use following
annotation:

```yaml
argocd-image-updater.argoproj.io/git-credentials: argocd-image-updater/git-creds
```

If the repository is accessed using HTTPS, the secret must contain two fields:
`username` which holds the Git username, and `password` which holds the user's
password or a private access token (PAT) with write access to the repository.
You can generate such a secret using `kubectl`, e.g.:

```bash
kubectl -n argocd-image-updater secret create generic git-creds \
--from-literal=username=someuser \
--from-literal=password=somepassword
```

If the repository is accessed using SSH, the secret must contain the field
`sshPrivateKey`, which holds a SSH private key in OpenSSH-compatible PEM
format. To create such a secret from an existing private key, you can use
`kubectl`, for example:

```bash
kubectl -n argocd-image-updater secret create generic git-creds \
--from-file=sshPrivateKey=~/.ssh/id_rsa
```

#### Specifying a branch to commit to

By default, Argo CD Image Updater will use the value found in the Application
spec at `.spec.source.targetRevision` as Git branch to checkout, commit to
and push back the changes it made. In some scenarios, this might not be what
is desired, and you can (and maybe have to) override the branch to use by
specifying the annotation `argocd-image-updater.argoproj.io/git-branch` on the
Application manifest.

The value of this annotation will define the Git branch to use, for example the
following would use GitHub's default `main` branch:

```yaml
argocd-image-updater.argoproj.io/git-branch: main
```

0 comments on commit 4a7c10b

Please sign in to comment.