Loading...
Loading...
A skill for creating new addons for Kubernetes deployments using the Mojaloop addon structure.
npx skill4agent add infitx-org/agent-skills addon-creatorapp-yamls/*.yamldefault.yamladdons/
└── <app-name>/
├── .config/
│ └── <app-name>.yaml # App configuration (REQUIRED)
├── <app-name>.app.yaml # ArgoCD Application definition (REQUIRED)
├── kustomization.yaml # Kustomize manifest (REQUIRED)
├── values-default.yaml # Default Helm values (if using Helm)
├── values-override.yaml # Template for env-specific overrides (if using Helm)
├── vs.yaml # Virtual Service for ingress (optional)
├── <resource>.yaml # Additional K8s resources
├── README.md # Documentation (recommended)
└── <subfolder>/ # Optional: misc files without templating.config/<app-name>.yaml<app-name>.app.yaml${app.*}.config/<app-name>.yamldefault.yamlapp-yamls/addons/
├── app-yamls/
│ └── <app-name>.yaml # ArgoCD Application (OLD - deprecated)
├── default.yaml # Global configuration (OLD - deprecated)
└── <app-name>/
├── kustomization.yaml
├── deployment.yaml
└── ...default.yamlapp-yamls/redis-insightmongo-expresscloud-beaverredis-insightchaos-meshmongo-expressapp-yamls/default.yaml/home/kalin/work/deploy/addons-dev/mkdir -p <app-name>/.config
cd <app-name><app-name>/
├── .config/
│ └── <app-name>.yaml # Start here
├── <app-name>.app.yaml # Then create this
├── kustomization.yaml # Then this
└── ... other resources.config/<app-name>.yaml${app.<field>}.config/<app-name>.yaml# .config/<app-name>.yaml
enabled: true
version: <chart-version> # For Helm charts
tag: <image-tag> # For container images
namespace: <app-name> # Default namespace
syncWave: 0 # ArgoCD sync wave (use negative for dependencies)
values: {} # Helm chart value overridesenabledversiontagnamespacesyncWavevaluesimage# chaosmesh
enabled: true
version: 2.7.0
namespace: chaosmesh
syncWave: 0
values: {}# cloud-beaver
enabled: true
image: dbeaver/cloudbeaver:25.0.4
namespace: cloud-beaver
syncWave: 0
secrets:
account-lookup: common-mojaloop-db-secret
central-ledger: common-mojaloop-db-secret# k6
enabled: true
version: 3.9.0
namespace: k6
syncWave: 0
prometheusEndpoint: http://prom-kube-prometheus-stack-prometheus.monitoring.svc.cluster.local:9090/api/v1/write
values: {}<app-name>.app.yaml# <app-name>.app.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
annotations:
argocd.argoproj.io/sync-wave: "${app.syncWave}"
name: ${app.name}
namespace: argocd
finalizers:
- resources-finalizer.argocd.argoproj.io
spec:
source:
path: apps/${app.name}
repoURL: ${cluster.gitlabProjectUrl}
targetRevision: HEAD
kustomize:
commonAnnotations:
addons-dev: ${app.name}
destination:
namespace: ${app.namespace}
server: https://kubernetes.default.svc
project: default
ignoreDifferences:
- group: batch
kind: CronJob
jsonPointers:
- /spec/suspend
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 5
backoff:
duration: 5s
maxDuration: 3m0s
factor: 2
syncOptions:
- CreateNamespace=true
- PrunePropagationPolicy=background
- PruneLast=truepathrepoURL${cluster.gitlabProjectUrl}destination.namespace${app.namespace}syncWave${app.syncWave}syncPolicy.automatedsyncOptionskustomization.yamlapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- vs.yaml # Optional: if app has ingress
- <additional-resources>.yaml
helmCharts:
- name: <chart-name>
releaseName: <release-name>
version: ${app.version}
repo: https://<chart-repo-url>
valuesFile: values-default.yaml
namespace: <app-name>
includeCRDs: true
additionalValuesFiles:
- values-override.yamlapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- vs.yaml
- k6-test-als-configmap.yaml
- kronic.yaml
helmCharts:
- name: k6-operator
releaseName: k6-operator
version: ${app.version}
repo: https://grafana.github.io/helm-charts
valuesFile: values-default.yaml
namespace: k6
includeCRDs: true
additionalValuesFiles:
- values-override.yamlapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
- vs.yaml
- external-secret.yaml
- pvc.yaml
configMapGenerator:
- name: <app-name>
files:
- config-file.confapiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- external-secret.yaml
- password-policy.yaml
- pvc.yaml
- random-secret.yaml
- service.yaml
- vault-secret.yaml
- vs.yaml
configMapGenerator:
- name: cloud-beaver
files:
- cloudbeaver.conf
- initial-data-sources.conf# values-default.yaml
image:
tag: ${app.tag}
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# App-specific configuration
config:
option1: value1
option2: value2chaosDaemon:
runtime: containerd
socketPath: /var/snap/microk8s/common/run/containerd.sockimage:
tag: ${app.tag}
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 50m
memory: 64Mi
serverBlock: |-
server {
listen 8080;
server_name _;
location / {
root /app;
index index.html;
}
}# values-override.yaml
# Environment-specific overrides can be added here
# These typically come from custom-config/<app-name>.yaml
# Example structure (commented out by default):
# ${app.values}apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: <app-name>
spec:
gateways:
- istio-ingress-int/internal-wildcard-gateway
hosts:
- <app-name>.int.${cluster.env}.${cluster.domain}
http:
- match:
- uri:
prefix: /
route:
- destination:
host: <app-name>
port:
number: 80apiVersion: apps/v1
kind: Deployment
metadata:
name: <app-name>
labels:
app: <app-name>
spec:
replicas: 1
selector:
matchLabels:
app: <app-name>
template:
metadata:
labels:
app: <app-name>
spec:
containers:
- name: <app-name>
image: ${app.image}
imagePullPolicy: IfNotPresent
resources:
limits:
cpu: 1000m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
ports:
- containerPort: 8080
name: httpapiVersion: v1
kind: Service
metadata:
name: <app-name>
spec:
selector:
app: <app-name>
ports:
- name: http
port: 80
targetPort: 8080
type: ClusterIPapiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: <app-name>
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Giapp.*${app.enabled}${app.namespace}${app.syncWave}${app.version}${app.tag}${app.image}${app.values}${app.<custom-field>}cluster.*${cluster.gitlabProjectUrl}${cluster.env}${cluster.domain}${cluster.domainSuffix}${cluster.cc}${cluster.sc}${cluster.cloud_platform}apps.*${apps.<other-app-name>.<field>}%{ if condition }%{ endif }%{ for item in list }%{ endfor }custom-config/<app-name>.yaml# custom-config/<app-name>.yaml
enabled: true # Enable the app
namespace: custom-ns # Override namespace
syncWave: 5 # Override sync wave
version: 2.0.0 # Override chart version
tag: custom-tag # Override image tag
values: # Helm chart overrides
resources:
limits:
cpu: 2000m
memory: 1Gi# Navigate to the addon directory
cd <addon-name>/<app-name>
# Validate kustomization
kustomize build .
# Check for template syntax (if using envsubst or similar)
# Set required variables
export app='{"enabled": true, "namespace": "test", "syncWave": "0", "version": "1.0.0"}'
export cluster='{"gitlabProjectUrl": "https://git.example.com/repo", "env": "dev", "domain": "example.com"}'
# Test ArgoCD application rendering (requires gomplate or similar)
gomplate -f <app-name>.app.yamlcustom-config/<app-name>.yamlenabled: truekubectl get applications -n argocdkubectl get all -n <namespace>.config/<app-name>.yaml<app-name>.app.yamlkustomization.yamlvalues-default.yamlvalues-override.yaml.config/<app-name>.yaml<app-name>.app.yamlkustomization.yamldeployment.yamlservice.yamlvs.yaml.config/<app-name>.yaml<app-name>.app.yamlkustomization.yamlcronjob.yaml.config/<app-name>.yaml<app-name>.app.yamlkustomization.yamlvalues-default.yaml.config/<app-name>.yaml<app>.int.<env>.<domain>values-default.yamlvalues-override.yaml.app.yamlapp.enabled${...}.app.yamlCreateNamespace=true.config/<app-name>.app.yamldefault.yamlapp-yamls/app-yamls/# WRONG - do not do this:
app-yamls/my-new-app.yamldefault.yaml# WRONG - do not add to default.yaml:
my-new-app:
image: my-image:latest
...# WRONG - old structure pattern:
image: ${my-app.image}# CORRECT:
<app-name>/<app-name>.app.yaml.config/<app-name>.yaml# CORRECT - in .config/<app-name>.yaml:
enabled: true
image: my-image:latest
namespace: my-app
syncWave: 0${app.*}# CORRECT - references .config/<app-name>.yaml:
image: ${app.image}
namespace: ${app.namespace}.config/mongo-express/
├── .config/
│ └── mongo-express.yaml # Configuration here
├── mongo-express.app.yaml # App definition here
├── kustomization.yaml
├── deployment.yaml
├── service.yaml
├── vs.yaml
└── README.md${app.image}${app.mongoUrl}app-yamls/
└── mongo-express.yaml # App definition (OLD location)
default.yaml # Configuration (OLD location)
mongo-express/
├── kustomization.yaml
├── deployment.yaml
└── service.yaml${mongo-express.image}