Skip to content

Commit

Permalink
feat: ArgoCD support (#41)
Browse files Browse the repository at this point in the history
Co-authored-by: Kris Budde <[email protected]>
  • Loading branch information
Zebradil and kbudde authored Aug 19, 2023
1 parent 144f5fd commit e45d585
Show file tree
Hide file tree
Showing 20 changed files with 414 additions and 159 deletions.
1 change: 0 additions & 1 deletion cmd/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ func init() {
Short: "Render manifests",
Long: "Render manifests",
Run: func(cmd *cobra.Command, args []string) {

g := myks.New(".")

if err := g.Init(asyncLevel, targetEnvironments, targetApplications); err != nil {
Expand Down
22 changes: 13 additions & 9 deletions internal/myks/application.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,15 @@ const (
)

type Application struct {
// Name of the application
Name string
// Application prototype directory
Name string
Prototype string
// Environment

e *Environment
// YTT data files
yttDataFiles []string
cached bool
yttPkgDirs []string

argoCDEnabled bool
cached bool
yttDataFiles []string
yttPkgDirs []string
}

type HelmConfig struct {
Expand Down Expand Up @@ -84,8 +83,11 @@ func (a *Application) Init() error {
return err
}

type ArgoCD struct {
Enabled bool `yaml:"enabled"`
}
type Cache struct {
Enabled bool
Enabled bool `yaml:"enabled"`
}
type YttPkg struct {
Dirs []string `yaml:"dirs"`
Expand All @@ -96,12 +98,14 @@ func (a *Application) Init() error {
Cache Cache `yaml:"cache"`
YttPkg YttPkg `yaml:"yttPkg"`
}
ArgoCD ArgoCD `yaml:"argocd"`
}

err = yaml.Unmarshal(dataYaml, &applicationData)
if err != nil {
return err
}
a.argoCDEnabled = applicationData.ArgoCD.Enabled
a.cached = applicationData.Application.Cache.Enabled
a.yttPkgDirs = applicationData.Application.YttPkg.Dirs

Expand Down
110 changes: 110 additions & 0 deletions internal/myks/application_plugin_argocd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package myks

import (
"bytes"
_ "embed"
"path/filepath"
"text/template"

"github.com/rs/zerolog/log"
)

const ArgoCDStepName = "argocd"

//go:embed templates/argocd/application.ytt.yaml
var argocd_application_template []byte

const argocd_data_values_schema = `
#@data/values
---
argocd:
app:
name: "{{ .AppName }}"
source:
path: "{{ .AppPath }}"
repoURL: "{{ .RepoURL }}"
targetRevision: "{{ .TargetRevision }}"
`

func (a *Application) renderArgoCD() (err error) {
if !a.argoCDEnabled {
log.Debug().Msg(a.Msg(ArgoCDStepName, "ArgoCD is disabled"))
return
}

schemaFile, err := a.argoCDPrepareSchema()
if err != nil {
return
}

// 0. Global data values schema and library files are added later in the a.yttS call
// 1. Dynamyc ArgoCD data values
yttFiles := []string{schemaFile}
// 2. Collection of application main data values and schemas
yttFiles = append(yttFiles, a.yttDataFiles...)
// 3. Collection of environment argocd-specific data values and schemas, and overlays
yttFiles = append(yttFiles, a.e.collectBySubpath(filepath.Join("_env", a.e.g.ArgoCDDataDirName))...)
// 4. Collection of application argocd-specific data values and schemas, and overlays
yttFiles = append(yttFiles, a.e.collectBySubpath(filepath.Join("_apps", a.Name, a.e.g.ArgoCDDataDirName))...)

res, err := a.yttS(
"argocd",
"create ArgoCD application yaml",
yttFiles,
bytes.NewReader(argocd_application_template),
)
if err != nil {
log.Error().Err(err).
Str("stdout", res.Stdout).
Str("stderr", res.Stderr).
Msg(a.Msg("argocd", "failed to render ArgoCD Application yaml"))
return
}

filepath := filepath.Join(a.getArgoCDDestinationDir(), "app-"+a.Name+".yaml")
err = writeFile(filepath, []byte(res.Stdout))
if err != nil {
return
}

return
}

func (a *Application) argoCDPrepareSchema() (filename string, err error) {
const name = "argocd_data_schema.ytt.yaml"

tmpl, err := template.New(name).Parse(string(argocd_data_values_schema))
if err != nil {
return
}

type Data struct {
AppName string
AppPath string
RepoURL string
TargetRevision string
}

data := Data{
AppName: a.Name,
AppPath: a.getDestinationDir(),
RepoURL: a.e.g.GitRepoUrl,
TargetRevision: a.e.g.GitRepoBranch,
}

buf := &bytes.Buffer{}
err = tmpl.Execute(buf, data)
if err != nil {
return
}

err = a.writeTempFile(name, buf.String())

filename = a.expandTempPath(name)

return
}

func (a *Application) getArgoCDDestinationDir() string {
return filepath.Join(a.e.g.RootDir, a.e.g.RenderedDir, "argocd", a.e.Id)
}
79 changes: 53 additions & 26 deletions internal/myks/assets/data-schema.ytt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,51 @@
---
#! Add here any application-specific data.
application: {}
argocd:
enabled: true
#! Namespace of the ArgoCD server.
namespace: argocd
app:
#! If not set, the name of the currently rendered application is used.
name: ""
#! Prefix of the ArgoCD application name.
prefix: ""
destination:
#! spec.destination.name of the ArgoCD application.
#! If not set, defaults to the name of the current environment.
name: ""
#! spec.destination.server of the ArgoCD application.
#! If set, used instead of spec.destination.name.
server: ""
#! spec.destination.namespace of the ArgoCD application.
#! If not set, defaults to argocd.app.name.
namespace: ""
source:
#! spec.source.path of the ArgoCD application.
#! If not set, defaults to the destination path of the currently rendered application.
#! With the default myks configuration: `rendered/envs/<environment.id>/<app.name>`
path: ""
#! spec.source.repoURL of the ArgoCD application.
#! If not set, defaults to the current git repository URL.
repoURL: ""
#! spec.source.targetRevision of the ArgoCD application.
#! If not set, defaults to the current git branch.
targetRevision: ""
env:
#! If not set, the name of the currently rendered environment is used (environment.id).
name: ""
#! Prefix of a target cluster name.
prefix: ""
#! If set to true, a dummy secret is generated for the target cluster.
#! The user has to create an overlay to set correct values for the secret.
#! See https://argo-cd.readthedocs.io/en/release-2.8/operator-manual/declarative-setup/#clusters
#! TODO: add link to the example overlay.
generateSecret: true
project:
#! If not set, the name of the currently rendered environment is used (environment.id).
name: ""
#! Prefix of the ArgoCD project name.
prefix: ""
environment:
#! Unique identifier of the environment, required by myks.
#@schema/validation min_len=1
Expand All @@ -23,6 +68,10 @@ environment:
#! Configuration of the step that renders Helm charts.
helm:
#! Used by myks.
#! If defined, passed as `--api-version` for `helm-template`.
capabilities:
- "" #! e.g. "monitoring.coreos.com/v1"
#! Used by myks.
#! If true, adds `--include-crds` flag to `helm template`.
includeCRDs: true
#! Used by myks.
Expand All @@ -31,33 +80,11 @@ helm:
#! Used by myks.
#! If defined, passed as a value of `--namespace` for `helm template`.
namespace: ""
#! Used by myks.
#! If defined, passed as `--api-version` for `helm-template`.
capabilities:
- "" #! e.g. "monitoring.coreos.com/v1"
#! Myks configuration and runtime data.
myks:
applicationDataFileName: ""
applicationNames: [""]
dataSchemaFileName: ""
environmentBaseDir: ""
environmentDataFileName: ""
#! Set by myks.
#! Set to the current git branch if available.
gitRepoBranch: ""
#! Set by myks.
#! Set to the current git repository URL if available.
gitRepoUrl: ""
helmChartsDirName: ""
myksDataFileName: ""
namespacePrefix: ""
prototypesDir: ""
renderedDir: ""
renderedEnvironmentDataFileName: ""
rootDir: ""
searchPaths: [""]
serviceDirName: ""
tempDirName: ""
vendirConfigFileName: ""
vendirLockFileName: ""
vendirSyncFileName: ""
vendorDirName: ""
yttLibraryDirName: ""
yttPkgStepDirName: ""
yttStepDirName: ""
12 changes: 12 additions & 0 deletions internal/myks/assets/envs/_env/argocd/annotations.overlay.ytt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#@ load("@ytt:overlay", "overlay")
#@ load("@ytt:data", "data")

#! Match all ArgoCD resources: Application, AppProject, Secret.
#@overlay/match by=overlay.all, expects="1+"
---
#@overlay/match missing_ok=True
#@overlay/match-child-defaults missing_ok=True
metadata:
annotations:
myks.dev/environment: #@ data.values.environment.id
app.kubernetes.io/source: #@ data.values.myks.gitRepoUrl
15 changes: 15 additions & 0 deletions internal/myks/assets/envs/_env/argocd/secret.overlay.ytt.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#@ load("@ytt:overlay", "overlay")
---
#@ def secret_fragment():
kind: Secret
metadata:
labels:
argocd.argoproj.io/secret-type: cluster
#@ end

#@overlay/match by=overlay.subset(secret_fragment()), expects="0+"
---
#! See https://argo-cd.readthedocs.io/en/release-2.8/operator-manual/declarative-setup/#clusters
stringData:
config: ARGOCD_CLUSTER_CONNECT_CONFIG
server: ARGOCD_CLUSTER_SERVER_URL
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#@ load("@ytt:overlay", "overlay")

#@overlay/match by=overlay.subset({"kind": "Application"})
---
spec:
syncPolicy:
automated:
#! Disable self-healing of the application to allow manual changes.
selfHeal: false
1 change: 0 additions & 1 deletion internal/myks/assets/envs/mykso/dev/env-data.ytt.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@ environment:
id: mykso-dev
applications:
- proto: argocd
- proto: argocd-apps
- proto: httpbingo
10 changes: 0 additions & 10 deletions internal/myks/assets/prototypes/argocd-apps/app-data.ytt.yaml

This file was deleted.

57 changes: 0 additions & 57 deletions internal/myks/assets/prototypes/argocd-apps/ytt/all.ytt.yaml

This file was deleted.

Loading

0 comments on commit e45d585

Please sign in to comment.