Skip to content

Commit

Permalink
Send Application Sync request to Argo CD Server (#44)
Browse files Browse the repository at this point in the history
* Add initial skeleton of app syncing code

* Create Argo CD clients on startup

* Formatting and variable naming updates

* Regen go.sum

* Restructure code to mock Argo CD client

* Return synced applications

* Fix configuration loading bug

* Add tests related to app sync

* Add mutex to mocked argocd app client

* Automatically create .prcconfig directory to run locally

* Add .prcconfig to .gitignore

* Adopt shellcheck recommendations

* Use mutex in mocked argocd app client

* Set up ability to run locally with env variables

* Reenable leader election

* Update README with information on configuration

* Update main.go

Co-authored-by: Sebastien Le Digabel <[email protected]>

* Address review comments

* Reset prog rollout definition to use v1beta1

* Address review comments

* Address review comments around configuration

* Move to mocks to mocks package

* Remove leftover generatorOptions

* Update README

* Update internal/utils/config.go

Co-authored-by: Matteo Ruina <[email protected]>

* Add config secret to helm chart

* Base 64 encode secrets

* Bump Helm chart version

* Merge controller test files

Co-authored-by: Sebastien Le Digabel <[email protected]>
Co-authored-by: Matteo Ruina <[email protected]>
  • Loading branch information
3 people authored Apr 5, 2021
1 parent f526010 commit 42c9374
Show file tree
Hide file tree
Showing 20 changed files with 456 additions and 76 deletions.
83 changes: 76 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,91 @@ Expect a non-functional controller and breaking changes until Milestone 2 is com

See [CONTRIBUTING.md](./CONTRIBUTING.md)

## Configuration

The controller connects to an Argo CD server and requires configuration to do so:
```
ARGOCD_AUTH_TOKEN: <token of the Argo CD user>
ARGOCD_SERVER_ADDR: <address of the Argo CD server>
ARGOCD_INSECURE: <true/false>
```

The above configuration is loaded taking into account the following priority order:

1. Environment Variables.


```
ARGOCD_AUTH_TOKEN=ey...
ARGOCD_SERVER_ADDR=argocd-server
ARGOCD_INSECURE=true
```
2. Files in the Config Directory (`/etc/prc-config/`).
```
/etc/
├── prcconfig/
│ ├── ARGOCD_AUTH_TOKEN # file content: ey...
│ ├── ARGOCD_SERVER_ADDR # file content: argocd-server
│ ├── ARGOCD_INSECURE # file content: true
```
If at least one of the options is missing, the controller will **fail** to start.
## Development
### Local development with Kubebuilder
To get the controller running against the configured Kubernetes cluster in ~/.kube/config, run:
```
```shell
make install
make run
```

Please remember the `ARGOCD_AUTH_TOKEN`, `ARGOCD_SERVER_ADDR` and `ARGOCD_INSECURE` environment variables need to be present in order
to run against a Kubernetes cluster with Argo CD. If the cluster was configured using the `hack/setup-dev.sh` script,
these variables are part of the `.env.local` file.


### Deploying to a Kubernetes cluster

To deploy the controller to a Kubernetes cluster, run:
```shell
make install
make docker-build
make deploy
```

In order to do so, the target cluster needs to have a secret named `prc-config` containing the three necessary
variables: `ARGOCD_AUTH_TOKEN`, `ARGOCD_SERVER_ADDR` and `ARGOCD_INSECURE`. If using the dev environment
in the following section, this secret has already been created.

If using `kind` clusters, docker images need to be loaded manually using `kind load docker-image <image>:<version> --name <cluster-name>`.

#### Configuration Secret

Here's a sample secret of the necessary configuration:

```yaml
apiVersion: v1
data:
ARGOCD_AUTH_TOKEN: ey...
ARGOCD_INSECURE: true
ARGOCD_SERVER_ADDR: argocd-server
kind: Secret
metadata:
name: prc-config
namespace: argocd
type: Opaque
```
### Setting up dev environment
To facilitate local debugging and testing against real clusters, you may run:
```
```shell
bash hack/install-dev-deps.sh
bash hack/setup-dev.sh [argocd-version] [appset-version]
make install
Expand All @@ -89,12 +158,12 @@ After running the script, you will have 3 kind clusters created locally:
- `kind-prc-cluster-1` and `kind-prc-cluster-2` - are the target clusters for deploying the apps to.

This gives us a total of 3 clusters allowing us to play with multiple stages of deploying. It will also log you in argocd cli. You can find additional login details in `.env.local` file that will be generated for your convenience.

#### Regenerating your access
#### Regenerating your access

In case that your access to the local argocd has become broken, you can regenerate it by running

```
```shell
bash hack/login-argocd-local.sh
```

Expand All @@ -104,7 +173,7 @@ After running the script, you will have 3 kind clusters created locally:
#### Registering additional clusters

If you want to create additional clusters, you can do so by running
```
```shell
bash hack/add-cluster <cluster-name> <recreate>
```
This will spin up another kind cluster and register it against ArgoCD running in `kind-argocd-control-plane`
Expand All @@ -113,7 +182,7 @@ After running the script, you will have 3 kind clusters created locally:

You can deploy a test appset to the default 3 clusters by running the following:

```
```shell
bash hack/deploy-test-appset.sh
```
Feel free to extend the cluster generation section of the appset spec if you want to deploy it clusters that you have manually created.
Expand Down
2 changes: 1 addition & 1 deletion charts/argocd-progressive-rollout/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ type: application
# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.1-prealpha
version: 0.1.2-prealpha

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
Expand Down
2 changes: 2 additions & 0 deletions charts/argocd-progressive-rollout/ci/test-values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
configSecret:
argoCDAuthToken: "citoken"
9 changes: 9 additions & 0 deletions charts/argocd-progressive-rollout/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "argocd-progressive-rollout.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "argocd-progressive-rollout.labels" . | nindent 4 }}
spec:
Expand All @@ -18,6 +19,10 @@ spec:
labels:
{{- include "argocd-progressive-rollout.selectorLabels" . | nindent 8 }}
spec:
volumes:
- name: prc-config
secret:
secretName: prc-config
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
Expand All @@ -43,6 +48,10 @@ spec:
protocol: TCP
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- mountPath: /etc/prcconfig
name: prc-config
readOnly: true
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand Down
1 change: 1 addition & 0 deletions charts/argocd-progressive-rollout/templates/psp.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
name: {{ template "argocd-progressive-rollout.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "argocd-progressive-rollout.labels" . | nindent 4 }}
annotations:
Expand Down
10 changes: 10 additions & 0 deletions charts/argocd-progressive-rollout/templates/secret.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
apiVersion: v1
kind: Secret
metadata:
name: prc-config
namespace: {{ .Release.Namespace }}
type: Opaque
data:
ARGOCD_AUTH_TOKEN: {{ required "An ArgoCD authentication token is required." .Values.configSecret.argoCDAuthToken | quote | b64enc }}
ARGOCD_SERVER_ADDR: {{ required "An ArgoCD server address is required." .Values.configSecret.argoCDServerAddr | quote | b64enc }}
ARGOCD_INSECURE: {{ required "An ArgoCD 'Insecure' flag is required." .Values.configSecret.argoCDInsecure | quote | b64enc }}
5 changes: 5 additions & 0 deletions charts/argocd-progressive-rollout/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,3 +62,8 @@ nodeSelector: {}
tolerations: []

affinity: {}

configSecret:
argoCDAuthToken: ""
argoCDServerAddr: "argocd-server"
argoCDInsecure: true
8 changes: 8 additions & 0 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ spec:
labels:
control-plane: controller-manager
spec:
volumes:
- name: prc-config
secret:
secretName: prc-config
containers:
- command:
- /manager
Expand All @@ -36,4 +40,8 @@ spec:
requests:
cpu: 100m
memory: 20Mi
volumeMounts:
- mountPath: /etc/prcconfig
name: prc-config
readOnly: true
terminationGracePeriodSeconds: 10
29 changes: 25 additions & 4 deletions controllers/progressiverollout_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ package controllers
import (
"context"
"fmt"

deploymentskyscannernetv1alpha1 "github.com/Skyscanner/argocd-progressive-rollout/api/v1alpha1"
"github.com/Skyscanner/argocd-progressive-rollout/internal/scheduler"
"github.com/Skyscanner/argocd-progressive-rollout/internal/utils"
applicationpkg "github.com/argoproj/argo-cd/pkg/apiclient/application"
argov1alpha1 "github.com/argoproj/argo-cd/pkg/apis/application/v1alpha1"
"github.com/go-logr/logr"
corev1 "k8s.io/api/core/v1"
Expand All @@ -37,13 +37,15 @@ import (
"sigs.k8s.io/controller-runtime/pkg/predicate"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
"strings"
)

// ProgressiveRolloutReconciler reconciles a ProgressiveRollout object
type ProgressiveRolloutReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Log logr.Logger
Scheme *runtime.Scheme
ArgoCDAppClient utils.ArgoCDAppClient
}

// +kubebuilder:rbac:groups=deployment.skyscanner.net,resources=progressiverollouts,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -95,8 +97,16 @@ func (r *ProgressiveRolloutReconciler) Reconcile(ctx context.Context, req ctrl.R
scheduledApps := scheduler.Scheduler(apps, stage)

for _, s := range scheduledApps {
// TODO: add sync method here
r.Log.Info("syncing app", "app", s)

_, err := r.syncApp(s.Name)

if err != nil {
if !strings.Contains(err.Error(), "another operation is already in progress") {
log.Error(err, "unable to sync app", "message", err.Error())
return ctrl.Result{}, err
}
}
}

if scheduler.IsStageFailed(apps, stage) {
Expand Down Expand Up @@ -304,3 +314,14 @@ func (r *ProgressiveRolloutReconciler) removeAnnotationFromApps(apps []argov1alp
}
return nil
}

// syncApp sends a sync request for the target app
func (r *ProgressiveRolloutReconciler) syncApp(appName string) (*argov1alpha1.Application, error) {
ctx := context.Background()

syncReq := applicationpkg.ApplicationSyncRequest{
Name: &appName,
}

return r.ArgoCDAppClient.Sync(ctx, &syncReq)
}
Loading

0 comments on commit 42c9374

Please sign in to comment.