├── controllers └── .gitkeep ├── .dockerignore ├── helm-charts └── open5gs │ ├── charts │ ├── common-1.17.1.tgz │ ├── mongodb-12.1.31.tgz │ ├── open5gs-amf-2.2.0.tgz │ ├── open5gs-ausf-2.2.0.tgz │ ├── open5gs-bsf-2.2.0.tgz │ ├── open5gs-hss-2.2.0.tgz │ ├── open5gs-mme-2.2.0.tgz │ ├── open5gs-nrf-2.2.1.tgz │ ├── open5gs-nssf-2.2.0.tgz │ ├── open5gs-pcf-2.2.0.tgz │ ├── open5gs-pcrf-2.2.0.tgz │ ├── open5gs-scp-2.2.0.tgz │ ├── open5gs-sgwc-2.2.0.tgz │ ├── open5gs-sgwu-2.2.0.tgz │ ├── open5gs-smf-2.2.0.tgz │ ├── open5gs-udm-2.2.0.tgz │ ├── open5gs-udr-2.2.0.tgz │ ├── open5gs-upf-2.2.1.tgz │ └── open5gs-webui-2.2.0.tgz │ ├── templates │ ├── _helpers.tpl │ └── populate-deployment.yaml │ ├── values.yaml │ ├── scp-values.yaml │ ├── Chart.yaml │ └── README.md ├── .gitignore ├── watches.yaml ├── charts └── open5gs-legacy-operator-chart │ ├── Chart.yaml │ ├── .helmignore │ ├── templates │ ├── serviceaccount.yaml │ ├── leader-election-rbac.yaml │ ├── open5gs-crd.yaml │ ├── deployment.yaml │ ├── _helpers.tpl │ ├── open5gsuser-crd.yaml │ └── manager-rbac.yaml │ └── values.yaml ├── config ├── manager │ ├── kustomization.yaml │ └── manager.yaml ├── default │ ├── manager_config_patch.yaml │ └── kustomization.yaml ├── samples │ ├── kustomization.yaml │ ├── net_v1_open5gsuser.yaml │ ├── net_v1_open5gsuser-2.yaml │ ├── net_v1_open5gs.yaml │ └── net_v1_open5gs-2.yaml ├── manifests │ └── kustomization.yaml ├── crd │ ├── kustomization.yaml │ ├── kustomizeconfig.yaml │ └── bases │ │ ├── net.gradiant.org_open5gs.yaml │ │ └── net.gradiant.org_open5gsusers.yaml └── rbac │ ├── service_account.yaml │ ├── role_binding.yaml │ ├── leader_election_role_binding.yaml │ ├── open5gs_viewer_role.yaml │ ├── open5gsuser_viewer_role.yaml │ ├── kustomization.yaml │ ├── open5gs_editor_role.yaml │ ├── open5gsuser_editor_role.yaml │ ├── leader_election_role.yaml │ └── role.yaml ├── hack └── boilerplate.go.txt ├── PROJECT ├── Dockerfile ├── api └── v1 │ ├── groupversion_info.go │ ├── open5gsuser_types.go │ └── zz_generated.deepcopy.go ├── internal └── controller │ ├── open5gsuser_controller_test.go │ ├── suite_test.go │ ├── mongo.go │ └── open5gsuser_controller.go ├── README.md ├── cmd └── main.go ├── go.mod ├── Makefile ├── LICENSE └── go.sum /controllers/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | testbin/ 5 | -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/common-1.17.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/common-1.17.1.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/mongodb-12.1.31.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/mongodb-12.1.31.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-amf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-amf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-ausf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-ausf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-bsf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-bsf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-hss-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-hss-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-mme-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-mme-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-nrf-2.2.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-nrf-2.2.1.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-nssf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-nssf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-pcf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-pcf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-pcrf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-pcrf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-scp-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-scp-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-sgwc-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-sgwc-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-sgwu-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-sgwu-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-smf-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-smf-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-udm-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-udm-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-udr-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-udr-2.2.0.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-upf-2.2.1.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-upf-2.2.1.tgz -------------------------------------------------------------------------------- /helm-charts/open5gs/charts/open5gs-webui-2.2.0.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Gradiant/open5gs-legacy-operator/HEAD/helm-charts/open5gs/charts/open5gs-webui-2.2.0.tgz -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Binaries for programs and plugins 3 | *.exe 4 | *.exe~ 5 | *.dll 6 | *.so 7 | *.dylib 8 | bin 9 | 10 | # editor and IDE paraphernalia 11 | .idea 12 | *.swp 13 | *.swo 14 | *~ 15 | -------------------------------------------------------------------------------- /watches.yaml: -------------------------------------------------------------------------------- 1 | # Use the 'create api' subcommand to add watches to this file. 2 | - group: net.gradiant.org 3 | version: v1 4 | kind: Open5GS 5 | chart: helm-charts/open5gs 6 | #+kubebuilder:scaffold:watch 7 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: open5gs-legacy-operator-chart 3 | description: A Helm chart for Kubernetes Open5GS Operator 4 | 5 | type: application 6 | 7 | version: 0.1.0 8 | appVersion: "0.1.0" 9 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | apiVersion: kustomize.config.k8s.io/v1beta1 4 | kind: Kustomization 5 | images: 6 | - name: controller 7 | newName: gradiant/open5gs-legacy-operator 8 | newTag: 0.1.0 9 | -------------------------------------------------------------------------------- /config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | -------------------------------------------------------------------------------- /config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples of your project ## 2 | resources: 3 | - net_v1_open5gs.yaml 4 | - net_v1_open5gs-2.yaml 5 | - net_v1_open5gsuser.yaml 6 | - net_v1_open5gsuser-2.yaml 7 | #+kubebuilder:scaffold:manifestskustomizesamples 8 | -------------------------------------------------------------------------------- /config/manifests/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # These resources constitute the fully configured set of manifests 2 | # used to generate the 'manifests/' directory in a bundle. 3 | resources: 4 | - bases/open5gs-operator.clusterserviceversion.yaml 5 | - ../default 6 | - ../samples 7 | - ../scorecard 8 | -------------------------------------------------------------------------------- /config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/net.gradiant.org_open5gs.yaml 6 | - bases/net.gradiant.org_open5gsusers.yaml 7 | #+kubebuilder:scaffold:crdkustomizeresource 8 | -------------------------------------------------------------------------------- /config/samples/net_v1_open5gsuser.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: net.gradiant.org/v1 2 | kind: Open5GSUser 3 | metadata: 4 | name: open5gsuser-1 5 | spec: 6 | imsi: "999700000000001" 7 | key: "465B5CE8B199B49FAA5F0A2EE238A6BC" 8 | opc: "E8ED289DEBA952E4283B54E88E6183CA" 9 | sd: "111111" 10 | sst: "1" 11 | apn: "internet" 12 | open5gs: 13 | name: "open5gs" 14 | namespace: "default" 15 | -------------------------------------------------------------------------------- /config/samples/net_v1_open5gsuser-2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: net.gradiant.org/v1 2 | kind: Open5GSUser 3 | metadata: 4 | name: open5gsuser-2 5 | spec: 6 | imsi: "999700000000002" 7 | key: "465B5CE8B199B49FAA5F0A2EE238A6BC" 8 | opc: "E8ED289DEBA952E4283B54E88E6183CA" 9 | sd: "111111" 10 | sst: "1" 11 | apn: "internet" 12 | open5gs: 13 | name: "open5gs" 14 | namespace: "default" 15 | -------------------------------------------------------------------------------- /config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: serviceaccount 6 | app.kubernetes.io/instance: controller-manager-sa 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: open5gs-operator 9 | app.kubernetes.io/part-of: open5gs-operator 10 | app.kubernetes.io/managed-by: kustomize 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: {{ include "open5gs-operator.fullname" . }}-controller-manager 5 | labels: 6 | app.kubernetes.io/component: rbac 7 | app.kubernetes.io/created-by: open5gs-operator 8 | app.kubernetes.io/part-of: open5gs-operator 9 | {{- include "open5gs-operator.labels" . | nindent 4 }} 10 | annotations: 11 | {{- toYaml .Values.controllerManager.serviceAccount.annotations | nindent 4 }} -------------------------------------------------------------------------------- /helm-charts/open5gs/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Return the proper Open5gs image name 3 | */}} 4 | {{- define "open5gs.populate.image" -}} 5 | {{- include "common.images.image" (dict "imageRoot" .Values.populate.image "global" .Values.global ) -}} 6 | {{- end -}} 7 | 8 | {{/* 9 | Return the proper Docker Image Registry Secret Names 10 | */}} 11 | {{- define "open5gs.populate.imagePullSecrets" -}} 12 | {{- include "common.images.pullSecrets" (dict "images" (list .Values.populate.image ) "global" .Values.global) -}} 13 | {{- end -}} -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/values.yaml: -------------------------------------------------------------------------------- 1 | controllerManager: 2 | manager: 3 | args: 4 | - --leader-elect 5 | - --leader-election-id=open5gs-operator 6 | containerSecurityContext: 7 | allowPrivilegeEscalation: false 8 | capabilities: 9 | drop: 10 | - ALL 11 | image: 12 | repository: gradiant/open5gs-legacy-operator 13 | tag: 0.1.0 14 | resources: 15 | requests: 16 | cpu: 100m 17 | memory: 128Mi 18 | replicas: 1 19 | serviceAccount: 20 | annotations: {} 21 | kubernetesClusterDomain: cluster.local 22 | -------------------------------------------------------------------------------- /config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: clusterrolebinding 6 | app.kubernetes.io/instance: manager-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: open5gs-operator 9 | app.kubernetes.io/part-of: open5gs-operator 10 | app.kubernetes.io/managed-by: kustomize 11 | name: manager-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: ClusterRole 15 | name: manager-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller-manager 19 | namespace: system 20 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: rolebinding 6 | app.kubernetes.io/instance: leader-election-rolebinding 7 | app.kubernetes.io/component: rbac 8 | app.kubernetes.io/created-by: open5gs-operator 9 | app.kubernetes.io/part-of: open5gs-operator 10 | app.kubernetes.io/managed-by: kustomize 11 | name: leader-election-rolebinding 12 | roleRef: 13 | apiGroup: rbac.authorization.k8s.io 14 | kind: Role 15 | name: leader-election-role 16 | subjects: 17 | - kind: ServiceAccount 18 | name: controller-manager 19 | namespace: system 20 | -------------------------------------------------------------------------------- /config/rbac/open5gs_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view open5gs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: open5gs-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: open5gs-viewer-role 13 | rules: 14 | - apiGroups: 15 | - net.gradiant.org 16 | resources: 17 | - open5gs 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - net.gradiant.org 24 | resources: 25 | - open5gs/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/open5gsuser_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view open5gsusers. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: open5gsuser-viewer-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: open5gsuser-viewer-role 13 | rules: 14 | - apiGroups: 15 | - net.gradiant.org 16 | resources: 17 | - open5gsusers 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - apiGroups: 23 | - net.gradiant.org 24 | resources: 25 | - open5gsusers/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | # - auth_proxy_service.yaml 16 | # - auth_proxy_role.yaml 17 | # - auth_proxy_role_binding.yaml 18 | # - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /config/rbac/open5gs_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit open5gs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: open5gs-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: open5gs-editor-role 13 | rules: 14 | - apiGroups: 15 | - net.gradiant.org 16 | resources: 17 | - open5gs 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - net.gradiant.org 28 | resources: 29 | - open5gs/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /config/rbac/open5gsuser_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit open5gsusers. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: clusterrole 7 | app.kubernetes.io/instance: open5gsuser-editor-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: open5gsuser-editor-role 13 | rules: 14 | - apiGroups: 15 | - net.gradiant.org 16 | resources: 17 | - open5gsusers 18 | verbs: 19 | - create 20 | - delete 21 | - get 22 | - list 23 | - patch 24 | - update 25 | - watch 26 | - apiGroups: 27 | - net.gradiant.org 28 | resources: 29 | - open5gsusers/status 30 | verbs: 31 | - get 32 | -------------------------------------------------------------------------------- /PROJECT: -------------------------------------------------------------------------------- 1 | # Code generated by tool. DO NOT EDIT. 2 | # This file is used to track the info used to scaffold your project 3 | # and allow the plugins properly work. 4 | # More info: https://book.kubebuilder.io/reference/project-config.html 5 | domain: gradiant.org 6 | layout: 7 | - hybrid.helm.sdk.operatorframework.io/v1-alpha 8 | plugins: 9 | manifests.sdk.operatorframework.io/v2: {} 10 | scorecard.sdk.operatorframework.io/v2: {} 11 | projectName: open5gs-operator 12 | repo: gradiant/open5gs-legacy-operator 13 | resources: 14 | - api: 15 | crdVersion: v1 16 | namespaced: true 17 | domain: gradiant.org 18 | group: net 19 | kind: Open5GS 20 | version: v1 21 | - api: 22 | crdVersion: v1 23 | namespaced: true 24 | controller: true 25 | domain: gradiant.org 26 | group: net 27 | kind: Open5GSUser 28 | path: gradiant/open5gs-legacy-operator/api/v1 29 | version: v1 30 | version: "3" 31 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: open5gs-operator-system 3 | 4 | # Value of this field is prepended to the 5 | # names of all resources, e.g. a deployment named 6 | # "wordpress" becomes "alices-wordpress". 7 | # Note that it should also match with the prefix (text before '-') of the namespace 8 | # field above. 9 | namePrefix: open5gs-operator- 10 | 11 | # Labels to add to all resources and selectors. 12 | #labels: 13 | #- includeSelectors: true 14 | # pairs: 15 | # someName: someValue 16 | 17 | resources: 18 | - ../crd 19 | - ../rbac 20 | - ../manager 21 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 22 | #- ../prometheus 23 | 24 | # patches: 25 | # Protect the /metrics endpoint by putting it behind auth. 26 | # If you want your controller-manager to expose the /metrics 27 | # endpoint w/o any authn/z, please comment the following line. 28 | # - path: manager_auth_proxy_patch.yaml 29 | -------------------------------------------------------------------------------- /config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: role 7 | app.kubernetes.io/instance: leader-election-role 8 | app.kubernetes.io/component: rbac 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: leader-election-role 13 | rules: 14 | - apiGroups: 15 | - "" 16 | resources: 17 | - configmaps 18 | verbs: 19 | - get 20 | - list 21 | - watch 22 | - create 23 | - update 24 | - patch 25 | - delete 26 | - apiGroups: 27 | - coordination.k8s.io 28 | resources: 29 | - leases 30 | verbs: 31 | - get 32 | - list 33 | - watch 34 | - create 35 | - update 36 | - patch 37 | - delete 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - events 42 | verbs: 43 | - create 44 | - patch 45 | -------------------------------------------------------------------------------- /config/samples/net_v1_open5gs.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: net.gradiant.org/v1 2 | kind: Open5GS 3 | metadata: 4 | name: open5gs 5 | spec: 6 | hss: 7 | enabled: false 8 | 9 | mme: 10 | enabled: false 11 | 12 | pcrf: 13 | enabled: false 14 | 15 | smf: 16 | config: 17 | pcrf: 18 | enabled: false 19 | 20 | sgwc: 21 | enabled: false 22 | 23 | sgwu: 24 | enabled: false 25 | 26 | amf: 27 | config: 28 | guamiList: 29 | - plmn_id: 30 | mcc: "999" 31 | mnc: "70" 32 | amf_id: 33 | region: 2 34 | set: 1 35 | taiList: 36 | - plmn_id: 37 | mcc: "999" 38 | mnc: "70" 39 | tac: [1] 40 | plmnList: 41 | - plmn_id: 42 | mcc: "999" 43 | mnc: "70" 44 | s_nssai: 45 | - sst: 1 46 | sd: "0x111111" 47 | 48 | nssf: 49 | config: 50 | nsiList: 51 | - uri: "" 52 | sst: 1 53 | sd: "0x111111" 54 | 55 | webui: 56 | enabled: false 57 | populate: 58 | enabled: false -------------------------------------------------------------------------------- /config/samples/net_v1_open5gs-2.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: net.gradiant.org/v1 2 | kind: Open5GS 3 | metadata: 4 | name: open5gs-2 5 | spec: 6 | hss: 7 | enabled: false 8 | 9 | mme: 10 | enabled: false 11 | 12 | pcrf: 13 | enabled: false 14 | 15 | smf: 16 | config: 17 | pcrf: 18 | enabled: false 19 | 20 | sgwc: 21 | enabled: false 22 | 23 | sgwu: 24 | enabled: false 25 | 26 | amf: 27 | config: 28 | guamiList: 29 | - plmn_id: 30 | mcc: "999" 31 | mnc: "70" 32 | amf_id: 33 | region: 2 34 | set: 1 35 | taiList: 36 | - plmn_id: 37 | mcc: "999" 38 | mnc: "70" 39 | tac: [1] 40 | plmnList: 41 | - plmn_id: 42 | mcc: "999" 43 | mnc: "70" 44 | s_nssai: 45 | - sst: 1 46 | sd: "0x111111" 47 | 48 | nssf: 49 | config: 50 | nsiList: 51 | - uri: "" 52 | sst: 1 53 | sd: "0x111111" 54 | 55 | webui: 56 | enabled: false 57 | populate: 58 | enabled: false 59 | 60 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.20 AS builder 3 | 4 | WORKDIR /workspace 5 | # Copy the Go Modules manifests 6 | COPY go.mod go.mod 7 | COPY go.sum go.sum 8 | # cache deps before building and copying source so that we don't need to re-download as much 9 | # and so that source changes don't invalidate our downloaded layer 10 | RUN go mod download 11 | 12 | # Copy the go source 13 | COPY cmd/ cmd/ 14 | COPY api/ api/ 15 | COPY controllers/ controllers/ 16 | COPY internal/controller internal/controller 17 | 18 | # Build 19 | RUN GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go build -a -o manager cmd/main.go 20 | 21 | FROM registry.access.redhat.com/ubi8/ubi-micro:8.7 22 | 23 | ENV HOME=/opt/helm \ 24 | USER_NAME=helm \ 25 | USER_UID=1001 26 | 27 | RUN echo "${USER_NAME}:x:${USER_UID}:0:${USER_NAME} user:${HOME}:/sbin/nologin" >> /etc/passwd 28 | 29 | # Copy necessary files with the right permissions 30 | COPY --chown=${USER_UID}:0 watches.yaml ${HOME}/watches.yaml 31 | COPY --chown=${USER_UID}:0 helm-charts ${HOME}/helm-charts 32 | 33 | # Copy manager binary 34 | COPY --from=builder /workspace/manager . 35 | 36 | USER ${USER_UID} 37 | 38 | WORKDIR ${HOME} 39 | 40 | ENTRYPOINT ["/manager"] 41 | -------------------------------------------------------------------------------- /api/v1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1 contains API Schema definitions for the net v1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=net.gradiant.org 20 | package v1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "net.gradiant.org", Version: "v1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /helm-charts/open5gs/values.yaml: -------------------------------------------------------------------------------- 1 | dbURI: "mongodb://{{ .Release.Name }}-mongodb/open5gs" 2 | 3 | populate: 4 | enabled: true 5 | image: 6 | registry: docker.io 7 | repository: gradiant/open5gs-dbctl 8 | tag: 0.10.3 9 | pullPolicy: IfNotPresent 10 | initCommands: [] 11 | # example of initCommands: 12 | # - open5gs-dbctl add 999700000000001 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA 13 | # - open5gs-dbctl add_ue_with_apn 999700000000002 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 14 | # - open5gs-dbctl add_ue_with_slice 999700000000003 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 1 111111 15 | 16 | # Common 17 | mongodb: 18 | enabled: true 19 | auth: 20 | enabled: false 21 | smf: 22 | enabled: true 23 | upf: 24 | enabled: true 25 | webui: 26 | enabled: true 27 | 28 | # 4G 29 | hss: 30 | enabled: true 31 | mongodb: 32 | enabled: false 33 | mme: 34 | enabled: true 35 | pcrf: 36 | enabled: true 37 | mongodb: 38 | enabled: false 39 | sgwc: 40 | enabled: true 41 | sgwu: 42 | enabled: true 43 | 44 | # 5G 45 | amf: 46 | enabled: true 47 | ausf: 48 | enabled: true 49 | bsf: 50 | enabled: true 51 | nrf: 52 | enabled: true 53 | nssf: 54 | enabled: true 55 | pcf: 56 | enabled: true 57 | mongodb: 58 | enabled: false 59 | scp: 60 | enabled: true 61 | mongodb: 62 | enabled: false 63 | udm: 64 | enabled: true 65 | udr: 66 | enabled: true 67 | mongodb: 68 | enabled: false 69 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/leader-election-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: Role 3 | metadata: 4 | name: {{ include "open5gs-operator.fullname" . }}-leader-election-role 5 | labels: 6 | app.kubernetes.io/component: rbac 7 | app.kubernetes.io/created-by: open5gs-operator 8 | app.kubernetes.io/part-of: open5gs-operator 9 | {{- include "open5gs-operator.labels" . | nindent 4 }} 10 | rules: 11 | - apiGroups: 12 | - "" 13 | resources: 14 | - configmaps 15 | verbs: 16 | - get 17 | - list 18 | - watch 19 | - create 20 | - update 21 | - patch 22 | - delete 23 | - apiGroups: 24 | - coordination.k8s.io 25 | resources: 26 | - leases 27 | verbs: 28 | - get 29 | - list 30 | - watch 31 | - create 32 | - update 33 | - patch 34 | - delete 35 | - apiGroups: 36 | - "" 37 | resources: 38 | - events 39 | verbs: 40 | - create 41 | - patch 42 | --- 43 | apiVersion: rbac.authorization.k8s.io/v1 44 | kind: RoleBinding 45 | metadata: 46 | name: {{ include "open5gs-operator.fullname" . }}-leader-election-rolebinding 47 | labels: 48 | app.kubernetes.io/component: rbac 49 | app.kubernetes.io/created-by: open5gs-operator 50 | app.kubernetes.io/part-of: open5gs-operator 51 | {{- include "open5gs-operator.labels" . | nindent 4 }} 52 | roleRef: 53 | apiGroup: rbac.authorization.k8s.io 54 | kind: Role 55 | name: '{{ include "open5gs-operator.fullname" . }}-leader-election-role' 56 | subjects: 57 | - kind: ServiceAccount 58 | name: '{{ include "open5gs-operator.fullname" . }}-controller-manager' 59 | namespace: '{{ .Release.Namespace }}' -------------------------------------------------------------------------------- /config/crd/bases/net.gradiant.org_open5gs.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: open5gs.net.gradiant.org 6 | spec: 7 | group: net.gradiant.org 8 | names: 9 | kind: Open5GS 10 | listKind: Open5GSList 11 | plural: open5gs 12 | singular: open5gs 13 | scope: Namespaced 14 | versions: 15 | - name: v1 16 | schema: 17 | openAPIV3Schema: 18 | description: Open5GS is the Schema for the open5gs API 19 | properties: 20 | apiVersion: 21 | description: 'APIVersion defines the versioned schema of this representation 22 | of an object. Servers should convert recognized schemas to the latest 23 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 24 | type: string 25 | kind: 26 | description: 'Kind is a string value representing the REST resource this 27 | object represents. Servers may infer this from the endpoint the client 28 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 29 | type: string 30 | metadata: 31 | type: object 32 | spec: 33 | description: Spec defines the desired state of Open5GS 34 | type: object 35 | x-kubernetes-preserve-unknown-fields: true 36 | status: 37 | description: Status defines the observed state of Open5GS 38 | type: object 39 | x-kubernetes-preserve-unknown-fields: true 40 | type: object 41 | served: true 42 | storage: true 43 | subresources: 44 | status: {} 45 | -------------------------------------------------------------------------------- /helm-charts/open5gs/templates/populate-deployment.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.populate.enabled }} 2 | apiVersion: {{ include "common.capabilities.deployment.apiVersion" . }} 3 | kind: Deployment 4 | metadata: 5 | name: {{ template "common.names.fullname" . }}-populate 6 | namespace: {{ .Release.Namespace | quote }} 7 | labels: {{- include "common.labels.standard" . | nindent 4 }} 8 | app.kubernetes.io/component: populate 9 | {{- if .Values.commonLabels }} 10 | {{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }} 11 | {{- end }} 12 | {{- if .Values.commonAnnotations }} 13 | annotations: {{- include "common.tplvalues.render" ( dict "value" .Values.commonAnnotations "context" $ ) | nindent 4 }} 14 | {{- end }} 15 | spec: 16 | selector: 17 | matchLabels: {{ include "common.labels.matchLabels" . | nindent 6 }} 18 | app.kubernetes.io/component: populate 19 | template: 20 | metadata: 21 | labels: {{- include "common.labels.standard" . | nindent 8 }} 22 | app.kubernetes.io/component: populate 23 | spec: 24 | {{- include "open5gs.populate.imagePullSecrets" . | nindent 6 }} 25 | initContainers: 26 | - name: init 27 | image: {{ template "open5gs.populate.image" . }} 28 | imagePullPolicy: {{ .Values.populate.pullPolicy | quote }} 29 | env: 30 | - name: DB_URI 31 | value: {{ tpl .Values.dbURI . }} 32 | command: 33 | - /bin/bash 34 | - -c 35 | - {{ join "&&" .Values.populate.initCommands | quote }} 36 | containers: 37 | - name: populate 38 | image: {{ template "open5gs.populate.image" . }} 39 | imagePullPolicy: {{ .Values.populate.pullPolicy | quote }} 40 | env: 41 | - name: DB_URI 42 | value: {{ tpl .Values.dbURI . }} 43 | command: 44 | - /bin/bash 45 | - -c 46 | - "tail -f /dev/null" 47 | {{- end }} -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/open5gs-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: open5gs.net.gradiant.org 5 | labels: 6 | {{- include "open5gs-operator.labels" . | nindent 4 }} 7 | spec: 8 | group: net.gradiant.org 9 | names: 10 | kind: Open5GS 11 | listKind: Open5GSList 12 | plural: open5gs 13 | singular: open5gs 14 | scope: Namespaced 15 | versions: 16 | - name: v1 17 | schema: 18 | openAPIV3Schema: 19 | description: Open5GS is the Schema for the open5gs API 20 | properties: 21 | apiVersion: 22 | description: 'APIVersion defines the versioned schema of this representation 23 | of an object. Servers should convert recognized schemas to the latest 24 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 25 | type: string 26 | kind: 27 | description: 'Kind is a string value representing the REST resource this 28 | object represents. Servers may infer this from the endpoint the client 29 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 30 | type: string 31 | metadata: 32 | type: object 33 | spec: 34 | description: Spec defines the desired state of Open5GS 35 | type: object 36 | x-kubernetes-preserve-unknown-fields: true 37 | status: 38 | description: Status defines the observed state of Open5GS 39 | type: object 40 | x-kubernetes-preserve-unknown-fields: true 41 | type: object 42 | served: true 43 | storage: true 44 | subresources: 45 | status: {} 46 | status: 47 | acceptedNames: 48 | kind: "" 49 | plural: "" 50 | conditions: [] 51 | storedVersions: [] -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: {{ include "open5gs-operator.fullname" . }}-controller-manager 5 | labels: 6 | app.kubernetes.io/component: manager 7 | app.kubernetes.io/created-by: open5gs-operator 8 | app.kubernetes.io/part-of: open5gs-operator 9 | control-plane: controller-manager 10 | {{- include "open5gs-operator.labels" . | nindent 4 }} 11 | spec: 12 | replicas: {{ .Values.controllerManager.replicas }} 13 | selector: 14 | matchLabels: 15 | control-plane: controller-manager 16 | {{- include "open5gs-operator.selectorLabels" . | nindent 6 }} 17 | template: 18 | metadata: 19 | labels: 20 | control-plane: controller-manager 21 | {{- include "open5gs-operator.selectorLabels" . | nindent 8 }} 22 | annotations: 23 | kubectl.kubernetes.io/default-container: manager 24 | spec: 25 | containers: 26 | - args: {{- toYaml .Values.controllerManager.manager.args | nindent 8 }} 27 | env: 28 | - name: KUBERNETES_CLUSTER_DOMAIN 29 | value: {{ quote .Values.kubernetesClusterDomain }} 30 | image: {{ .Values.controllerManager.manager.image.repository }}:{{ .Values.controllerManager.manager.image.tag 31 | | default .Chart.AppVersion }} 32 | livenessProbe: 33 | httpGet: 34 | path: /healthz 35 | port: 8081 36 | initialDelaySeconds: 15 37 | periodSeconds: 20 38 | name: manager 39 | readinessProbe: 40 | httpGet: 41 | path: /readyz 42 | port: 8081 43 | initialDelaySeconds: 5 44 | periodSeconds: 10 45 | resources: {{- toYaml .Values.controllerManager.manager.resources | nindent 10 46 | }} 47 | securityContext: {{- toYaml .Values.controllerManager.manager.containerSecurityContext 48 | | nindent 10 }} 49 | securityContext: 50 | runAsNonRoot: true 51 | serviceAccountName: {{ include "open5gs-operator.fullname" . }}-controller-manager 52 | terminationGracePeriodSeconds: 10 -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "open5gs-operator.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Create a default fully qualified app name. 10 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 11 | If release name contains chart name it will be used as a full name. 12 | */}} 13 | {{- define "open5gs-operator.fullname" -}} 14 | {{- if .Values.fullnameOverride }} 15 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 16 | {{- else }} 17 | {{- $name := default .Chart.Name .Values.nameOverride }} 18 | {{- if contains $name .Release.Name }} 19 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 20 | {{- else }} 21 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 22 | {{- end }} 23 | {{- end }} 24 | {{- end }} 25 | 26 | {{/* 27 | Create chart name and version as used by the chart label. 28 | */}} 29 | {{- define "open5gs-operator.chart" -}} 30 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 31 | {{- end }} 32 | 33 | {{/* 34 | Common labels 35 | */}} 36 | {{- define "open5gs-operator.labels" -}} 37 | helm.sh/chart: {{ include "open5gs-operator.chart" . }} 38 | {{ include "open5gs-operator.selectorLabels" . }} 39 | {{- if .Chart.AppVersion }} 40 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 41 | {{- end }} 42 | app.kubernetes.io/managed-by: {{ .Release.Service }} 43 | {{- end }} 44 | 45 | {{/* 46 | Selector labels 47 | */}} 48 | {{- define "open5gs-operator.selectorLabels" -}} 49 | app.kubernetes.io/name: {{ include "open5gs-operator.name" . }} 50 | app.kubernetes.io/instance: {{ .Release.Name }} 51 | {{- end }} 52 | 53 | {{/* 54 | Create the name of the service account to use 55 | */}} 56 | {{- define "open5gs-operator.serviceAccountName" -}} 57 | {{- if .Values.serviceAccount.create }} 58 | {{- default (include "open5gs-operator.fullname" .) .Values.serviceAccount.name }} 59 | {{- else }} 60 | {{- default "default" .Values.serviceAccount.name }} 61 | {{- end }} 62 | {{- end }} 63 | -------------------------------------------------------------------------------- /api/v1/open5gsuser_types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package v1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // Open5GSReference defines the reference to an Open5GS instance 24 | type Open5GSReference struct { 25 | Name string `json:"name,omitempty"` 26 | Namespace string `json:"namespace,omitempty"` 27 | } 28 | 29 | // Open5GSUserSpec defines the desired state of Open5GSUser 30 | type Open5GSUserSpec struct { 31 | IMSI string `json:"imsi,omitempty"` 32 | Key string `json:"key,omitempty"` 33 | OPC string `json:"opc,omitempty"` 34 | SD string `json:"sd,omitempty"` 35 | SST string `json:"sst,omitempty"` 36 | APN string `json:"apn,omitempty"` 37 | Open5GS Open5GSReference `json:"open5gs,omitempty"` 38 | } 39 | 40 | // Open5GSUserStatus defines the observed state of Open5GSUser 41 | type Open5GSUserStatus struct { 42 | // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster 43 | // Important: Run "make" to regenerate code after modifying this file 44 | } 45 | 46 | //+kubebuilder:object:root=true 47 | //+kubebuilder:subresource:status 48 | 49 | // Open5GSUser is the Schema for the open5gsusers API 50 | type Open5GSUser struct { 51 | metav1.TypeMeta `json:",inline"` 52 | metav1.ObjectMeta `json:"metadata,omitempty"` 53 | 54 | Spec Open5GSUserSpec `json:"spec,omitempty"` 55 | Status Open5GSUserStatus `json:"status,omitempty"` 56 | } 57 | 58 | //+kubebuilder:object:root=true 59 | 60 | // Open5GSUserList contains a list of Open5GSUser 61 | type Open5GSUserList struct { 62 | metav1.TypeMeta `json:",inline"` 63 | metav1.ListMeta `json:"metadata,omitempty"` 64 | Items []Open5GSUser `json:"items"` 65 | } 66 | 67 | func init() { 68 | SchemeBuilder.Register(&Open5GSUser{}, &Open5GSUserList{}) 69 | } 70 | -------------------------------------------------------------------------------- /config/crd/bases/net.gradiant.org_open5gsusers.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.13.0 7 | name: open5gsusers.net.gradiant.org 8 | spec: 9 | group: net.gradiant.org 10 | names: 11 | kind: Open5GSUser 12 | listKind: Open5GSUserList 13 | plural: open5gsusers 14 | singular: open5gsuser 15 | scope: Namespaced 16 | versions: 17 | - name: v1 18 | schema: 19 | openAPIV3Schema: 20 | description: Open5GSUser is the Schema for the open5gsusers API 21 | properties: 22 | apiVersion: 23 | description: 'APIVersion defines the versioned schema of this representation 24 | of an object. Servers should convert recognized schemas to the latest 25 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 26 | type: string 27 | kind: 28 | description: 'Kind is a string value representing the REST resource this 29 | object represents. Servers may infer this from the endpoint the client 30 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 31 | type: string 32 | metadata: 33 | type: object 34 | spec: 35 | description: Open5GSUserSpec defines the desired state of Open5GSUser 36 | properties: 37 | apn: 38 | type: string 39 | imsi: 40 | type: string 41 | key: 42 | type: string 43 | opc: 44 | type: string 45 | open5gs: 46 | description: Open5GSReference defines the reference to an Open5GS 47 | instance 48 | properties: 49 | name: 50 | type: string 51 | namespace: 52 | type: string 53 | type: object 54 | sd: 55 | type: string 56 | sst: 57 | type: string 58 | type: object 59 | status: 60 | description: Open5GSUserStatus defines the observed state of Open5GSUser 61 | type: object 62 | type: object 63 | served: true 64 | storage: true 65 | subresources: 66 | status: {} 67 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/open5gsuser-crd.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apiextensions.k8s.io/v1 2 | kind: CustomResourceDefinition 3 | metadata: 4 | name: open5gsusers.net.gradiant.org 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.13.0 7 | labels: 8 | {{- include "open5gs-operator.labels" . | nindent 4 }} 9 | spec: 10 | group: net.gradiant.org 11 | names: 12 | kind: Open5GSUser 13 | listKind: Open5GSUserList 14 | plural: open5gsusers 15 | singular: open5gsuser 16 | scope: Namespaced 17 | versions: 18 | - name: v1 19 | schema: 20 | openAPIV3Schema: 21 | description: Open5GSUser is the Schema for the open5gsusers API 22 | properties: 23 | apiVersion: 24 | description: 'APIVersion defines the versioned schema of this representation 25 | of an object. Servers should convert recognized schemas to the latest 26 | internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' 27 | type: string 28 | kind: 29 | description: 'Kind is a string value representing the REST resource this 30 | object represents. Servers may infer this from the endpoint the client 31 | submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' 32 | type: string 33 | metadata: 34 | type: object 35 | spec: 36 | description: Open5GSUserSpec defines the desired state of Open5GSUser 37 | properties: 38 | apn: 39 | type: string 40 | imsi: 41 | type: string 42 | key: 43 | type: string 44 | opc: 45 | type: string 46 | open5gs: 47 | description: Open5GSReference defines the reference to an Open5GS instance 48 | properties: 49 | name: 50 | type: string 51 | namespace: 52 | type: string 53 | type: object 54 | sd: 55 | type: string 56 | sst: 57 | type: string 58 | type: object 59 | status: 60 | description: Open5GSUserStatus defines the observed state of Open5GSUser 61 | type: object 62 | type: object 63 | served: true 64 | storage: true 65 | subresources: 66 | status: {} 67 | status: 68 | acceptedNames: 69 | kind: "" 70 | plural: "" 71 | conditions: [] 72 | storedVersions: [] -------------------------------------------------------------------------------- /internal/controller/open5gsuser_controller_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | 22 | . "github.com/onsi/ginkgo/v2" 23 | . "github.com/onsi/gomega" 24 | "k8s.io/apimachinery/pkg/api/errors" 25 | "k8s.io/apimachinery/pkg/types" 26 | "sigs.k8s.io/controller-runtime/pkg/reconcile" 27 | 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | 30 | netv1 "gradiant/open5gs-legacy-operator/api/v1" 31 | ) 32 | 33 | var _ = Describe("Open5GSUser Controller", func() { 34 | Context("When reconciling a resource", func() { 35 | const resourceName = "test-resource" 36 | 37 | ctx := context.Background() 38 | 39 | typeNamespacedName := types.NamespacedName{ 40 | Name: resourceName, 41 | Namespace: "default", // TODO(user):Modify as needed 42 | } 43 | open5gsuser := &netv1.Open5GSUser{} 44 | 45 | BeforeEach(func() { 46 | By("creating the custom resource for the Kind Open5GSUser") 47 | err := k8sClient.Get(ctx, typeNamespacedName, open5gsuser) 48 | if err != nil && errors.IsNotFound(err) { 49 | resource := &netv1.Open5GSUser{ 50 | ObjectMeta: metav1.ObjectMeta{ 51 | Name: resourceName, 52 | Namespace: "default", 53 | }, 54 | // TODO(user): Specify other spec details if needed. 55 | } 56 | Expect(k8sClient.Create(ctx, resource)).To(Succeed()) 57 | } 58 | }) 59 | 60 | AfterEach(func() { 61 | // TODO(user): Cleanup logic after each test, like removing the resource instance. 62 | resource := &netv1.Open5GSUser{} 63 | err := k8sClient.Get(ctx, typeNamespacedName, resource) 64 | Expect(err).NotTo(HaveOccurred()) 65 | 66 | By("Cleanup the specific resource instance Open5GSUser") 67 | Expect(k8sClient.Delete(ctx, resource)).To(Succeed()) 68 | }) 69 | It("should successfully reconcile the resource", func() { 70 | By("Reconciling the created resource") 71 | controllerReconciler := &Open5GSUserReconciler{ 72 | Client: k8sClient, 73 | Scheme: k8sClient.Scheme(), 74 | } 75 | 76 | _, err := controllerReconciler.Reconcile(ctx, reconcile.Request{ 77 | NamespacedName: typeNamespacedName, 78 | }) 79 | Expect(err).NotTo(HaveOccurred()) 80 | // TODO(user): Add more specific assertions depending on your controller's reconciliation logic. 81 | // Example: If you expect a certain status condition after reconciliation, verify it here. 82 | }) 83 | }) 84 | }) 85 | -------------------------------------------------------------------------------- /internal/controller/suite_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "fmt" 21 | "path/filepath" 22 | "runtime" 23 | "testing" 24 | 25 | . "github.com/onsi/ginkgo/v2" 26 | . "github.com/onsi/gomega" 27 | 28 | "k8s.io/client-go/kubernetes/scheme" 29 | "k8s.io/client-go/rest" 30 | "sigs.k8s.io/controller-runtime/pkg/client" 31 | "sigs.k8s.io/controller-runtime/pkg/envtest" 32 | logf "sigs.k8s.io/controller-runtime/pkg/log" 33 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 34 | 35 | netv1 "gradiant/open5gs-legacy-operator/api/v1" 36 | //+kubebuilder:scaffold:imports 37 | ) 38 | 39 | // These tests use Ginkgo (BDD-style Go testing framework). Refer to 40 | // http://onsi.github.io/ginkgo/ to learn more about Ginkgo. 41 | 42 | var cfg *rest.Config 43 | var k8sClient client.Client 44 | var testEnv *envtest.Environment 45 | 46 | func TestControllers(t *testing.T) { 47 | RegisterFailHandler(Fail) 48 | 49 | RunSpecs(t, "Controller Suite") 50 | } 51 | 52 | var _ = BeforeSuite(func() { 53 | logf.SetLogger(zap.New(zap.WriteTo(GinkgoWriter), zap.UseDevMode(true))) 54 | 55 | By("bootstrapping test environment") 56 | testEnv = &envtest.Environment{ 57 | CRDDirectoryPaths: []string{filepath.Join("..", "..", "config", "crd", "bases")}, 58 | ErrorIfCRDPathMissing: true, 59 | 60 | // The BinaryAssetsDirectory is only required if you want to run the tests directly 61 | // without call the makefile target test. If not informed it will look for the 62 | // default path defined in controller-runtime which is /usr/local/kubebuilder/. 63 | // Note that you must have the required binaries setup under the bin directory to perform 64 | // the tests directly. When we run make test it will be setup and used automatically. 65 | BinaryAssetsDirectory: filepath.Join("..", "..", "bin", "k8s", 66 | fmt.Sprintf("1.28.3-%s-%s", runtime.GOOS, runtime.GOARCH)), 67 | } 68 | 69 | var err error 70 | // cfg is defined in this file globally. 71 | cfg, err = testEnv.Start() 72 | Expect(err).NotTo(HaveOccurred()) 73 | Expect(cfg).NotTo(BeNil()) 74 | 75 | err = netv1.AddToScheme(scheme.Scheme) 76 | Expect(err).NotTo(HaveOccurred()) 77 | 78 | //+kubebuilder:scaffold:scheme 79 | 80 | k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) 81 | Expect(err).NotTo(HaveOccurred()) 82 | Expect(k8sClient).NotTo(BeNil()) 83 | 84 | }) 85 | 86 | var _ = AfterSuite(func() { 87 | By("tearing down the test environment") 88 | err := testEnv.Stop() 89 | Expect(err).NotTo(HaveOccurred()) 90 | }) 91 | -------------------------------------------------------------------------------- /helm-charts/open5gs/scp-values.yaml: -------------------------------------------------------------------------------- 1 | dbURI: "mongodb://{{ .Release.Name }}-mongodb/open5gs" 2 | 3 | populate: 4 | enabled: true 5 | image: 6 | registry: docker.io 7 | repository: gradiant/open5gs-dbctl 8 | tag: 0.10.3 9 | pullPolicy: IfNotPresent 10 | initCommands: 11 | - open5gs-dbctl add_ue_with_slice 999700000000001 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 1 111111 12 | - open5gs-dbctl add_ue_with_slice 999700000000002 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 1 111111 13 | # example of initCommands: 14 | # - open5gs-dbctl add 999700000000001 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA 15 | # - open5gs-dbctl add_ue_with_apn 999700000000002 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 16 | # - open5gs-dbctl add_ue_with_slice 999700000000003 465B5CE8B199B49FAA5F0A2EE238A6BC E8ED289DEBA952E4283B54E88E6183CA internet 1 111111 17 | 18 | # Common 19 | mongodb: 20 | enabled: true 21 | auth: 22 | enabled: false 23 | smf: 24 | enabled: true 25 | config: 26 | sbi: 27 | client: 28 | scp: 29 | enabled: true 30 | pcrf: 31 | enabled: false 32 | upf: 33 | enabled: true 34 | webui: 35 | enabled: true 36 | 37 | # 4G 38 | hss: 39 | enabled: false 40 | mongodb: 41 | enabled: false 42 | mme: 43 | enabled: false 44 | pcrf: 45 | enabled: false 46 | mongodb: 47 | enabled: false 48 | sgwc: 49 | enabled: false 50 | sgwu: 51 | enabled: false 52 | 53 | # 5G 54 | amf: 55 | enabled: true 56 | config: 57 | sbi: 58 | client: 59 | scp: 60 | enabled: true 61 | guamiList: 62 | - plmn_id: 63 | mcc: "999" 64 | mnc: "70" 65 | amf_id: 66 | region: 2 67 | set: 1 68 | taiList: 69 | - plmn_id: 70 | mcc: "999" 71 | mnc: "70" 72 | tac: [1] 73 | plmnList: 74 | - plmn_id: 75 | mcc: "999" 76 | mnc: "70" 77 | s_nssai: 78 | - sst: 1 79 | sd: "0x111111" 80 | ausf: 81 | enabled: true 82 | config: 83 | sbi: 84 | client: 85 | scp: 86 | enabled: true 87 | bsf: 88 | enabled: true 89 | config: 90 | sbi: 91 | client: 92 | scp: 93 | enabled: true 94 | nrf: 95 | enabled: true 96 | nssf: 97 | enabled: true 98 | config: 99 | sbi: 100 | client: 101 | scp: 102 | enabled: true 103 | nsiList: 104 | - nrf: 105 | hostname: "" # if empty default is autogenerated open5gs svc fullname 106 | port: 7777 107 | sst: 1 108 | sd: "0x111111" 109 | pcf: 110 | enabled: true 111 | config: 112 | sbi: 113 | client: 114 | scp: 115 | enabled: true 116 | mongodb: 117 | enabled: false 118 | udm: 119 | enabled: true 120 | config: 121 | sbi: 122 | client: 123 | scp: 124 | enabled: true 125 | udr: 126 | enabled: true 127 | config: 128 | sbi: 129 | client: 130 | scp: 131 | enabled: true 132 | mongodb: 133 | enabled: false 134 | scp: 135 | enabled: true 136 | mongodb: 137 | enabled: false 138 | -------------------------------------------------------------------------------- /helm-charts/open5gs/Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | appVersion: "2.7.0" 3 | description: > 4 | Helm chart to deploy Open5gs services on Kubernetes. 5 | home: https://github.com/gradiant/openverso-charts 6 | sources: 7 | - http://open5gs.org 8 | icon: https://open5gs.org/assets/img/open5gs-logo.png 9 | maintainers: 10 | - email: cgiraldo@gradiant.org 11 | name: cgiraldo 12 | name: open5gs 13 | version: 2.2.2 14 | annotations: 15 | artifacthub.io/category: networking 16 | keywords: 17 | - network 18 | - epc 19 | - ngc 20 | - gradiant 21 | dependencies: 22 | - name: common 23 | repository: https://charts.bitnami.com/bitnami 24 | tags: 25 | - bitnami-common 26 | version: 1.x.x 27 | - name: mongodb 28 | version: ~12.1.19 29 | repository: https://charts.bitnami.com/bitnami 30 | condition: mongodb.enabled 31 | - name: open5gs-amf 32 | version: ~2.2.0 33 | repository: file://../open5gs-amf 34 | condition: amf.enabled 35 | alias: amf 36 | - name: open5gs-ausf 37 | version: ~2.2.0 38 | repository: file://../open5gs-ausf 39 | condition: ausf.enabled 40 | alias: ausf 41 | - name: open5gs-bsf 42 | version: ~2.2.0 43 | repository: file://../open5gs-bsf 44 | condition: bsf.enabled 45 | alias: bsf 46 | - name: open5gs-hss 47 | version: ~2.2.0 48 | repository: file://../open5gs-hss 49 | condition: hss.enabled 50 | alias: hss 51 | - name: open5gs-mme 52 | version: ~2.2.0 53 | repository: file://../open5gs-mme 54 | condition: mme.enabled 55 | alias: mme 56 | - name: open5gs-nrf 57 | version: ~2.2.0 58 | repository: file://../open5gs-nrf 59 | condition: nrf.enabled 60 | alias: nrf 61 | - name: open5gs-nssf 62 | version: ~2.2.0 63 | repository: file://../open5gs-nssf 64 | condition: nssf.enabled 65 | alias: nssf 66 | - name: open5gs-pcf 67 | version: ~2.2.0 68 | repository: file://../open5gs-pcf 69 | condition: pcf.enabled 70 | alias: pcf 71 | - name: open5gs-pcrf 72 | version: ~2.2.0 73 | repository: file://../open5gs-pcrf 74 | condition: pcrf.enabled 75 | alias: pcrf 76 | - name: open5gs-scp 77 | version: ~2.2.0 78 | repository: file://../open5gs-scp 79 | condition: scp.enabled 80 | alias: scp 81 | - name: open5gs-sgwc 82 | version: ~2.2.0 83 | repository: file://../open5gs-sgwc 84 | condition: sgwc.enabled 85 | alias: sgwc 86 | - name: open5gs-sgwu 87 | version: ~2.2.0 88 | repository: file://../open5gs-sgwu 89 | condition: sgwu.enabled 90 | alias: sgwu 91 | - name: open5gs-smf 92 | version: ~2.2.0 93 | repository: file://../open5gs-smf 94 | condition: smf.enabled 95 | alias: smf 96 | - name: open5gs-udm 97 | version: ~2.2.0 98 | repository: file://../open5gs-udm 99 | condition: udm.enabled 100 | alias: udm 101 | - name: open5gs-udr 102 | version: ~2.2.0 103 | repository: file://../open5gs-udr 104 | condition: udr.enabled 105 | alias: udr 106 | - name: open5gs-upf 107 | version: ~2.2.0 108 | repository: file://../open5gs-upf 109 | condition: upf.enabled 110 | alias: upf 111 | - name: open5gs-webui 112 | version: ~2.2.0 113 | repository: file://../open5gs-webui 114 | condition: webui.enabled 115 | alias: webui 116 | -------------------------------------------------------------------------------- /api/v1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | 3 | // Code generated by controller-gen. DO NOT EDIT. 4 | 5 | package v1 6 | 7 | import ( 8 | runtime "k8s.io/apimachinery/pkg/runtime" 9 | ) 10 | 11 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 12 | func (in *Open5GSReference) DeepCopyInto(out *Open5GSReference) { 13 | *out = *in 14 | } 15 | 16 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Open5GSReference. 17 | func (in *Open5GSReference) DeepCopy() *Open5GSReference { 18 | if in == nil { 19 | return nil 20 | } 21 | out := new(Open5GSReference) 22 | in.DeepCopyInto(out) 23 | return out 24 | } 25 | 26 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 27 | func (in *Open5GSUser) DeepCopyInto(out *Open5GSUser) { 28 | *out = *in 29 | out.TypeMeta = in.TypeMeta 30 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 31 | out.Spec = in.Spec 32 | out.Status = in.Status 33 | } 34 | 35 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Open5GSUser. 36 | func (in *Open5GSUser) DeepCopy() *Open5GSUser { 37 | if in == nil { 38 | return nil 39 | } 40 | out := new(Open5GSUser) 41 | in.DeepCopyInto(out) 42 | return out 43 | } 44 | 45 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 46 | func (in *Open5GSUser) DeepCopyObject() runtime.Object { 47 | if c := in.DeepCopy(); c != nil { 48 | return c 49 | } 50 | return nil 51 | } 52 | 53 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 54 | func (in *Open5GSUserList) DeepCopyInto(out *Open5GSUserList) { 55 | *out = *in 56 | out.TypeMeta = in.TypeMeta 57 | in.ListMeta.DeepCopyInto(&out.ListMeta) 58 | if in.Items != nil { 59 | in, out := &in.Items, &out.Items 60 | *out = make([]Open5GSUser, len(*in)) 61 | for i := range *in { 62 | (*in)[i].DeepCopyInto(&(*out)[i]) 63 | } 64 | } 65 | } 66 | 67 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Open5GSUserList. 68 | func (in *Open5GSUserList) DeepCopy() *Open5GSUserList { 69 | if in == nil { 70 | return nil 71 | } 72 | out := new(Open5GSUserList) 73 | in.DeepCopyInto(out) 74 | return out 75 | } 76 | 77 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 78 | func (in *Open5GSUserList) DeepCopyObject() runtime.Object { 79 | if c := in.DeepCopy(); c != nil { 80 | return c 81 | } 82 | return nil 83 | } 84 | 85 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 86 | func (in *Open5GSUserSpec) DeepCopyInto(out *Open5GSUserSpec) { 87 | *out = *in 88 | out.Open5GS = in.Open5GS 89 | } 90 | 91 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Open5GSUserSpec. 92 | func (in *Open5GSUserSpec) DeepCopy() *Open5GSUserSpec { 93 | if in == nil { 94 | return nil 95 | } 96 | out := new(Open5GSUserSpec) 97 | in.DeepCopyInto(out) 98 | return out 99 | } 100 | 101 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 102 | func (in *Open5GSUserStatus) DeepCopyInto(out *Open5GSUserStatus) { 103 | *out = *in 104 | } 105 | 106 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Open5GSUserStatus. 107 | func (in *Open5GSUserStatus) DeepCopy() *Open5GSUserStatus { 108 | if in == nil { 109 | return nil 110 | } 111 | out := new(Open5GSUserStatus) 112 | in.DeepCopyInto(out) 113 | return out 114 | } 115 | -------------------------------------------------------------------------------- /config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | app.kubernetes.io/name: namespace 7 | app.kubernetes.io/instance: system 8 | app.kubernetes.io/component: manager 9 | app.kubernetes.io/created-by: open5gs-operator 10 | app.kubernetes.io/part-of: open5gs-operator 11 | app.kubernetes.io/managed-by: kustomize 12 | name: system 13 | --- 14 | apiVersion: apps/v1 15 | kind: Deployment 16 | metadata: 17 | name: controller-manager 18 | namespace: system 19 | labels: 20 | control-plane: controller-manager 21 | app.kubernetes.io/name: deployment 22 | app.kubernetes.io/instance: controller-manager 23 | app.kubernetes.io/component: manager 24 | app.kubernetes.io/created-by: open5gs-operator 25 | app.kubernetes.io/part-of: open5gs-operator 26 | app.kubernetes.io/managed-by: kustomize 27 | spec: 28 | selector: 29 | matchLabels: 30 | control-plane: controller-manager 31 | replicas: 1 32 | template: 33 | metadata: 34 | annotations: 35 | kubectl.kubernetes.io/default-container: manager 36 | labels: 37 | control-plane: controller-manager 38 | spec: 39 | # TODO(user): Uncomment the following code to configure the nodeAffinity expression 40 | # according to the platforms which are supported by your solution. 41 | # It is considered best practice to support multiple architectures. You can 42 | # build your manager image using the makefile target docker-buildx. 43 | # affinity: 44 | # nodeAffinity: 45 | # requiredDuringSchedulingIgnoredDuringExecution: 46 | # nodeSelectorTerms: 47 | # - matchExpressions: 48 | # - key: kubernetes.io/arch 49 | # operator: In 50 | # values: 51 | # - amd64 52 | # - arm64 53 | # - ppc64le 54 | # - s390x 55 | # - key: kubernetes.io/os 56 | # operator: In 57 | # values: 58 | # - linux 59 | securityContext: 60 | runAsNonRoot: true 61 | # TODO(user): For common cases that do not require escalating privileges 62 | # it is recommended to ensure that all your Pods/Containers are restrictive. 63 | # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted 64 | # Please uncomment the following code if your project does NOT have to work on old Kubernetes 65 | # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). 66 | # seccompProfile: 67 | # type: RuntimeDefault 68 | containers: 69 | - args: 70 | - --leader-elect 71 | - --leader-election-id=open5gs-operator 72 | image: controller:latest 73 | name: manager 74 | securityContext: 75 | allowPrivilegeEscalation: false 76 | capabilities: 77 | drop: 78 | - "ALL" 79 | livenessProbe: 80 | httpGet: 81 | path: /healthz 82 | port: 8081 83 | initialDelaySeconds: 15 84 | periodSeconds: 20 85 | readinessProbe: 86 | httpGet: 87 | path: /readyz 88 | port: 8081 89 | initialDelaySeconds: 5 90 | periodSeconds: 10 91 | # TODO(user): Configure the resources accordingly based on the project requirements. 92 | # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ 93 | resources: 94 | # limits: 95 | # cpu: 1 96 | # memory: 256Mi 97 | requests: 98 | cpu: 100m 99 | memory: 128Mi 100 | serviceAccountName: controller-manager 101 | terminationGracePeriodSeconds: 10 102 | -------------------------------------------------------------------------------- /helm-charts/open5gs/README.md: -------------------------------------------------------------------------------- 1 | # open5gs 2 | 3 | ![Version: 2.1.0](https://img.shields.io/badge/Version-2.1.0-informational?style=flat-square) ![AppVersion: 2.4.11](https://img.shields.io/badge/AppVersion-2.4.11-informational?style=flat-square) 4 | 5 | Helm chart to deploy Open5gs services on Kubernetes. 6 | 7 | **Homepage:** 8 | 9 | ## Maintainers 10 | 11 | | Name | Email | Url | 12 | | ---- | ------ | --- | 13 | | cgiraldo | | | 14 | 15 | ## Source Code 16 | 17 | * 18 | 19 | ## Requirements 20 | 21 | | Repository | Name | Version | 22 | |------------|------|---------| 23 | | file://../open5gs-amf | amf(open5gs-amf) | ~2.1.0 | 24 | | file://../open5gs-ausf | ausf(open5gs-ausf) | ~2.1.0 | 25 | | file://../open5gs-bsf | bsf(open5gs-bsf) | ~2.1.0 | 26 | | file://../open5gs-hss | hss(open5gs-hss) | ~2.1.0 | 27 | | file://../open5gs-mme | mme(open5gs-mme) | ~2.1.0 | 28 | | file://../open5gs-nrf | nrf(open5gs-nrf) | ~2.1.0 | 29 | | file://../open5gs-nssf | nssf(open5gs-nssf) | ~2.1.0 | 30 | | file://../open5gs-pcf | pcf(open5gs-pcf) | ~2.1.0 | 31 | | file://../open5gs-pcrf | pcrf(open5gs-pcrf) | ~2.1.0 | 32 | | file://../open5gs-scp | scp(open5gs-scp) | ~2.1.0 | 33 | | file://../open5gs-sgwc | sgwc(open5gs-sgwc) | ~2.1.0 | 34 | | file://../open5gs-sgwu | sgwu(open5gs-sgwu) | ~2.1.0 | 35 | | file://../open5gs-smf | smf(open5gs-smf) | ~2.1.0 | 36 | | file://../open5gs-udm | udm(open5gs-udm) | ~2.1.0 | 37 | | file://../open5gs-udr | udr(open5gs-udr) | ~2.1.0 | 38 | | file://../open5gs-upf | upf(open5gs-upf) | ~2.1.0 | 39 | | file://../open5gs-webui | webui(open5gs-webui) | ~2.1.0 | 40 | | https://charts.bitnami.com/bitnami | common | 1.x.x | 41 | | https://charts.bitnami.com/bitnami | mongodb | ~12.1.19 | 42 | 43 | ## Values 44 | 45 | | Key | Type | Default | Description | 46 | |-----|------|---------|-------------| 47 | | amf.enabled | bool | `true` | | 48 | | amf.image.tag | string | `"2.6.4"` | | 49 | | ausf.enabled | bool | `true` | | 50 | | ausf.image.tag | string | `"2.6.4"` | | 51 | | bsf.enabled | bool | `true` | | 52 | | bsf.image.tag | string | `"2.6.4"` | | 53 | | dbURI | string | `"mongodb://{{ .Release.Name }}-mongodb/open5gs"` | | 54 | | hss.enabled | bool | `true` | | 55 | | hss.image.tag | string | `"2.6.4"` | | 56 | | hss.mongodb.enabled | bool | `false` | | 57 | | mme.enabled | bool | `true` | | 58 | | mme.image.tag | string | `"2.6.4"` | | 59 | | mongodb.auth.enabled | bool | `false` | | 60 | | mongodb.enabled | bool | `true` | | 61 | | nrf.enabled | bool | `true` | | 62 | | nrf.image.tag | string | `"2.6.4"` | | 63 | | nssf.enabled | bool | `true` | | 64 | | nssf.image.tag | string | `"2.6.4"` | | 65 | | pcf.enabled | bool | `true` | | 66 | | pcf.image.tag | string | `"2.6.4"` | | 67 | | pcf.mongodb.enabled | bool | `false` | | 68 | | pcrf.enabled | bool | `true` | | 69 | | pcrf.image.tag | string | `"2.6.4"` | | 70 | | pcrf.mongodb.enabled | bool | `false` | | 71 | | populate.enabled | bool | `true` | | 72 | | populate.image.pullPolicy | string | `"IfNotPresent"` | | 73 | | populate.image.registry | string | `"docker.io"` | | 74 | | populate.image.repository | string | `"gradiant/open5gs-dbctl"` | | 75 | | populate.image.tag | string | `"0.10.2"` | | 76 | | populate.initCommands | list | `[]` | | 77 | | scp.enabled | bool | `false` | | 78 | | scp.image.tag | string | `"2.6.4"` | | 79 | | scp.mongodb.enabled | bool | `false` | | 80 | | sgwc.enabled | bool | `true` | | 81 | | sgwc.image.tag | string | `"2.6.4"` | | 82 | | sgwu.enabled | bool | `true` | | 83 | | sgwu.image.tag | string | `"2.6.4"` | | 84 | | smf.enabled | bool | `true` | | 85 | | smf.image.tag | string | `"2.6.4"` | | 86 | | udm.enabled | bool | `true` | | 87 | | udm.image.tag | string | `"2.6.4"` | | 88 | | udr.enabled | bool | `true` | | 89 | | udr.image.tag | string | `"2.6.4"` | | 90 | | udr.mongodb.enabled | bool | `false` | | 91 | | upf.enabled | bool | `true` | | 92 | | upf.image.tag | string | `"2.6.4"` | | 93 | | webui.enabled | bool | `true` | | 94 | | webui.image.tag | string | `"2.6.4"` | | 95 | 96 | ---------------------------------------------- 97 | Autogenerated from chart metadata using [helm-docs v1.11.0](https://github.com/norwoodj/helm-docs/releases/v1.11.0) 98 | -------------------------------------------------------------------------------- /config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: manager-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - "" 21 | resources: 22 | - events 23 | verbs: 24 | - create 25 | - get 26 | - list 27 | - patch 28 | - update 29 | - watch 30 | - apiGroups: 31 | - "" 32 | resources: 33 | - namespaces 34 | verbs: 35 | - get 36 | - list 37 | - watch 38 | - apiGroups: 39 | - "" 40 | resources: 41 | - persistentvolumeclaims 42 | verbs: 43 | - create 44 | - delete 45 | - get 46 | - list 47 | - patch 48 | - update 49 | - watch 50 | - apiGroups: 51 | - "" 52 | resources: 53 | - pods 54 | verbs: 55 | - create 56 | - delete 57 | - get 58 | - list 59 | - patch 60 | - update 61 | - watch 62 | - apiGroups: 63 | - "" 64 | resources: 65 | - secrets 66 | verbs: 67 | - create 68 | - delete 69 | - get 70 | - list 71 | - patch 72 | - update 73 | - watch 74 | - apiGroups: 75 | - "" 76 | resources: 77 | - serviceaccounts 78 | verbs: 79 | - create 80 | - delete 81 | - get 82 | - list 83 | - patch 84 | - update 85 | - watch 86 | - apiGroups: 87 | - "" 88 | resources: 89 | - services 90 | verbs: 91 | - create 92 | - delete 93 | - get 94 | - list 95 | - patch 96 | - update 97 | - watch 98 | - apiGroups: 99 | - apps 100 | resources: 101 | - deployments 102 | verbs: 103 | - create 104 | - delete 105 | - get 106 | - list 107 | - patch 108 | - update 109 | - watch 110 | - apiGroups: 111 | - apps 112 | resources: 113 | - statefulsets 114 | verbs: 115 | - create 116 | - delete 117 | - get 118 | - list 119 | - patch 120 | - update 121 | - watch 122 | - apiGroups: 123 | - autoscaling 124 | resources: 125 | - horizontalpodautoscalers 126 | verbs: 127 | - create 128 | - delete 129 | - get 130 | - list 131 | - patch 132 | - update 133 | - watch 134 | - apiGroups: 135 | - batch 136 | resources: 137 | - cronjobs 138 | verbs: 139 | - create 140 | - delete 141 | - get 142 | - list 143 | - patch 144 | - update 145 | - watch 146 | - apiGroups: 147 | - batch 148 | resources: 149 | - jobs 150 | verbs: 151 | - create 152 | - delete 153 | - get 154 | - list 155 | - patch 156 | - update 157 | - watch 158 | - apiGroups: 159 | - helm.toolkit.fluxcd.io 160 | resources: 161 | - helmreleases 162 | verbs: 163 | - create 164 | - delete 165 | - get 166 | - list 167 | - patch 168 | - update 169 | - watch 170 | - apiGroups: 171 | - monitoring.coreos.com 172 | resources: 173 | - servicemonitors 174 | verbs: 175 | - create 176 | - delete 177 | - get 178 | - list 179 | - patch 180 | - update 181 | - watch 182 | - apiGroups: 183 | - net.gradiant.org 184 | resources: 185 | - open5gs 186 | verbs: 187 | - create 188 | - delete 189 | - get 190 | - list 191 | - patch 192 | - update 193 | - watch 194 | - apiGroups: 195 | - net.gradiant.org 196 | resources: 197 | - open5gs/finalizers 198 | verbs: 199 | - update 200 | - apiGroups: 201 | - net.gradiant.org 202 | resources: 203 | - open5gs/status 204 | verbs: 205 | - get 206 | - patch 207 | - update 208 | - apiGroups: 209 | - net.gradiant.org 210 | resources: 211 | - open5gsusers 212 | verbs: 213 | - create 214 | - delete 215 | - get 216 | - list 217 | - patch 218 | - update 219 | - watch 220 | - apiGroups: 221 | - networking.k8s.io 222 | resources: 223 | - ingresses 224 | verbs: 225 | - create 226 | - delete 227 | - get 228 | - list 229 | - patch 230 | - update 231 | - watch 232 | - apiGroups: 233 | - networking.k8s.io 234 | resources: 235 | - networkpolicies 236 | verbs: 237 | - create 238 | - delete 239 | - get 240 | - list 241 | - patch 242 | - update 243 | - watch 244 | - apiGroups: 245 | - policy 246 | resources: 247 | - poddisruptionbudgets 248 | verbs: 249 | - create 250 | - delete 251 | - get 252 | - list 253 | - patch 254 | - update 255 | - watch 256 | - apiGroups: 257 | - rbac.authorization.k8s.io 258 | resources: 259 | - rolebindings 260 | verbs: 261 | - create 262 | - delete 263 | - get 264 | - list 265 | - patch 266 | - update 267 | - watch 268 | - apiGroups: 269 | - rbac.authorization.k8s.io 270 | resources: 271 | - roles 272 | verbs: 273 | - create 274 | - delete 275 | - get 276 | - list 277 | - patch 278 | - update 279 | - watch 280 | -------------------------------------------------------------------------------- /charts/open5gs-legacy-operator-chart/templates/manager-rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: {{ include "open5gs-operator.fullname" . }}-manager-role 5 | labels: 6 | {{- include "open5gs-operator.labels" . | nindent 4 }} 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - configmaps 12 | verbs: 13 | - create 14 | - delete 15 | - get 16 | - list 17 | - patch 18 | - update 19 | - watch 20 | - apiGroups: 21 | - "" 22 | resources: 23 | - events 24 | verbs: 25 | - create 26 | - get 27 | - list 28 | - patch 29 | - update 30 | - watch 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - namespaces 35 | verbs: 36 | - get 37 | - list 38 | - watch 39 | - apiGroups: 40 | - "" 41 | resources: 42 | - persistentvolumeclaims 43 | verbs: 44 | - create 45 | - delete 46 | - get 47 | - list 48 | - patch 49 | - update 50 | - watch 51 | - apiGroups: 52 | - "" 53 | resources: 54 | - pods 55 | verbs: 56 | - create 57 | - delete 58 | - get 59 | - list 60 | - patch 61 | - update 62 | - watch 63 | - apiGroups: 64 | - "" 65 | resources: 66 | - secrets 67 | verbs: 68 | - create 69 | - delete 70 | - get 71 | - list 72 | - patch 73 | - update 74 | - watch 75 | - apiGroups: 76 | - "" 77 | resources: 78 | - serviceaccounts 79 | verbs: 80 | - create 81 | - delete 82 | - get 83 | - list 84 | - patch 85 | - update 86 | - watch 87 | - apiGroups: 88 | - "" 89 | resources: 90 | - services 91 | verbs: 92 | - create 93 | - delete 94 | - get 95 | - list 96 | - patch 97 | - update 98 | - watch 99 | - apiGroups: 100 | - apps 101 | resources: 102 | - deployments 103 | verbs: 104 | - create 105 | - delete 106 | - get 107 | - list 108 | - patch 109 | - update 110 | - watch 111 | - apiGroups: 112 | - apps 113 | resources: 114 | - statefulsets 115 | verbs: 116 | - create 117 | - delete 118 | - get 119 | - list 120 | - patch 121 | - update 122 | - watch 123 | - apiGroups: 124 | - autoscaling 125 | resources: 126 | - horizontalpodautoscalers 127 | verbs: 128 | - create 129 | - delete 130 | - get 131 | - list 132 | - patch 133 | - update 134 | - watch 135 | - apiGroups: 136 | - batch 137 | resources: 138 | - cronjobs 139 | verbs: 140 | - create 141 | - delete 142 | - get 143 | - list 144 | - patch 145 | - update 146 | - watch 147 | - apiGroups: 148 | - batch 149 | resources: 150 | - jobs 151 | verbs: 152 | - create 153 | - delete 154 | - get 155 | - list 156 | - patch 157 | - update 158 | - watch 159 | - apiGroups: 160 | - helm.toolkit.fluxcd.io 161 | resources: 162 | - helmreleases 163 | verbs: 164 | - create 165 | - delete 166 | - get 167 | - list 168 | - patch 169 | - update 170 | - watch 171 | - apiGroups: 172 | - monitoring.coreos.com 173 | resources: 174 | - servicemonitors 175 | verbs: 176 | - create 177 | - delete 178 | - get 179 | - list 180 | - patch 181 | - update 182 | - watch 183 | - apiGroups: 184 | - net.gradiant.org 185 | resources: 186 | - open5gs 187 | verbs: 188 | - create 189 | - delete 190 | - get 191 | - list 192 | - patch 193 | - update 194 | - watch 195 | - apiGroups: 196 | - net.gradiant.org 197 | resources: 198 | - open5gs/finalizers 199 | verbs: 200 | - update 201 | - apiGroups: 202 | - net.gradiant.org 203 | resources: 204 | - open5gs/status 205 | verbs: 206 | - get 207 | - patch 208 | - update 209 | - apiGroups: 210 | - net.gradiant.org 211 | resources: 212 | - open5gsusers 213 | verbs: 214 | - create 215 | - delete 216 | - get 217 | - list 218 | - patch 219 | - update 220 | - watch 221 | - apiGroups: 222 | - networking.k8s.io 223 | resources: 224 | - ingresses 225 | verbs: 226 | - create 227 | - delete 228 | - get 229 | - list 230 | - patch 231 | - update 232 | - watch 233 | - apiGroups: 234 | - networking.k8s.io 235 | resources: 236 | - networkpolicies 237 | verbs: 238 | - create 239 | - delete 240 | - get 241 | - list 242 | - patch 243 | - update 244 | - watch 245 | - apiGroups: 246 | - policy 247 | resources: 248 | - poddisruptionbudgets 249 | verbs: 250 | - create 251 | - delete 252 | - get 253 | - list 254 | - patch 255 | - update 256 | - watch 257 | - apiGroups: 258 | - rbac.authorization.k8s.io 259 | resources: 260 | - rolebindings 261 | verbs: 262 | - create 263 | - delete 264 | - get 265 | - list 266 | - patch 267 | - update 268 | - watch 269 | - apiGroups: 270 | - rbac.authorization.k8s.io 271 | resources: 272 | - roles 273 | verbs: 274 | - create 275 | - delete 276 | - get 277 | - list 278 | - patch 279 | - update 280 | - watch 281 | --- 282 | apiVersion: rbac.authorization.k8s.io/v1 283 | kind: ClusterRoleBinding 284 | metadata: 285 | name: {{ include "open5gs-operator.fullname" . }}-manager-rolebinding 286 | labels: 287 | app.kubernetes.io/component: rbac 288 | app.kubernetes.io/created-by: open5gs-operator 289 | app.kubernetes.io/part-of: open5gs-operator 290 | {{- include "open5gs-operator.labels" . | nindent 4 }} 291 | roleRef: 292 | apiGroup: rbac.authorization.k8s.io 293 | kind: ClusterRole 294 | name: '{{ include "open5gs-operator.fullname" . }}-manager-role' 295 | subjects: 296 | - kind: ServiceAccount 297 | name: '{{ include "open5gs-operator.fullname" . }}-controller-manager' 298 | namespace: '{{ .Release.Namespace }}' -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Open5GS Kubernetes Operator 2 | 3 | **⚠️ WARNING: This repository is NO LONGER MAINTAINED. ⚠️** 4 | 5 | **For the updated and maintained version, please visit:** [https://github.com/Gradiant/open5gs-operator](https://github.com/Gradiant/open5gs-operator) 6 | 7 | ## What is it? 8 | 9 | The **Open5GS Kubernetes Operator** is a custom Kubernetes operator designed to automate the deployment, configuration, and lifecycle management of Open5GS and its subscribers in a declarative way. It uses two CRDs (Custom Resource Definitions): one for managing Open5GS deployments and another for managing Open5GS users, allowing efficient and automated core and subscriber management. 10 | 11 | ## Features 12 | 13 | ### Open5GS Deployment and Reconfiguration 14 | 15 | Using the Helm plugin of the Operator SDK, the Open5GS Operator deploys the Open5GS Helm charts developed by Gradiant, enabling the reconfiguration of these deployments as needed. With the 2.2.2 version of the charts, it is possible to modify the configuration of individual Open5GS functions. The controller detects changes and only deletes and restarts the pod of the specific function that needs updating, without affecting the entire core. This is done through a mechanism that generates a hash from the `ConfigMap` contents, allowing the controller to apply updates efficiently while minimizing service downtime. 16 | 17 | ### Multi-Namespace Support 18 | 19 | The operator handles multiple Open5GS deployments across different Kubernetes namespaces, ensuring resource isolation. It can also manage several Open5GS deployments within the same namespace, allowing independent management of each Open5GS instance. 20 | 21 | ### Open5GS Users Management 22 | 23 | The operator provides full management of Open5GS subscribers, including configuration of network slices and the target Open5GS deployment to which they should be assigned. It distinguishes between **Managed Users** and **Unmanaged Users**: 24 | 25 | - **Managed Users**: These are users whose IMSI is defined in a CR (Custom Resource). The operator controls their configuration, and any discrepancy between the actual state and the desired state in the CR will be detected as drift and corrected automatically, ensuring the configuration always aligns with the declarative source of truth. 26 | 27 | - **Unmanaged Users**: These users are not controlled by the operator and are created externally (e.g., via scripts that directly modify the database or the Open5GS WebUI). Unmanaged users will not be altered by the operator, allowing compatibility with external tools and temporary deployments that don't need strict management by the operator. 28 | 29 | ## Prerequisites 30 | 31 | - **Kubernetes**: A running Kubernetes cluster. 32 | - **Helm** (optional): Only if you want to install the operator using the Helm chart. If you prefer not to use Helm, there is an alternative method to install it without Helm. 33 | 34 | ## Development Requirements 35 | 36 | - **Kubernetes**: A running Kubernetes cluster between 1.25 and 1.28. 37 | - **Operator SDK**: OperatorSDK 1.34.1 version 38 | - **Go**: go 1.21.7 version 39 | 40 | ## How to Install 41 | 42 | ### Option 1: Installation using Helm (recommended) 43 | ```bash 44 | helm install open5gs-operator oci://registry-1.docker.io/gradiant/open5gs-legacy-operator-chart --version 0.1.0 45 | ``` 46 | 47 | #### Uninstall with Helm 48 | 49 | Delete all the Open5GS and Open5GSUser resources and run: 50 | 51 | ```bash 52 | helm uninstall open5gs-operator 53 | ``` 54 | 55 | ### Option 2: Installation without Helm 56 | 57 | If you prefer not to use Helm, you can apply the Kubernetes manifests directly or use the Makefile to install de CRD and deploy de operator. 58 | 59 | ```bash 60 | make deploy IMG=gradiant/open5gs-legacy-operator:0.1.0 61 | ``` 62 | 63 | #### Uninstall without Helm 64 | 65 | Delete all the Open5GS and Open5GSUser resources and run: 66 | 67 | ```bash 68 | make undeploy 69 | ``` 70 | 71 | ### Option 3: Run locally (outside the cluster) 72 | 73 | This option is only recommended for development 74 | 75 | ```bash 76 | make install run 77 | ``` 78 | 79 | ## How to Use 80 | 81 | ### Create an Open5GS Deployment 82 | 83 | 1. Create a deployment configuration file for Open5GS. Here’s a basic example: 84 | 85 | ```yaml 86 | apiVersion: net.gradiant.org/v1 87 | kind: Open5GS 88 | metadata: 89 | name: open5gs-1 90 | spec: 91 | hss: 92 | enabled: false 93 | mme: 94 | enabled: false 95 | pcrf: 96 | enabled: false 97 | smf: 98 | config: 99 | pcrf: 100 | enabled: false 101 | sgwc: 102 | enabled: false 103 | sgwu: 104 | enabled: false 105 | amf: 106 | config: 107 | guamiList: 108 | - plmn_id: 109 | mcc: "999" 110 | mnc: "70" 111 | amf_id: 112 | region: 2 113 | set: 1 114 | taiList: 115 | - plmn_id: 116 | mcc: "999" 117 | mnc: "70" 118 | tac: [1] 119 | plmnList: 120 | - plmn_id: 121 | mcc: "999" 122 | mnc: "70" 123 | s_nssai: 124 | - sst: 1 125 | sd: "0x111111" 126 | nssf: 127 | config: 128 | nsiList: 129 | - uri: "" 130 | sst: 1 131 | sd: "0x111111" 132 | webui: 133 | enabled: false 134 | populate: 135 | enabled: false 136 | ``` 137 | 138 | These values are the ones defined in the Gradiant Open5GS Helm Charts. 139 | 140 | 2. Apply the deployment file: 141 | 142 | ```bash 143 | kubectl apply -f open5gs-deployment.yaml 144 | ``` 145 | 146 | ### Create Open5GS Users 147 | 148 | 1. Create a configuration file for the users you want to add. Here’s an example: 149 | 150 | ```yaml 151 | apiVersion: net.gradiant.org/v1 152 | kind: Open5GSUser 153 | metadata: 154 | name: open5gsuser-1 155 | spec: 156 | imsi: "999700000000001" 157 | key: "465B5CE8B199B49FAA5F0A2EE238A6BC" 158 | opc: "E8ED289DEBA952E4283B54E88E6183CA" 159 | sd: "111111" 160 | sst: "1" 161 | apn: "internet" 162 | open5gs: 163 | name: "open5gs-1" 164 | namespace: "default" 165 | ``` 166 | 167 | The apn, sst, and sd fields are optional. If they are not provided in the configuration, default values will be used by the system. 168 | 169 | 2. Apply the user configuration: 170 | 171 | ```bash 172 | kubectl apply -f open5gsuser-1.yaml 173 | ``` 174 | -------------------------------------------------------------------------------- /cmd/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2024. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "crypto/tls" 21 | "flag" 22 | "os" 23 | "runtime" 24 | "time" 25 | 26 | // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) 27 | "github.com/operator-framework/helm-operator-plugins/pkg/annotation" 28 | "github.com/operator-framework/helm-operator-plugins/pkg/reconciler" 29 | "github.com/operator-framework/helm-operator-plugins/pkg/watches" 30 | _ "k8s.io/client-go/plugin/pkg/client/auth" 31 | 32 | ctrlruntime "k8s.io/apimachinery/pkg/runtime" 33 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 34 | clientgoscheme "k8s.io/client-go/kubernetes/scheme" 35 | ctrl "sigs.k8s.io/controller-runtime" 36 | "sigs.k8s.io/controller-runtime/pkg/healthz" 37 | "sigs.k8s.io/controller-runtime/pkg/log/zap" 38 | metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" 39 | "sigs.k8s.io/controller-runtime/pkg/webhook" 40 | 41 | netv1 "gradiant/open5gs-legacy-operator/api/v1" 42 | "gradiant/open5gs-legacy-operator/internal/controller" 43 | //+kubebuilder:scaffold:imports 44 | ) 45 | 46 | var ( 47 | scheme = ctrlruntime.NewScheme() 48 | setupLog = ctrl.Log.WithName("setup") 49 | defaultMaxConcurrentReconciles = runtime.NumCPU() 50 | defaultReconcilePeriod = time.Minute 51 | ) 52 | 53 | func init() { 54 | utilruntime.Must(clientgoscheme.AddToScheme(scheme)) 55 | 56 | utilruntime.Must(netv1.AddToScheme(scheme)) 57 | //+kubebuilder:scaffold:scheme 58 | } 59 | 60 | func main() { 61 | var ( 62 | metricsAddr string 63 | leaderElectionID string 64 | watchesPath string 65 | probeAddr string 66 | enableLeaderElection bool 67 | enableHTTP2 bool 68 | secureMetrics bool 69 | ) 70 | 71 | flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") 72 | flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") 73 | flag.StringVar(&watchesPath, "watches-file", "watches.yaml", "path to watches file") 74 | flag.StringVar(&leaderElectionID, "leader-election-id", "7becc4b8.gradiant.org", "provide leader election") 75 | flag.BoolVar(&enableLeaderElection, "leader-elect", false, 76 | "Enable leader election for controller manager. "+ 77 | "Enabling this will ensure there is only one active controller manager.") 78 | flag.BoolVar(&secureMetrics, "metrics-secure", false, 79 | "Whether or not the metrics endpoint should be served securely") 80 | flag.BoolVar(&enableHTTP2, "enable-http2", false, 81 | "Whether or not HTTP/2 should be enabled for the metrics and webhook servers") 82 | opts := zap.Options{ 83 | Development: true, 84 | } 85 | opts.BindFlags(flag.CommandLine) 86 | flag.Parse() 87 | 88 | ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) 89 | 90 | disableHTTP2 := func(c *tls.Config) { 91 | setupLog.Info("disabling http/2") 92 | c.NextProtos = []string{"http/1.1"} 93 | } 94 | 95 | tlsOpts := []func(*tls.Config){} 96 | if !enableHTTP2 { 97 | tlsOpts = append(tlsOpts, disableHTTP2) 98 | } 99 | 100 | webhookServer := webhook.NewServer(webhook.Options{ 101 | TLSOpts: tlsOpts, 102 | }) 103 | 104 | mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ 105 | Scheme: scheme, 106 | Metrics: metricsserver.Options{ 107 | BindAddress: metricsAddr, 108 | SecureServing: secureMetrics, 109 | TLSOpts: tlsOpts, 110 | }, 111 | WebhookServer: webhookServer, 112 | HealthProbeBindAddress: probeAddr, 113 | LeaderElection: enableLeaderElection, 114 | LeaderElectionID: leaderElectionID, 115 | }) 116 | if err != nil { 117 | setupLog.Error(err, "unable to start manager") 118 | os.Exit(1) 119 | } 120 | 121 | if err = (&controller.Open5GSUserReconciler{ 122 | Client: mgr.GetClient(), 123 | Scheme: mgr.GetScheme(), 124 | }).SetupWithManager(mgr); err != nil { 125 | setupLog.Error(err, "unable to create controller", "controller", "Open5GSUser") 126 | os.Exit(1) 127 | } 128 | //+kubebuilder:scaffold:builder 129 | 130 | if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { 131 | setupLog.Error(err, "unable to set up health check") 132 | os.Exit(1) 133 | } 134 | if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { 135 | setupLog.Error(err, "unable to set up ready check") 136 | os.Exit(1) 137 | } 138 | 139 | ws, err := watches.Load(watchesPath) 140 | if err != nil { 141 | setupLog.Error(err, "Failed to create new manager factories") 142 | os.Exit(1) 143 | } 144 | 145 | for _, w := range ws { 146 | // Register controller with the factory 147 | reconcilePeriod := defaultReconcilePeriod 148 | if w.ReconcilePeriod != nil { 149 | reconcilePeriod = w.ReconcilePeriod.Duration 150 | } 151 | 152 | maxConcurrentReconciles := defaultMaxConcurrentReconciles 153 | if w.MaxConcurrentReconciles != nil { 154 | maxConcurrentReconciles = *w.MaxConcurrentReconciles 155 | } 156 | 157 | r, err := reconciler.New( 158 | reconciler.WithChart(*w.Chart), 159 | reconciler.WithGroupVersionKind(w.GroupVersionKind), 160 | reconciler.WithOverrideValues(w.OverrideValues), 161 | reconciler.SkipDependentWatches(w.WatchDependentResources != nil && !*w.WatchDependentResources), 162 | reconciler.WithMaxConcurrentReconciles(maxConcurrentReconciles), 163 | reconciler.WithReconcilePeriod(reconcilePeriod), 164 | reconciler.WithInstallAnnotations(annotation.DefaultInstallAnnotations...), 165 | reconciler.WithUpgradeAnnotations(annotation.DefaultUpgradeAnnotations...), 166 | reconciler.WithUninstallAnnotations(annotation.DefaultUninstallAnnotations...), 167 | ) 168 | if err != nil { 169 | setupLog.Error(err, "unable to create helm reconciler", "controller", "Helm") 170 | os.Exit(1) 171 | } 172 | if err := r.SetupWithManager(mgr); err != nil { 173 | setupLog.Error(err, "unable to create controller", "controller", "Helm") 174 | os.Exit(1) 175 | } 176 | setupLog.Info("configured watch", "gvk", w.GroupVersionKind, "chartPath", w.ChartPath, "maxConcurrentReconciles", maxConcurrentReconciles, "reconcilePeriod", reconcilePeriod) 177 | } 178 | 179 | setupLog.Info("starting manager") 180 | if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { 181 | setupLog.Error(err, "problem running manager") 182 | os.Exit(1) 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module gradiant/open5gs-legacy-operator 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/onsi/ginkgo/v2 v2.13.0 7 | github.com/onsi/gomega v1.30.0 8 | github.com/operator-framework/helm-operator-plugins v0.1.3 9 | go.mongodb.org/mongo-driver v1.15.0 10 | k8s.io/api v0.28.5 11 | k8s.io/apimachinery v0.28.5 12 | k8s.io/client-go v0.28.5 13 | sigs.k8s.io/controller-runtime v0.16.3 14 | ) 15 | 16 | require ( 17 | github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 // indirect 18 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect 19 | github.com/BurntSushi/toml v1.3.2 // indirect 20 | github.com/MakeNowJust/heredoc v1.0.0 // indirect 21 | github.com/Masterminds/goutils v1.1.1 // indirect 22 | github.com/Masterminds/semver/v3 v3.2.1 // indirect 23 | github.com/Masterminds/sprig/v3 v3.2.3 // indirect 24 | github.com/Masterminds/squirrel v1.5.4 // indirect 25 | github.com/Microsoft/hcsshim v0.11.4 // indirect 26 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect 27 | github.com/beorn7/perks v1.0.1 // indirect 28 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 29 | github.com/chai2010/gettext-go v1.0.2 // indirect 30 | github.com/containerd/containerd v1.7.11 // indirect 31 | github.com/containerd/log v0.1.0 // indirect 32 | github.com/cyphar/filepath-securejoin v0.2.4 // indirect 33 | github.com/davecgh/go-spew v1.1.1 // indirect 34 | github.com/docker/cli v24.0.6+incompatible // indirect 35 | github.com/docker/distribution v2.8.2+incompatible // indirect 36 | github.com/docker/docker v24.0.7+incompatible // indirect 37 | github.com/docker/docker-credential-helpers v0.7.0 // indirect 38 | github.com/docker/go-connections v0.4.0 // indirect 39 | github.com/docker/go-metrics v0.0.1 // indirect 40 | github.com/docker/go-units v0.5.0 // indirect 41 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 42 | github.com/evanphx/json-patch v5.6.0+incompatible // indirect 43 | github.com/evanphx/json-patch/v5 v5.6.0 // indirect 44 | github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f // indirect 45 | github.com/fatih/color v1.13.0 // indirect 46 | github.com/felixge/httpsnoop v1.0.3 // indirect 47 | github.com/fsnotify/fsnotify v1.6.0 // indirect 48 | github.com/go-errors/errors v1.4.2 // indirect 49 | github.com/go-gorp/gorp/v3 v3.1.0 // indirect 50 | github.com/go-logr/logr v1.2.4 // indirect 51 | github.com/go-logr/stdr v1.2.2 // indirect 52 | github.com/go-logr/zapr v1.2.4 // indirect 53 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 54 | github.com/go-openapi/jsonreference v0.20.2 // indirect 55 | github.com/go-openapi/swag v0.22.4 // indirect 56 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect 57 | github.com/gobwas/glob v0.2.3 // indirect 58 | github.com/gogo/protobuf v1.3.2 // indirect 59 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 60 | github.com/golang/protobuf v1.5.3 // indirect 61 | github.com/golang/snappy v0.0.1 // indirect 62 | github.com/google/btree v1.1.2 // indirect 63 | github.com/google/gnostic-models v0.6.8 // indirect 64 | github.com/google/go-cmp v0.6.0 // indirect 65 | github.com/google/gofuzz v1.2.0 // indirect 66 | github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb // indirect 67 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect 68 | github.com/google/uuid v1.3.1 // indirect 69 | github.com/gorilla/mux v1.8.0 // indirect 70 | github.com/gosuri/uitable v0.0.4 // indirect 71 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect 72 | github.com/hashicorp/errwrap v1.1.0 // indirect 73 | github.com/hashicorp/go-multierror v1.1.1 // indirect 74 | github.com/huandu/xstrings v1.4.0 // indirect 75 | github.com/imdario/mergo v0.3.16 // indirect 76 | github.com/inconshreveable/mousetrap v1.1.0 // indirect 77 | github.com/jmoiron/sqlx v1.3.5 // indirect 78 | github.com/josharian/intern v1.0.0 // indirect 79 | github.com/json-iterator/go v1.1.12 // indirect 80 | github.com/klauspost/compress v1.16.0 // indirect 81 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect 82 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect 83 | github.com/lib/pq v1.10.9 // indirect 84 | github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect 85 | github.com/mailru/easyjson v0.7.7 // indirect 86 | github.com/mattn/go-colorable v0.1.13 // indirect 87 | github.com/mattn/go-isatty v0.0.17 // indirect 88 | github.com/mattn/go-runewidth v0.0.14 // indirect 89 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect 90 | github.com/mitchellh/copystructure v1.2.0 // indirect 91 | github.com/mitchellh/go-wordwrap v1.0.1 // indirect 92 | github.com/mitchellh/reflectwalk v1.0.2 // indirect 93 | github.com/moby/locker v1.0.1 // indirect 94 | github.com/moby/spdystream v0.2.0 // indirect 95 | github.com/moby/term v0.5.0 // indirect 96 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 97 | github.com/modern-go/reflect2 v1.0.2 // indirect 98 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect 99 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect 100 | github.com/morikuni/aec v1.0.0 // indirect 101 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 102 | github.com/opencontainers/go-digest v1.0.0 // indirect 103 | github.com/opencontainers/image-spec v1.1.0-rc5 // indirect 104 | github.com/operator-framework/operator-lib v0.12.0 // indirect 105 | github.com/peterbourgon/diskv v2.0.1+incompatible // indirect 106 | github.com/pkg/errors v0.9.1 // indirect 107 | github.com/prometheus/client_golang v1.18.0 // indirect 108 | github.com/prometheus/client_model v0.5.0 // indirect 109 | github.com/prometheus/common v0.45.0 // indirect 110 | github.com/prometheus/procfs v0.12.0 // indirect 111 | github.com/rivo/uniseg v0.4.2 // indirect 112 | github.com/rubenv/sql-migrate v1.5.2 // indirect 113 | github.com/russross/blackfriday/v2 v2.1.0 // indirect 114 | github.com/sergi/go-diff v1.2.0 // indirect 115 | github.com/shopspring/decimal v1.3.1 // indirect 116 | github.com/sirupsen/logrus v1.9.3 // indirect 117 | github.com/spf13/cast v1.5.0 // indirect 118 | github.com/spf13/cobra v1.8.0 // indirect 119 | github.com/spf13/pflag v1.0.5 // indirect 120 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect 121 | github.com/xdg-go/scram v1.1.2 // indirect 122 | github.com/xdg-go/stringprep v1.0.4 // indirect 123 | github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect 124 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect 125 | github.com/xeipuuv/gojsonschema v1.2.0 // indirect 126 | github.com/xlab/treeprint v1.2.0 // indirect 127 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect 128 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 // indirect 129 | go.opentelemetry.io/otel v1.19.0 // indirect 130 | go.opentelemetry.io/otel/metric v1.19.0 // indirect 131 | go.opentelemetry.io/otel/trace v1.19.0 // indirect 132 | go.starlark.net v0.0.0-20230612165344-9532f5667272 // indirect 133 | go.uber.org/multierr v1.11.0 // indirect 134 | go.uber.org/zap v1.25.0 // indirect 135 | golang.org/x/crypto v0.17.0 // indirect 136 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect 137 | golang.org/x/net v0.17.0 // indirect 138 | golang.org/x/oauth2 v0.12.0 // indirect 139 | golang.org/x/sync v0.4.0 // indirect 140 | golang.org/x/sys v0.15.0 // indirect 141 | golang.org/x/term v0.15.0 // indirect 142 | golang.org/x/text v0.14.0 // indirect 143 | golang.org/x/time v0.3.0 // indirect 144 | golang.org/x/tools v0.14.0 // indirect 145 | gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect 146 | google.golang.org/appengine v1.6.7 // indirect 147 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect 148 | google.golang.org/grpc v1.58.3 // indirect 149 | google.golang.org/protobuf v1.31.0 // indirect 150 | gopkg.in/inf.v0 v0.9.1 // indirect 151 | gopkg.in/yaml.v2 v2.4.0 // indirect 152 | gopkg.in/yaml.v3 v3.0.1 // indirect 153 | helm.sh/helm/v3 v3.13.3 // indirect 154 | k8s.io/apiextensions-apiserver v0.28.5 // indirect 155 | k8s.io/apiserver v0.28.5 // indirect 156 | k8s.io/cli-runtime v0.28.5 // indirect 157 | k8s.io/component-base v0.28.5 // indirect 158 | k8s.io/klog/v2 v2.100.1 // indirect 159 | k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect 160 | k8s.io/kubectl v0.28.5 // indirect 161 | k8s.io/utils v0.0.0-20230505201702-9f6742963106 // indirect 162 | oras.land/oras-go v1.2.4 // indirect 163 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 164 | sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect 165 | sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect 166 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect 167 | sigs.k8s.io/yaml v1.4.0 // indirect 168 | ) 169 | -------------------------------------------------------------------------------- /internal/controller/mongo.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "strconv" 7 | "time" 8 | 9 | netv1 "gradiant/open5gs-legacy-operator/api/v1" 10 | 11 | "go.mongodb.org/mongo-driver/bson" 12 | "go.mongodb.org/mongo-driver/bson/primitive" 13 | "go.mongodb.org/mongo-driver/mongo" 14 | "go.mongodb.org/mongo-driver/mongo/options" 15 | ) 16 | 17 | func updateSubscriber(Open5GSUser netv1.Open5GSUser, mongoURI string) error { 18 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 19 | defer cancel() 20 | 21 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) 22 | if err != nil { 23 | return fmt.Errorf("failed to connect to mongo: %v", err) 24 | } 25 | defer client.Disconnect(ctx) 26 | 27 | collection := client.Database("open5gs").Collection("subscribers") 28 | 29 | updateFields := bson.M{ 30 | "security.k": Open5GSUser.Spec.Key, 31 | "security.opc": Open5GSUser.Spec.OPC, 32 | } 33 | 34 | if Open5GSUser.Spec.SST != "" || Open5GSUser.Spec.SD != "" { 35 | sst, err := strconv.Atoi(Open5GSUser.Spec.SST) 36 | if err != nil { 37 | return fmt.Errorf("failed to convert SST to int: %v", err) 38 | } 39 | updateFields["slice.0.sst"] = sst 40 | updateFields["slice.0.sd"] = Open5GSUser.Spec.SD 41 | } 42 | 43 | updateFields["slice.0.session.0.name"] = Open5GSUser.Spec.APN 44 | 45 | update := bson.M{"$set": updateFields} 46 | filter := bson.M{"imsi": Open5GSUser.Spec.IMSI} 47 | result, err := collection.UpdateOne(ctx, filter, update) 48 | if err != nil { 49 | return fmt.Errorf("failed to update subscriber: %v", err) 50 | } 51 | 52 | if result.MatchedCount == 0 { 53 | return fmt.Errorf("no subscriber found with IMSI %s", Open5GSUser.Spec.IMSI) 54 | } 55 | 56 | return nil 57 | } 58 | 59 | func deleteSubscriber(Open5GSUser netv1.Open5GSUser, mongoURI string) error { 60 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 61 | defer cancel() 62 | 63 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) 64 | if err != nil { 65 | return fmt.Errorf("failed to connect to mongo: %v", err) 66 | } 67 | defer client.Disconnect(ctx) 68 | 69 | collection := client.Database("open5gs").Collection("subscribers") 70 | 71 | result, err := collection.DeleteOne(ctx, bson.M{"imsi": Open5GSUser.Spec.IMSI}) 72 | if err != nil { 73 | return fmt.Errorf("failed to delete subscriber: %v", err) 74 | } 75 | 76 | if result.DeletedCount == 0 { 77 | return fmt.Errorf("no subscriber found with IMSI %s", Open5GSUser.Spec.IMSI) 78 | } 79 | 80 | return nil 81 | } 82 | 83 | func addSubscriberWithSlice(Open5GSUser netv1.Open5GSUser, mongoURI string) error { 84 | 85 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 86 | defer cancel() 87 | 88 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) 89 | if err != nil { 90 | return fmt.Errorf("failed to connect to mongo: %v", err) 91 | } 92 | defer client.Disconnect(ctx) 93 | 94 | collection := client.Database("open5gs").Collection("subscribers") 95 | 96 | sst, err := strconv.Atoi(Open5GSUser.Spec.SST) 97 | if err != nil { 98 | return fmt.Errorf("failed to convert SST to int: %v", err) 99 | } 100 | 101 | subscriber := bson.M{ 102 | "_id": primitive.NewObjectID(), 103 | "schema_version": 1, 104 | "imsi": Open5GSUser.Spec.IMSI, 105 | "msisdn": []string{}, 106 | "imeisv": []string{}, 107 | "mme_host": []string{}, 108 | "mm_realm": []string{}, 109 | "purge_flag": []string{}, 110 | "slice": []bson.M{ 111 | { 112 | "sst": sst, 113 | "sd": Open5GSUser.Spec.SD, 114 | "default_indicator": true, 115 | "session": []bson.M{ 116 | { 117 | "name": Open5GSUser.Spec.APN, 118 | "type": 3, 119 | "qos": bson.M{ 120 | "index": 9, 121 | "arp": bson.M{ 122 | "priority_level": 8, 123 | "pre_emption_capability": 1, 124 | "pre_emption_vulnerability": 2, 125 | }, 126 | }, 127 | "ambr": bson.M{ 128 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 129 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 130 | }, 131 | "pcc_rule": []string{}, 132 | "_id": primitive.NewObjectID(), 133 | }, 134 | }, 135 | "_id": primitive.NewObjectID(), 136 | }, 137 | }, 138 | "security": bson.M{ 139 | "k": Open5GSUser.Spec.Key, 140 | "opc": Open5GSUser.Spec.OPC, 141 | "amf": "8000", 142 | }, 143 | "ambr": bson.M{ 144 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 145 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 146 | }, 147 | "access_restriction_data": 32, 148 | "network_access_mode": 0, 149 | "subscriber_status": 0, 150 | "operator_determined_barring": 0, 151 | "subscribed_rau_tau_timer": 12, 152 | "__v": 0, 153 | } 154 | 155 | _, err = collection.InsertOne(ctx, subscriber) 156 | if err != nil { 157 | return fmt.Errorf("failed to insert subscriber: %v", err) 158 | } 159 | 160 | return nil 161 | } 162 | 163 | func addSubscriberWithAPN(Open5GSUser netv1.Open5GSUser, mongoURI string) error { 164 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 165 | defer cancel() 166 | 167 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) 168 | if err != nil { 169 | return fmt.Errorf("failed to connect to mongo: %v", err) 170 | } 171 | defer client.Disconnect(ctx) 172 | 173 | collection := client.Database("open5gs").Collection("subscribers") 174 | 175 | const defaultSST = 1 176 | 177 | subscriber := bson.M{ 178 | "_id": primitive.NewObjectID(), 179 | "schema_version": 1, 180 | "imsi": Open5GSUser.Spec.IMSI, 181 | "msisdn": []string{}, 182 | "imeisv": []string{}, 183 | "mme_host": []string{}, 184 | "mm_realm": []string{}, 185 | "purge_flag": []string{}, 186 | "slice": []bson.M{ 187 | { 188 | "sst": defaultSST, 189 | "default_indicator": true, 190 | "session": []bson.M{ 191 | { 192 | "name": Open5GSUser.Spec.APN, 193 | "type": 3, 194 | "qos": bson.M{ 195 | "index": 9, 196 | "arp": bson.M{ 197 | "priority_level": 8, 198 | "pre_emption_capability": 1, 199 | "pre_emption_vulnerability": 2, 200 | }, 201 | }, 202 | "ambr": bson.M{ 203 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 204 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 205 | }, 206 | "pcc_rule": []string{}, 207 | "_id": primitive.NewObjectID(), 208 | }, 209 | }, 210 | "_id": primitive.NewObjectID(), 211 | }, 212 | }, 213 | "security": bson.M{ 214 | "k": Open5GSUser.Spec.Key, 215 | "opc": Open5GSUser.Spec.OPC, 216 | "amf": "8000", 217 | }, 218 | "ambr": bson.M{ 219 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 220 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 221 | }, 222 | "access_restriction_data": 32, 223 | "network_access_mode": 0, 224 | "subscriber_status": 0, 225 | "operator_determined_barring": 0, 226 | "subscribed_rau_tau_timer": 12, 227 | "__v": 0, 228 | } 229 | 230 | _, err = collection.InsertOne(ctx, subscriber) 231 | if err != nil { 232 | return fmt.Errorf("failed to insert subscriber: %v", err) 233 | } 234 | 235 | return nil 236 | } 237 | func addSubscriberWithDefaults(Open5GSUser netv1.Open5GSUser, mongoURI string) error { 238 | ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 239 | defer cancel() 240 | 241 | client, err := mongo.Connect(ctx, options.Client().ApplyURI(mongoURI)) 242 | if err != nil { 243 | return fmt.Errorf("failed to connect to mongo: %v", err) 244 | } 245 | defer client.Disconnect(ctx) 246 | 247 | collection := client.Database("open5gs").Collection("subscribers") 248 | 249 | const defaultSST = 1 250 | const defaultAPN = "internet" 251 | 252 | subscriber := bson.M{ 253 | "_id": primitive.NewObjectID(), 254 | "schema_version": 1, 255 | "imsi": Open5GSUser.Spec.IMSI, 256 | "msisdn": []string{}, 257 | "imeisv": []string{}, 258 | "mme_host": []string{}, 259 | "mm_realm": []string{}, 260 | "purge_flag": []string{}, 261 | "slice": []bson.M{ 262 | { 263 | "sst": defaultSST, 264 | "default_indicator": true, 265 | "session": []bson.M{ 266 | { 267 | "name": defaultAPN, 268 | "type": 3, 269 | "qos": bson.M{ 270 | "index": 9, 271 | "arp": bson.M{ 272 | "priority_level": 8, 273 | "pre_emption_capability": 1, 274 | "pre_emption_vulnerability": 2, 275 | }, 276 | }, 277 | "ambr": bson.M{ 278 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 279 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 280 | }, 281 | "pcc_rule": []string{}, 282 | "_id": primitive.NewObjectID(), 283 | }, 284 | }, 285 | "_id": primitive.NewObjectID(), 286 | }, 287 | }, 288 | "security": bson.M{ 289 | "k": Open5GSUser.Spec.Key, 290 | "opc": Open5GSUser.Spec.OPC, 291 | "amf": "8000", 292 | }, 293 | "ambr": bson.M{ 294 | "downlink": bson.M{"value": 1000000000, "unit": 0}, 295 | "uplink": bson.M{"value": 1000000000, "unit": 0}, 296 | }, 297 | "access_restriction_data": 32, 298 | "network_access_mode": 0, 299 | "subscriber_status": 0, 300 | "operator_determined_barring": 0, 301 | "subscribed_rau_tau_timer": 12, 302 | "__v": 0, 303 | } 304 | 305 | _, err = collection.InsertOne(ctx, subscriber) 306 | if err != nil { 307 | return fmt.Errorf("failed to insert subscriber with defaults: %v", err) 308 | } 309 | 310 | return nil 311 | } 312 | 313 | func hasDrift(open5GSUser netv1.Open5GSUser, subscriber bson.M) bool { 314 | if subscriber["security"].(bson.M)["k"] != open5GSUser.Spec.Key { 315 | return true 316 | } 317 | if subscriber["security"].(bson.M)["opc"] != open5GSUser.Spec.OPC { 318 | return true 319 | } 320 | 321 | if sst, ok := subscriber["slice"].(bson.A)[0].(bson.M)["sst"].(int); ok && strconv.Itoa(sst) != open5GSUser.Spec.SST { 322 | return true 323 | } 324 | 325 | if sd, ok := subscriber["slice"].(bson.A)[0].(bson.M)["sd"].(string); ok && sd != open5GSUser.Spec.SD { 326 | return true 327 | } 328 | 329 | if name, ok := subscriber["slice"].(bson.A)[0].(bson.M)["session"].(bson.A)[0].(bson.M)["name"].(string); ok && name != open5GSUser.Spec.APN { 330 | return true 331 | } 332 | 333 | return false 334 | } 335 | 336 | func (r *Open5GSUserReconciler) ListOpen5GSUsers(ctx context.Context) ([]netv1.Open5GSUser, error) { 337 | var userList netv1.Open5GSUserList 338 | if err := r.List(ctx, &userList); err != nil { 339 | return nil, err 340 | } 341 | return userList.Items, nil 342 | } 343 | func listSubscribers(ctx context.Context, mongoURI string) ([]bson.M, error) { 344 | clientOptions := options.Client().ApplyURI(mongoURI) 345 | client, err := mongo.Connect(ctx, clientOptions) 346 | if err != nil { 347 | return nil, err 348 | } 349 | defer client.Disconnect(ctx) 350 | 351 | collection := client.Database("open5gs").Collection("subscribers") 352 | cursor, err := collection.Find(ctx, bson.M{}) 353 | if err != nil { 354 | return nil, err 355 | } 356 | defer cursor.Close(ctx) 357 | 358 | var subscribers []bson.M 359 | if err = cursor.All(ctx, &subscribers); err != nil { 360 | return nil, err 361 | } 362 | return subscribers, nil 363 | } 364 | -------------------------------------------------------------------------------- /internal/controller/open5gsuser_controller.go: -------------------------------------------------------------------------------- 1 | package controller 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | netv1 "gradiant/open5gs-legacy-operator/api/v1" 7 | "log" 8 | "strings" 9 | "time" 10 | 11 | "go.mongodb.org/mongo-driver/bson" 12 | "go.mongodb.org/mongo-driver/mongo" 13 | "go.mongodb.org/mongo-driver/mongo/options" 14 | corev1 "k8s.io/api/core/v1" 15 | "k8s.io/apimachinery/pkg/api/errors" 16 | "k8s.io/apimachinery/pkg/runtime" 17 | ctrl "sigs.k8s.io/controller-runtime" 18 | "sigs.k8s.io/controller-runtime/pkg/client" 19 | ) 20 | 21 | // Core resources 22 | //+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch;delete 23 | //+kubebuilder:rbac:groups="",resources=configmaps,verbs=get;list;watch;create;update;patch;delete 24 | //+kubebuilder:rbac:groups="",resources=services,verbs=get;list;watch;create;update;patch;delete 25 | //+kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch;delete 26 | //+kubebuilder:rbac:groups="",resources=persistentvolumeclaims,verbs=get;list;watch;create;update;patch;delete 27 | //+kubebuilder:rbac:groups="",resources=pods,verbs=get;list;watch;create;update;patch;delete 28 | //+kubebuilder:rbac:groups="",resources=events,verbs=get;list;watch;create;update;patch 29 | //+kubebuilder:rbac:groups="",resources=namespaces,verbs=get;list;watch 30 | 31 | // net group resources 32 | //+kubebuilder:rbac:groups=net.gradiant.org,resources=open5gs,verbs=get;list;watch;create;update;patch;delete 33 | //+kubebuilder:rbac:groups=net.gradiant.org,resources=open5gs/status,verbs=get;update;patch 34 | //+kubebuilder:rbac:groups=net.gradiant.org,resources=open5gs/finalizers,verbs=update 35 | //+kubebuilder:rbac:groups=net.gradiant.org,resources=open5gsusers,verbs=get;list;watch;create;update;patch;delete 36 | 37 | // Apps resources 38 | //+kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete 39 | //+kubebuilder:rbac:groups=apps,resources=statefulsets,verbs=get;list;watch;create;update;patch;delete 40 | 41 | // Batch resources 42 | //+kubebuilder:rbac:groups=batch,resources=jobs,verbs=get;list;watch;create;update;patch;delete 43 | //+kubebuilder:rbac:groups=batch,resources=cronjobs,verbs=get;list;watch;create;update;patch;delete 44 | 45 | // RBAC resources 46 | //+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=roles,verbs=get;list;watch;create;update;patch;delete 47 | //+kubebuilder:rbac:groups=rbac.authorization.k8s.io,resources=rolebindings,verbs=get;list;watch;create;update;patch;delete 48 | 49 | // Autoscaling resources 50 | //+kubebuilder:rbac:groups=autoscaling,resources=horizontalpodautoscalers,verbs=get;list;watch;create;update;patch;delete 51 | 52 | // Policy resources 53 | //+kubebuilder:rbac:groups=policy,resources=poddisruptionbudgets,verbs=get;list;watch;create;update;patch;delete 54 | 55 | // Network resources 56 | //+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete 57 | //+kubebuilder:rbac:groups=networking.k8s.io,resources=networkpolicies,verbs=get;list;watch;create;update;patch;delete 58 | 59 | // Monitoring resources 60 | //+kubebuilder:rbac:groups=monitoring.coreos.com,resources=servicemonitors,verbs=get;list;watch;create;update;patch;delete 61 | 62 | // Helm-specific resources 63 | //+kubebuilder:rbac:groups=helm.toolkit.fluxcd.io,resources=helmreleases,verbs=get;list;watch;create;update;patch;delete 64 | 65 | const ( 66 | Open5GSUserFinalizer = "finalizer.open5gsuser.net.gradiant.org/user" 67 | lastAppliedConfig = "kubectl.kubernetes.io/last-applied-configuration" 68 | ) 69 | 70 | type Open5GSUserReconciler struct { 71 | client.Client 72 | Scheme *runtime.Scheme 73 | } 74 | 75 | func (r *Open5GSUserReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 76 | var Open5GSUser netv1.Open5GSUser 77 | var ipService string 78 | var err error 79 | if err := r.Get(ctx, req.NamespacedName, &Open5GSUser); err != nil { 80 | if errors.IsNotFound(err) { 81 | return ctrl.Result{}, nil 82 | } 83 | log.Printf("Error retrieving Open5GSUser %s: %v", req.NamespacedName, err) 84 | return ctrl.Result{}, err 85 | } 86 | serviceName := fmt.Sprintf("%s-mongodb", strings.ToLower(Open5GSUser.Spec.Open5GS.Name)) 87 | if Open5GSUser.Spec.Open5GS.Namespace == "" { 88 | ipService, err = r.GetServiceIp(ctx, serviceName, Open5GSUser.Namespace) 89 | } else { 90 | ipService, err = r.GetServiceIp(ctx, serviceName, Open5GSUser.Spec.Open5GS.Namespace) 91 | } 92 | 93 | if err != nil { 94 | log.Printf("Failed to get IP for service %s: %v", serviceName, err) 95 | return ctrl.Result{}, err 96 | } 97 | 98 | mongoURI := "mongodb://" + ipService + ":27017" 99 | 100 | if Open5GSUser.ObjectMeta.DeletionTimestamp.IsZero() { 101 | // Resource is not being deleted 102 | if !containsString(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) { 103 | log.Printf("Creating subscriber IMSI: %s", Open5GSUser.Spec.IMSI) 104 | if Open5GSUser.Spec.SST != "" || Open5GSUser.Spec.SD != "" { 105 | // SST or SD specified, call function handling slice. 106 | if err := addSubscriberWithSlice(Open5GSUser, mongoURI); err != nil { 107 | log.Printf("Failed to create subscriber with slice %s", err) 108 | return ctrl.Result{}, err 109 | } 110 | log.Printf("Subscriber with slice created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 111 | Open5GSUser.ObjectMeta.Finalizers = append(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) 112 | if err := r.Update(ctx, &Open5GSUser); err != nil { 113 | return ctrl.Result{}, err 114 | } 115 | } else if Open5GSUser.Spec.APN != "" { 116 | // APN specified without SST and SD, use function for default APN. 117 | if err := addSubscriberWithAPN(Open5GSUser, mongoURI); err != nil { 118 | log.Printf("Failed to create subscriber with APN %s", err) 119 | return ctrl.Result{}, err 120 | } 121 | log.Printf("Subscriber with APN created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 122 | Open5GSUser.ObjectMeta.Finalizers = append(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) 123 | if err := r.Update(ctx, &Open5GSUser); err != nil { 124 | return ctrl.Result{}, err 125 | } 126 | } else { 127 | // If SST, SD, and APN not specified but Key and OPC are, use defaults. 128 | if Open5GSUser.Spec.Key != "" && Open5GSUser.Spec.OPC != "" { 129 | if err := addSubscriberWithDefaults(Open5GSUser, mongoURI); err != nil { 130 | log.Printf("Failed to create subscriber with defaults %s", err) 131 | return ctrl.Result{}, err 132 | } 133 | log.Printf("Subscriber with defaults created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 134 | Open5GSUser.ObjectMeta.Finalizers = append(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) 135 | if err := r.Update(ctx, &Open5GSUser); err != nil { 136 | return ctrl.Result{}, err 137 | } 138 | } else { 139 | // Handle the case where necessary data is not provided. 140 | log.Printf("Cannot create subscriber, missing key data IMSI: %s", Open5GSUser.Spec.IMSI) 141 | return ctrl.Result{}, fmt.Errorf("insufficient data provided for subscriber creation") 142 | } 143 | } 144 | } else { 145 | // Resource already has the finalizer 146 | var subscriber bson.M 147 | clientOptions := options.Client().ApplyURI(mongoURI) 148 | client, err := mongo.Connect(ctx, clientOptions) 149 | if err != nil { 150 | return ctrl.Result{}, fmt.Errorf("failed to connect to mongo: %v", err) 151 | } 152 | defer client.Disconnect(ctx) 153 | collection := client.Database("open5gs").Collection("subscribers") 154 | 155 | err = collection.FindOne(ctx, bson.M{"imsi": Open5GSUser.Spec.IMSI}).Decode(&subscriber) 156 | if err != nil { 157 | if err == mongo.ErrNoDocuments { 158 | log.Printf("Subscriber %s not found in database, creating it", Open5GSUser.Spec.IMSI) 159 | if Open5GSUser.Spec.SST != "" || Open5GSUser.Spec.SD != "" { 160 | // SST or SD specified, call function handling slice. 161 | if err := addSubscriberWithSlice(Open5GSUser, mongoURI); err != nil { 162 | log.Printf("Failed to create subscriber with slice %s", err) 163 | return ctrl.Result{}, err 164 | } 165 | log.Printf("Subscriber with slice created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 166 | } else if Open5GSUser.Spec.APN != "" { 167 | // APN specified without SST and SD, use function for default APN. 168 | if err := addSubscriberWithAPN(Open5GSUser, mongoURI); err != nil { 169 | log.Printf("Failed to create subscriber with APN %s", err) 170 | return ctrl.Result{}, err 171 | } 172 | log.Printf("Subscriber with APN created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 173 | } else { 174 | // If SST, SD, and APN not specified but Key and OPC are, use defaults. 175 | if Open5GSUser.Spec.Key != "" && Open5GSUser.Spec.OPC != "" { 176 | if err := addSubscriberWithDefaults(Open5GSUser, mongoURI); err != nil { 177 | log.Printf("Failed to create subscriber with defaults %s", err) 178 | return ctrl.Result{}, err 179 | } 180 | log.Printf("Subscriber with defaults created successfully IMSI: %s", Open5GSUser.Spec.IMSI) 181 | } else { 182 | // Handle the case where necessary data is not provided. 183 | log.Printf("Cannot create subscriber, missing key data IMSI: %s", Open5GSUser.Spec.IMSI) 184 | return ctrl.Result{}, fmt.Errorf("insufficient data provided for subscriber creation") 185 | } 186 | } 187 | } else { 188 | log.Printf("Failed to find subscriber %s in database: %v", Open5GSUser.Spec.IMSI, err) 189 | return ctrl.Result{}, err 190 | } 191 | } else { 192 | if hasDrift(Open5GSUser, subscriber) { 193 | log.Printf("Change detected for subscriber %s, updating it", Open5GSUser.Spec.IMSI) 194 | if err := updateSubscriber(Open5GSUser, mongoURI); err != nil { 195 | log.Printf("Failed to correct drift for subscriber %s: %v", Open5GSUser.Spec.IMSI, err) 196 | return ctrl.Result{}, err 197 | } 198 | } 199 | } 200 | } 201 | } else { 202 | if containsString(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) { 203 | log.Printf("Deleting subscriber for Open5GSUser %s", Open5GSUser.Name) 204 | if err := deleteSubscriber(Open5GSUser, mongoURI); err != nil { 205 | log.Printf("Failed to delete subscriber for Open5GSUser %s: %v", Open5GSUser.Name, err) 206 | return ctrl.Result{}, err 207 | } 208 | Open5GSUser.ObjectMeta.Finalizers = removeString(Open5GSUser.ObjectMeta.Finalizers, Open5GSUserFinalizer) 209 | if err := r.Update(ctx, &Open5GSUser); err != nil { 210 | log.Printf("Failed to remove finalizer for Open5GSUser %s: %v", Open5GSUser.Name, err) 211 | return ctrl.Result{}, err 212 | } 213 | } 214 | } 215 | 216 | return ctrl.Result{RequeueAfter: 15 * time.Second}, nil // Requeue every 15 seconds 217 | } 218 | 219 | func (r *Open5GSUserReconciler) GetServiceIp(ctx context.Context, serviceName string, namespace string) (string, error) { 220 | var service corev1.Service 221 | namespacedName := client.ObjectKey{Name: serviceName, Namespace: namespace} 222 | if err := r.Get(ctx, namespacedName, &service); err != nil { 223 | log.Printf("Failed to get service %s: %v", serviceName, err) 224 | return "", err 225 | } 226 | return service.Spec.ClusterIP, nil 227 | } 228 | 229 | func containsString(slice []string, s string) bool { 230 | for _, item := range slice { 231 | if item == s { 232 | return true 233 | } 234 | } 235 | return false 236 | } 237 | 238 | func removeString(slice []string, s string) (result []string) { 239 | for _, item := range slice { 240 | if item != s { 241 | result = append(result, item) 242 | } 243 | } 244 | return 245 | } 246 | 247 | func (r *Open5GSUserReconciler) SetupWithManager(mgr ctrl.Manager) error { 248 | return ctrl.NewControllerManagedBy(mgr). 249 | For(&netv1.Open5GSUser{}). 250 | Complete(r) 251 | } 252 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # VERSION defines the project version for the bundle. 2 | # Update this value when you upgrade the version of your project. 3 | # To re-generate a bundle for another specific version without changing the standard setup, you can: 4 | # - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) 5 | # - use environment variables to overwrite this value (e.g export VERSION=0.0.2) 6 | VERSION ?= 0.0.1 7 | 8 | # CHANNELS define the bundle channels used in the bundle. 9 | # Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") 10 | # To re-generate a bundle for other specific channels without changing the standard setup, you can: 11 | # - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) 12 | # - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") 13 | ifneq ($(origin CHANNELS), undefined) 14 | BUNDLE_CHANNELS := --channels=$(CHANNELS) 15 | endif 16 | 17 | # DEFAULT_CHANNEL defines the default channel used in the bundle. 18 | # Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") 19 | # To re-generate a bundle for any other default channel without changing the default setup, you can: 20 | # - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) 21 | # - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") 22 | ifneq ($(origin DEFAULT_CHANNEL), undefined) 23 | BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 24 | endif 25 | BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 26 | 27 | # IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. 28 | # This variable is used to construct full image tags for bundle and catalog images. 29 | # 30 | # For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both 31 | # gradiant.org/open5gs-operator-bundle:$VERSION and gradiant.org/open5gs-operator-catalog:$VERSION. 32 | IMAGE_TAG_BASE ?= gradiant.org/open5gs-operator 33 | 34 | # BUNDLE_IMG defines the image:tag used for the bundle. 35 | # You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=/:) 36 | BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) 37 | 38 | # BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command 39 | BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 40 | 41 | # USE_IMAGE_DIGESTS defines if images are resolved via tags or digests 42 | # You can enable this value if you would like to use SHA Based Digests 43 | # To enable set flag to true 44 | USE_IMAGE_DIGESTS ?= false 45 | ifeq ($(USE_IMAGE_DIGESTS), true) 46 | BUNDLE_GEN_FLAGS += --use-image-digests 47 | endif 48 | 49 | # Set the Operator SDK version to use. By default, what is installed on the system is used. 50 | # This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. 51 | OPERATOR_SDK_VERSION ?= v1.34.0 52 | 53 | # Image URL to use all building/pushing image targets 54 | IMG ?= controller:latest 55 | # ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary. 56 | ENVTEST_K8S_VERSION = 1.25.0 57 | 58 | # Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) 59 | ifeq (,$(shell go env GOBIN)) 60 | GOBIN=$(shell go env GOPATH)/bin 61 | else 62 | GOBIN=$(shell go env GOBIN) 63 | endif 64 | 65 | # Setting SHELL to bash allows bash commands to be executed by recipes. 66 | # Options are set to exit when a recipe line exits non-zero or a piped command fails. 67 | SHELL = /usr/bin/env bash -o pipefail 68 | .SHELLFLAGS = -ec 69 | 70 | .PHONY: all 71 | all: build 72 | 73 | ##@ General 74 | 75 | # The help target prints out all targets with their descriptions organized 76 | # beneath their categories. The categories are represented by '##@' and the 77 | # target descriptions by '##'. The awk commands is responsible for reading the 78 | # entire set of makefiles included in this invocation, looking for lines of the 79 | # file as xyz: ## something, and then pretty-format the target and help. Then, 80 | # if there's a line with ##@ something, that gets pretty-printed as a category. 81 | # More info on the usage of ANSI control characters for terminal formatting: 82 | # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters 83 | # More info on the awk command: 84 | # http://linuxcommand.org/lc3_adv_awk.php 85 | 86 | .PHONY: help 87 | help: ## Display this help. 88 | @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 89 | 90 | ##@ Build 91 | .PHONY: build 92 | build: manifests generate fmt vet ## Build manager binary. 93 | go build -o bin/manager cmd/main.go 94 | 95 | .PHONY: run 96 | run: manifests generate fmt vet ## Run against the configured Kubernetes cluster in ~/.kube/config 97 | go run cmd/main.go 98 | 99 | .PHONY: docker-build 100 | docker-build: ## Build docker image with the manager. 101 | docker build -t ${IMG} . 102 | 103 | .PHONY: docker-push 104 | docker-push: ## Push docker image with the manager. 105 | docker push ${IMG} 106 | 107 | ##@ Development 108 | 109 | .PHONY: manifests 110 | manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. 111 | $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases 112 | 113 | .PHONY: generate 114 | generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 115 | $(CONTROLLER_GEN) object:headerFile="" paths="./..." 116 | 117 | .PHONY: fmt 118 | fmt: ## Run go fmt against code. 119 | go fmt ./... 120 | 121 | .PHONY: vet 122 | vet: ## Run go vet against code. 123 | go vet ./... 124 | 125 | .PHONY: test 126 | test: manifests generate fmt vet envtest ## Run tests. 127 | KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) -p path)" go test ./... -coverprofile cover.out 128 | 129 | ##@ Deployment 130 | 131 | ifndef ignore-not-found 132 | ignore-not-found = false 133 | endif 134 | 135 | .PHONY: install 136 | install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. 137 | $(KUSTOMIZE) build config/crd | kubectl apply -f - 138 | 139 | .PHONY: uninstall 140 | uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 141 | $(KUSTOMIZE) build config/crd | kubectl delete --ignore-not-found=$(ignore-not-found) -f - 142 | 143 | .PHONY: deploy 144 | deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. 145 | cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 146 | $(KUSTOMIZE) build config/default | kubectl apply -f - 147 | 148 | .PHONY: undeploy 149 | undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 150 | $(KUSTOMIZE) build config/default | kubectl delete --force --timeout=10s --ignore-not-found=$(ignore-not-found) -f - || true 151 | 152 | ##@ Build Dependencies 153 | 154 | ## Location to install dependencies to 155 | LOCALBIN ?= $(shell pwd)/bin 156 | $(LOCALBIN): 157 | mkdir -p $(LOCALBIN) 158 | 159 | ## Tool Binaries 160 | KUSTOMIZE ?= $(LOCALBIN)/kustomize 161 | CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen 162 | ENVTEST ?= $(LOCALBIN)/setup-envtest 163 | 164 | ## Tool Versions 165 | KUSTOMIZE_VERSION ?= v5.2.1 166 | CONTROLLER_TOOLS_VERSION ?= v0.13.0 167 | 168 | KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh" 169 | .PHONY: kustomize 170 | kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. 171 | $(KUSTOMIZE): $(LOCALBIN) 172 | test -s $(LOCALBIN)/kustomize || { curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN); } 173 | 174 | .PHONY: controller-gen 175 | controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. 176 | $(CONTROLLER_GEN): $(LOCALBIN) 177 | test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION) 178 | 179 | .PHONY: envtest 180 | envtest: $(ENVTEST) ## Download envtest-setup locally if necessary. 181 | $(ENVTEST): $(LOCALBIN) 182 | test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@latest 183 | 184 | .PHONY: operator-sdk 185 | OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk 186 | operator-sdk: ## Download operator-sdk locally if necessary. 187 | ifeq (,$(wildcard $(OPERATOR_SDK))) 188 | ifeq (, $(shell which operator-sdk 2>/dev/null)) 189 | @{ \ 190 | set -e ;\ 191 | mkdir -p $(dir $(OPERATOR_SDK)) ;\ 192 | curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$(OS)_$(ARCH) ;\ 193 | chmod +x $(OPERATOR_SDK) ;\ 194 | } 195 | else 196 | OPERATOR_SDK = $(shell which operator-sdk) 197 | endif 198 | endif 199 | 200 | .PHONY: bundle 201 | bundle: kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. 202 | $(OPERATOR_SDK) generate kustomize manifests -q 203 | cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 204 | $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) 205 | $(OPERATOR_SDK) bundle validate ./bundle 206 | 207 | .PHONY: bundle-build 208 | bundle-build: ## Build the bundle image. 209 | docker build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 210 | 211 | .PHONY: bundle-push 212 | bundle-push: ## Push the bundle image. 213 | $(MAKE) docker-push IMG=$(BUNDLE_IMG) 214 | 215 | .PHONY: opm 216 | OPM = $(LOCALBIN)/opm 217 | opm: ## Download opm locally if necessary. 218 | ifeq (,$(wildcard $(OPM))) 219 | ifeq (,$(shell which opm 2>/dev/null)) 220 | @{ \ 221 | set -e ;\ 222 | mkdir -p $(dir $(OPM)) ;\ 223 | curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.23.0/$(OS)-$(ARCH)-opm ;\ 224 | chmod +x $(OPM) ;\ 225 | } 226 | else 227 | OPM = $(shell which opm) 228 | endif 229 | endif 230 | 231 | # A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). 232 | # These images MUST exist in a registry and be pull-able. 233 | BUNDLE_IMGS ?= $(BUNDLE_IMG) 234 | 235 | # The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). 236 | CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) 237 | 238 | # Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. 239 | ifneq ($(origin CATALOG_BASE_IMG), undefined) 240 | FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) 241 | endif 242 | 243 | # Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. 244 | # This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: 245 | # https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator 246 | .PHONY: catalog-build 247 | catalog-build: opm ## Build a catalog image. 248 | $(OPM) index add --container-tool docker --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) 249 | 250 | # Push the catalog image. 251 | .PHONY: catalog-push 252 | catalog-push: ## Push a catalog image. 253 | $(MAKE) docker-push IMG=$(CATALOG_IMG) 254 | 255 | ######################### Helmify 256 | HELMIFY ?= $(LOCALBIN)/helmify 257 | 258 | .PHONY: helmify 259 | helmify: $(HELMIFY) ## Download helmify locally if necessary. 260 | $(HELMIFY): $(LOCALBIN) 261 | test -s $(LOCALBIN)/helmify || GOBIN=$(LOCALBIN) go install github.com/arttor/helmify/cmd/helmify@v0.4.12 262 | 263 | helm: manifests kustomize helmify 264 | $(KUSTOMIZE) build config/default | $(HELMIFY) charts/open5gs-legacy-operator-chart -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= 2 | github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= 3 | github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= 4 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= 5 | github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= 6 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 7 | github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= 8 | github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= 9 | github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= 10 | github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= 11 | github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= 12 | github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= 13 | github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= 14 | github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 15 | github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= 16 | github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= 17 | github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= 18 | github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= 19 | github.com/Masterminds/squirrel v1.5.4 h1:uUcX/aBc8O7Fg9kaISIUsHXdKuqehiXAMQTYX8afzqM= 20 | github.com/Masterminds/squirrel v1.5.4/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10= 21 | github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= 22 | github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= 23 | github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= 24 | github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs= 25 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 26 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 27 | github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= 28 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= 29 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= 30 | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 31 | github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= 32 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 33 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 34 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 35 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 36 | github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= 37 | github.com/bugsnag/bugsnag-go v1.5.3 h1:yeRUT3mUE13jL1tGwvoQsKdVbAsQx9AJ+fqahKveP04= 38 | github.com/bugsnag/panicwrap v1.2.0 h1:OzrKrRvXis8qEvOkfcxNcYbOd2O7xXS2nnKMEMABFQA= 39 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 40 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 41 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 42 | github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk= 43 | github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA= 44 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= 45 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= 46 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= 47 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 48 | github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= 49 | github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= 50 | github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= 51 | github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= 52 | github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= 53 | github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= 54 | github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= 55 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 56 | github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= 57 | github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= 58 | github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= 59 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 60 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 61 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 62 | github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= 63 | github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= 64 | github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= 65 | github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= 66 | github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= 67 | github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= 68 | github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= 69 | github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= 70 | github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= 71 | github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= 72 | github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= 73 | github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8= 74 | github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= 75 | github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= 76 | github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= 77 | github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= 78 | github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= 79 | github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= 80 | github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 81 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 82 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 83 | github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= 84 | github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 85 | github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= 86 | github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= 87 | github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f h1:Wl78ApPPB2Wvf/TIe2xdyJxTlb6obmF18d8QdkxNDu4= 88 | github.com/exponent-io/jsonpath v0.0.0-20210407135951-1de76d718b3f/go.mod h1:OSYXu++VVOHnXeitef/D8n/6y4QV8uLHSFXX4NeXMGc= 89 | github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= 90 | github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= 91 | github.com/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk= 92 | github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= 93 | github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= 94 | github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE= 95 | github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= 96 | github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= 97 | github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= 98 | github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og= 99 | github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs= 100 | github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw= 101 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 102 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 103 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 104 | github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 105 | github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 106 | github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= 107 | github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= 108 | github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= 109 | github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= 110 | github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= 111 | github.com/go-logr/zapr v1.2.4/go.mod h1:FyHWQIzQORZ0QVE1BtVHv3cKtNLuXsbNLtpuhNapBOA= 112 | github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= 113 | github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 114 | github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 115 | github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 116 | github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 117 | github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= 118 | github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 119 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 120 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 121 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 122 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 123 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 124 | github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU= 125 | github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= 126 | github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY= 127 | github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= 128 | github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= 129 | github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= 130 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 131 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 132 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 133 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 134 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 135 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 136 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 137 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 138 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 139 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 140 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 141 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 142 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 143 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 144 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 145 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 146 | github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= 147 | github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= 148 | github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= 149 | github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= 150 | github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= 151 | github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= 152 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 153 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 154 | github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= 155 | github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= 156 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 157 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 158 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 159 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 160 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 161 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 162 | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 163 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 164 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 165 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 166 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 167 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 168 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 169 | github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb h1:LCMfzVg3sflxTs4UvuP4D8CkoZnfHLe2qzqgDn/4OHs= 170 | github.com/google/pprof v0.0.0-20230907193218-d3ddc7976beb/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik= 171 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= 172 | github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= 173 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 174 | github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= 175 | github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 176 | github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= 177 | github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= 178 | github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= 179 | github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= 180 | github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY= 181 | github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo= 182 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 h1:+ngKgrYPPJrOjhax5N+uePQ0Fh1Z7PheYoUI/0nzkPA= 183 | github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= 184 | github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 185 | github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= 186 | github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= 187 | github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= 188 | github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= 189 | github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= 190 | github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 191 | github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= 192 | github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= 193 | github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= 194 | github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= 195 | github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= 196 | github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= 197 | github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= 198 | github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= 199 | github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g= 200 | github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ= 201 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 202 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 203 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 204 | github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 205 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 206 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 207 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 208 | github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= 209 | github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw= 210 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 211 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 212 | github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4= 213 | github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= 214 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 215 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 216 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 217 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 218 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 219 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 220 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 221 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 222 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 223 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw= 224 | github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o= 225 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk= 226 | github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw= 227 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= 228 | github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= 229 | github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= 230 | github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= 231 | github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE= 232 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 233 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 234 | github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI= 235 | github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY= 236 | github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI= 237 | github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= 238 | github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= 239 | github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= 240 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 241 | github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= 242 | github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 243 | github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= 244 | github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= 245 | github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= 246 | github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= 247 | github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= 248 | github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= 249 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 250 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg= 251 | github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k= 252 | github.com/miekg/dns v1.1.25 h1:dFwPR6SfLtrSwgDcIq2bcU/gVutB4sNApq2HBdqcakg= 253 | github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= 254 | github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= 255 | github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= 256 | github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= 257 | github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= 258 | github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 259 | github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= 260 | github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= 261 | github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= 262 | github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= 263 | github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= 264 | github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= 265 | github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= 266 | github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= 267 | github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= 268 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 269 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 270 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 271 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 272 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 273 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 274 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 275 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0= 276 | github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4= 277 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= 278 | github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= 279 | github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= 280 | github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= 281 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 282 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 283 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 284 | github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= 285 | github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= 286 | github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= 287 | github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= 288 | github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= 289 | github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= 290 | github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= 291 | github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= 292 | github.com/operator-framework/helm-operator-plugins v0.1.3 h1:nwl9K1Pq0NZmanpEF/DYO00S7QO/iAmEdRIuLROrYpk= 293 | github.com/operator-framework/helm-operator-plugins v0.1.3/go.mod h1:f/AR6r2DiSRK5zv9MD+NgWbayP6qDbQMw+unFuw0rPQ= 294 | github.com/operator-framework/operator-lib v0.12.0 h1:OzpMU5N7mvFgg/uje8FUUeD24Ahq64R6TdN25uswCYA= 295 | github.com/operator-framework/operator-lib v0.12.0/go.mod h1:ClpLUI7hctEF7F5DBe/kg041dq/4NLR7XC5tArY7bG4= 296 | github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= 297 | github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= 298 | github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= 299 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 300 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 301 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 302 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 303 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 304 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 305 | github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= 306 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 307 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 308 | github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g= 309 | github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk= 310 | github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA= 311 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 312 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 313 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 314 | github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= 315 | github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= 316 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 317 | github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc= 318 | github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM= 319 | github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY= 320 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 321 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 322 | github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ= 323 | github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= 324 | github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= 325 | github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 326 | github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= 327 | github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= 328 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 329 | github.com/rubenv/sql-migrate v1.5.2 h1:bMDqOnrJVV/6JQgQ/MxOpU+AdO8uzYYA/TxFUBzFtS0= 330 | github.com/rubenv/sql-migrate v1.5.2/go.mod h1:H38GW8Vqf8F0Su5XignRyaRcbXbJunSWxs+kmzlg0Is= 331 | github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= 332 | github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= 333 | github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= 334 | github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= 335 | github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 336 | github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= 337 | github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= 338 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 339 | github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= 340 | github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= 341 | github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= 342 | github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= 343 | github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU= 344 | github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= 345 | github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= 346 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 347 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 348 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 349 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 350 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 351 | github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= 352 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 353 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 354 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 355 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 356 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 357 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 358 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 359 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 360 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 361 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 362 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 363 | github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= 364 | github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= 365 | github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= 366 | github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= 367 | github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= 368 | github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= 369 | github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 370 | github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= 371 | github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= 372 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= 373 | github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= 374 | github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= 375 | github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= 376 | github.com/xlab/treeprint v1.2.0 h1:HzHnuAF1plUN2zGlAFHbSQP2qJ0ZAD3XF5XD7OesXRQ= 377 | github.com/xlab/treeprint v1.2.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= 378 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= 379 | github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= 380 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 381 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 382 | github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= 383 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 384 | github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U= 385 | github.com/yvasiyarov/gorelic v0.0.7 h1:4DTF1WOM2ZZS/xMOkTFBOcb6XiHu/PKn3rVo6dbewQE= 386 | github.com/yvasiyarov/newrelic_platform_go v0.0.0-20160601141957-9c099fbc30e9 h1:AsFN8kXcCVkUFHyuzp1FtYbzp1nCO/H6+1uPSGEyPzM= 387 | go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= 388 | go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= 389 | go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= 390 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0 h1:x8Z78aZx8cOF0+Kkazoc7lwUNMGy0LrzEMxTm4BbTxg= 391 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.45.0/go.mod h1:62CPTSry9QZtOaSsE3tOzhx6LzDhHnXJ6xHeMNNiM6Q= 392 | go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs= 393 | go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY= 394 | go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE= 395 | go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8= 396 | go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg= 397 | go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo= 398 | go.starlark.net v0.0.0-20230612165344-9532f5667272 h1:2/wtqS591wZyD2OsClsVBKRPEvBsQt/Js+fsCiYhwu8= 399 | go.starlark.net v0.0.0-20230612165344-9532f5667272/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= 400 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 401 | go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= 402 | go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= 403 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 404 | go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= 405 | go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= 406 | go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= 407 | go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= 408 | go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= 409 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 410 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 411 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 412 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 413 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 414 | golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= 415 | golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= 416 | golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= 417 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 418 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= 419 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= 420 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 421 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 422 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 423 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 424 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 425 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 426 | golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 427 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 428 | golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= 429 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 430 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 431 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 432 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 433 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 434 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 435 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 436 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 437 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 438 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 439 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 440 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 441 | golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= 442 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 443 | golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= 444 | golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= 445 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 446 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 447 | golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= 448 | golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 449 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 450 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 451 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 452 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 453 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 454 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 455 | golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 456 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 457 | golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= 458 | golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= 459 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 460 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 461 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 462 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 463 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 464 | golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 465 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 466 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 467 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 468 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 469 | golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 470 | golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 471 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 472 | golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 473 | golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 474 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 475 | golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 476 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 477 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 478 | golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 479 | golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 480 | golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= 481 | golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 482 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 483 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 484 | golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 485 | golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= 486 | golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4= 487 | golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= 488 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 489 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 490 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 491 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 492 | golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= 493 | golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 494 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 495 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 496 | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 497 | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 498 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 499 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 500 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 501 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 502 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 503 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 504 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 505 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 506 | golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= 507 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 508 | golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= 509 | golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= 510 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 511 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 512 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 513 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 514 | gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= 515 | gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= 516 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 517 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 518 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 519 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 520 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 521 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 522 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 523 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U= 524 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM= 525 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 526 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 527 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 528 | google.golang.org/grpc v1.58.3 h1:BjnpXut1btbtgN/6sp+brB2Kbm2LjNXnidYujAVbSoQ= 529 | google.golang.org/grpc v1.58.3/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= 530 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 531 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 532 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 533 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 534 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 535 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 536 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 537 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 538 | google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= 539 | google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= 540 | google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= 541 | google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= 542 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 543 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 544 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 545 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 546 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 547 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 548 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 549 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 550 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 551 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 552 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 553 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 554 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 555 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 556 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 557 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 558 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 559 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 560 | gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= 561 | helm.sh/helm/v3 v3.13.3 h1:0zPEdGqHcubehJHP9emCtzRmu8oYsJFRrlVF3TFj8xY= 562 | helm.sh/helm/v3 v3.13.3/go.mod h1:3OKO33yI3p4YEXtTITN2+4oScsHeQe71KuzhlZ+aPfg= 563 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 564 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 565 | k8s.io/api v0.28.5 h1:XIPNr3nBgTEaCdEiwZ+dXaO9SB4NeTOZ2pNDRrFgfb4= 566 | k8s.io/api v0.28.5/go.mod h1:98zkTCc60iSnqqCIyCB1GI7PYDiRDYTSfL0PRIxpM4c= 567 | k8s.io/apiextensions-apiserver v0.28.5 h1:YKW9O9T/0Gkyl6LTFDLIhCbouSRh+pHt2vMLB38Snfc= 568 | k8s.io/apiextensions-apiserver v0.28.5/go.mod h1:7p7TQ0X9zCJLNFlOTi5dncAi2dkPsdsrcvu5ILa7PEk= 569 | k8s.io/apimachinery v0.28.5 h1:EEj2q1qdTcv2p5wl88KavAn3VlFRjREgRu8Sm/EuMPY= 570 | k8s.io/apimachinery v0.28.5/go.mod h1:wI37ncBvfAoswfq626yPTe6Bz1c22L7uaJ8dho83mgg= 571 | k8s.io/apiserver v0.28.5 h1:3hRmQvqkWPCQr6kYi9lrMQF84V8/ScNx/8VyjhbPTi4= 572 | k8s.io/apiserver v0.28.5/go.mod h1:tLFNbfELieGsn/utLLdSarJ99MjguBe11jkKITe3z4w= 573 | k8s.io/cli-runtime v0.28.5 h1:xTL2Zpx//2+mKysdDUogpY0qwYf5Qkuij3Ikmr6xh5Q= 574 | k8s.io/cli-runtime v0.28.5/go.mod h1:FZZy7DAfum2co5rjGMM86sumPojroT3V06mP45erB/0= 575 | k8s.io/client-go v0.28.5 h1:6UNmc33vuJhh3+SAOEKku3QnKa+DtPKGnhO2MR0IEbk= 576 | k8s.io/client-go v0.28.5/go.mod h1:+pt086yx1i0HAlHzM9S+RZQDqdlzuXFl4hY01uhpcpA= 577 | k8s.io/component-base v0.28.5 h1:uFCW7USa8Fpme8dVtn2ZrdVaUPBRDwYJ+kNrV9OO1Cc= 578 | k8s.io/component-base v0.28.5/go.mod h1:gw2d8O28okS9RrsPuJnD2mFl2It0HH9neHiGi2xoXcY= 579 | k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= 580 | k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= 581 | k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= 582 | k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= 583 | k8s.io/kubectl v0.28.5 h1:jq8xtiCCZPR8Cl/Qe1D7bLU0h8KtcunwfROqIekCUeU= 584 | k8s.io/kubectl v0.28.5/go.mod h1:9WiwzqeKs3vLiDtEQPbjhqqysX+BIVMLt7C7gN+T5w8= 585 | k8s.io/utils v0.0.0-20230505201702-9f6742963106 h1:EObNQ3TW2D+WptiYXlApGNLVy0zm/JIBVY9i+M4wpAU= 586 | k8s.io/utils v0.0.0-20230505201702-9f6742963106/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 587 | oras.land/oras-go v1.2.4 h1:djpBY2/2Cs1PV87GSJlxv4voajVOMZxqqtq9AB8YNvY= 588 | oras.land/oras-go v1.2.4/go.mod h1:DYcGfb3YF1nKjcezfX2SNlDAeQFKSXmf+qrFmrh4324= 589 | sigs.k8s.io/controller-runtime v0.16.3 h1:2TuvuokmfXvDUamSx1SuAOO3eTyye+47mJCigwG62c4= 590 | sigs.k8s.io/controller-runtime v0.16.3/go.mod h1:j7bialYoSn142nv9sCOJmQgDXQXxnroFU4VnX/brVJ0= 591 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= 592 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 593 | sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 h1:XX3Ajgzov2RKUdc5jW3t5jwY7Bo7dcRm+tFxT+NfgY0= 594 | sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3/go.mod h1:9n16EZKMhXBNSiUC5kSdFQJkdH3zbxS/JoO619G1VAY= 595 | sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 h1:W6cLQc5pnqM7vh3b7HvGNfXrJ/xL6BDMS0v1V/HHg5U= 596 | sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3/go.mod h1:JWP1Fj0VWGHyw3YUPjXSQnRnrwezrZSrApfX5S0nIag= 597 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= 598 | sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= 599 | sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= 600 | sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= 601 | --------------------------------------------------------------------------------