diff --git a/.github/workflows/account-operator-crds.yaml b/.github/workflows/account-operator-crds.yaml new file mode 100644 index 000000000..f1155214c --- /dev/null +++ b/.github/workflows/account-operator-crds.yaml @@ -0,0 +1,28 @@ +name: Build account-operator-crds Workflow +on: + push: + paths: + - 'charts/account-operator-crds/**' + - '.github/workflows/account-operator-crds.yaml' + +jobs: + pipeline: + concurrency: + group: account-operator-crds-${{ github.ref }} + cancel-in-progress: true + uses: openmfp/gha/.github/workflows/pipeline-chart.yml@main + with: + chartFolder: charts + chartName: account-operator-crds + additionalTestFilesCommand: '' + chartRepos: 'bitnami=https://charts.bitnami.com/bitnami,openfga=https://openfga.github.io/helm-charts' + secrets: inherit + + updateVersionFile: + if: ${{ github.ref == 'refs/heads/main' }} + needs: [pipeline] + uses: openmfp/gha/.github/workflows/job-update-version-file.yml@main + secrets: inherit + with: + componentVersionKey: "account-operator-crds" + version: ${{ needs.pipeline.outputs.version }} diff --git a/.github/workflows/account-operator.yaml b/.github/workflows/account-operator.yaml new file mode 100644 index 000000000..ae256929a --- /dev/null +++ b/.github/workflows/account-operator.yaml @@ -0,0 +1,28 @@ +name: Build account-operator Workflow +on: + push: + paths: + - 'charts/account-operator/**' + - '.github/workflows/account-operator.yaml' + +jobs: + pipeline: + concurrency: + group: account-operator-${{ github.ref }} + cancel-in-progress: true + uses: openmfp/gha/.github/workflows/pipeline-chart.yml@main + with: + chartFolder: charts + chartName: account-operator + additionalTestFilesCommand: '' + chartRepos: 'bitnami=https://charts.bitnami.com/bitnami,openfga=https://openfga.github.io/helm-charts' + secrets: inherit + + updateVersionFile: + if: ${{ github.ref == 'refs/heads/main' }} + needs: [pipeline] + uses: openmfp/gha/.github/workflows/job-update-version-file.yml@main + secrets: inherit + with: + componentVersionKey: "account-operator" + version: ${{ needs.pipeline.outputs.version }} \ No newline at end of file diff --git a/.github/workflows/update-chart-parameters.yaml b/.github/workflows/update-chart-parameters.yaml new file mode 100644 index 000000000..44426d63b --- /dev/null +++ b/.github/workflows/update-chart-parameters.yaml @@ -0,0 +1,71 @@ +name: Update chart parameters + +on: + workflow_dispatch: + inputs: + chart: + description: 'The name of the helm chart' + required: true + default: '' + appVersion: + description: 'The version tag of the docker image' + required: true + default: '0.0.0' + +jobs: + version-update: + runs-on: ubuntu-latest + steps: + - uses: actions/create-github-app-token@v1 + id: app-token + with: + app-id: "838464" + private-key: ${{ secrets.OPENMFP_PUBLISHER_PRIVATE_KEY }} + - uses: actions/checkout@v4 + with: + token: ${{ steps.app-token.outputs.token }} + - name: Setup yq@latest + run: | + if ! command -v yq &>/dev/null + then + mkdir -p /home/runner/.local/bin + wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /home/runner/.local/bin/yq &&\ + chmod +x /home/runner/.local/bin/yq + fi + - name: Configure GIT + run: | + git config --global user.name "OpenMFP Publisher" + git config --global user.email "openmfp@gmail.com" + - name: Update appVersion in Chart.yaml + run: | + chart_file="charts/${{ inputs.chart }}/Chart.yaml" + ls -al charts/ + if [ -f "$chart_file" ]; then + echo "Chart.yaml file found at $chart_file" + yq e -i '.appVersion = "${{ inputs.appVersion }}"' "$chart_file" + echo "Updated appVersion to ${{ inputs.appVersion }} in $chart_file" + + # bump version parameter in chart + CHART_VERSION=$(yq '.version' "$chart_file") + IFS='.' read -r -a VERSION_PARTS <<< "$CHART_VERSION" + MAJOR=${VERSION_PARTS[0]} + MINOR=${VERSION_PARTS[1]} + PATCH=${VERSION_PARTS[2]} + NEW_PATCH=$((PATCH + 1)) + NEW_CHART_VERSION="$MAJOR.$MINOR.$NEW_PATCH" + yq e -i ".version = \"$NEW_CHART_VERSION\"" "$chart_file" + echo "Version bumped to $NEW_CHART_VERSION in $chart_file" + + git add "$chart_file" + git commit -m "Updating appVersion to ${{ inputs.appVersion }} in $chart_file" || echo "appVersion was already up to date" + else + echo "Chart.yaml file not found at $chart_file" + exit 1 + fi + - name: Git push + run: | + git push origin main + echo "Pushed changes to main" + git show HEAD + + diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..02ad061a1 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,22 @@ +{ + "workbench.colorCustomizations": { + "activityBar.activeBackground": "#5d57d5", + "activityBar.background": "#5d57d5", + "activityBar.foreground": "#e7e7e7", + "activityBar.inactiveForeground": "#e7e7e799", + "activityBarBadge.background": "#df847f", + "activityBarBadge.foreground": "#15202b", + "commandCenter.border": "#e7e7e799", + "sash.hoverBorder": "#5d57d5", + "statusBar.background": "#3932c7", + "statusBar.foreground": "#e7e7e7", + "statusBarItem.hoverBackground": "#5d57d5", + "statusBarItem.remoteBackground": "#3932c7", + "statusBarItem.remoteForeground": "#e7e7e7", + "titleBar.activeBackground": "#3932c7", + "titleBar.activeForeground": "#e7e7e7", + "titleBar.inactiveBackground": "#3932c799", + "titleBar.inactiveForeground": "#e7e7e799" + }, + "peacock.color": "#3932c7" +} \ No newline at end of file diff --git a/Taskfile.yaml b/Taskfile.yaml new file mode 100644 index 000000000..1de1b48cc --- /dev/null +++ b/Taskfile.yaml @@ -0,0 +1,33 @@ +version: '3' + +vars: + LOCAL_BIN: bin + CHARTS: + sh: "ls charts/ | sed 's/^/charts\\//g' | paste -sd ',' -" +tasks: + ## Development + lint: + deps: [] + cmds: + - "ct lint --target-branch main --validate-maintainers=false --charts={{.CHARTS}}" + package: + cmds: + - helm package ./charts/openmfp + helmtest: + cmds: + - helm unittest ./charts/common + - helm unittest ./charts/account-operator-crds + - helm unittest ./charts/account-operator + test: + deps: + - task: helmtest + update: + cmds: + - helm dependency update ./charts/common + - helm dependency update ./charts/account-operator-crds + - helm dependency update ./charts/account-operator + validate: + cmds: + - task: lint + - task: package + - task: test diff --git a/charts/account-operator-crds/Chart.yaml b/charts/account-operator-crds/Chart.yaml new file mode 100644 index 000000000..8cfdf803e --- /dev/null +++ b/charts/account-operator-crds/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: account-operator-crds +description: A Helm chart for Kubernetes + +type: application + +version: 0.0.2 + +appVersion: "1.16.0" diff --git a/charts/account-operator-crds/templates/core.openmfp.io_accounts.yaml b/charts/account-operator-crds/templates/core.openmfp.io_accounts.yaml new file mode 100644 index 000000000..e38f6597a --- /dev/null +++ b/charts/account-operator-crds/templates/core.openmfp.io_accounts.yaml @@ -0,0 +1,197 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: accounts.core.openmfp.io +spec: + group: core.openmfp.io + names: + kind: Account + listKind: AccountList + plural: accounts + singular: account + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.displayName + name: Display Name + type: string + - jsonPath: .status.namespace + name: Account Namespace + type: string + - jsonPath: .spec.type + name: Type + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Account is the Schema for the accounts API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AccountSpec defines the desired state of Account + properties: + creator: + description: The initial creator of this account + type: string + data: + description: Additional information that should be stored with the + account + x-kubernetes-preserve-unknown-fields: true + description: + description: An optional description for this account + type: string + displayName: + description: The display name for this account + maxLength: 255 + type: string + extensions: + items: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + readyConditionType: + description: |- + The type of a condition that must be set to True on the Extension object + for the extension to be considered reconciled and ready. If this is empty, + the extension is considered ready. + type: string + specGoTemplate: + x-kubernetes-preserve-unknown-fields: true + required: + - specGoTemplate + type: object + type: array + namespace: + description: Namespace is the account should take ownership of + type: string + type: + description: Type specifies the intended type for this Account object. + enum: + - folder + - account + type: string + required: + - displayName + - type + type: object + status: + description: AccountStatus defines the observed state of Account + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + namespace: + type: string + nextReconcileTime: + format: date-time + type: string + observedGeneration: + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/charts/account-operator-crds/test-values.yaml b/charts/account-operator-crds/test-values.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/charts/account-operator-crds/tests/__snapshot__/deployment_test.yaml.snap b/charts/account-operator-crds/tests/__snapshot__/deployment_test.yaml.snap new file mode 100644 index 000000000..b4837184c --- /dev/null +++ b/charts/account-operator-crds/tests/__snapshot__/deployment_test.yaml.snap @@ -0,0 +1,205 @@ +operator match the snapshot: + 1: | + apiVersion: apiextensions.k8s.io/v1 + kind: CustomResourceDefinition + metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.14.0 + name: accounts.core.openmfp.io + spec: + group: core.openmfp.io + names: + kind: Account + listKind: AccountList + plural: accounts + singular: account + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .spec.displayName + name: Display Name + type: string + - jsonPath: .status.namespace + name: Account Namespace + type: string + - jsonPath: .spec.type + name: Type + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Account is the Schema for the accounts API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: AccountSpec defines the desired state of Account + properties: + creator: + description: The initial creator of this account + type: string + data: + description: Additional information that should be stored with the account + x-kubernetes-preserve-unknown-fields: true + description: + description: An optional description for this account + type: string + displayName: + description: The display name for this account + maxLength: 255 + type: string + extensions: + items: + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + readyConditionType: + description: |- + The type of a condition that must be set to True on the Extension object + for the extension to be considered reconciled and ready. If this is empty, + the extension is considered ready. + type: string + specGoTemplate: + x-kubernetes-preserve-unknown-fields: true + required: + - specGoTemplate + type: object + type: array + namespace: + description: Namespace is the account should take ownership of + type: string + type: + description: Type specifies the intended type for this Account object. + enum: + - folder + - account + type: string + required: + - displayName + - type + type: object + status: + description: AccountStatus defines the observed state of Account + properties: + conditions: + items: + description: |- + Condition contains details for one aspect of the current state of this API Resource. + --- + This struct is intended for direct use as an array at the field path .status.conditions. For example, + + + type FooStatus struct{ + // Represents the observations of a foo's current state. + // Known .status.conditions.type are: "Available", "Progressing", and "Degraded" + // +patchMergeKey=type + // +patchStrategy=merge + // +listType=map + // +listMapKey=type + Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` + + + // other fields + } + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: |- + type of condition in CamelCase or in foo.example.com/CamelCase. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + namespace: + type: string + nextReconcileTime: + format: date-time + type: string + observedGeneration: + format: int64 + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/charts/account-operator-crds/tests/deployment_test.yaml b/charts/account-operator-crds/tests/deployment_test.yaml new file mode 100644 index 000000000..0eca5c3c6 --- /dev/null +++ b/charts/account-operator-crds/tests/deployment_test.yaml @@ -0,0 +1,12 @@ +suite: operator +templates: + - core.openmfp.io_accounts.yaml +values: + - ../test-values.yaml +chart: + version: 0.1.1 + appVersion: 1.16.0 +tests: + - it: operator match the snapshot + asserts: + - matchSnapshot: {} \ No newline at end of file diff --git a/charts/account-operator-crds/values.yaml b/charts/account-operator-crds/values.yaml new file mode 100644 index 000000000..e69de29bb diff --git a/charts/account-operator/.helmignore b/charts/account-operator/.helmignore new file mode 100644 index 000000000..0e8a0eb36 --- /dev/null +++ b/charts/account-operator/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/account-operator/Chart.lock b/charts/account-operator/Chart.lock new file mode 100644 index 000000000..b05b88ff5 --- /dev/null +++ b/charts/account-operator/Chart.lock @@ -0,0 +1,9 @@ +dependencies: +- name: account-operator-crds + repository: file://../account-operator-crds + version: 0.0.2 +- name: common + repository: file://../common + version: 0.1.3 +digest: sha256:730dc28746874baa598e3ff9907363d78806445b26f348daedfe2a01582cd803 +generated: "2024-10-11T11:32:48.745658+02:00" diff --git a/charts/account-operator/Chart.yaml b/charts/account-operator/Chart.yaml new file mode 100644 index 000000000..ca8ff8e03 --- /dev/null +++ b/charts/account-operator/Chart.yaml @@ -0,0 +1,14 @@ +apiVersion: v2 +name: account-operator +description: A Helm chart for Kubernetes +type: application +version: 0.1.11 +appVersion: "0.54.0" +dependencies: + - name: account-operator-crds + version: 0.0.2 + condition: crds.enabled + repository: file://../account-operator-crds + - name: common + version: 0.1.3 + repository: file://../common diff --git a/charts/account-operator/charts/account-operator-crds-0.0.2.tgz b/charts/account-operator/charts/account-operator-crds-0.0.2.tgz new file mode 100644 index 000000000..e77e53019 Binary files /dev/null and b/charts/account-operator/charts/account-operator-crds-0.0.2.tgz differ diff --git a/charts/account-operator/charts/common-0.1.3.tgz b/charts/account-operator/charts/common-0.1.3.tgz new file mode 100644 index 000000000..efd5812a8 Binary files /dev/null and b/charts/account-operator/charts/common-0.1.3.tgz differ diff --git a/charts/account-operator/templates/cluster-role.yaml b/charts/account-operator/templates/cluster-role.yaml new file mode 100644 index 000000000..0935a46c8 --- /dev/null +++ b/charts/account-operator/templates/cluster-role.yaml @@ -0,0 +1,55 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "entity.name" . }} +rules: +- apiGroups: + - core.openmfp.io + resources: + - accounts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - core.openmfp.io + resources: + - accounts + - accounts/status + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - namespaces + - events + verbs: + - get + - list + - watch + - create + - update + - patch + - delete diff --git a/charts/account-operator/templates/cluster-rolebinding.yaml b/charts/account-operator/templates/cluster-rolebinding.yaml new file mode 100644 index 000000000..11a6492a1 --- /dev/null +++ b/charts/account-operator/templates/cluster-rolebinding.yaml @@ -0,0 +1,12 @@ +kind: ClusterRoleBinding +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: {{ include "entity.name" . }} +subjects: +- kind: ServiceAccount + name: {{ include "entity.name" . }} + namespace: {{ .Release.Namespace }} +roleRef: + kind: ClusterRole + name: {{ include "entity.name" . }} + apiGroup: rbac.authorization.k8s.io diff --git a/charts/account-operator/templates/deployment.yaml b/charts/account-operator/templates/deployment.yaml new file mode 100644 index 000000000..07f9d7a8d --- /dev/null +++ b/charts/account-operator/templates/deployment.yaml @@ -0,0 +1,59 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "entity.name" . }} + namespace: {{ .Release.Namespace }} +spec: + revisionHistoryLimit: {{ .Values.deployment.revisionHistoryLimit }} + selector: + matchLabels: + service: {{ include "entity.name" . }} + template: + metadata: + labels: + service: {{ include "entity.name" . }} + control-plane: controller-manager + annotations: + sidecar.istio.io/inject: "false" + spec: + serviceAccountName: {{ include "entity.name" . }} + containers: + - args: + - operator + - --leader-elect + - --log-level={{ .Values.logLevel }} + - "--health-probe-bind-address=:{{ .Values.health.port }}" + image: {{ .Values.image.name }}:{{ .Chart.AppVersion }} + name: manager + securityContext: + runAsNonRoot: true + ports: + - containerPort: {{ .Values.metrics.port }} + name: metrics + protocol: TCP + - name: health-port + containerPort: {{ .Values.health.port }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.health.port}} + initialDelaySeconds: 15 + periodSeconds: 20 + readinessProbe: + httpGet: + path: /readyz + port: {{ .Values.health.port}} + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: {{ .Values.deployment.resources.limits.cpu }} + memory: {{ .Values.deployment.resources.limits.memory }} + requests: + cpu: {{ .Values.deployment.resources.requests.cpu }} + memory: {{ .Values.deployment.resources.requests.memory }} + terminationGracePeriodSeconds: 10 + + + diff --git a/charts/account-operator/templates/service-account.yaml b/charts/account-operator/templates/service-account.yaml new file mode 100644 index 000000000..ae4599a68 --- /dev/null +++ b/charts/account-operator/templates/service-account.yaml @@ -0,0 +1,6 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "entity.name" . }} + namespace: {{ .Release.Namespace }} +{{- include "global.imagePullSecret" . }} diff --git a/charts/account-operator/tests/__snapshot__/deployment_test.yaml.snap b/charts/account-operator/tests/__snapshot__/deployment_test.yaml.snap new file mode 100644 index 000000000..e94112d71 --- /dev/null +++ b/charts/account-operator/tests/__snapshot__/deployment_test.yaml.snap @@ -0,0 +1,135 @@ +operator match the snapshot: + 1: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRole + metadata: + name: RELEASE-NAME-account-operator + rules: + - apiGroups: + - core.openmfp.io + resources: + - accounts + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - core.openmfp.io + resources: + - accounts + - accounts/status + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - "" + resources: + - namespaces + - events + verbs: + - get + - list + - watch + - create + - update + - patch + - delete + 2: | + apiVersion: rbac.authorization.k8s.io/v1 + kind: ClusterRoleBinding + metadata: + name: RELEASE-NAME-account-operator + roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: RELEASE-NAME-account-operator + subjects: + - kind: ServiceAccount + name: RELEASE-NAME-account-operator + namespace: NAMESPACE + 3: | + apiVersion: apps/v1 + kind: Deployment + metadata: + name: RELEASE-NAME-account-operator + namespace: NAMESPACE + spec: + revisionHistoryLimit: 3 + selector: + matchLabels: + service: RELEASE-NAME-account-operator + template: + metadata: + annotations: + sidecar.istio.io/inject: "false" + labels: + control-plane: controller-manager + service: RELEASE-NAME-account-operator + spec: + containers: + - args: + - operator + - --leader-elect + - --log-level= + - --health-probe-bind-address=:8081 + image: ghcr.io/openmfp/account-operator:0.0.0 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + ports: + - containerPort: 8080 + name: metrics + protocol: TCP + - containerPort: 8081 + name: health-port + protocol: TCP + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 260m + memory: 512Mi + requests: + cpu: 150m + memory: 128Mi + securityContext: + runAsNonRoot: true + serviceAccountName: RELEASE-NAME-account-operator + terminationGracePeriodSeconds: 10 + 4: | + apiVersion: v1 + imagePullSecrets: + - name: github + kind: ServiceAccount + metadata: + name: RELEASE-NAME-account-operator + namespace: NAMESPACE diff --git a/charts/account-operator/tests/deployment_test.yaml b/charts/account-operator/tests/deployment_test.yaml new file mode 100644 index 000000000..7a3973ff6 --- /dev/null +++ b/charts/account-operator/tests/deployment_test.yaml @@ -0,0 +1,12 @@ +suite: operator +templates: + - deployment.yaml + - service-account.yaml + - cluster-role.yaml + - cluster-rolebinding.yaml +chart: + appVersion: 0.0.0 +tests: + - it: operator match the snapshot + asserts: + - matchSnapshot: {} \ No newline at end of file diff --git a/charts/account-operator/values.yaml b/charts/account-operator/values.yaml new file mode 100644 index 000000000..069938647 --- /dev/null +++ b/charts/account-operator/values.yaml @@ -0,0 +1,24 @@ +image: + name: ghcr.io/openmfp/account-operator + tag: latest + +imagePullSecret: "github" + +crds: + enabled: true + +health: + port: 8081 + +metrics: + port: 8080 + +deployment: + revisionHistoryLimit: 3 + resources: + limits: + cpu: 260m + memory: 512Mi + requests: + cpu: 150m + memory: 128Mi diff --git a/charts/common/Chart.yaml b/charts/common/Chart.yaml new file mode 100644 index 000000000..4b819a39a --- /dev/null +++ b/charts/common/Chart.yaml @@ -0,0 +1,7 @@ +apiVersion: v2 +name: common +description: A Helm chart for Kubernetes + +type: library + +version: 0.1.3 diff --git a/charts/common/templates/_entityName.tpl b/charts/common/templates/_entityName.tpl new file mode 100644 index 000000000..4681cf01c --- /dev/null +++ b/charts/common/templates/_entityName.tpl @@ -0,0 +1,11 @@ +{{- define "entity.name" -}} +{{- if contains .Chart.Name .Release.Name }} +{{- printf "%s" .Chart.Name | trunc 63 }} +{{- else }} +{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 }} +{{- end -}} +{{- end -}} + +{{- define "release.name" -}} +{{- printf "%s" .Release.Name | trunc 63 }} +{{- end -}} diff --git a/charts/common/templates/_imagePullSecret.tpl b/charts/common/templates/_imagePullSecret.tpl new file mode 100644 index 000000000..6a8771952 --- /dev/null +++ b/charts/common/templates/_imagePullSecret.tpl @@ -0,0 +1,4 @@ +{{- define "global.imagePullSecret" }} +imagePullSecrets: + - name: {{ default .Values.imagePullSecret (.Values.global).imagePullSecret }} +{{- end -}} \ No newline at end of file diff --git a/charts/common/values.yaml b/charts/common/values.yaml new file mode 100644 index 000000000..e69de29bb