Skip to content

Commit

Permalink
feat: Bootstrap Mage Kubernetes library
Browse files Browse the repository at this point in the history
* 1:1 Copies what is in the engineering kubernetes image (https://github.com/coopnorge/engineering-docker-images/tree/main/images/devtools-kubernetes-v1beta1/context/magefiles)
* Modify it to make it a library
* Make it validate using golang devtools

next up is adding features/tests
  • Loading branch information
AtzeDeVries committed Dec 6, 2023
1 parent 66248d0 commit bd3fe1a
Show file tree
Hide file tree
Showing 64 changed files with 2,178 additions and 0 deletions.
41 changes: 41 additions & 0 deletions .github/workflows/cicd.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
on:
pull_request: {}
push:
branches:
- main
jobs:
go-ci:
name: Go CI
runs-on: ubuntu-latest
env:
docker-compose-service: golang-devtools
XDG_CACHE_HOME: ${{ github.workspace }}/.cache/xdg
steps:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- id: xdg_cache_hash
run: echo "xdg_cache_hash=${{hashFiles('./docker-compose.yml', './docker-compose/Dockerfile', './go.sum')}}" >> $GITHUB_OUTPUT
- name: Cache xdg
uses: actions/cache@v3
with:
path: ${{ env.XDG_CACHE_HOME }}
key: xdg-${{ github.repository }}-${{ github.job }}-${{ steps.xdg_cache_hash.outputs.xdg_cache_hash }}
restore-keys: |
xdg-${{ github.repository }}-${{ github.job }}-${{ steps.xdg_cache_hash.outputs.xdg_cache_hash }}
xdg-${{ github.repository }}-${{ github.job }}-
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Configure access to internal and private GitHub repos
run: git config --global url."https://${{ secrets.REVIEWBOT_GITHUB_TOKEN }}:[email protected]/coopnorge".insteadOf "https://github.com/coopnorge"
- name: Build devtools
run: docker compose build
- name: Validate
run: docker compose run --rm ${{ env.docker-compose-service }} validate VERBOSE=all
1 change: 1 addition & 0 deletions .pallet/gitconfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ spec:
requiredStatusChecks:
checks:
- "policy-bot: main"
- "Go CI"
strict: false
requiredPullRequestReviews:
requiredApprovingReviewCount: 0
Expand Down
112 changes: 112 additions & 0 deletions argocd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package magekubernetes

import (
"fmt"
"os"
"strings"

"github.com/magefile/mage/sh"
"gopkg.in/yaml.v3"
)

// ArgoCDAppHelm contains the info for rendering a helm file
type ArgoCDAppHelm struct {
ReleaseName string `yaml:"releaseName"`
ValueFiles []string `yaml:"valueFiles"`
}

// ArgoCDAppSource contains the info where to find the source for rendering
type ArgoCDAppSource struct {
Helm ArgoCDAppHelm `yaml:"helm"`
Path string `yaml:"path"`
}

// ArgoCDAppSpec contains the app source
type ArgoCDAppSpec struct {
Source ArgoCDAppSource `yaml:"source"`
}

// ArgoCDAppMetadata contains the app name
type ArgoCDAppMetadata struct {
Name string `yaml:"name"`
}

// ArgoCDApp contains the spec and metadata of an app
type ArgoCDApp struct {
Spec ArgoCDAppSpec `yaml:"spec"`
Metadata ArgoCDAppMetadata `yaml:"metadata"`
}

func getArgoCDDeployments(repoURL string) ([]ArgoCDApp, error) {
var argoCDAppList []ArgoCDApp
env := map[string]string{}

if token, ok := os.LookupEnv("ARGOCD_API_TOKEN"); ok {
server, ok := env["ARGOCD_SERVER_NAME"]
if !ok {
return nil, fmt.Errorf("When using ARGOCD_API_TOKEN, you are also required to set ARGOCD_SERVER_NAME")
}
env["ARGOCD_API_TOKEN"] = token
env["ARGOCD_SERVER_NAME"] = server
} else {
err := sh.Run("argocd", "context")
if err != nil {
fmt.Println("Make use $HOME/.argocd is correctly mounted or use ARGOCD_API_TOKEN env var")
return nil, err
}
}

appYaml, err := sh.OutputWith(env, "argocd", "--grpc-web", "app", "list", "-r", repoURL, "-o", "yaml")
if err != nil {
return nil, err
}
err = yaml.Unmarshal([]byte(appYaml), &argoCDAppList)
if err != nil {
return nil, err
}
return argoCDAppList, nil
}

func getArgoCDDiff(apps []ArgoCDApp) error {
env := map[string]string{"KUBECTL_EXTERNAL_DIFF": "dyff between --omit-header"}
if token, ok := os.LookupEnv("ARGOCD_API_TOKEN"); ok {
env["ARGOCD_API_TOKEN"] = token
}
for _, app := range apps {
diff, err := sh.OutputWith(env, "argocd", "--loglevel", "error", "--grpc-web", "app", "diff", app.Metadata.Name, "--refresh", "--local", app.Spec.Source.Path)
if sh.ExitStatus(err) == 2 {
return err
}
fmt.Println("---- Diff of " + app.Metadata.Name + " ----")
fmt.Println(diff)
}
return nil
}

func listArgoCDDeployments() error {
repo, err := repoURL()
if err != nil {
return err
}
apps, err := getArgoCDDeployments(repo)
if err != nil {
return err
}
for _, trackedDeployment := range apps {
if trackedDeployment.Spec.Source.Helm.ReleaseName != "" {
fmt.Println("---")
fmt.Println("Found helm deployment with name: " + trackedDeployment.Metadata.Name)
fmt.Println(" path: " + trackedDeployment.Spec.Source.Path)
fmt.Println(" valueFiles: " + strings.Join(trackedDeployment.Spec.Source.Helm.ValueFiles, ", "))
} else if _, err := os.Stat(trackedDeployment.Spec.Source.Path + "/kustomize.yaml"); err == nil {
fmt.Println("---")
fmt.Println("Found kustomize deployment with name: " + trackedDeployment.Metadata.Name)
fmt.Println(" path: " + trackedDeployment.Spec.Source.Path)
} else {
fmt.Println("---")
fmt.Println("Found plain deployment with name: " + trackedDeployment.Metadata.Name)
fmt.Println(" path: " + trackedDeployment.Spec.Source.Path)
}
}
return nil
}
107 changes: 107 additions & 0 deletions coverage.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
mode: atomic
mage/argocd.go:40.64,44.55 3 0
mage/argocd.go:44.55,46.10 2 0
mage/argocd.go:46.10,48.4 1 0
mage/argocd.go:49.3,50.37 2 0
mage/argocd.go:51.8,53.17 2 0
mage/argocd.go:53.17,56.4 2 0
mage/argocd.go:59.2,60.16 2 0
mage/argocd.go:60.16,62.3 1 0
mage/argocd.go:63.2,64.16 2 0
mage/argocd.go:64.16,66.3 1 0
mage/argocd.go:67.2,67.27 1 0
mage/argocd.go:70.44,72.55 2 0
mage/argocd.go:72.55,74.3 1 0
mage/argocd.go:75.2,75.27 1 0
mage/argocd.go:75.27,77.30 2 0
mage/argocd.go:77.30,79.4 1 0
mage/argocd.go:80.3,81.20 2 0
mage/argocd.go:83.2,83.12 1 0
mage/argocd.go:86.36,88.16 2 0
mage/argocd.go:88.16,90.3 1 0
mage/argocd.go:91.2,92.16 2 0
mage/argocd.go:92.16,94.3 1 0
mage/argocd.go:95.2,95.41 1 0
mage/argocd.go:95.41,96.59 1 0
mage/argocd.go:96.59,101.4 4 0
mage/argocd.go:101.9,101.99 1 0
mage/argocd.go:101.99,105.4 3 0
mage/argocd.go:105.9,109.4 3 0
mage/argocd.go:111.2,111.12 1 0
mage/metadata.go:25.33,29.16 3 0
mage/metadata.go:29.16,32.3 2 0
mage/metadata.go:33.2,34.16 2 0
mage/metadata.go:34.16,37.3 2 0
mage/metadata.go:38.2,38.58 1 0
mage/metadata.go:41.32,43.16 2 0
mage/metadata.go:43.16,45.3 1 0
mage/metadata.go:46.2,46.46 1 0
mage/targets.go:12.23,14.16 2 0
mage/targets.go:14.16,16.3 1 0
mage/targets.go:17.2,20.12 4 0
mage/targets.go:24.24,26.16 2 0
mage/targets.go:26.16,28.3 1 0
mage/targets.go:29.2,29.29 1 0
mage/targets.go:33.26,35.16 2 0
mage/targets.go:35.16,37.3 1 0
mage/targets.go:38.2,38.31 1 0
mage/targets.go:42.29,44.16 2 0
mage/targets.go:44.16,46.3 1 0
mage/targets.go:47.2,47.12 1 0
mage/targets.go:51.25,53.16 2 0
mage/targets.go:53.16,55.3 1 0
mage/targets.go:56.2,57.16 2 0
mage/targets.go:57.16,59.3 1 0
mage/targets.go:60.2,61.16 2 0
mage/targets.go:61.16,63.3 1 0
mage/targets.go:64.2,64.12 1 0
mage/targets.go:67.36,71.16 3 2
mage/targets.go:71.16,74.3 2 1
mage/targets.go:75.2,76.12 2 1
mage/targets.go:79.38,87.16 3 2
mage/targets.go:87.16,90.3 2 1
mage/targets.go:91.2,92.12 2 1
mage/template.go:12.52,13.44 1 0
mage/template.go:13.44,15.3 1 0
mage/template.go:15.8,15.88 1 0
mage/template.go:15.88,17.3 1 0
mage/template.go:18.2,18.34 1 0
mage/template.go:21.57,23.16 2 2
mage/template.go:23.16,25.3 1 0
mage/template.go:26.2,27.16 2 2
mage/template.go:27.16,29.3 1 0
mage/template.go:30.2,31.16 2 2
mage/template.go:31.16,33.3 1 0
mage/template.go:34.2,36.16 3 2
mage/template.go:36.16,38.3 1 1
mage/template.go:39.2,43.16 2 1
mage/template.go:43.16,45.3 1 0
mage/template.go:46.2,47.16 2 1
mage/template.go:47.16,49.3 1 0
mage/template.go:50.2,50.17 1 1
mage/template.go:53.51,55.16 2 2
mage/template.go:55.16,57.3 1 0
mage/template.go:58.2,60.16 3 2
mage/template.go:60.16,62.3 1 1
mage/template.go:63.2,63.17 1 1
mage/template.go:68.40,71.16 3 0
mage/template.go:71.16,73.3 1 0
mage/template.go:74.2,75.16 2 0
mage/template.go:75.16,77.3 1 0
mage/template.go:78.2,78.41 1 0
mage/template.go:78.41,80.17 2 0
mage/template.go:80.17,82.4 1 0
mage/template.go:83.3,84.17 2 0
mage/template.go:84.17,86.4 1 0
mage/template.go:87.3,87.40 1 0
mage/template.go:89.2,89.38 1 0
mage/template.go:92.58,94.82 2 1
mage/template.go:94.82,95.20 1 4
mage/template.go:95.20,97.4 1 2
mage/template.go:98.3,98.13 1 4
mage/template.go:100.2,100.16 1 1
mage/template.go:100.16,102.3 1 0
mage/template.go:103.2,103.19 1 1
mage/template.go:106.32,108.16 2 5
mage/template.go:108.16,110.3 1 0
mage/template.go:111.2,111.17 1 5
23 changes: 23 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
services:
golang-devtools:
build:
context: docker-compose
target: golang-devtools
dockerfile: Dockerfile
privileged: false
command: validate
security_opt:
- seccomp:unconfined
- apparmor:unconfined
volumes:
- .:/srv/workspace:z
- ${DOCKER_CONFIG:-~/.docker}:/root/.docker
- ${GIT_CONFIG:-~/.gitconfig}:${GIT_CONFIG_GUEST:-/root/.gitconfig}
- ${SSH_CONFIG:-~/.ssh}:/root/.ssh
- ${XDG_CACHE_HOME:-xdg-cache-home}:/root/.cache
# ${x:-y} explained here https://www.gnu.org/software/bash/manual/html_node/Shell-Parameter-Expansion.html#:~:text=3.5.3%20Shell%20Parameter%20Expansion
environment:
GOMODCACHE: /root/.cache/go-mod
volumes:
xdg-cache-home: { }
nothing: { }
12 changes: 12 additions & 0 deletions docker-compose/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@

FROM docker.io/argoproj/argocd:v2.6.15@sha256:58ebb4ed23c8db4cd4cc3f954f8d94c4b4e3d9669c0751c484108d22b86d52de as argocd
FROM zegl/kube-score:v1.17.0@sha256:d4c34b9560d9ad35a5113fbbff6d798c87e6986a306ee097a0eb4242f9714810 as kube-score
FROM ghcr.io/yannh/kubeconform:v0.6.4@sha256:e68a0b638c6e9b76f1b7d58b4ec94340ef3b6601db25b2e40b29e3ac2d68e4bf as kubeconform

FROM ghcr.io/coopnorge/engineering-docker-images/e0/devtools-golang-v1beta1:latest@sha256:7726a5038270ece93360e3ec0c6928ef3813eb6b11007f18bab982d42c769f01 AS golang-devtools

COPY --from=kube-score /kube-score /usr/local/bin/kube-score
COPY --from=argocd /usr/local/bin/argocd /usr/local/bin/argocd
COPY --from=argocd /usr/local/bin/helm /usr/local/bin/helm
COPY --from=argocd /usr/local/bin/kustomize /usr/local/bin/kustomize
COPY --from=kubeconform /kubeconform /usr/local/bin/kubeconform
8 changes: 8 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module mage

go 1.20

require (
github.com/magefile/mage v1.15.0
gopkg.in/yaml.v3 v3.0.1
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
47 changes: 47 additions & 0 deletions metadata.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package magekubernetes

import (
"fmt"
"os"

"gopkg.in/yaml.v3"
)

// Annotations contains the github repo slug
type Annotations struct {
ProjectSlug string `yaml:"github.com/project-slug"`
}

// Metadata contains the annotations struct
type Metadata struct {
Annotations Annotations `yaml:"annotations"`
}

// CatalogInfo contains the metadata of this repo
type CatalogInfo struct {
Metadata Metadata `yaml:"metadata"`
}

func repoName() (string, error) {
var catalogInfo CatalogInfo

yamlFile, err := os.ReadFile("catalog-info.yaml")
if err != nil {
fmt.Printf("yamlFile.Get err #%v ", err)
return "", err
}
err = yaml.Unmarshal(yamlFile, &catalogInfo)
if err != nil {
fmt.Printf("Unmarshal: %v", err)
return "", err
}
return catalogInfo.Metadata.Annotations.ProjectSlug, nil
}

func repoURL() (string, error) {
repoName, err := repoName()
if err != nil {
return "", err
}
return "https://github.com/" + repoName, nil
}
Loading

0 comments on commit bd3fe1a

Please sign in to comment.