├── internal ├── alertmanagerapi │ ├── .openapi-generator │ │ ├── VERSION │ │ └── FILES │ ├── response.go │ ├── api_general.go │ ├── api_receiver.go │ ├── model_post_silences_200_response.go │ ├── model_receiver.go │ ├── model_silence_status.go │ ├── model_alertmanager_config.go │ ├── model_peer_status.go │ ├── model_alert.go │ ├── model_alert_group.go │ ├── model_alert_status.go │ ├── model_cluster_status.go │ ├── model_matcher.go │ ├── api_alertgroup.go │ ├── model_alertmanager_status.go │ ├── configuration.go │ ├── model_silence.go │ ├── model_version_info.go │ ├── utils.go │ ├── model_postable_silence.go │ └── model_postable_alert.go └── controller │ ├── alert_controller_test.go │ ├── silence_controller_test.go │ ├── suite_test.go │ └── alert_controller.go ├── config ├── manager │ ├── kustomization.yaml │ └── manager.yaml ├── prometheus │ ├── kustomization.yaml │ └── monitor.yaml ├── default │ ├── manager_metrics_patch.yaml │ ├── metrics_service.yaml │ └── kustomization.yaml ├── rbac │ ├── metrics_reader_role.yaml │ ├── service_account.yaml │ ├── metrics_auth_role_binding.yaml │ ├── metrics_auth_role.yaml │ ├── role_binding.yaml │ ├── leader_election_role_binding.yaml │ ├── alert_viewer_role.yaml │ ├── silence_viewer_role.yaml │ ├── alert_editor_role.yaml │ ├── silence_editor_role.yaml │ ├── leader_election_role.yaml │ ├── role.yaml │ └── kustomization.yaml ├── samples │ ├── kustomization.yaml │ ├── alertmanager.prometheus.io_v1alpha1_alert.yaml │ └── alertmanager.prometheus.io_v1alpha1_silence.yaml └── crd │ ├── kustomizeconfig.yaml │ ├── kustomization.yaml │ └── bases │ ├── alertmanager.prometheus.io.alertmanager.prometheus.io_alerts.yaml │ └── alertmanager.prometheus.io.alertmanager.prometheus.io_silences.yaml ├── .dockerignore ├── .gitignore ├── hack └── boilerplate.go.txt ├── openapi-generator-config.yaml ├── fakeprometheus.go ├── PROJECT ├── test ├── e2e │ ├── e2e_suite_test.go │ └── e2e_test.go └── utils │ └── utils.go ├── .golangci.yml ├── Dockerfile ├── api └── v1alpha1 │ ├── groupversion_info.go │ ├── alert_types.go │ ├── silence_types.go │ └── zz_generated.deepcopy.go ├── go.mod └── README.md /internal/alertmanagerapi/.openapi-generator/VERSION: -------------------------------------------------------------------------------- 1 | 7.6.0 2 | -------------------------------------------------------------------------------- /config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | -------------------------------------------------------------------------------- /config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | # More info: https://docs.docker.com/engine/reference/builder/#dockerignore-file 2 | # Ignore build and test binaries. 3 | bin/ 4 | -------------------------------------------------------------------------------- /config/default/manager_metrics_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch adds the args to allow exposing the metrics endpoint using HTTPS 2 | - op: add 3 | path: /spec/template/spec/containers/0/args/0 4 | value: --metrics-bind-address=:8443 5 | -------------------------------------------------------------------------------- /config/rbac/metrics_reader_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /config/samples/kustomization.yaml: -------------------------------------------------------------------------------- 1 | ## Append samples of your project ## 2 | resources: 3 | - alertmanager.prometheus.io_v1alpha1_alert.yaml 4 | - alertmanager.prometheus.io_v1alpha1_silence.yaml 5 | # +kubebuilder:scaffold:manifestskustomizesamples 6 | -------------------------------------------------------------------------------- /config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: alert-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: controller-manager 8 | namespace: system 9 | -------------------------------------------------------------------------------- /config/samples/alertmanager.prometheus.io_v1alpha1_alert.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: alertmanager.prometheus.io.alertmanager.prometheus.io/v1alpha1 2 | kind: Alert 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: alert-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: alert-sample 8 | spec: 9 | # TODO(user): Add fields here 10 | -------------------------------------------------------------------------------- /config/samples/alertmanager.prometheus.io_v1alpha1_silence.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: alertmanager.prometheus.io.alertmanager.prometheus.io/v1alpha1 2 | kind: Silence 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: alert-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: silence-sample 8 | spec: 9 | # TODO(user): Add fields here 10 | -------------------------------------------------------------------------------- /config/rbac/metrics_auth_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: metrics-auth-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: metrics-auth-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /config/rbac/metrics_auth_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-auth-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | labels: 5 | app.kubernetes.io/name: alert-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: manager-rolebinding 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: ClusterRole 11 | name: manager-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: controller-manager 15 | namespace: system 16 | -------------------------------------------------------------------------------- /config/default/metrics_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: controller-manager-metrics-service 9 | namespace: system 10 | spec: 11 | ports: 12 | - name: https 13 | port: 8443 14 | protocol: TCP 15 | targetPort: 8443 16 | selector: 17 | control-plane: controller-manager 18 | -------------------------------------------------------------------------------- /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: alert-operator 6 | app.kubernetes.io/managed-by: kustomize 7 | name: leader-election-rolebinding 8 | roleRef: 9 | apiGroup: rbac.authorization.k8s.io 10 | kind: Role 11 | name: leader-election-role 12 | subjects: 13 | - kind: ServiceAccount 14 | name: controller-manager 15 | namespace: system 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | bin/* 8 | Dockerfile.cross 9 | 10 | # Test binary, built with `go test -c` 11 | *.test 12 | 13 | # Output of the go coverage tool, specifically when used with LiteIDE 14 | *.out 15 | 16 | # Go workspace file 17 | go.work 18 | 19 | # Kubernetes Generated files - skip generated files, except for vendored files 20 | !vendor/**/zz_generated.* 21 | 22 | # editor and IDE paraphernalia 23 | .idea 24 | .vscode 25 | *.swp 26 | *.swo 27 | *~ 28 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /config/rbac/alert_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view alerts. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: alert-viewer-role 9 | rules: 10 | - apiGroups: 11 | - alertmanager.prometheus.io.alertmanager.prometheus.io 12 | resources: 13 | - alerts 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - apiGroups: 19 | - alertmanager.prometheus.io.alertmanager.prometheus.io 20 | resources: 21 | - alerts/status 22 | verbs: 23 | - get 24 | -------------------------------------------------------------------------------- /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/silence_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view silences. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: silence-viewer-role 9 | rules: 10 | - apiGroups: 11 | - alertmanager.prometheus.io.alertmanager.prometheus.io 12 | resources: 13 | - silences 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - apiGroups: 19 | - alertmanager.prometheus.io.alertmanager.prometheus.io 20 | resources: 21 | - silences/status 22 | verbs: 23 | - get 24 | -------------------------------------------------------------------------------- /openapi-generator-config.yaml: -------------------------------------------------------------------------------- 1 | # https://github.com/OpenAPITools/openapi-generator/blob/master/docs/customization.md 2 | globalProperties: 3 | apis: "" # generate all APIs 4 | models: "" # generate all models 5 | supportingFiles: "client.go,response.go,utils.go,configuration.go" 6 | # we don't need this extra stuff 7 | modelDocs: "false" 8 | modelTests: "false" 9 | apiTests: "false" 10 | apiDocs: "false" 11 | 12 | # https://github.com/OpenAPITools/openapi-generator/blob/master/docs/generators/go.md 13 | additionalProperties: 14 | packageName: alertmanagerapi 15 | isGoSubmodule: true 16 | withGoMod: false 17 | enumClassPrefix: true 18 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/.openapi-generator/FILES: -------------------------------------------------------------------------------- 1 | api_alert.go 2 | api_alertgroup.go 3 | api_general.go 4 | api_receiver.go 5 | api_silence.go 6 | client.go 7 | configuration.go 8 | model_alert.go 9 | model_alert_group.go 10 | model_alert_status.go 11 | model_alertmanager_config.go 12 | model_alertmanager_status.go 13 | model_cluster_status.go 14 | model_gettable_alert.go 15 | model_gettable_silence.go 16 | model_matcher.go 17 | model_peer_status.go 18 | model_post_silences_200_response.go 19 | model_postable_alert.go 20 | model_postable_silence.go 21 | model_receiver.go 22 | model_silence.go 23 | model_silence_status.go 24 | model_version_info.go 25 | response.go 26 | utils.go 27 | -------------------------------------------------------------------------------- /config/rbac/alert_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit alerts. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: alert-editor-role 9 | rules: 10 | - apiGroups: 11 | - alertmanager.prometheus.io.alertmanager.prometheus.io 12 | resources: 13 | - alerts 14 | verbs: 15 | - create 16 | - delete 17 | - get 18 | - list 19 | - patch 20 | - update 21 | - watch 22 | - apiGroups: 23 | - alertmanager.prometheus.io.alertmanager.prometheus.io 24 | resources: 25 | - alerts/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /config/rbac/silence_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit silences. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | labels: 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: silence-editor-role 9 | rules: 10 | - apiGroups: 11 | - alertmanager.prometheus.io.alertmanager.prometheus.io 12 | resources: 13 | - silences 14 | verbs: 15 | - create 16 | - delete 17 | - get 18 | - list 19 | - patch 20 | - update 21 | - watch 22 | - apiGroups: 23 | - alertmanager.prometheus.io.alertmanager.prometheus.io 24 | resources: 25 | - silences/status 26 | verbs: 27 | - get 28 | -------------------------------------------------------------------------------- /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: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: leader-election-role 9 | rules: 10 | - apiGroups: 11 | - "" 12 | resources: 13 | - configmaps 14 | verbs: 15 | - get 16 | - list 17 | - watch 18 | - create 19 | - update 20 | - patch 21 | - delete 22 | - apiGroups: 23 | - coordination.k8s.io 24 | resources: 25 | - leases 26 | verbs: 27 | - get 28 | - list 29 | - watch 30 | - create 31 | - update 32 | - patch 33 | - delete 34 | - apiGroups: 35 | - "" 36 | resources: 37 | - events 38 | verbs: 39 | - create 40 | - patch 41 | -------------------------------------------------------------------------------- /fakeprometheus.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | ) 7 | 8 | // https://prometheus.io/docs/prometheus/latest/querying/api/#alerts 9 | func prometheusAlerts(w http.ResponseWriter, req *http.Request) { 10 | fmt.Fprintf(w, `{ 11 | "data": { 12 | "alerts": [ 13 | { 14 | "activeAt": "2018-07-04T20:27:12.60602144+02:00", 15 | "annotations": {}, 16 | "labels": { 17 | "alertname": "my-alert" 18 | }, 19 | "state": "firing", 20 | "value": "1e+00" 21 | } 22 | ] 23 | }, 24 | "status": "success" 25 | }`) 26 | } 27 | 28 | func main() { 29 | http.HandleFunc("/api/v1/alerts", prometheusAlerts) 30 | 31 | fmt.Println("Running on port 9090 ...") 32 | http.ListenAndServe("localhost:9090", nil) 33 | } 34 | -------------------------------------------------------------------------------- /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: alertmanager.prometheus.io 6 | layout: 7 | - go.kubebuilder.io/v4 8 | projectName: alert-operator 9 | repo: github.com/jacksgt/alert-operator 10 | resources: 11 | - api: 12 | crdVersion: v1 13 | namespaced: true 14 | controller: true 15 | domain: alertmanager.prometheus.io 16 | group: alertmanager.prometheus.io 17 | kind: Alert 18 | path: github.com/jacksgt/alert-operator/api/v1alpha1 19 | version: v1alpha1 20 | - api: 21 | crdVersion: v1 22 | namespaced: true 23 | controller: true 24 | domain: alertmanager.prometheus.io 25 | group: alertmanager.prometheus.io 26 | kind: Silence 27 | path: github.com/jacksgt/alert-operator/api/v1alpha1 28 | version: v1alpha1 29 | version: "3" 30 | -------------------------------------------------------------------------------- /test/e2e/e2e_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 e2e 18 | 19 | import ( 20 | "fmt" 21 | "testing" 22 | 23 | . "github.com/onsi/ginkgo/v2" 24 | . "github.com/onsi/gomega" 25 | ) 26 | 27 | // Run e2e tests using the Ginkgo runner. 28 | func TestE2E(t *testing.T) { 29 | RegisterFailHandler(Fail) 30 | fmt.Fprintf(GinkgoWriter, "Starting alert-operator suite\n") 31 | RunSpecs(t, "e2e suite") 32 | } 33 | -------------------------------------------------------------------------------- /.golangci.yml: -------------------------------------------------------------------------------- 1 | run: 2 | timeout: 5m 3 | allow-parallel-runners: true 4 | 5 | issues: 6 | # don't skip warning about doc comments 7 | # don't exclude the default set of lint 8 | exclude-use-default: false 9 | # restore some of the defaults 10 | # (fill in the rest as needed) 11 | exclude-rules: 12 | - path: "api/*" 13 | linters: 14 | - lll 15 | - path: "internal/*" 16 | linters: 17 | - dupl 18 | - lll 19 | linters: 20 | disable-all: true 21 | enable: 22 | - dupl 23 | - errcheck 24 | - exportloopref 25 | - ginkgolinter 26 | - goconst 27 | - gocyclo 28 | - gofmt 29 | - goimports 30 | - gosimple 31 | - govet 32 | - ineffassign 33 | - lll 34 | - misspell 35 | - nakedret 36 | - prealloc 37 | - revive 38 | - staticcheck 39 | - typecheck 40 | - unconvert 41 | - unparam 42 | - unused 43 | 44 | linters-settings: 45 | revive: 46 | rules: 47 | - name: comment-spacings 48 | -------------------------------------------------------------------------------- /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/alertmanager.prometheus.io.alertmanager.prometheus.io_alerts.yaml 6 | - bases/alertmanager.prometheus.io.alertmanager.prometheus.io_silences.yaml 7 | # +kubebuilder:scaffold:crdkustomizeresource 8 | 9 | patches: 10 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 11 | # patches here are for enabling the conversion webhook for each CRD 12 | # +kubebuilder:scaffold:crdkustomizewebhookpatch 13 | 14 | # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix. 15 | # patches here are for enabling the CA injection for each CRD 16 | #- path: patches/cainjection_in_alerts.yaml 17 | #- path: patches/cainjection_in_silences.yaml 18 | # +kubebuilder:scaffold:crdkustomizecainjectionpatch 19 | 20 | # [WEBHOOK] To enable webhook, uncomment the following section 21 | # the following config is for teaching kustomize how to do kustomization for CRDs. 22 | 23 | #configurations: 24 | #- kustomizeconfig.yaml 25 | -------------------------------------------------------------------------------- /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 | - alertmanager.prometheus.io.alertmanager.prometheus.io 9 | resources: 10 | - alerts 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - alertmanager.prometheus.io.alertmanager.prometheus.io 21 | resources: 22 | - alerts/finalizers 23 | verbs: 24 | - update 25 | - apiGroups: 26 | - alertmanager.prometheus.io.alertmanager.prometheus.io 27 | resources: 28 | - alerts/status 29 | verbs: 30 | - get 31 | - patch 32 | - update 33 | - apiGroups: 34 | - alertmanager.prometheus.io.alertmanager.prometheus.io 35 | resources: 36 | - silences 37 | verbs: 38 | - create 39 | - delete 40 | - get 41 | - list 42 | - patch 43 | - update 44 | - watch 45 | - apiGroups: 46 | - alertmanager.prometheus.io.alertmanager.prometheus.io 47 | resources: 48 | - silences/finalizers 49 | verbs: 50 | - update 51 | - apiGroups: 52 | - alertmanager.prometheus.io.alertmanager.prometheus.io 53 | resources: 54 | - silences/status 55 | verbs: 56 | - get 57 | - patch 58 | - update 59 | -------------------------------------------------------------------------------- /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 | # The following RBAC configurations are used to protect 13 | # the metrics endpoint with authn/authz. These configurations 14 | # ensure that only authorized users and service accounts 15 | # can access the metrics endpoint. Comment the following 16 | # permissions if you want to disable this protection. 17 | # More info: https://book.kubebuilder.io/reference/metrics.html 18 | - metrics_auth_role.yaml 19 | - metrics_auth_role_binding.yaml 20 | - metrics_reader_role.yaml 21 | # For each CRD, "Editor" and "Viewer" roles are scaffolded by 22 | # default, aiding admins in cluster management. Those roles are 23 | # not used by the Project itself. You can comment the following lines 24 | # if you do not want those helpers be installed with your Project. 25 | - silence_editor_role.yaml 26 | - silence_viewer_role.yaml 27 | - alert_editor_role.yaml 28 | - alert_viewer_role.yaml 29 | 30 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Build the manager binary 2 | FROM golang:1.22 AS builder 3 | ARG TARGETOS 4 | ARG TARGETARCH 5 | 6 | WORKDIR /workspace 7 | # Copy the Go Modules manifests 8 | COPY go.mod go.mod 9 | COPY go.sum go.sum 10 | # cache deps before building and copying source so that we don't need to re-download as much 11 | # and so that source changes don't invalidate our downloaded layer 12 | RUN go mod download 13 | 14 | # Copy the go source 15 | COPY cmd/main.go cmd/main.go 16 | COPY api/ api/ 17 | COPY internal/controller/ internal/controller/ 18 | 19 | # Build 20 | # the GOARCH has not a default value to allow the binary be built according to the host where the command 21 | # was called. For example, if we call make docker-build in a local env which has the Apple Silicon M1 SO 22 | # the docker BUILDPLATFORM arg will be linux/arm64 when for Apple x86 it will be linux/amd64. Therefore, 23 | # by leaving it empty we can ensure that the container and binary shipped on it will have the same platform. 24 | RUN CGO_ENABLED=0 GOOS=${TARGETOS:-linux} GOARCH=${TARGETARCH} go build -a -o manager cmd/main.go 25 | 26 | # Use distroless as minimal base image to package the manager binary 27 | # Refer to https://github.com/GoogleContainerTools/distroless for more details 28 | FROM gcr.io/distroless/static:nonroot 29 | WORKDIR / 30 | COPY --from=builder /workspace/manager . 31 | USER 65532:65532 32 | 33 | ENTRYPOINT ["/manager"] 34 | -------------------------------------------------------------------------------- /api/v1alpha1/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 v1alpha1 contains API Schema definitions for the alertmanager.prometheus.io v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=alertmanager.prometheus.io.alertmanager.prometheus.io 20 | package v1alpha1 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: "alertmanager.prometheus.io.alertmanager.prometheus.io", Version: "v1alpha1"} 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 | -------------------------------------------------------------------------------- /config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | # Prometheus Monitor Service (Metrics) 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | control-plane: controller-manager 7 | app.kubernetes.io/name: alert-operator 8 | app.kubernetes.io/managed-by: kustomize 9 | name: controller-manager-metrics-monitor 10 | namespace: system 11 | spec: 12 | endpoints: 13 | - path: /metrics 14 | port: https # Ensure this is the name of the port that exposes HTTPS metrics 15 | scheme: https 16 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 17 | tlsConfig: 18 | # TODO(user): The option insecureSkipVerify: true is not recommended for production since it disables 19 | # certificate verification. This poses a significant security risk by making the system vulnerable to 20 | # man-in-the-middle attacks, where an attacker could intercept and manipulate the communication between 21 | # Prometheus and the monitored services. This could lead to unauthorized access to sensitive metrics data, 22 | # compromising the integrity and confidentiality of the information. 23 | # Please use the following options for secure configurations: 24 | # caFile: /etc/metrics-certs/ca.crt 25 | # certFile: /etc/metrics-certs/tls.crt 26 | # keyFile: /etc/metrics-certs/tls.key 27 | insecureSkipVerify: true 28 | selector: 29 | matchLabels: 30 | control-plane: controller-manager 31 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/response.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "net/http" 15 | ) 16 | 17 | // APIResponse stores the API response returned by the server. 18 | type APIResponse struct { 19 | *http.Response `json:"-"` 20 | Message string `json:"message,omitempty"` 21 | // Operation is the name of the OpenAPI operation. 22 | Operation string `json:"operation,omitempty"` 23 | // RequestURL is the request URL. This value is always available, even if the 24 | // embedded *http.Response is nil. 25 | RequestURL string `json:"url,omitempty"` 26 | // Method is the HTTP method used for the request. This value is always 27 | // available, even if the embedded *http.Response is nil. 28 | Method string `json:"method,omitempty"` 29 | // Payload holds the contents of the response body (which may be nil or empty). 30 | // This is provided here as the raw response.Body() reader will have already 31 | // been drained. 32 | Payload []byte `json:"-"` 33 | } 34 | 35 | // NewAPIResponse returns a new APIResponse object. 36 | func NewAPIResponse(r *http.Response) *APIResponse { 37 | 38 | response := &APIResponse{Response: r} 39 | return response 40 | } 41 | 42 | // NewAPIResponseWithError returns a new APIResponse object with the provided error message. 43 | func NewAPIResponseWithError(errorMessage string) *APIResponse { 44 | 45 | response := &APIResponse{Message: errorMessage} 46 | return response 47 | } 48 | -------------------------------------------------------------------------------- /api/v1alpha1/alert_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 v1alpha1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // AlertSpec defines the desired state of Alert 24 | type AlertSpec struct { 25 | // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster 26 | // Important: Run "make" to regenerate code after modifying this file 27 | 28 | } 29 | 30 | // AlertStatus defines the observed state of Alert 31 | type AlertStatus struct { 32 | // State describes if the alert is currently active or not. 33 | State string `json:"state,omitempty"` 34 | // Annotations contains key-value data associated to the alert. 35 | Annotations map[string]string `json:"annotations,omitempty"` 36 | // Labels contains key-value data associated to the alert. 37 | Labels map[string]string `json:"labels,omitempty"` 38 | // Describes since which timestamp the alert is active. 39 | Since string `json:"since,omitempty"` // TODO: use a proper timestamp 40 | // The current value of alert expression. 41 | Value string `json:"value,omitempty"` 42 | } 43 | 44 | // +kubebuilder:object:root=true 45 | // +kubebuilder:subresource:status 46 | 47 | // Alert is the Schema for the alerts API 48 | // +kubebuilder:printcolumn:name="State",type=string,JSONPath=`.status.state` 49 | // +kubebuilder:printcolumn:name="Since",type=string,JSONPath=`.status.since` 50 | // https://book.kubebuilder.io/reference/generating-crd.html#additional-printer-columns 51 | type Alert struct { 52 | metav1.TypeMeta `json:",inline"` 53 | metav1.ObjectMeta `json:"metadata,omitempty"` 54 | 55 | Spec AlertSpec `json:"spec,omitempty"` 56 | Status AlertStatus `json:"status,omitempty"` 57 | } 58 | 59 | // +kubebuilder:object:root=true 60 | 61 | // AlertList contains a list of Alert 62 | type AlertList struct { 63 | metav1.TypeMeta `json:",inline"` 64 | metav1.ListMeta `json:"metadata,omitempty"` 65 | Items []Alert `json:"items"` 66 | } 67 | 68 | func init() { 69 | SchemeBuilder.Register(&Alert{}, &AlertList{}) 70 | } 71 | -------------------------------------------------------------------------------- /internal/controller/alert_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 | alertmanagerprometheusiov1alpha1 "github.com/jacksgt/alert-operator/api/v1alpha1" 31 | ) 32 | 33 | var _ = Describe("Alert 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 | alert := &alertmanagerprometheusiov1alpha1.Alert{} 44 | 45 | BeforeEach(func() { 46 | By("creating the custom resource for the Kind Alert") 47 | err := k8sClient.Get(ctx, typeNamespacedName, alert) 48 | if err != nil && errors.IsNotFound(err) { 49 | resource := &alertmanagerprometheusiov1alpha1.Alert{ 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 := &alertmanagerprometheusiov1alpha1.Alert{} 63 | err := k8sClient.Get(ctx, typeNamespacedName, resource) 64 | Expect(err).NotTo(HaveOccurred()) 65 | 66 | By("Cleanup the specific resource instance Alert") 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 := &AlertReconciler{ 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/silence_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 | alertmanagerprometheusiov1alpha1 "github.com/jacksgt/alert-operator/api/v1alpha1" 31 | ) 32 | 33 | var _ = Describe("Silence 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 | silence := &alertmanagerprometheusiov1alpha1.Silence{} 44 | 45 | BeforeEach(func() { 46 | By("creating the custom resource for the Kind Silence") 47 | err := k8sClient.Get(ctx, typeNamespacedName, silence) 48 | if err != nil && errors.IsNotFound(err) { 49 | resource := &alertmanagerprometheusiov1alpha1.Silence{ 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 := &alertmanagerprometheusiov1alpha1.Silence{} 63 | err := k8sClient.Get(ctx, typeNamespacedName, resource) 64 | Expect(err).NotTo(HaveOccurred()) 65 | 66 | By("Cleanup the specific resource instance Silence") 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 := &SilenceReconciler{ 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 | alertmanagerprometheusiov1alpha1 "github.com/jacksgt/alert-operator/api/v1alpha1" 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.30.0-%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 = alertmanagerprometheusiov1alpha1.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 | -------------------------------------------------------------------------------- /config/crd/bases/alertmanager.prometheus.io.alertmanager.prometheus.io_alerts.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.15.0 7 | name: alerts.alertmanager.prometheus.io.alertmanager.prometheus.io 8 | spec: 9 | group: alertmanager.prometheus.io.alertmanager.prometheus.io 10 | names: 11 | kind: Alert 12 | listKind: AlertList 13 | plural: alerts 14 | singular: alert 15 | scope: Namespaced 16 | versions: 17 | - additionalPrinterColumns: 18 | - jsonPath: .status.state 19 | name: State 20 | type: string 21 | - jsonPath: .status.since 22 | name: Since 23 | type: string 24 | name: v1alpha1 25 | schema: 26 | openAPIV3Schema: 27 | description: |- 28 | Alert is the Schema for the alerts API 29 | https://book.kubebuilder.io/reference/generating-crd.html#additional-printer-columns 30 | properties: 31 | apiVersion: 32 | description: |- 33 | APIVersion defines the versioned schema of this representation of an object. 34 | Servers should convert recognized schemas to the latest internal value, and 35 | may reject unrecognized values. 36 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 37 | type: string 38 | kind: 39 | description: |- 40 | Kind is a string value representing the REST resource this object represents. 41 | Servers may infer this from the endpoint the client submits requests to. 42 | Cannot be updated. 43 | In CamelCase. 44 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 45 | type: string 46 | metadata: 47 | type: object 48 | spec: 49 | description: AlertSpec defines the desired state of Alert 50 | type: object 51 | status: 52 | description: AlertStatus defines the observed state of Alert 53 | properties: 54 | annotations: 55 | additionalProperties: 56 | type: string 57 | description: Annotations contains key-value data associated to the 58 | alert. 59 | type: object 60 | labels: 61 | additionalProperties: 62 | type: string 63 | description: Labels contains key-value data associated to the alert. 64 | type: object 65 | since: 66 | description: Describes since which timestamp the alert is active. 67 | type: string 68 | state: 69 | description: State describes if the alert is currently active or not. 70 | type: string 71 | value: 72 | description: The current value of alert expression. 73 | type: string 74 | type: object 75 | type: object 76 | served: true 77 | storage: true 78 | subresources: 79 | status: {} 80 | -------------------------------------------------------------------------------- /api/v1alpha1/silence_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 v1alpha1 18 | 19 | import ( 20 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 21 | ) 22 | 23 | // SilenceSpec defines the desired state of Silence 24 | type SilenceSpec struct { 25 | // TODO: CRD validation https://book.kubebuilder.io/reference/markers/crd-validation.html 26 | // TODO: MatchRegexes 27 | 28 | // MatchLabels contains the set of labels (non-regexed) that this silence applies to. 29 | MatchLabels map[string]string `json:"matchLabels,omitempty"` 30 | // StartsAt contains the timestamp indicating at which time the silence began. 31 | StartsAt metav1.Time `json:"startsAt,omitempty"` // should be auto-filled 32 | // EndsAt contains the timestamp indicating at which time the silence ends. 33 | EndsAt metav1.Time `json:"endsAt,omitempty"` // provide go-duration input? 34 | // CreatedBy indicates the user who created the silence. 35 | CreatedBy string `json:"createdBy,omitempty"` // creator 36 | // Comment contains additional information about the silence, e.g. the reason for it. 37 | Comment string `json:"comment,omitempty"` 38 | } 39 | 40 | // SilenceStatus defines the observed state of Silence 41 | type SilenceStatus struct { 42 | // SilenceId is the unique identifier for this silence (generated by Alertmanager) 43 | SilenceId string `json:"silenceID,omitempty"` 44 | // Represents the observations of a Memcached's current state. 45 | // Memcached.status.conditions.type are: "Available", "Progressing", and "Degraded" 46 | // Memcached.status.conditions.status are one of True, False, Unknown. 47 | // Memcached.status.conditions.reason the value should be a CamelCase string and producers of specific 48 | // condition types may define expected values and meanings for this field, and whether the values 49 | // are considered a guaranteed API. 50 | // Memcached.status.conditions.Message is a human readable message indicating details about the transition. 51 | // For further information see: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties 52 | 53 | Conditions []metav1.Condition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,1,rep,name=conditions"` 54 | } 55 | 56 | // +kubebuilder:object:root=true 57 | // +kubebuilder:subresource:status 58 | 59 | // Silence is the Schema for the silences API 60 | type Silence struct { 61 | metav1.TypeMeta `json:",inline"` 62 | metav1.ObjectMeta `json:"metadata,omitempty"` 63 | 64 | Spec SilenceSpec `json:"spec,omitempty"` 65 | Status SilenceStatus `json:"status,omitempty"` 66 | } 67 | 68 | // +kubebuilder:object:root=true 69 | 70 | // SilenceList contains a list of Silence 71 | type SilenceList struct { 72 | metav1.TypeMeta `json:",inline"` 73 | metav1.ListMeta `json:"metadata,omitempty"` 74 | Items []Silence `json:"items"` 75 | } 76 | 77 | func init() { 78 | SchemeBuilder.Register(&Silence{}, &SilenceList{}) 79 | } 80 | -------------------------------------------------------------------------------- /config/manager/manager.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Namespace 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | app.kubernetes.io/name: alert-operator 7 | app.kubernetes.io/managed-by: kustomize 8 | name: system 9 | --- 10 | apiVersion: apps/v1 11 | kind: Deployment 12 | metadata: 13 | name: controller-manager 14 | namespace: system 15 | labels: 16 | control-plane: controller-manager 17 | app.kubernetes.io/name: alert-operator 18 | app.kubernetes.io/managed-by: kustomize 19 | spec: 20 | selector: 21 | matchLabels: 22 | control-plane: controller-manager 23 | replicas: 1 24 | template: 25 | metadata: 26 | annotations: 27 | kubectl.kubernetes.io/default-container: manager 28 | labels: 29 | control-plane: controller-manager 30 | spec: 31 | # TODO(user): Uncomment the following code to configure the nodeAffinity expression 32 | # according to the platforms which are supported by your solution. 33 | # It is considered best practice to support multiple architectures. You can 34 | # build your manager image using the makefile target docker-buildx. 35 | # affinity: 36 | # nodeAffinity: 37 | # requiredDuringSchedulingIgnoredDuringExecution: 38 | # nodeSelectorTerms: 39 | # - matchExpressions: 40 | # - key: kubernetes.io/arch 41 | # operator: In 42 | # values: 43 | # - amd64 44 | # - arm64 45 | # - ppc64le 46 | # - s390x 47 | # - key: kubernetes.io/os 48 | # operator: In 49 | # values: 50 | # - linux 51 | securityContext: 52 | runAsNonRoot: true 53 | # TODO(user): For common cases that do not require escalating privileges 54 | # it is recommended to ensure that all your Pods/Containers are restrictive. 55 | # More info: https://kubernetes.io/docs/concepts/security/pod-security-standards/#restricted 56 | # Please uncomment the following code if your project does NOT have to work on old Kubernetes 57 | # versions < 1.19 or on vendors versions which do NOT support this field by default (i.e. Openshift < 4.11 ). 58 | # seccompProfile: 59 | # type: RuntimeDefault 60 | containers: 61 | - command: 62 | - /manager 63 | args: 64 | - --leader-elect 65 | - --health-probe-bind-address=:8081 66 | image: controller:latest 67 | name: manager 68 | securityContext: 69 | allowPrivilegeEscalation: false 70 | capabilities: 71 | drop: 72 | - "ALL" 73 | livenessProbe: 74 | httpGet: 75 | path: /healthz 76 | port: 8081 77 | initialDelaySeconds: 15 78 | periodSeconds: 20 79 | readinessProbe: 80 | httpGet: 81 | path: /readyz 82 | port: 8081 83 | initialDelaySeconds: 5 84 | periodSeconds: 10 85 | # TODO(user): Configure the resources accordingly based on the project requirements. 86 | # More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ 87 | resources: 88 | limits: 89 | cpu: 500m 90 | memory: 128Mi 91 | requests: 92 | cpu: 10m 93 | memory: 64Mi 94 | serviceAccountName: controller-manager 95 | terminationGracePeriodSeconds: 10 96 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/api_general.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "io" 17 | "net/http" 18 | "net/url" 19 | ) 20 | 21 | 22 | // GeneralAPIService GeneralAPI service 23 | type GeneralAPIService service 24 | 25 | type ApiGetStatusRequest struct { 26 | ctx context.Context 27 | ApiService *GeneralAPIService 28 | } 29 | 30 | func (r ApiGetStatusRequest) Execute() (*AlertmanagerStatus, *http.Response, error) { 31 | return r.ApiService.GetStatusExecute(r) 32 | } 33 | 34 | /* 35 | GetStatus Method for GetStatus 36 | 37 | Get current status of an Alertmanager instance and its cluster 38 | 39 | @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). 40 | @return ApiGetStatusRequest 41 | */ 42 | func (a *GeneralAPIService) GetStatus(ctx context.Context) ApiGetStatusRequest { 43 | return ApiGetStatusRequest{ 44 | ApiService: a, 45 | ctx: ctx, 46 | } 47 | } 48 | 49 | // Execute executes the request 50 | // @return AlertmanagerStatus 51 | func (a *GeneralAPIService) GetStatusExecute(r ApiGetStatusRequest) (*AlertmanagerStatus, *http.Response, error) { 52 | var ( 53 | localVarHTTPMethod = http.MethodGet 54 | localVarPostBody interface{} 55 | formFiles []formFile 56 | localVarReturnValue *AlertmanagerStatus 57 | ) 58 | 59 | localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "GeneralAPIService.GetStatus") 60 | if err != nil { 61 | return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} 62 | } 63 | 64 | localVarPath := localBasePath + "/status" 65 | 66 | localVarHeaderParams := make(map[string]string) 67 | localVarQueryParams := url.Values{} 68 | localVarFormParams := url.Values{} 69 | 70 | // to determine the Content-Type header 71 | localVarHTTPContentTypes := []string{} 72 | 73 | // set Content-Type header 74 | localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) 75 | if localVarHTTPContentType != "" { 76 | localVarHeaderParams["Content-Type"] = localVarHTTPContentType 77 | } 78 | 79 | // to determine the Accept header 80 | localVarHTTPHeaderAccepts := []string{"application/json"} 81 | 82 | // set Accept header 83 | localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) 84 | if localVarHTTPHeaderAccept != "" { 85 | localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept 86 | } 87 | req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) 88 | if err != nil { 89 | return localVarReturnValue, nil, err 90 | } 91 | 92 | localVarHTTPResponse, err := a.client.callAPI(req) 93 | if err != nil || localVarHTTPResponse == nil { 94 | return localVarReturnValue, localVarHTTPResponse, err 95 | } 96 | 97 | localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) 98 | localVarHTTPResponse.Body.Close() 99 | localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) 100 | if err != nil { 101 | return localVarReturnValue, localVarHTTPResponse, err 102 | } 103 | 104 | if localVarHTTPResponse.StatusCode >= 300 { 105 | newErr := &GenericOpenAPIError{ 106 | body: localVarBody, 107 | error: localVarHTTPResponse.Status, 108 | } 109 | return localVarReturnValue, localVarHTTPResponse, newErr 110 | } 111 | 112 | err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) 113 | if err != nil { 114 | newErr := &GenericOpenAPIError{ 115 | body: localVarBody, 116 | error: err.Error(), 117 | } 118 | return localVarReturnValue, localVarHTTPResponse, newErr 119 | } 120 | 121 | return localVarReturnValue, localVarHTTPResponse, nil 122 | } 123 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/api_receiver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "io" 17 | "net/http" 18 | "net/url" 19 | ) 20 | 21 | 22 | // ReceiverAPIService ReceiverAPI service 23 | type ReceiverAPIService service 24 | 25 | type ApiGetReceiversRequest struct { 26 | ctx context.Context 27 | ApiService *ReceiverAPIService 28 | } 29 | 30 | func (r ApiGetReceiversRequest) Execute() ([]Receiver, *http.Response, error) { 31 | return r.ApiService.GetReceiversExecute(r) 32 | } 33 | 34 | /* 35 | GetReceivers Method for GetReceivers 36 | 37 | Get list of all receivers (name of notification integrations) 38 | 39 | @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). 40 | @return ApiGetReceiversRequest 41 | */ 42 | func (a *ReceiverAPIService) GetReceivers(ctx context.Context) ApiGetReceiversRequest { 43 | return ApiGetReceiversRequest{ 44 | ApiService: a, 45 | ctx: ctx, 46 | } 47 | } 48 | 49 | // Execute executes the request 50 | // @return []Receiver 51 | func (a *ReceiverAPIService) GetReceiversExecute(r ApiGetReceiversRequest) ([]Receiver, *http.Response, error) { 52 | var ( 53 | localVarHTTPMethod = http.MethodGet 54 | localVarPostBody interface{} 55 | formFiles []formFile 56 | localVarReturnValue []Receiver 57 | ) 58 | 59 | localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "ReceiverAPIService.GetReceivers") 60 | if err != nil { 61 | return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} 62 | } 63 | 64 | localVarPath := localBasePath + "/receivers" 65 | 66 | localVarHeaderParams := make(map[string]string) 67 | localVarQueryParams := url.Values{} 68 | localVarFormParams := url.Values{} 69 | 70 | // to determine the Content-Type header 71 | localVarHTTPContentTypes := []string{} 72 | 73 | // set Content-Type header 74 | localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) 75 | if localVarHTTPContentType != "" { 76 | localVarHeaderParams["Content-Type"] = localVarHTTPContentType 77 | } 78 | 79 | // to determine the Accept header 80 | localVarHTTPHeaderAccepts := []string{"application/json"} 81 | 82 | // set Accept header 83 | localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) 84 | if localVarHTTPHeaderAccept != "" { 85 | localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept 86 | } 87 | req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) 88 | if err != nil { 89 | return localVarReturnValue, nil, err 90 | } 91 | 92 | localVarHTTPResponse, err := a.client.callAPI(req) 93 | if err != nil || localVarHTTPResponse == nil { 94 | return localVarReturnValue, localVarHTTPResponse, err 95 | } 96 | 97 | localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) 98 | localVarHTTPResponse.Body.Close() 99 | localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) 100 | if err != nil { 101 | return localVarReturnValue, localVarHTTPResponse, err 102 | } 103 | 104 | if localVarHTTPResponse.StatusCode >= 300 { 105 | newErr := &GenericOpenAPIError{ 106 | body: localVarBody, 107 | error: localVarHTTPResponse.Status, 108 | } 109 | return localVarReturnValue, localVarHTTPResponse, newErr 110 | } 111 | 112 | err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) 113 | if err != nil { 114 | newErr := &GenericOpenAPIError{ 115 | body: localVarBody, 116 | error: err.Error(), 117 | } 118 | return localVarReturnValue, localVarHTTPResponse, newErr 119 | } 120 | 121 | return localVarReturnValue, localVarHTTPResponse, nil 122 | } 123 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_post_silences_200_response.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | ) 16 | 17 | // checks if the PostSilences200Response type satisfies the MappedNullable interface at compile time 18 | var _ MappedNullable = &PostSilences200Response{} 19 | 20 | // PostSilences200Response struct for PostSilences200Response 21 | type PostSilences200Response struct { 22 | SilenceID *string `json:"silenceID,omitempty"` 23 | } 24 | 25 | // NewPostSilences200Response instantiates a new PostSilences200Response object 26 | // This constructor will assign default values to properties that have it defined, 27 | // and makes sure properties required by API are set, but the set of arguments 28 | // will change when the set of required properties is changed 29 | func NewPostSilences200Response() *PostSilences200Response { 30 | this := PostSilences200Response{} 31 | return &this 32 | } 33 | 34 | // NewPostSilences200ResponseWithDefaults instantiates a new PostSilences200Response object 35 | // This constructor will only assign default values to properties that have it defined, 36 | // but it doesn't guarantee that properties required by API are set 37 | func NewPostSilences200ResponseWithDefaults() *PostSilences200Response { 38 | this := PostSilences200Response{} 39 | return &this 40 | } 41 | 42 | // GetSilenceID returns the SilenceID field value if set, zero value otherwise. 43 | func (o *PostSilences200Response) GetSilenceID() string { 44 | if o == nil || IsNil(o.SilenceID) { 45 | var ret string 46 | return ret 47 | } 48 | return *o.SilenceID 49 | } 50 | 51 | // GetSilenceIDOk returns a tuple with the SilenceID field value if set, nil otherwise 52 | // and a boolean to check if the value has been set. 53 | func (o *PostSilences200Response) GetSilenceIDOk() (*string, bool) { 54 | if o == nil || IsNil(o.SilenceID) { 55 | return nil, false 56 | } 57 | return o.SilenceID, true 58 | } 59 | 60 | // HasSilenceID returns a boolean if a field has been set. 61 | func (o *PostSilences200Response) HasSilenceID() bool { 62 | if o != nil && !IsNil(o.SilenceID) { 63 | return true 64 | } 65 | 66 | return false 67 | } 68 | 69 | // SetSilenceID gets a reference to the given string and assigns it to the SilenceID field. 70 | func (o *PostSilences200Response) SetSilenceID(v string) { 71 | o.SilenceID = &v 72 | } 73 | 74 | func (o PostSilences200Response) MarshalJSON() ([]byte, error) { 75 | toSerialize,err := o.ToMap() 76 | if err != nil { 77 | return []byte{}, err 78 | } 79 | return json.Marshal(toSerialize) 80 | } 81 | 82 | func (o PostSilences200Response) ToMap() (map[string]interface{}, error) { 83 | toSerialize := map[string]interface{}{} 84 | if !IsNil(o.SilenceID) { 85 | toSerialize["silenceID"] = o.SilenceID 86 | } 87 | return toSerialize, nil 88 | } 89 | 90 | type NullablePostSilences200Response struct { 91 | value *PostSilences200Response 92 | isSet bool 93 | } 94 | 95 | func (v NullablePostSilences200Response) Get() *PostSilences200Response { 96 | return v.value 97 | } 98 | 99 | func (v *NullablePostSilences200Response) Set(val *PostSilences200Response) { 100 | v.value = val 101 | v.isSet = true 102 | } 103 | 104 | func (v NullablePostSilences200Response) IsSet() bool { 105 | return v.isSet 106 | } 107 | 108 | func (v *NullablePostSilences200Response) Unset() { 109 | v.value = nil 110 | v.isSet = false 111 | } 112 | 113 | func NewNullablePostSilences200Response(val *PostSilences200Response) *NullablePostSilences200Response { 114 | return &NullablePostSilences200Response{value: val, isSet: true} 115 | } 116 | 117 | func (v NullablePostSilences200Response) MarshalJSON() ([]byte, error) { 118 | return json.Marshal(v.value) 119 | } 120 | 121 | func (v *NullablePostSilences200Response) UnmarshalJSON(src []byte) error { 122 | v.isSet = true 123 | return json.Unmarshal(src, &v.value) 124 | } 125 | 126 | 127 | -------------------------------------------------------------------------------- /test/e2e/e2e_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 e2e 18 | 19 | import ( 20 | "fmt" 21 | "os/exec" 22 | "time" 23 | 24 | . "github.com/onsi/ginkgo/v2" 25 | . "github.com/onsi/gomega" 26 | 27 | "github.com/jacksgt/alert-operator/test/utils" 28 | ) 29 | 30 | const namespace = "alert-operator-system" 31 | 32 | var _ = Describe("controller", Ordered, func() { 33 | BeforeAll(func() { 34 | By("installing prometheus operator") 35 | Expect(utils.InstallPrometheusOperator()).To(Succeed()) 36 | 37 | By("installing the cert-manager") 38 | Expect(utils.InstallCertManager()).To(Succeed()) 39 | 40 | By("creating manager namespace") 41 | cmd := exec.Command("kubectl", "create", "ns", namespace) 42 | _, _ = utils.Run(cmd) 43 | }) 44 | 45 | AfterAll(func() { 46 | By("uninstalling the Prometheus manager bundle") 47 | utils.UninstallPrometheusOperator() 48 | 49 | By("uninstalling the cert-manager bundle") 50 | utils.UninstallCertManager() 51 | 52 | By("removing manager namespace") 53 | cmd := exec.Command("kubectl", "delete", "ns", namespace) 54 | _, _ = utils.Run(cmd) 55 | }) 56 | 57 | Context("Operator", func() { 58 | It("should run successfully", func() { 59 | var controllerPodName string 60 | var err error 61 | 62 | // projectimage stores the name of the image used in the example 63 | var projectimage = "example.com/alert-operator:v0.0.1" 64 | 65 | By("building the manager(Operator) image") 66 | cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", projectimage)) 67 | _, err = utils.Run(cmd) 68 | ExpectWithOffset(1, err).NotTo(HaveOccurred()) 69 | 70 | By("loading the the manager(Operator) image on Kind") 71 | err = utils.LoadImageToKindClusterWithName(projectimage) 72 | ExpectWithOffset(1, err).NotTo(HaveOccurred()) 73 | 74 | By("installing CRDs") 75 | cmd = exec.Command("make", "install") 76 | _, err = utils.Run(cmd) 77 | ExpectWithOffset(1, err).NotTo(HaveOccurred()) 78 | 79 | By("deploying the controller-manager") 80 | cmd = exec.Command("make", "deploy", fmt.Sprintf("IMG=%s", projectimage)) 81 | _, err = utils.Run(cmd) 82 | ExpectWithOffset(1, err).NotTo(HaveOccurred()) 83 | 84 | By("validating that the controller-manager pod is running as expected") 85 | verifyControllerUp := func() error { 86 | // Get pod name 87 | 88 | cmd = exec.Command("kubectl", "get", 89 | "pods", "-l", "control-plane=controller-manager", 90 | "-o", "go-template={{ range .items }}"+ 91 | "{{ if not .metadata.deletionTimestamp }}"+ 92 | "{{ .metadata.name }}"+ 93 | "{{ \"\\n\" }}{{ end }}{{ end }}", 94 | "-n", namespace, 95 | ) 96 | 97 | podOutput, err := utils.Run(cmd) 98 | ExpectWithOffset(2, err).NotTo(HaveOccurred()) 99 | podNames := utils.GetNonEmptyLines(string(podOutput)) 100 | if len(podNames) != 1 { 101 | return fmt.Errorf("expect 1 controller pods running, but got %d", len(podNames)) 102 | } 103 | controllerPodName = podNames[0] 104 | ExpectWithOffset(2, controllerPodName).Should(ContainSubstring("controller-manager")) 105 | 106 | // Validate pod status 107 | cmd = exec.Command("kubectl", "get", 108 | "pods", controllerPodName, "-o", "jsonpath={.status.phase}", 109 | "-n", namespace, 110 | ) 111 | status, err := utils.Run(cmd) 112 | ExpectWithOffset(2, err).NotTo(HaveOccurred()) 113 | if string(status) != "Running" { 114 | return fmt.Errorf("controller pod in %s status", status) 115 | } 116 | return nil 117 | } 118 | EventuallyWithOffset(1, verifyControllerUp, time.Minute, time.Second).Should(Succeed()) 119 | 120 | }) 121 | }) 122 | }) 123 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_receiver.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the Receiver type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &Receiver{} 21 | 22 | // Receiver struct for Receiver 23 | type Receiver struct { 24 | Name string `json:"name"` 25 | } 26 | 27 | type _Receiver Receiver 28 | 29 | // NewReceiver instantiates a new Receiver object 30 | // This constructor will assign default values to properties that have it defined, 31 | // and makes sure properties required by API are set, but the set of arguments 32 | // will change when the set of required properties is changed 33 | func NewReceiver(name string) *Receiver { 34 | this := Receiver{} 35 | this.Name = name 36 | return &this 37 | } 38 | 39 | // NewReceiverWithDefaults instantiates a new Receiver object 40 | // This constructor will only assign default values to properties that have it defined, 41 | // but it doesn't guarantee that properties required by API are set 42 | func NewReceiverWithDefaults() *Receiver { 43 | this := Receiver{} 44 | return &this 45 | } 46 | 47 | // GetName returns the Name field value 48 | func (o *Receiver) GetName() string { 49 | if o == nil { 50 | var ret string 51 | return ret 52 | } 53 | 54 | return o.Name 55 | } 56 | 57 | // GetNameOk returns a tuple with the Name field value 58 | // and a boolean to check if the value has been set. 59 | func (o *Receiver) GetNameOk() (*string, bool) { 60 | if o == nil { 61 | return nil, false 62 | } 63 | return &o.Name, true 64 | } 65 | 66 | // SetName sets field value 67 | func (o *Receiver) SetName(v string) { 68 | o.Name = v 69 | } 70 | 71 | func (o Receiver) MarshalJSON() ([]byte, error) { 72 | toSerialize,err := o.ToMap() 73 | if err != nil { 74 | return []byte{}, err 75 | } 76 | return json.Marshal(toSerialize) 77 | } 78 | 79 | func (o Receiver) ToMap() (map[string]interface{}, error) { 80 | toSerialize := map[string]interface{}{} 81 | toSerialize["name"] = o.Name 82 | return toSerialize, nil 83 | } 84 | 85 | func (o *Receiver) UnmarshalJSON(data []byte) (err error) { 86 | // This validates that all required properties are included in the JSON object 87 | // by unmarshalling the object into a generic map with string keys and checking 88 | // that every required field exists as a key in the generic map. 89 | requiredProperties := []string{ 90 | "name", 91 | } 92 | 93 | allProperties := make(map[string]interface{}) 94 | 95 | err = json.Unmarshal(data, &allProperties) 96 | 97 | if err != nil { 98 | return err; 99 | } 100 | 101 | for _, requiredProperty := range(requiredProperties) { 102 | if _, exists := allProperties[requiredProperty]; !exists { 103 | return fmt.Errorf("no value given for required property %v", requiredProperty) 104 | } 105 | } 106 | 107 | varReceiver := _Receiver{} 108 | 109 | decoder := json.NewDecoder(bytes.NewReader(data)) 110 | decoder.DisallowUnknownFields() 111 | err = decoder.Decode(&varReceiver) 112 | 113 | if err != nil { 114 | return err 115 | } 116 | 117 | *o = Receiver(varReceiver) 118 | 119 | return err 120 | } 121 | 122 | type NullableReceiver struct { 123 | value *Receiver 124 | isSet bool 125 | } 126 | 127 | func (v NullableReceiver) Get() *Receiver { 128 | return v.value 129 | } 130 | 131 | func (v *NullableReceiver) Set(val *Receiver) { 132 | v.value = val 133 | v.isSet = true 134 | } 135 | 136 | func (v NullableReceiver) IsSet() bool { 137 | return v.isSet 138 | } 139 | 140 | func (v *NullableReceiver) Unset() { 141 | v.value = nil 142 | v.isSet = false 143 | } 144 | 145 | func NewNullableReceiver(val *Receiver) *NullableReceiver { 146 | return &NullableReceiver{value: val, isSet: true} 147 | } 148 | 149 | func (v NullableReceiver) MarshalJSON() ([]byte, error) { 150 | return json.Marshal(v.value) 151 | } 152 | 153 | func (v *NullableReceiver) UnmarshalJSON(src []byte) error { 154 | v.isSet = true 155 | return json.Unmarshal(src, &v.value) 156 | } 157 | 158 | 159 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_silence_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the SilenceStatus type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &SilenceStatus{} 21 | 22 | // SilenceStatus struct for SilenceStatus 23 | type SilenceStatus struct { 24 | State string `json:"state"` 25 | } 26 | 27 | type _SilenceStatus SilenceStatus 28 | 29 | // NewSilenceStatus instantiates a new SilenceStatus object 30 | // This constructor will assign default values to properties that have it defined, 31 | // and makes sure properties required by API are set, but the set of arguments 32 | // will change when the set of required properties is changed 33 | func NewSilenceStatus(state string) *SilenceStatus { 34 | this := SilenceStatus{} 35 | this.State = state 36 | return &this 37 | } 38 | 39 | // NewSilenceStatusWithDefaults instantiates a new SilenceStatus object 40 | // This constructor will only assign default values to properties that have it defined, 41 | // but it doesn't guarantee that properties required by API are set 42 | func NewSilenceStatusWithDefaults() *SilenceStatus { 43 | this := SilenceStatus{} 44 | return &this 45 | } 46 | 47 | // GetState returns the State field value 48 | func (o *SilenceStatus) GetState() string { 49 | if o == nil { 50 | var ret string 51 | return ret 52 | } 53 | 54 | return o.State 55 | } 56 | 57 | // GetStateOk returns a tuple with the State field value 58 | // and a boolean to check if the value has been set. 59 | func (o *SilenceStatus) GetStateOk() (*string, bool) { 60 | if o == nil { 61 | return nil, false 62 | } 63 | return &o.State, true 64 | } 65 | 66 | // SetState sets field value 67 | func (o *SilenceStatus) SetState(v string) { 68 | o.State = v 69 | } 70 | 71 | func (o SilenceStatus) MarshalJSON() ([]byte, error) { 72 | toSerialize,err := o.ToMap() 73 | if err != nil { 74 | return []byte{}, err 75 | } 76 | return json.Marshal(toSerialize) 77 | } 78 | 79 | func (o SilenceStatus) ToMap() (map[string]interface{}, error) { 80 | toSerialize := map[string]interface{}{} 81 | toSerialize["state"] = o.State 82 | return toSerialize, nil 83 | } 84 | 85 | func (o *SilenceStatus) UnmarshalJSON(data []byte) (err error) { 86 | // This validates that all required properties are included in the JSON object 87 | // by unmarshalling the object into a generic map with string keys and checking 88 | // that every required field exists as a key in the generic map. 89 | requiredProperties := []string{ 90 | "state", 91 | } 92 | 93 | allProperties := make(map[string]interface{}) 94 | 95 | err = json.Unmarshal(data, &allProperties) 96 | 97 | if err != nil { 98 | return err; 99 | } 100 | 101 | for _, requiredProperty := range(requiredProperties) { 102 | if _, exists := allProperties[requiredProperty]; !exists { 103 | return fmt.Errorf("no value given for required property %v", requiredProperty) 104 | } 105 | } 106 | 107 | varSilenceStatus := _SilenceStatus{} 108 | 109 | decoder := json.NewDecoder(bytes.NewReader(data)) 110 | decoder.DisallowUnknownFields() 111 | err = decoder.Decode(&varSilenceStatus) 112 | 113 | if err != nil { 114 | return err 115 | } 116 | 117 | *o = SilenceStatus(varSilenceStatus) 118 | 119 | return err 120 | } 121 | 122 | type NullableSilenceStatus struct { 123 | value *SilenceStatus 124 | isSet bool 125 | } 126 | 127 | func (v NullableSilenceStatus) Get() *SilenceStatus { 128 | return v.value 129 | } 130 | 131 | func (v *NullableSilenceStatus) Set(val *SilenceStatus) { 132 | v.value = val 133 | v.isSet = true 134 | } 135 | 136 | func (v NullableSilenceStatus) IsSet() bool { 137 | return v.isSet 138 | } 139 | 140 | func (v *NullableSilenceStatus) Unset() { 141 | v.value = nil 142 | v.isSet = false 143 | } 144 | 145 | func NewNullableSilenceStatus(val *SilenceStatus) *NullableSilenceStatus { 146 | return &NullableSilenceStatus{value: val, isSet: true} 147 | } 148 | 149 | func (v NullableSilenceStatus) MarshalJSON() ([]byte, error) { 150 | return json.Marshal(v.value) 151 | } 152 | 153 | func (v *NullableSilenceStatus) UnmarshalJSON(src []byte) error { 154 | v.isSet = true 155 | return json.Unmarshal(src, &v.value) 156 | } 157 | 158 | 159 | -------------------------------------------------------------------------------- /test/utils/utils.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 utils 18 | 19 | import ( 20 | "fmt" 21 | "os" 22 | "os/exec" 23 | "strings" 24 | 25 | . "github.com/onsi/ginkgo/v2" //nolint:golint,revive 26 | ) 27 | 28 | const ( 29 | prometheusOperatorVersion = "v0.72.0" 30 | prometheusOperatorURL = "https://github.com/prometheus-operator/prometheus-operator/" + 31 | "releases/download/%s/bundle.yaml" 32 | 33 | certmanagerVersion = "v1.14.4" 34 | certmanagerURLTmpl = "https://github.com/jetstack/cert-manager/releases/download/%s/cert-manager.yaml" 35 | ) 36 | 37 | func warnError(err error) { 38 | fmt.Fprintf(GinkgoWriter, "warning: %v\n", err) 39 | } 40 | 41 | // InstallPrometheusOperator installs the prometheus Operator to be used to export the enabled metrics. 42 | func InstallPrometheusOperator() error { 43 | url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion) 44 | cmd := exec.Command("kubectl", "create", "-f", url) 45 | _, err := Run(cmd) 46 | return err 47 | } 48 | 49 | // Run executes the provided command within this context 50 | func Run(cmd *exec.Cmd) ([]byte, error) { 51 | dir, _ := GetProjectDir() 52 | cmd.Dir = dir 53 | 54 | if err := os.Chdir(cmd.Dir); err != nil { 55 | fmt.Fprintf(GinkgoWriter, "chdir dir: %s\n", err) 56 | } 57 | 58 | cmd.Env = append(os.Environ(), "GO111MODULE=on") 59 | command := strings.Join(cmd.Args, " ") 60 | fmt.Fprintf(GinkgoWriter, "running: %s\n", command) 61 | output, err := cmd.CombinedOutput() 62 | if err != nil { 63 | return output, fmt.Errorf("%s failed with error: (%v) %s", command, err, string(output)) 64 | } 65 | 66 | return output, nil 67 | } 68 | 69 | // UninstallPrometheusOperator uninstalls the prometheus 70 | func UninstallPrometheusOperator() { 71 | url := fmt.Sprintf(prometheusOperatorURL, prometheusOperatorVersion) 72 | cmd := exec.Command("kubectl", "delete", "-f", url) 73 | if _, err := Run(cmd); err != nil { 74 | warnError(err) 75 | } 76 | } 77 | 78 | // UninstallCertManager uninstalls the cert manager 79 | func UninstallCertManager() { 80 | url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion) 81 | cmd := exec.Command("kubectl", "delete", "-f", url) 82 | if _, err := Run(cmd); err != nil { 83 | warnError(err) 84 | } 85 | } 86 | 87 | // InstallCertManager installs the cert manager bundle. 88 | func InstallCertManager() error { 89 | url := fmt.Sprintf(certmanagerURLTmpl, certmanagerVersion) 90 | cmd := exec.Command("kubectl", "apply", "-f", url) 91 | if _, err := Run(cmd); err != nil { 92 | return err 93 | } 94 | // Wait for cert-manager-webhook to be ready, which can take time if cert-manager 95 | // was re-installed after uninstalling on a cluster. 96 | cmd = exec.Command("kubectl", "wait", "deployment.apps/cert-manager-webhook", 97 | "--for", "condition=Available", 98 | "--namespace", "cert-manager", 99 | "--timeout", "5m", 100 | ) 101 | 102 | _, err := Run(cmd) 103 | return err 104 | } 105 | 106 | // LoadImageToKindCluster loads a local docker image to the kind cluster 107 | func LoadImageToKindClusterWithName(name string) error { 108 | cluster := "kind" 109 | if v, ok := os.LookupEnv("KIND_CLUSTER"); ok { 110 | cluster = v 111 | } 112 | kindOptions := []string{"load", "docker-image", name, "--name", cluster} 113 | cmd := exec.Command("kind", kindOptions...) 114 | _, err := Run(cmd) 115 | return err 116 | } 117 | 118 | // GetNonEmptyLines converts given command output string into individual objects 119 | // according to line breakers, and ignores the empty elements in it. 120 | func GetNonEmptyLines(output string) []string { 121 | var res []string 122 | elements := strings.Split(output, "\n") 123 | for _, element := range elements { 124 | if element != "" { 125 | res = append(res, element) 126 | } 127 | } 128 | 129 | return res 130 | } 131 | 132 | // GetProjectDir will return the directory where the project is 133 | func GetProjectDir() (string, error) { 134 | wd, err := os.Getwd() 135 | if err != nil { 136 | return wd, err 137 | } 138 | wd = strings.Replace(wd, "/test/e2e", "", -1) 139 | return wd, nil 140 | } 141 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/jacksgt/alert-operator 2 | 3 | go 1.22.0 4 | 5 | toolchain go1.22.4 6 | 7 | require ( 8 | github.com/onsi/ginkgo/v2 v2.17.1 9 | github.com/onsi/gomega v1.32.0 10 | k8s.io/apimachinery v0.30.1 11 | k8s.io/client-go v0.30.1 12 | sigs.k8s.io/controller-runtime v0.18.4 13 | ) 14 | 15 | require ( 16 | github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect 17 | github.com/beorn7/perks v1.0.1 // indirect 18 | github.com/blang/semver/v4 v4.0.0 // indirect 19 | github.com/cenkalti/backoff/v4 v4.2.1 // indirect 20 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 23 | github.com/evanphx/json-patch/v5 v5.9.0 // indirect 24 | github.com/felixge/httpsnoop v1.0.3 // indirect 25 | github.com/fsnotify/fsnotify v1.7.0 // indirect 26 | github.com/go-logr/logr v1.4.1 // indirect 27 | github.com/go-logr/stdr v1.2.2 // indirect 28 | github.com/go-logr/zapr v1.3.0 // indirect 29 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 30 | github.com/go-openapi/jsonreference v0.20.2 // indirect 31 | github.com/go-openapi/swag v0.22.3 // indirect 32 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect 33 | github.com/gogo/protobuf v1.3.2 // indirect 34 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 35 | github.com/golang/protobuf v1.5.4 // indirect 36 | github.com/google/cel-go v0.17.8 // indirect 37 | github.com/google/gnostic-models v0.6.8 // indirect 38 | github.com/google/go-cmp v0.6.0 // indirect 39 | github.com/google/gofuzz v1.2.0 // indirect 40 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect 41 | github.com/google/uuid v1.3.0 // indirect 42 | github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 // indirect 43 | github.com/imdario/mergo v0.3.6 // indirect 44 | github.com/josharian/intern v1.0.0 // indirect 45 | github.com/json-iterator/go v1.1.12 // indirect 46 | github.com/mailru/easyjson v0.7.7 // indirect 47 | github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect 48 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 49 | github.com/modern-go/reflect2 v1.0.2 // indirect 50 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 51 | github.com/pkg/errors v0.9.1 // indirect 52 | github.com/prometheus/client_golang v1.16.0 // indirect 53 | github.com/prometheus/client_model v0.4.0 // indirect 54 | github.com/prometheus/common v0.44.0 // indirect 55 | github.com/prometheus/procfs v0.12.0 // indirect 56 | github.com/spf13/pflag v1.0.5 // indirect 57 | github.com/stoewer/go-strcase v1.2.0 // indirect 58 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.44.0 // indirect 59 | go.opentelemetry.io/otel v1.19.0 // indirect 60 | go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.19.0 // indirect 61 | go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.19.0 // indirect 62 | go.opentelemetry.io/otel/metric v1.19.0 // indirect 63 | go.opentelemetry.io/otel/sdk v1.19.0 // indirect 64 | go.opentelemetry.io/otel/trace v1.19.0 // indirect 65 | go.opentelemetry.io/proto/otlp v1.0.0 // indirect 66 | go.uber.org/multierr v1.11.0 // indirect 67 | go.uber.org/zap v1.26.0 // indirect 68 | golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect 69 | golang.org/x/net v0.23.0 // indirect 70 | golang.org/x/oauth2 v0.12.0 // indirect 71 | golang.org/x/sync v0.6.0 // indirect 72 | golang.org/x/sys v0.18.0 // indirect 73 | golang.org/x/term v0.18.0 // indirect 74 | golang.org/x/text v0.14.0 // indirect 75 | golang.org/x/time v0.3.0 // indirect 76 | golang.org/x/tools v0.18.0 // indirect 77 | gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect 78 | google.golang.org/appengine v1.6.7 // indirect 79 | google.golang.org/genproto/googleapis/api v0.0.0-20230726155614-23370e0ffb3e // indirect 80 | google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect 81 | google.golang.org/grpc v1.58.3 // indirect 82 | google.golang.org/protobuf v1.33.0 // indirect 83 | gopkg.in/inf.v0 v0.9.1 // indirect 84 | gopkg.in/yaml.v2 v2.4.0 // indirect 85 | gopkg.in/yaml.v3 v3.0.1 // indirect 86 | k8s.io/api v0.30.1 // indirect 87 | k8s.io/apiextensions-apiserver v0.30.1 // indirect 88 | k8s.io/apiserver v0.30.1 // indirect 89 | k8s.io/component-base v0.30.1 // indirect 90 | k8s.io/klog/v2 v2.120.1 // indirect 91 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect 92 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 93 | sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.29.0 // indirect 94 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 95 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 96 | sigs.k8s.io/yaml v1.3.0 // indirect 97 | ) 98 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_alertmanager_config.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the AlertmanagerConfig type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &AlertmanagerConfig{} 21 | 22 | // AlertmanagerConfig struct for AlertmanagerConfig 23 | type AlertmanagerConfig struct { 24 | Original string `json:"original"` 25 | } 26 | 27 | type _AlertmanagerConfig AlertmanagerConfig 28 | 29 | // NewAlertmanagerConfig instantiates a new AlertmanagerConfig object 30 | // This constructor will assign default values to properties that have it defined, 31 | // and makes sure properties required by API are set, but the set of arguments 32 | // will change when the set of required properties is changed 33 | func NewAlertmanagerConfig(original string) *AlertmanagerConfig { 34 | this := AlertmanagerConfig{} 35 | this.Original = original 36 | return &this 37 | } 38 | 39 | // NewAlertmanagerConfigWithDefaults instantiates a new AlertmanagerConfig object 40 | // This constructor will only assign default values to properties that have it defined, 41 | // but it doesn't guarantee that properties required by API are set 42 | func NewAlertmanagerConfigWithDefaults() *AlertmanagerConfig { 43 | this := AlertmanagerConfig{} 44 | return &this 45 | } 46 | 47 | // GetOriginal returns the Original field value 48 | func (o *AlertmanagerConfig) GetOriginal() string { 49 | if o == nil { 50 | var ret string 51 | return ret 52 | } 53 | 54 | return o.Original 55 | } 56 | 57 | // GetOriginalOk returns a tuple with the Original field value 58 | // and a boolean to check if the value has been set. 59 | func (o *AlertmanagerConfig) GetOriginalOk() (*string, bool) { 60 | if o == nil { 61 | return nil, false 62 | } 63 | return &o.Original, true 64 | } 65 | 66 | // SetOriginal sets field value 67 | func (o *AlertmanagerConfig) SetOriginal(v string) { 68 | o.Original = v 69 | } 70 | 71 | func (o AlertmanagerConfig) MarshalJSON() ([]byte, error) { 72 | toSerialize,err := o.ToMap() 73 | if err != nil { 74 | return []byte{}, err 75 | } 76 | return json.Marshal(toSerialize) 77 | } 78 | 79 | func (o AlertmanagerConfig) ToMap() (map[string]interface{}, error) { 80 | toSerialize := map[string]interface{}{} 81 | toSerialize["original"] = o.Original 82 | return toSerialize, nil 83 | } 84 | 85 | func (o *AlertmanagerConfig) UnmarshalJSON(data []byte) (err error) { 86 | // This validates that all required properties are included in the JSON object 87 | // by unmarshalling the object into a generic map with string keys and checking 88 | // that every required field exists as a key in the generic map. 89 | requiredProperties := []string{ 90 | "original", 91 | } 92 | 93 | allProperties := make(map[string]interface{}) 94 | 95 | err = json.Unmarshal(data, &allProperties) 96 | 97 | if err != nil { 98 | return err; 99 | } 100 | 101 | for _, requiredProperty := range(requiredProperties) { 102 | if _, exists := allProperties[requiredProperty]; !exists { 103 | return fmt.Errorf("no value given for required property %v", requiredProperty) 104 | } 105 | } 106 | 107 | varAlertmanagerConfig := _AlertmanagerConfig{} 108 | 109 | decoder := json.NewDecoder(bytes.NewReader(data)) 110 | decoder.DisallowUnknownFields() 111 | err = decoder.Decode(&varAlertmanagerConfig) 112 | 113 | if err != nil { 114 | return err 115 | } 116 | 117 | *o = AlertmanagerConfig(varAlertmanagerConfig) 118 | 119 | return err 120 | } 121 | 122 | type NullableAlertmanagerConfig struct { 123 | value *AlertmanagerConfig 124 | isSet bool 125 | } 126 | 127 | func (v NullableAlertmanagerConfig) Get() *AlertmanagerConfig { 128 | return v.value 129 | } 130 | 131 | func (v *NullableAlertmanagerConfig) Set(val *AlertmanagerConfig) { 132 | v.value = val 133 | v.isSet = true 134 | } 135 | 136 | func (v NullableAlertmanagerConfig) IsSet() bool { 137 | return v.isSet 138 | } 139 | 140 | func (v *NullableAlertmanagerConfig) Unset() { 141 | v.value = nil 142 | v.isSet = false 143 | } 144 | 145 | func NewNullableAlertmanagerConfig(val *AlertmanagerConfig) *NullableAlertmanagerConfig { 146 | return &NullableAlertmanagerConfig{value: val, isSet: true} 147 | } 148 | 149 | func (v NullableAlertmanagerConfig) MarshalJSON() ([]byte, error) { 150 | return json.Marshal(v.value) 151 | } 152 | 153 | func (v *NullableAlertmanagerConfig) UnmarshalJSON(src []byte) error { 154 | v.isSet = true 155 | return json.Unmarshal(src, &v.value) 156 | } 157 | 158 | 159 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_peer_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the PeerStatus type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &PeerStatus{} 21 | 22 | // PeerStatus struct for PeerStatus 23 | type PeerStatus struct { 24 | Name string `json:"name"` 25 | Address string `json:"address"` 26 | } 27 | 28 | type _PeerStatus PeerStatus 29 | 30 | // NewPeerStatus instantiates a new PeerStatus object 31 | // This constructor will assign default values to properties that have it defined, 32 | // and makes sure properties required by API are set, but the set of arguments 33 | // will change when the set of required properties is changed 34 | func NewPeerStatus(name string, address string) *PeerStatus { 35 | this := PeerStatus{} 36 | this.Name = name 37 | this.Address = address 38 | return &this 39 | } 40 | 41 | // NewPeerStatusWithDefaults instantiates a new PeerStatus object 42 | // This constructor will only assign default values to properties that have it defined, 43 | // but it doesn't guarantee that properties required by API are set 44 | func NewPeerStatusWithDefaults() *PeerStatus { 45 | this := PeerStatus{} 46 | return &this 47 | } 48 | 49 | // GetName returns the Name field value 50 | func (o *PeerStatus) GetName() string { 51 | if o == nil { 52 | var ret string 53 | return ret 54 | } 55 | 56 | return o.Name 57 | } 58 | 59 | // GetNameOk returns a tuple with the Name field value 60 | // and a boolean to check if the value has been set. 61 | func (o *PeerStatus) GetNameOk() (*string, bool) { 62 | if o == nil { 63 | return nil, false 64 | } 65 | return &o.Name, true 66 | } 67 | 68 | // SetName sets field value 69 | func (o *PeerStatus) SetName(v string) { 70 | o.Name = v 71 | } 72 | 73 | // GetAddress returns the Address field value 74 | func (o *PeerStatus) GetAddress() string { 75 | if o == nil { 76 | var ret string 77 | return ret 78 | } 79 | 80 | return o.Address 81 | } 82 | 83 | // GetAddressOk returns a tuple with the Address field value 84 | // and a boolean to check if the value has been set. 85 | func (o *PeerStatus) GetAddressOk() (*string, bool) { 86 | if o == nil { 87 | return nil, false 88 | } 89 | return &o.Address, true 90 | } 91 | 92 | // SetAddress sets field value 93 | func (o *PeerStatus) SetAddress(v string) { 94 | o.Address = v 95 | } 96 | 97 | func (o PeerStatus) MarshalJSON() ([]byte, error) { 98 | toSerialize,err := o.ToMap() 99 | if err != nil { 100 | return []byte{}, err 101 | } 102 | return json.Marshal(toSerialize) 103 | } 104 | 105 | func (o PeerStatus) ToMap() (map[string]interface{}, error) { 106 | toSerialize := map[string]interface{}{} 107 | toSerialize["name"] = o.Name 108 | toSerialize["address"] = o.Address 109 | return toSerialize, nil 110 | } 111 | 112 | func (o *PeerStatus) UnmarshalJSON(data []byte) (err error) { 113 | // This validates that all required properties are included in the JSON object 114 | // by unmarshalling the object into a generic map with string keys and checking 115 | // that every required field exists as a key in the generic map. 116 | requiredProperties := []string{ 117 | "name", 118 | "address", 119 | } 120 | 121 | allProperties := make(map[string]interface{}) 122 | 123 | err = json.Unmarshal(data, &allProperties) 124 | 125 | if err != nil { 126 | return err; 127 | } 128 | 129 | for _, requiredProperty := range(requiredProperties) { 130 | if _, exists := allProperties[requiredProperty]; !exists { 131 | return fmt.Errorf("no value given for required property %v", requiredProperty) 132 | } 133 | } 134 | 135 | varPeerStatus := _PeerStatus{} 136 | 137 | decoder := json.NewDecoder(bytes.NewReader(data)) 138 | decoder.DisallowUnknownFields() 139 | err = decoder.Decode(&varPeerStatus) 140 | 141 | if err != nil { 142 | return err 143 | } 144 | 145 | *o = PeerStatus(varPeerStatus) 146 | 147 | return err 148 | } 149 | 150 | type NullablePeerStatus struct { 151 | value *PeerStatus 152 | isSet bool 153 | } 154 | 155 | func (v NullablePeerStatus) Get() *PeerStatus { 156 | return v.value 157 | } 158 | 159 | func (v *NullablePeerStatus) Set(val *PeerStatus) { 160 | v.value = val 161 | v.isSet = true 162 | } 163 | 164 | func (v NullablePeerStatus) IsSet() bool { 165 | return v.isSet 166 | } 167 | 168 | func (v *NullablePeerStatus) Unset() { 169 | v.value = nil 170 | v.isSet = false 171 | } 172 | 173 | func NewNullablePeerStatus(val *PeerStatus) *NullablePeerStatus { 174 | return &NullablePeerStatus{value: val, isSet: true} 175 | } 176 | 177 | func (v NullablePeerStatus) MarshalJSON() ([]byte, error) { 178 | return json.Marshal(v.value) 179 | } 180 | 181 | func (v *NullablePeerStatus) UnmarshalJSON(src []byte) error { 182 | v.isSet = true 183 | return json.Unmarshal(src, &v.value) 184 | } 185 | 186 | 187 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_alert.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the Alert type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &Alert{} 21 | 22 | // Alert struct for Alert 23 | type Alert struct { 24 | Labels map[string]string `json:"labels"` 25 | GeneratorURL *string `json:"generatorURL,omitempty"` 26 | } 27 | 28 | type _Alert Alert 29 | 30 | // NewAlert instantiates a new Alert object 31 | // This constructor will assign default values to properties that have it defined, 32 | // and makes sure properties required by API are set, but the set of arguments 33 | // will change when the set of required properties is changed 34 | func NewAlert(labels map[string]string) *Alert { 35 | this := Alert{} 36 | this.Labels = labels 37 | return &this 38 | } 39 | 40 | // NewAlertWithDefaults instantiates a new Alert object 41 | // This constructor will only assign default values to properties that have it defined, 42 | // but it doesn't guarantee that properties required by API are set 43 | func NewAlertWithDefaults() *Alert { 44 | this := Alert{} 45 | return &this 46 | } 47 | 48 | // GetLabels returns the Labels field value 49 | func (o *Alert) GetLabels() map[string]string { 50 | if o == nil { 51 | var ret map[string]string 52 | return ret 53 | } 54 | 55 | return o.Labels 56 | } 57 | 58 | // GetLabelsOk returns a tuple with the Labels field value 59 | // and a boolean to check if the value has been set. 60 | func (o *Alert) GetLabelsOk() (*map[string]string, bool) { 61 | if o == nil { 62 | return nil, false 63 | } 64 | return &o.Labels, true 65 | } 66 | 67 | // SetLabels sets field value 68 | func (o *Alert) SetLabels(v map[string]string) { 69 | o.Labels = v 70 | } 71 | 72 | // GetGeneratorURL returns the GeneratorURL field value if set, zero value otherwise. 73 | func (o *Alert) GetGeneratorURL() string { 74 | if o == nil || IsNil(o.GeneratorURL) { 75 | var ret string 76 | return ret 77 | } 78 | return *o.GeneratorURL 79 | } 80 | 81 | // GetGeneratorURLOk returns a tuple with the GeneratorURL field value if set, nil otherwise 82 | // and a boolean to check if the value has been set. 83 | func (o *Alert) GetGeneratorURLOk() (*string, bool) { 84 | if o == nil || IsNil(o.GeneratorURL) { 85 | return nil, false 86 | } 87 | return o.GeneratorURL, true 88 | } 89 | 90 | // HasGeneratorURL returns a boolean if a field has been set. 91 | func (o *Alert) HasGeneratorURL() bool { 92 | if o != nil && !IsNil(o.GeneratorURL) { 93 | return true 94 | } 95 | 96 | return false 97 | } 98 | 99 | // SetGeneratorURL gets a reference to the given string and assigns it to the GeneratorURL field. 100 | func (o *Alert) SetGeneratorURL(v string) { 101 | o.GeneratorURL = &v 102 | } 103 | 104 | func (o Alert) MarshalJSON() ([]byte, error) { 105 | toSerialize,err := o.ToMap() 106 | if err != nil { 107 | return []byte{}, err 108 | } 109 | return json.Marshal(toSerialize) 110 | } 111 | 112 | func (o Alert) ToMap() (map[string]interface{}, error) { 113 | toSerialize := map[string]interface{}{} 114 | toSerialize["labels"] = o.Labels 115 | if !IsNil(o.GeneratorURL) { 116 | toSerialize["generatorURL"] = o.GeneratorURL 117 | } 118 | return toSerialize, nil 119 | } 120 | 121 | func (o *Alert) UnmarshalJSON(data []byte) (err error) { 122 | // This validates that all required properties are included in the JSON object 123 | // by unmarshalling the object into a generic map with string keys and checking 124 | // that every required field exists as a key in the generic map. 125 | requiredProperties := []string{ 126 | "labels", 127 | } 128 | 129 | allProperties := make(map[string]interface{}) 130 | 131 | err = json.Unmarshal(data, &allProperties) 132 | 133 | if err != nil { 134 | return err; 135 | } 136 | 137 | for _, requiredProperty := range(requiredProperties) { 138 | if _, exists := allProperties[requiredProperty]; !exists { 139 | return fmt.Errorf("no value given for required property %v", requiredProperty) 140 | } 141 | } 142 | 143 | varAlert := _Alert{} 144 | 145 | decoder := json.NewDecoder(bytes.NewReader(data)) 146 | decoder.DisallowUnknownFields() 147 | err = decoder.Decode(&varAlert) 148 | 149 | if err != nil { 150 | return err 151 | } 152 | 153 | *o = Alert(varAlert) 154 | 155 | return err 156 | } 157 | 158 | type NullableAlert struct { 159 | value *Alert 160 | isSet bool 161 | } 162 | 163 | func (v NullableAlert) Get() *Alert { 164 | return v.value 165 | } 166 | 167 | func (v *NullableAlert) Set(val *Alert) { 168 | v.value = val 169 | v.isSet = true 170 | } 171 | 172 | func (v NullableAlert) IsSet() bool { 173 | return v.isSet 174 | } 175 | 176 | func (v *NullableAlert) Unset() { 177 | v.value = nil 178 | v.isSet = false 179 | } 180 | 181 | func NewNullableAlert(val *Alert) *NullableAlert { 182 | return &NullableAlert{value: val, isSet: true} 183 | } 184 | 185 | func (v NullableAlert) MarshalJSON() ([]byte, error) { 186 | return json.Marshal(v.value) 187 | } 188 | 189 | func (v *NullableAlert) UnmarshalJSON(src []byte) error { 190 | v.isSet = true 191 | return json.Unmarshal(src, &v.value) 192 | } 193 | 194 | 195 | -------------------------------------------------------------------------------- /config/default/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # Adds namespace to all resources. 2 | namespace: alert-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: alert-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 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 22 | # crd/kustomization.yaml 23 | #- ../webhook 24 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required. 25 | #- ../certmanager 26 | # [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'. 27 | #- ../prometheus 28 | # [METRICS] Expose the controller manager metrics service. 29 | - metrics_service.yaml 30 | 31 | # Uncomment the patches line if you enable Metrics, and/or are using webhooks and cert-manager 32 | patches: 33 | # [METRICS] The following patch will enable the metrics endpoint using HTTPS and the port :8443. 34 | # More info: https://book.kubebuilder.io/reference/metrics 35 | - path: manager_metrics_patch.yaml 36 | target: 37 | kind: Deployment 38 | 39 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in 40 | # crd/kustomization.yaml 41 | #- path: manager_webhook_patch.yaml 42 | 43 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 44 | # Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks. 45 | # 'CERTMANAGER' needs to be enabled to use ca injection 46 | #- path: webhookcainjection_patch.yaml 47 | 48 | # [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER' prefix. 49 | # Uncomment the following replacements to add the cert-manager CA injection annotations 50 | #replacements: 51 | # - source: # Add cert-manager annotation to ValidatingWebhookConfiguration, MutatingWebhookConfiguration and CRDs 52 | # kind: Certificate 53 | # group: cert-manager.io 54 | # version: v1 55 | # name: serving-cert # this name should match the one in certificate.yaml 56 | # fieldPath: .metadata.namespace # namespace of the certificate CR 57 | # targets: 58 | # - select: 59 | # kind: ValidatingWebhookConfiguration 60 | # fieldPaths: 61 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 62 | # options: 63 | # delimiter: '/' 64 | # index: 0 65 | # create: true 66 | # - select: 67 | # kind: MutatingWebhookConfiguration 68 | # fieldPaths: 69 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 70 | # options: 71 | # delimiter: '/' 72 | # index: 0 73 | # create: true 74 | # - select: 75 | # kind: CustomResourceDefinition 76 | # fieldPaths: 77 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 78 | # options: 79 | # delimiter: '/' 80 | # index: 0 81 | # create: true 82 | # - source: 83 | # kind: Certificate 84 | # group: cert-manager.io 85 | # version: v1 86 | # name: serving-cert # this name should match the one in certificate.yaml 87 | # fieldPath: .metadata.name 88 | # targets: 89 | # - select: 90 | # kind: ValidatingWebhookConfiguration 91 | # fieldPaths: 92 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 93 | # options: 94 | # delimiter: '/' 95 | # index: 1 96 | # create: true 97 | # - select: 98 | # kind: MutatingWebhookConfiguration 99 | # fieldPaths: 100 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 101 | # options: 102 | # delimiter: '/' 103 | # index: 1 104 | # create: true 105 | # - select: 106 | # kind: CustomResourceDefinition 107 | # fieldPaths: 108 | # - .metadata.annotations.[cert-manager.io/inject-ca-from] 109 | # options: 110 | # delimiter: '/' 111 | # index: 1 112 | # create: true 113 | # - source: # Add cert-manager annotation to the webhook Service 114 | # kind: Service 115 | # version: v1 116 | # name: webhook-service 117 | # fieldPath: .metadata.name # namespace of the service 118 | # targets: 119 | # - select: 120 | # kind: Certificate 121 | # group: cert-manager.io 122 | # version: v1 123 | # fieldPaths: 124 | # - .spec.dnsNames.0 125 | # - .spec.dnsNames.1 126 | # options: 127 | # delimiter: '.' 128 | # index: 0 129 | # create: true 130 | # - source: 131 | # kind: Service 132 | # version: v1 133 | # name: webhook-service 134 | # fieldPath: .metadata.namespace # namespace of the service 135 | # targets: 136 | # - select: 137 | # kind: Certificate 138 | # group: cert-manager.io 139 | # version: v1 140 | # fieldPaths: 141 | # - .spec.dnsNames.0 142 | # - .spec.dnsNames.1 143 | # options: 144 | # delimiter: '.' 145 | # index: 1 146 | # create: true 147 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_alert_group.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the AlertGroup type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &AlertGroup{} 21 | 22 | // AlertGroup struct for AlertGroup 23 | type AlertGroup struct { 24 | Labels map[string]string `json:"labels"` 25 | Receiver Receiver `json:"receiver"` 26 | Alerts []GettableAlert `json:"alerts"` 27 | } 28 | 29 | type _AlertGroup AlertGroup 30 | 31 | // NewAlertGroup instantiates a new AlertGroup object 32 | // This constructor will assign default values to properties that have it defined, 33 | // and makes sure properties required by API are set, but the set of arguments 34 | // will change when the set of required properties is changed 35 | func NewAlertGroup(labels map[string]string, receiver Receiver, alerts []GettableAlert) *AlertGroup { 36 | this := AlertGroup{} 37 | this.Labels = labels 38 | this.Receiver = receiver 39 | this.Alerts = alerts 40 | return &this 41 | } 42 | 43 | // NewAlertGroupWithDefaults instantiates a new AlertGroup object 44 | // This constructor will only assign default values to properties that have it defined, 45 | // but it doesn't guarantee that properties required by API are set 46 | func NewAlertGroupWithDefaults() *AlertGroup { 47 | this := AlertGroup{} 48 | return &this 49 | } 50 | 51 | // GetLabels returns the Labels field value 52 | func (o *AlertGroup) GetLabels() map[string]string { 53 | if o == nil { 54 | var ret map[string]string 55 | return ret 56 | } 57 | 58 | return o.Labels 59 | } 60 | 61 | // GetLabelsOk returns a tuple with the Labels field value 62 | // and a boolean to check if the value has been set. 63 | func (o *AlertGroup) GetLabelsOk() (*map[string]string, bool) { 64 | if o == nil { 65 | return nil, false 66 | } 67 | return &o.Labels, true 68 | } 69 | 70 | // SetLabels sets field value 71 | func (o *AlertGroup) SetLabels(v map[string]string) { 72 | o.Labels = v 73 | } 74 | 75 | // GetReceiver returns the Receiver field value 76 | func (o *AlertGroup) GetReceiver() Receiver { 77 | if o == nil { 78 | var ret Receiver 79 | return ret 80 | } 81 | 82 | return o.Receiver 83 | } 84 | 85 | // GetReceiverOk returns a tuple with the Receiver field value 86 | // and a boolean to check if the value has been set. 87 | func (o *AlertGroup) GetReceiverOk() (*Receiver, bool) { 88 | if o == nil { 89 | return nil, false 90 | } 91 | return &o.Receiver, true 92 | } 93 | 94 | // SetReceiver sets field value 95 | func (o *AlertGroup) SetReceiver(v Receiver) { 96 | o.Receiver = v 97 | } 98 | 99 | // GetAlerts returns the Alerts field value 100 | func (o *AlertGroup) GetAlerts() []GettableAlert { 101 | if o == nil { 102 | var ret []GettableAlert 103 | return ret 104 | } 105 | 106 | return o.Alerts 107 | } 108 | 109 | // GetAlertsOk returns a tuple with the Alerts field value 110 | // and a boolean to check if the value has been set. 111 | func (o *AlertGroup) GetAlertsOk() ([]GettableAlert, bool) { 112 | if o == nil { 113 | return nil, false 114 | } 115 | return o.Alerts, true 116 | } 117 | 118 | // SetAlerts sets field value 119 | func (o *AlertGroup) SetAlerts(v []GettableAlert) { 120 | o.Alerts = v 121 | } 122 | 123 | func (o AlertGroup) MarshalJSON() ([]byte, error) { 124 | toSerialize,err := o.ToMap() 125 | if err != nil { 126 | return []byte{}, err 127 | } 128 | return json.Marshal(toSerialize) 129 | } 130 | 131 | func (o AlertGroup) ToMap() (map[string]interface{}, error) { 132 | toSerialize := map[string]interface{}{} 133 | toSerialize["labels"] = o.Labels 134 | toSerialize["receiver"] = o.Receiver 135 | toSerialize["alerts"] = o.Alerts 136 | return toSerialize, nil 137 | } 138 | 139 | func (o *AlertGroup) UnmarshalJSON(data []byte) (err error) { 140 | // This validates that all required properties are included in the JSON object 141 | // by unmarshalling the object into a generic map with string keys and checking 142 | // that every required field exists as a key in the generic map. 143 | requiredProperties := []string{ 144 | "labels", 145 | "receiver", 146 | "alerts", 147 | } 148 | 149 | allProperties := make(map[string]interface{}) 150 | 151 | err = json.Unmarshal(data, &allProperties) 152 | 153 | if err != nil { 154 | return err; 155 | } 156 | 157 | for _, requiredProperty := range(requiredProperties) { 158 | if _, exists := allProperties[requiredProperty]; !exists { 159 | return fmt.Errorf("no value given for required property %v", requiredProperty) 160 | } 161 | } 162 | 163 | varAlertGroup := _AlertGroup{} 164 | 165 | decoder := json.NewDecoder(bytes.NewReader(data)) 166 | decoder.DisallowUnknownFields() 167 | err = decoder.Decode(&varAlertGroup) 168 | 169 | if err != nil { 170 | return err 171 | } 172 | 173 | *o = AlertGroup(varAlertGroup) 174 | 175 | return err 176 | } 177 | 178 | type NullableAlertGroup struct { 179 | value *AlertGroup 180 | isSet bool 181 | } 182 | 183 | func (v NullableAlertGroup) Get() *AlertGroup { 184 | return v.value 185 | } 186 | 187 | func (v *NullableAlertGroup) Set(val *AlertGroup) { 188 | v.value = val 189 | v.isSet = true 190 | } 191 | 192 | func (v NullableAlertGroup) IsSet() bool { 193 | return v.isSet 194 | } 195 | 196 | func (v *NullableAlertGroup) Unset() { 197 | v.value = nil 198 | v.isSet = false 199 | } 200 | 201 | func NewNullableAlertGroup(val *AlertGroup) *NullableAlertGroup { 202 | return &NullableAlertGroup{value: val, isSet: true} 203 | } 204 | 205 | func (v NullableAlertGroup) MarshalJSON() ([]byte, error) { 206 | return json.Marshal(v.value) 207 | } 208 | 209 | func (v *NullableAlertGroup) UnmarshalJSON(src []byte) error { 210 | v.isSet = true 211 | return json.Unmarshal(src, &v.value) 212 | } 213 | 214 | 215 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_alert_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the AlertStatus type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &AlertStatus{} 21 | 22 | // AlertStatus struct for AlertStatus 23 | type AlertStatus struct { 24 | State string `json:"state"` 25 | SilencedBy []string `json:"silencedBy"` 26 | InhibitedBy []string `json:"inhibitedBy"` 27 | } 28 | 29 | type _AlertStatus AlertStatus 30 | 31 | // NewAlertStatus instantiates a new AlertStatus object 32 | // This constructor will assign default values to properties that have it defined, 33 | // and makes sure properties required by API are set, but the set of arguments 34 | // will change when the set of required properties is changed 35 | func NewAlertStatus(state string, silencedBy []string, inhibitedBy []string) *AlertStatus { 36 | this := AlertStatus{} 37 | this.State = state 38 | this.SilencedBy = silencedBy 39 | this.InhibitedBy = inhibitedBy 40 | return &this 41 | } 42 | 43 | // NewAlertStatusWithDefaults instantiates a new AlertStatus object 44 | // This constructor will only assign default values to properties that have it defined, 45 | // but it doesn't guarantee that properties required by API are set 46 | func NewAlertStatusWithDefaults() *AlertStatus { 47 | this := AlertStatus{} 48 | return &this 49 | } 50 | 51 | // GetState returns the State field value 52 | func (o *AlertStatus) GetState() string { 53 | if o == nil { 54 | var ret string 55 | return ret 56 | } 57 | 58 | return o.State 59 | } 60 | 61 | // GetStateOk returns a tuple with the State field value 62 | // and a boolean to check if the value has been set. 63 | func (o *AlertStatus) GetStateOk() (*string, bool) { 64 | if o == nil { 65 | return nil, false 66 | } 67 | return &o.State, true 68 | } 69 | 70 | // SetState sets field value 71 | func (o *AlertStatus) SetState(v string) { 72 | o.State = v 73 | } 74 | 75 | // GetSilencedBy returns the SilencedBy field value 76 | func (o *AlertStatus) GetSilencedBy() []string { 77 | if o == nil { 78 | var ret []string 79 | return ret 80 | } 81 | 82 | return o.SilencedBy 83 | } 84 | 85 | // GetSilencedByOk returns a tuple with the SilencedBy field value 86 | // and a boolean to check if the value has been set. 87 | func (o *AlertStatus) GetSilencedByOk() ([]string, bool) { 88 | if o == nil { 89 | return nil, false 90 | } 91 | return o.SilencedBy, true 92 | } 93 | 94 | // SetSilencedBy sets field value 95 | func (o *AlertStatus) SetSilencedBy(v []string) { 96 | o.SilencedBy = v 97 | } 98 | 99 | // GetInhibitedBy returns the InhibitedBy field value 100 | func (o *AlertStatus) GetInhibitedBy() []string { 101 | if o == nil { 102 | var ret []string 103 | return ret 104 | } 105 | 106 | return o.InhibitedBy 107 | } 108 | 109 | // GetInhibitedByOk returns a tuple with the InhibitedBy field value 110 | // and a boolean to check if the value has been set. 111 | func (o *AlertStatus) GetInhibitedByOk() ([]string, bool) { 112 | if o == nil { 113 | return nil, false 114 | } 115 | return o.InhibitedBy, true 116 | } 117 | 118 | // SetInhibitedBy sets field value 119 | func (o *AlertStatus) SetInhibitedBy(v []string) { 120 | o.InhibitedBy = v 121 | } 122 | 123 | func (o AlertStatus) MarshalJSON() ([]byte, error) { 124 | toSerialize,err := o.ToMap() 125 | if err != nil { 126 | return []byte{}, err 127 | } 128 | return json.Marshal(toSerialize) 129 | } 130 | 131 | func (o AlertStatus) ToMap() (map[string]interface{}, error) { 132 | toSerialize := map[string]interface{}{} 133 | toSerialize["state"] = o.State 134 | toSerialize["silencedBy"] = o.SilencedBy 135 | toSerialize["inhibitedBy"] = o.InhibitedBy 136 | return toSerialize, nil 137 | } 138 | 139 | func (o *AlertStatus) UnmarshalJSON(data []byte) (err error) { 140 | // This validates that all required properties are included in the JSON object 141 | // by unmarshalling the object into a generic map with string keys and checking 142 | // that every required field exists as a key in the generic map. 143 | requiredProperties := []string{ 144 | "state", 145 | "silencedBy", 146 | "inhibitedBy", 147 | } 148 | 149 | allProperties := make(map[string]interface{}) 150 | 151 | err = json.Unmarshal(data, &allProperties) 152 | 153 | if err != nil { 154 | return err; 155 | } 156 | 157 | for _, requiredProperty := range(requiredProperties) { 158 | if _, exists := allProperties[requiredProperty]; !exists { 159 | return fmt.Errorf("no value given for required property %v", requiredProperty) 160 | } 161 | } 162 | 163 | varAlertStatus := _AlertStatus{} 164 | 165 | decoder := json.NewDecoder(bytes.NewReader(data)) 166 | decoder.DisallowUnknownFields() 167 | err = decoder.Decode(&varAlertStatus) 168 | 169 | if err != nil { 170 | return err 171 | } 172 | 173 | *o = AlertStatus(varAlertStatus) 174 | 175 | return err 176 | } 177 | 178 | type NullableAlertStatus struct { 179 | value *AlertStatus 180 | isSet bool 181 | } 182 | 183 | func (v NullableAlertStatus) Get() *AlertStatus { 184 | return v.value 185 | } 186 | 187 | func (v *NullableAlertStatus) Set(val *AlertStatus) { 188 | v.value = val 189 | v.isSet = true 190 | } 191 | 192 | func (v NullableAlertStatus) IsSet() bool { 193 | return v.isSet 194 | } 195 | 196 | func (v *NullableAlertStatus) Unset() { 197 | v.value = nil 198 | v.isSet = false 199 | } 200 | 201 | func NewNullableAlertStatus(val *AlertStatus) *NullableAlertStatus { 202 | return &NullableAlertStatus{value: val, isSet: true} 203 | } 204 | 205 | func (v NullableAlertStatus) MarshalJSON() ([]byte, error) { 206 | return json.Marshal(v.value) 207 | } 208 | 209 | func (v *NullableAlertStatus) UnmarshalJSON(src []byte) error { 210 | v.isSet = true 211 | return json.Unmarshal(src, &v.value) 212 | } 213 | 214 | 215 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # alert-operator 2 | 3 | The Alert-Operator is the missing component of the [kube-prometheus stack](https://github.com/prometheus-operator/kube-prometheus/) for observability on Kubernetes: 4 | it allows you to view active **Alerts** from the comfort of your `kubectl` CLI and lets you manage associated **Silences** declaratively, for example with GitOps. 5 | 6 | ```sh 7 | $ kubectl get alerts 8 | NAME STATE VALUE SINCE LABELS 9 | ContainerOOM-asxi firing 1 3h17m pod=prometheus-k8s-db-prometheus-k8s-0,severity=warning 10 | KubeJobFailed-kp2md firing 3 42m alertname=KubeJobFailed,job_name=image-pruner-28679172,namespace=openshift-image-registry 11 | 12 | $ kubectl get alert ContainerOOM-asxi -o yaml 13 | apiVersion: alertmanager.prometheus.io/v1alpha1 14 | kind: Alert 15 | metadata: 16 | name: ContainerOOM-asxi 17 | spec: {} 18 | status: 19 | since: 2018-07-04 20:27:12.60602144 +0200 CEST 20 | state: firing 21 | value: "1e+00" 22 | labels: 23 | alertname: ContainerOOM 24 | endpoint: https-metrics 25 | instance: 1.2.3.4:10250 26 | job: kubelet 27 | metrics_path: /metrics 28 | namespace: openshift-monitoring 29 | node: infra-avz-a-5phgg 30 | pod: prometheus-k8s-db-prometheus-k8s-0 31 | service: kubelet 32 | severity: warning 33 | annotations: 34 | summary: The container 'prometheus' of pod 'prometheus-k8s-db-prometheus-k8s-0' has been restarted multiple times due to running out of memory. 35 | ``` 36 | 37 | ```sh 38 | $ kubectl get silences 39 | NAME STATE CREATOR COMMENT 40 | out-of-memory-issues active foobar Currently scaling up the cluster and waiting for new nodes 41 | ``` 42 | 43 | ## Development 44 | 45 | ### Prerequisites 46 | - go version v1.22.0+ 47 | - docker version 17.03+. 48 | - kubectl version v1.11.3+. 49 | - Access to a Kubernetes v1.11.3+ cluster. 50 | 51 | ### To Deploy on the cluster 52 | **Build and push your image to the location specified by `IMG`:** 53 | 54 | ```sh 55 | make docker-build docker-push IMG=/alert-operator:tag 56 | ``` 57 | 58 | **NOTE:** This image ought to be published in the personal registry you specified. 59 | And it is required to have access to pull the image from the working environment. 60 | Make sure you have the proper permission to the registry if the above commands don’t work. 61 | 62 | **Install the CRDs into the cluster:** 63 | 64 | ```sh 65 | make install 66 | 67 | # to uninstall (delete CRDs from the cluster): 68 | make uninstall 69 | ``` 70 | 71 | **Deploy the Manager to the cluster with the image specified by `IMG`:** 72 | 73 | ```sh 74 | make deploy IMG=/alert-operator:tag 75 | 76 | # to uninstall (remove controller from the cluster): 77 | make undeploy 78 | ``` 79 | 80 | > **NOTE**: If you encounter RBAC errors, you may need to grant yourself cluster-admin 81 | privileges or be logged in as admin. 82 | 83 | **Create instances of your solution** 84 | You can apply the samples (examples) from the config/sample: 85 | 86 | ```sh 87 | kubectl apply -k config/samples/ 88 | 89 | # to uninstall: 90 | kubectl delete -k config/samples/ 91 | ``` 92 | 93 | > **NOTE**: Ensure that the samples has default values to test it out. 94 | 95 | > **NOTE:** Run `make help` for more information on all potential `make` targets 96 | 97 | More information can be found via the [Kubebuilder Documentation](https://book.kubebuilder.io/introduction.html) 98 | 99 | ### Generate Alertmanger API client 100 | 101 | we use [OpenAPI Generator](https://openapi-generator.tech/docs/usage/) that generates the Go code based on the OpenAPI spec (*"Swagger"*). 102 | This generated code might need to be updated from time to time to get access to new endpoints in the API. 103 | 104 | ```sh 105 | # fetch API schema (commit it to Git so we can track changes) 106 | curl -sSL https://raw.githubusercontent.com/prometheus/alertmanager/main/api/v2/openapi.yaml -o alertmanager-openapi.yaml 107 | 108 | # generate Go client and models (see details in the config file) 109 | rm -rf pkg/alertmanagerapi/ 110 | podman run --rm -v "${PWD}:/local" docker.io/openapitools/openapi-generator-cli:v7.6.0 generate \ 111 | --input-spec /local/alertmanager-openapi.yaml \ 112 | --generator-name go \ 113 | --output /local/pkg/alertmanagerapi \ 114 | --config /local/openapi-generator-config.yaml 115 | # fetch dependencies 116 | go get -u ./pkg/alertmanagerapi/... 117 | go mod tidy 118 | go mod vendor 119 | ``` 120 | 121 | ## Project Distribution 122 | 123 | Following are the steps to build the installer and distribute this project to users. 124 | 125 | 1. Build the installer for the image built and published in the registry: 126 | 127 | ```sh 128 | make build-installer IMG=/alert-operator:tag 129 | ``` 130 | 131 | NOTE: The makefile target mentioned above generates an 'install.yaml' 132 | file in the dist directory. This file contains all the resources built 133 | with Kustomize, which are necessary to install this project without 134 | its dependencies. 135 | 136 | 2. Using the installer 137 | 138 | Users can just run kubectl apply -f to install the project, i.e.: 139 | 140 | ```sh 141 | kubectl apply -f https://raw.githubusercontent.com//alert-operator//dist/install.yaml 142 | ``` 143 | 144 | ## Contributing 145 | 146 | Contributions are welcome! Feel free to submit feedback and ideas by opening [GitHub issues](https://github.com/jacksgt/alert-operator/issues). 147 | It is recommended to discuss your feature in an issue before opening a pull request. 148 | 149 | ## License 150 | 151 | Copyright 2024. 152 | 153 | Licensed under the Apache License, Version 2.0 (the "License"); 154 | you may not use this file except in compliance with the License. 155 | You may obtain a copy of the License at 156 | 157 | http://www.apache.org/licenses/LICENSE-2.0 158 | 159 | Unless required by applicable law or agreed to in writing, software 160 | distributed under the License is distributed on an "AS IS" BASIS, 161 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 162 | See the License for the specific language governing permissions and 163 | limitations under the License. 164 | 165 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_cluster_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the ClusterStatus type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &ClusterStatus{} 21 | 22 | // ClusterStatus struct for ClusterStatus 23 | type ClusterStatus struct { 24 | Name *string `json:"name,omitempty"` 25 | Status string `json:"status"` 26 | Peers []PeerStatus `json:"peers,omitempty"` 27 | } 28 | 29 | type _ClusterStatus ClusterStatus 30 | 31 | // NewClusterStatus instantiates a new ClusterStatus object 32 | // This constructor will assign default values to properties that have it defined, 33 | // and makes sure properties required by API are set, but the set of arguments 34 | // will change when the set of required properties is changed 35 | func NewClusterStatus(status string) *ClusterStatus { 36 | this := ClusterStatus{} 37 | this.Status = status 38 | return &this 39 | } 40 | 41 | // NewClusterStatusWithDefaults instantiates a new ClusterStatus object 42 | // This constructor will only assign default values to properties that have it defined, 43 | // but it doesn't guarantee that properties required by API are set 44 | func NewClusterStatusWithDefaults() *ClusterStatus { 45 | this := ClusterStatus{} 46 | return &this 47 | } 48 | 49 | // GetName returns the Name field value if set, zero value otherwise. 50 | func (o *ClusterStatus) GetName() string { 51 | if o == nil || IsNil(o.Name) { 52 | var ret string 53 | return ret 54 | } 55 | return *o.Name 56 | } 57 | 58 | // GetNameOk returns a tuple with the Name field value if set, nil otherwise 59 | // and a boolean to check if the value has been set. 60 | func (o *ClusterStatus) GetNameOk() (*string, bool) { 61 | if o == nil || IsNil(o.Name) { 62 | return nil, false 63 | } 64 | return o.Name, true 65 | } 66 | 67 | // HasName returns a boolean if a field has been set. 68 | func (o *ClusterStatus) HasName() bool { 69 | if o != nil && !IsNil(o.Name) { 70 | return true 71 | } 72 | 73 | return false 74 | } 75 | 76 | // SetName gets a reference to the given string and assigns it to the Name field. 77 | func (o *ClusterStatus) SetName(v string) { 78 | o.Name = &v 79 | } 80 | 81 | // GetStatus returns the Status field value 82 | func (o *ClusterStatus) GetStatus() string { 83 | if o == nil { 84 | var ret string 85 | return ret 86 | } 87 | 88 | return o.Status 89 | } 90 | 91 | // GetStatusOk returns a tuple with the Status field value 92 | // and a boolean to check if the value has been set. 93 | func (o *ClusterStatus) GetStatusOk() (*string, bool) { 94 | if o == nil { 95 | return nil, false 96 | } 97 | return &o.Status, true 98 | } 99 | 100 | // SetStatus sets field value 101 | func (o *ClusterStatus) SetStatus(v string) { 102 | o.Status = v 103 | } 104 | 105 | // GetPeers returns the Peers field value if set, zero value otherwise. 106 | func (o *ClusterStatus) GetPeers() []PeerStatus { 107 | if o == nil || IsNil(o.Peers) { 108 | var ret []PeerStatus 109 | return ret 110 | } 111 | return o.Peers 112 | } 113 | 114 | // GetPeersOk returns a tuple with the Peers field value if set, nil otherwise 115 | // and a boolean to check if the value has been set. 116 | func (o *ClusterStatus) GetPeersOk() ([]PeerStatus, bool) { 117 | if o == nil || IsNil(o.Peers) { 118 | return nil, false 119 | } 120 | return o.Peers, true 121 | } 122 | 123 | // HasPeers returns a boolean if a field has been set. 124 | func (o *ClusterStatus) HasPeers() bool { 125 | if o != nil && !IsNil(o.Peers) { 126 | return true 127 | } 128 | 129 | return false 130 | } 131 | 132 | // SetPeers gets a reference to the given []PeerStatus and assigns it to the Peers field. 133 | func (o *ClusterStatus) SetPeers(v []PeerStatus) { 134 | o.Peers = v 135 | } 136 | 137 | func (o ClusterStatus) MarshalJSON() ([]byte, error) { 138 | toSerialize,err := o.ToMap() 139 | if err != nil { 140 | return []byte{}, err 141 | } 142 | return json.Marshal(toSerialize) 143 | } 144 | 145 | func (o ClusterStatus) ToMap() (map[string]interface{}, error) { 146 | toSerialize := map[string]interface{}{} 147 | if !IsNil(o.Name) { 148 | toSerialize["name"] = o.Name 149 | } 150 | toSerialize["status"] = o.Status 151 | if !IsNil(o.Peers) { 152 | toSerialize["peers"] = o.Peers 153 | } 154 | return toSerialize, nil 155 | } 156 | 157 | func (o *ClusterStatus) UnmarshalJSON(data []byte) (err error) { 158 | // This validates that all required properties are included in the JSON object 159 | // by unmarshalling the object into a generic map with string keys and checking 160 | // that every required field exists as a key in the generic map. 161 | requiredProperties := []string{ 162 | "status", 163 | } 164 | 165 | allProperties := make(map[string]interface{}) 166 | 167 | err = json.Unmarshal(data, &allProperties) 168 | 169 | if err != nil { 170 | return err; 171 | } 172 | 173 | for _, requiredProperty := range(requiredProperties) { 174 | if _, exists := allProperties[requiredProperty]; !exists { 175 | return fmt.Errorf("no value given for required property %v", requiredProperty) 176 | } 177 | } 178 | 179 | varClusterStatus := _ClusterStatus{} 180 | 181 | decoder := json.NewDecoder(bytes.NewReader(data)) 182 | decoder.DisallowUnknownFields() 183 | err = decoder.Decode(&varClusterStatus) 184 | 185 | if err != nil { 186 | return err 187 | } 188 | 189 | *o = ClusterStatus(varClusterStatus) 190 | 191 | return err 192 | } 193 | 194 | type NullableClusterStatus struct { 195 | value *ClusterStatus 196 | isSet bool 197 | } 198 | 199 | func (v NullableClusterStatus) Get() *ClusterStatus { 200 | return v.value 201 | } 202 | 203 | func (v *NullableClusterStatus) Set(val *ClusterStatus) { 204 | v.value = val 205 | v.isSet = true 206 | } 207 | 208 | func (v NullableClusterStatus) IsSet() bool { 209 | return v.isSet 210 | } 211 | 212 | func (v *NullableClusterStatus) Unset() { 213 | v.value = nil 214 | v.isSet = false 215 | } 216 | 217 | func NewNullableClusterStatus(val *ClusterStatus) *NullableClusterStatus { 218 | return &NullableClusterStatus{value: val, isSet: true} 219 | } 220 | 221 | func (v NullableClusterStatus) MarshalJSON() ([]byte, error) { 222 | return json.Marshal(v.value) 223 | } 224 | 225 | func (v *NullableClusterStatus) UnmarshalJSON(src []byte) error { 226 | v.isSet = true 227 | return json.Unmarshal(src, &v.value) 228 | } 229 | 230 | 231 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_matcher.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the Matcher type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &Matcher{} 21 | 22 | // Matcher struct for Matcher 23 | type Matcher struct { 24 | Name string `json:"name"` 25 | Value string `json:"value"` 26 | IsRegex bool `json:"isRegex"` 27 | IsEqual *bool `json:"isEqual,omitempty"` 28 | } 29 | 30 | type _Matcher Matcher 31 | 32 | // NewMatcher instantiates a new Matcher object 33 | // This constructor will assign default values to properties that have it defined, 34 | // and makes sure properties required by API are set, but the set of arguments 35 | // will change when the set of required properties is changed 36 | func NewMatcher(name string, value string, isRegex bool) *Matcher { 37 | this := Matcher{} 38 | this.Name = name 39 | this.Value = value 40 | this.IsRegex = isRegex 41 | var isEqual bool = true 42 | this.IsEqual = &isEqual 43 | return &this 44 | } 45 | 46 | // NewMatcherWithDefaults instantiates a new Matcher object 47 | // This constructor will only assign default values to properties that have it defined, 48 | // but it doesn't guarantee that properties required by API are set 49 | func NewMatcherWithDefaults() *Matcher { 50 | this := Matcher{} 51 | var isEqual bool = true 52 | this.IsEqual = &isEqual 53 | return &this 54 | } 55 | 56 | // GetName returns the Name field value 57 | func (o *Matcher) GetName() string { 58 | if o == nil { 59 | var ret string 60 | return ret 61 | } 62 | 63 | return o.Name 64 | } 65 | 66 | // GetNameOk returns a tuple with the Name field value 67 | // and a boolean to check if the value has been set. 68 | func (o *Matcher) GetNameOk() (*string, bool) { 69 | if o == nil { 70 | return nil, false 71 | } 72 | return &o.Name, true 73 | } 74 | 75 | // SetName sets field value 76 | func (o *Matcher) SetName(v string) { 77 | o.Name = v 78 | } 79 | 80 | // GetValue returns the Value field value 81 | func (o *Matcher) GetValue() string { 82 | if o == nil { 83 | var ret string 84 | return ret 85 | } 86 | 87 | return o.Value 88 | } 89 | 90 | // GetValueOk returns a tuple with the Value field value 91 | // and a boolean to check if the value has been set. 92 | func (o *Matcher) GetValueOk() (*string, bool) { 93 | if o == nil { 94 | return nil, false 95 | } 96 | return &o.Value, true 97 | } 98 | 99 | // SetValue sets field value 100 | func (o *Matcher) SetValue(v string) { 101 | o.Value = v 102 | } 103 | 104 | // GetIsRegex returns the IsRegex field value 105 | func (o *Matcher) GetIsRegex() bool { 106 | if o == nil { 107 | var ret bool 108 | return ret 109 | } 110 | 111 | return o.IsRegex 112 | } 113 | 114 | // GetIsRegexOk returns a tuple with the IsRegex field value 115 | // and a boolean to check if the value has been set. 116 | func (o *Matcher) GetIsRegexOk() (*bool, bool) { 117 | if o == nil { 118 | return nil, false 119 | } 120 | return &o.IsRegex, true 121 | } 122 | 123 | // SetIsRegex sets field value 124 | func (o *Matcher) SetIsRegex(v bool) { 125 | o.IsRegex = v 126 | } 127 | 128 | // GetIsEqual returns the IsEqual field value if set, zero value otherwise. 129 | func (o *Matcher) GetIsEqual() bool { 130 | if o == nil || IsNil(o.IsEqual) { 131 | var ret bool 132 | return ret 133 | } 134 | return *o.IsEqual 135 | } 136 | 137 | // GetIsEqualOk returns a tuple with the IsEqual field value if set, nil otherwise 138 | // and a boolean to check if the value has been set. 139 | func (o *Matcher) GetIsEqualOk() (*bool, bool) { 140 | if o == nil || IsNil(o.IsEqual) { 141 | return nil, false 142 | } 143 | return o.IsEqual, true 144 | } 145 | 146 | // HasIsEqual returns a boolean if a field has been set. 147 | func (o *Matcher) HasIsEqual() bool { 148 | if o != nil && !IsNil(o.IsEqual) { 149 | return true 150 | } 151 | 152 | return false 153 | } 154 | 155 | // SetIsEqual gets a reference to the given bool and assigns it to the IsEqual field. 156 | func (o *Matcher) SetIsEqual(v bool) { 157 | o.IsEqual = &v 158 | } 159 | 160 | func (o Matcher) MarshalJSON() ([]byte, error) { 161 | toSerialize,err := o.ToMap() 162 | if err != nil { 163 | return []byte{}, err 164 | } 165 | return json.Marshal(toSerialize) 166 | } 167 | 168 | func (o Matcher) ToMap() (map[string]interface{}, error) { 169 | toSerialize := map[string]interface{}{} 170 | toSerialize["name"] = o.Name 171 | toSerialize["value"] = o.Value 172 | toSerialize["isRegex"] = o.IsRegex 173 | if !IsNil(o.IsEqual) { 174 | toSerialize["isEqual"] = o.IsEqual 175 | } 176 | return toSerialize, nil 177 | } 178 | 179 | func (o *Matcher) UnmarshalJSON(data []byte) (err error) { 180 | // This validates that all required properties are included in the JSON object 181 | // by unmarshalling the object into a generic map with string keys and checking 182 | // that every required field exists as a key in the generic map. 183 | requiredProperties := []string{ 184 | "name", 185 | "value", 186 | "isRegex", 187 | } 188 | 189 | allProperties := make(map[string]interface{}) 190 | 191 | err = json.Unmarshal(data, &allProperties) 192 | 193 | if err != nil { 194 | return err; 195 | } 196 | 197 | for _, requiredProperty := range(requiredProperties) { 198 | if _, exists := allProperties[requiredProperty]; !exists { 199 | return fmt.Errorf("no value given for required property %v", requiredProperty) 200 | } 201 | } 202 | 203 | varMatcher := _Matcher{} 204 | 205 | decoder := json.NewDecoder(bytes.NewReader(data)) 206 | decoder.DisallowUnknownFields() 207 | err = decoder.Decode(&varMatcher) 208 | 209 | if err != nil { 210 | return err 211 | } 212 | 213 | *o = Matcher(varMatcher) 214 | 215 | return err 216 | } 217 | 218 | type NullableMatcher struct { 219 | value *Matcher 220 | isSet bool 221 | } 222 | 223 | func (v NullableMatcher) Get() *Matcher { 224 | return v.value 225 | } 226 | 227 | func (v *NullableMatcher) Set(val *Matcher) { 228 | v.value = val 229 | v.isSet = true 230 | } 231 | 232 | func (v NullableMatcher) IsSet() bool { 233 | return v.isSet 234 | } 235 | 236 | func (v *NullableMatcher) Unset() { 237 | v.value = nil 238 | v.isSet = false 239 | } 240 | 241 | func NewNullableMatcher(val *Matcher) *NullableMatcher { 242 | return &NullableMatcher{value: val, isSet: true} 243 | } 244 | 245 | func (v NullableMatcher) MarshalJSON() ([]byte, error) { 246 | return json.Marshal(v.value) 247 | } 248 | 249 | func (v *NullableMatcher) UnmarshalJSON(src []byte) error { 250 | v.isSet = true 251 | return json.Unmarshal(src, &v.value) 252 | } 253 | 254 | 255 | -------------------------------------------------------------------------------- /internal/controller/alert_controller.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 | "crypto/sha256" 22 | "encoding/json" 23 | "fmt" 24 | "io" 25 | "net/http" 26 | "time" 27 | 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | "k8s.io/apimachinery/pkg/runtime" 30 | ctrl "sigs.k8s.io/controller-runtime" 31 | "sigs.k8s.io/controller-runtime/pkg/client" 32 | "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" 33 | "sigs.k8s.io/controller-runtime/pkg/event" 34 | "sigs.k8s.io/controller-runtime/pkg/handler" 35 | "sigs.k8s.io/controller-runtime/pkg/log" 36 | "sigs.k8s.io/controller-runtime/pkg/source" 37 | 38 | alertmanagerprometheusiov1alpha1 "github.com/jacksgt/alert-operator/api/v1alpha1" 39 | ) 40 | 41 | // AlertReconciler reconciles a Alert object 42 | type AlertReconciler struct { 43 | client.Client 44 | Scheme *runtime.Scheme 45 | ControllerNamespace string 46 | PrometheusBaseURL string 47 | SyncChannel chan event.GenericEvent 48 | } 49 | 50 | // +kubebuilder:rbac:groups=alertmanager.prometheus.io.alertmanager.prometheus.io,resources=alerts,verbs=get;list;watch;create;update;patch;delete 51 | // +kubebuilder:rbac:groups=alertmanager.prometheus.io.alertmanager.prometheus.io,resources=alerts/status,verbs=get;update;patch 52 | // +kubebuilder:rbac:groups=alertmanager.prometheus.io.alertmanager.prometheus.io,resources=alerts/finalizers,verbs=update 53 | 54 | // Reconcile is part of the main kubernetes reconciliation loop which aims to 55 | // move the current state of the cluster closer to the desired state. 56 | // TODO(user): Modify the Reconcile function to compare the state specified by 57 | // the Alert object against the actual cluster state, and then 58 | // perform operations to make the cluster state reflect the state specified by 59 | // the user. 60 | // 61 | // For more details, check Reconcile and its Result here: 62 | // - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.18.4/pkg/reconcile 63 | func (r *AlertReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { 64 | log := log.FromContext(ctx) 65 | 66 | if req.NamespacedName.Name != "" { 67 | // TODO: reconcile individual alert 68 | return ctrl.Result{}, nil 69 | } 70 | 71 | log.Info("syncing all alerts") 72 | 73 | alerts, err := getActiveAlerts(ctx, r.PrometheusBaseURL) 74 | if err != nil { 75 | // error talking to prometheus, retry later 76 | return ctrl.Result{}, err 77 | } 78 | 79 | log.Info(fmt.Sprintf("Got %d alerts from Prometheus", len(alerts))) 80 | 81 | for _, a := range alerts { 82 | var alertObj = alertmanagerprometheusiov1alpha1.Alert{ 83 | ObjectMeta: metav1.ObjectMeta{ 84 | Name: generateAlertName(a), 85 | Namespace: r.ControllerNamespace, 86 | }, 87 | } 88 | 89 | _, err := controllerutil.CreateOrUpdate(ctx, r.Client, &alertObj, func() error { 90 | return nil 91 | }) 92 | if err != nil { 93 | log.Error(err, "Unable to create Alert", alertObj.ObjectMeta.Name) 94 | continue 95 | } 96 | 97 | // TODO: consider using something like CreateOrUpdate 98 | // Set status 99 | alertObj.Status.State = a.State 100 | alertObj.Status.Annotations = a.Annotations 101 | alertObj.Status.Labels = a.Labels 102 | alertObj.Status.Since = a.ActiveAt.String() 103 | alertObj.Status.Value = a.Value 104 | 105 | err = r.updateAlertStatus(&alertObj) 106 | if err != nil { 107 | log.Error(err, "Unable to set alert status") 108 | continue 109 | } 110 | } 111 | 112 | // TODO: garbage collect old alerts 113 | 114 | return ctrl.Result{}, nil 115 | } 116 | 117 | func (r *AlertReconciler) updateAlertStatus(a *alertmanagerprometheusiov1alpha1.Alert) error { 118 | if err := r.Status().Update(context.TODO(), a); err != nil { 119 | return fmt.Errorf("Failed to update Alert.status with err: %w", err) 120 | } 121 | return nil 122 | } 123 | 124 | func generateAlertName(a Alert) string { 125 | alertName := a.Labels["alertname"] 126 | if alertName == "" { 127 | // According to https://github.com/prometheus/prometheus/blob/d002fad00c20eaad029d6d122bfc513b091f78ad/rules/alerting.go#L394 128 | // the "alertname" label should always be set 129 | panic("alertname label is not set!") 130 | } 131 | // TODO: include labels / annotations in calculation as well? 132 | data := a.ActiveAt.String() 133 | hash := sha256.Sum256([]byte(data)) 134 | return fmt.Sprintf("%s-%x", alertName, hash[0:8]) 135 | } 136 | 137 | func getActiveAlerts(ctx context.Context, baseURL string) ([]Alert, error) { 138 | var alerts []Alert 139 | // TODO: authentication 140 | resp, err := http.Get(baseURL + "/api/v1/alerts") 141 | if err != nil { 142 | return alerts, fmt.Errorf("Error making HTTP request: %w", err) 143 | } 144 | defer resp.Body.Close() 145 | 146 | // Read the response body 147 | body, err := io.ReadAll(resp.Body) 148 | if err != nil { 149 | return alerts, fmt.Errorf("Error reading response body: %w", err) 150 | } 151 | 152 | // Parse the JSON response 153 | var alertResponse PrometheusAlertResponse 154 | err = json.Unmarshal(body, &alertResponse) 155 | if err != nil { 156 | return alerts, fmt.Errorf("Error parsing JSON: %w", err) 157 | } 158 | 159 | if alertResponse.Status != "success" { 160 | return alerts, fmt.Errorf("Unexpected response status in JSON: '%s'", alertResponse.Status) 161 | } 162 | 163 | // All good, return the alerts 164 | return alertResponse.Data.Alerts, nil 165 | } 166 | 167 | // SetupWithManager sets up the controller with the Manager. 168 | func (r *AlertReconciler) SetupWithManager(mgr ctrl.Manager) error { 169 | // whenever we get an event on this channel, we trigger a sync ("reconciliation") for all alerts 170 | return ctrl.NewControllerManagedBy(mgr). 171 | Named("alert_controller_syncall"). // Must be compatible with a Prometheus metric name i.e. alphanum + underscore 172 | WatchesRawSource( 173 | source.Channel(r.SyncChannel, &handler.EnqueueRequestForObject{}), 174 | ). 175 | Complete(r) 176 | } 177 | 178 | type PrometheusAlertResponse struct { 179 | Data struct { 180 | Alerts []Alert `json:"alerts"` 181 | } `json:"data"` 182 | Status string `json:"status"` 183 | } 184 | 185 | type Alert struct { 186 | ActiveAt time.Time `json:"activeAt"` 187 | Annotations map[string]string `json:"annotations"` 188 | Labels map[string]string `json:"labels"` 189 | State string `json:"state"` 190 | Value string `json:"value"` 191 | } 192 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/api_alertgroup.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "bytes" 15 | "context" 16 | "io" 17 | "net/http" 18 | "net/url" 19 | "reflect" 20 | ) 21 | 22 | 23 | // AlertgroupAPIService AlertgroupAPI service 24 | type AlertgroupAPIService service 25 | 26 | type ApiGetAlertGroupsRequest struct { 27 | ctx context.Context 28 | ApiService *AlertgroupAPIService 29 | active *bool 30 | silenced *bool 31 | inhibited *bool 32 | filter *[]string 33 | receiver *string 34 | } 35 | 36 | // Show active alerts 37 | func (r ApiGetAlertGroupsRequest) Active(active bool) ApiGetAlertGroupsRequest { 38 | r.active = &active 39 | return r 40 | } 41 | 42 | // Show silenced alerts 43 | func (r ApiGetAlertGroupsRequest) Silenced(silenced bool) ApiGetAlertGroupsRequest { 44 | r.silenced = &silenced 45 | return r 46 | } 47 | 48 | // Show inhibited alerts 49 | func (r ApiGetAlertGroupsRequest) Inhibited(inhibited bool) ApiGetAlertGroupsRequest { 50 | r.inhibited = &inhibited 51 | return r 52 | } 53 | 54 | // A list of matchers to filter alerts by 55 | func (r ApiGetAlertGroupsRequest) Filter(filter []string) ApiGetAlertGroupsRequest { 56 | r.filter = &filter 57 | return r 58 | } 59 | 60 | // A regex matching receivers to filter alerts by 61 | func (r ApiGetAlertGroupsRequest) Receiver(receiver string) ApiGetAlertGroupsRequest { 62 | r.receiver = &receiver 63 | return r 64 | } 65 | 66 | func (r ApiGetAlertGroupsRequest) Execute() ([]AlertGroup, *http.Response, error) { 67 | return r.ApiService.GetAlertGroupsExecute(r) 68 | } 69 | 70 | /* 71 | GetAlertGroups Method for GetAlertGroups 72 | 73 | Get a list of alert groups 74 | 75 | @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). 76 | @return ApiGetAlertGroupsRequest 77 | */ 78 | func (a *AlertgroupAPIService) GetAlertGroups(ctx context.Context) ApiGetAlertGroupsRequest { 79 | return ApiGetAlertGroupsRequest{ 80 | ApiService: a, 81 | ctx: ctx, 82 | } 83 | } 84 | 85 | // Execute executes the request 86 | // @return []AlertGroup 87 | func (a *AlertgroupAPIService) GetAlertGroupsExecute(r ApiGetAlertGroupsRequest) ([]AlertGroup, *http.Response, error) { 88 | var ( 89 | localVarHTTPMethod = http.MethodGet 90 | localVarPostBody interface{} 91 | formFiles []formFile 92 | localVarReturnValue []AlertGroup 93 | ) 94 | 95 | localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "AlertgroupAPIService.GetAlertGroups") 96 | if err != nil { 97 | return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} 98 | } 99 | 100 | localVarPath := localBasePath + "/alerts/groups" 101 | 102 | localVarHeaderParams := make(map[string]string) 103 | localVarQueryParams := url.Values{} 104 | localVarFormParams := url.Values{} 105 | 106 | if r.active != nil { 107 | parameterAddToHeaderOrQuery(localVarQueryParams, "active", r.active, "") 108 | } else { 109 | var defaultValue bool = true 110 | r.active = &defaultValue 111 | } 112 | if r.silenced != nil { 113 | parameterAddToHeaderOrQuery(localVarQueryParams, "silenced", r.silenced, "") 114 | } else { 115 | var defaultValue bool = true 116 | r.silenced = &defaultValue 117 | } 118 | if r.inhibited != nil { 119 | parameterAddToHeaderOrQuery(localVarQueryParams, "inhibited", r.inhibited, "") 120 | } else { 121 | var defaultValue bool = true 122 | r.inhibited = &defaultValue 123 | } 124 | if r.filter != nil { 125 | t := *r.filter 126 | if reflect.TypeOf(t).Kind() == reflect.Slice { 127 | s := reflect.ValueOf(t) 128 | for i := 0; i < s.Len(); i++ { 129 | parameterAddToHeaderOrQuery(localVarQueryParams, "filter", s.Index(i).Interface(), "multi") 130 | } 131 | } else { 132 | parameterAddToHeaderOrQuery(localVarQueryParams, "filter", t, "multi") 133 | } 134 | } 135 | if r.receiver != nil { 136 | parameterAddToHeaderOrQuery(localVarQueryParams, "receiver", r.receiver, "") 137 | } 138 | // to determine the Content-Type header 139 | localVarHTTPContentTypes := []string{} 140 | 141 | // set Content-Type header 142 | localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) 143 | if localVarHTTPContentType != "" { 144 | localVarHeaderParams["Content-Type"] = localVarHTTPContentType 145 | } 146 | 147 | // to determine the Accept header 148 | localVarHTTPHeaderAccepts := []string{"application/json"} 149 | 150 | // set Accept header 151 | localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) 152 | if localVarHTTPHeaderAccept != "" { 153 | localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept 154 | } 155 | req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) 156 | if err != nil { 157 | return localVarReturnValue, nil, err 158 | } 159 | 160 | localVarHTTPResponse, err := a.client.callAPI(req) 161 | if err != nil || localVarHTTPResponse == nil { 162 | return localVarReturnValue, localVarHTTPResponse, err 163 | } 164 | 165 | localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) 166 | localVarHTTPResponse.Body.Close() 167 | localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) 168 | if err != nil { 169 | return localVarReturnValue, localVarHTTPResponse, err 170 | } 171 | 172 | if localVarHTTPResponse.StatusCode >= 300 { 173 | newErr := &GenericOpenAPIError{ 174 | body: localVarBody, 175 | error: localVarHTTPResponse.Status, 176 | } 177 | if localVarHTTPResponse.StatusCode == 400 { 178 | var v string 179 | err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) 180 | if err != nil { 181 | newErr.error = err.Error() 182 | return localVarReturnValue, localVarHTTPResponse, newErr 183 | } 184 | newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) 185 | newErr.model = v 186 | return localVarReturnValue, localVarHTTPResponse, newErr 187 | } 188 | if localVarHTTPResponse.StatusCode == 500 { 189 | var v string 190 | err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) 191 | if err != nil { 192 | newErr.error = err.Error() 193 | return localVarReturnValue, localVarHTTPResponse, newErr 194 | } 195 | newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) 196 | newErr.model = v 197 | } 198 | return localVarReturnValue, localVarHTTPResponse, newErr 199 | } 200 | 201 | err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) 202 | if err != nil { 203 | newErr := &GenericOpenAPIError{ 204 | body: localVarBody, 205 | error: err.Error(), 206 | } 207 | return localVarReturnValue, localVarHTTPResponse, newErr 208 | } 209 | 210 | return localVarReturnValue, localVarHTTPResponse, nil 211 | } 212 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_alertmanager_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "time" 16 | "bytes" 17 | "fmt" 18 | ) 19 | 20 | // checks if the AlertmanagerStatus type satisfies the MappedNullable interface at compile time 21 | var _ MappedNullable = &AlertmanagerStatus{} 22 | 23 | // AlertmanagerStatus struct for AlertmanagerStatus 24 | type AlertmanagerStatus struct { 25 | Cluster ClusterStatus `json:"cluster"` 26 | VersionInfo VersionInfo `json:"versionInfo"` 27 | Config AlertmanagerConfig `json:"config"` 28 | Uptime time.Time `json:"uptime"` 29 | } 30 | 31 | type _AlertmanagerStatus AlertmanagerStatus 32 | 33 | // NewAlertmanagerStatus instantiates a new AlertmanagerStatus object 34 | // This constructor will assign default values to properties that have it defined, 35 | // and makes sure properties required by API are set, but the set of arguments 36 | // will change when the set of required properties is changed 37 | func NewAlertmanagerStatus(cluster ClusterStatus, versionInfo VersionInfo, config AlertmanagerConfig, uptime time.Time) *AlertmanagerStatus { 38 | this := AlertmanagerStatus{} 39 | this.Cluster = cluster 40 | this.VersionInfo = versionInfo 41 | this.Config = config 42 | this.Uptime = uptime 43 | return &this 44 | } 45 | 46 | // NewAlertmanagerStatusWithDefaults instantiates a new AlertmanagerStatus object 47 | // This constructor will only assign default values to properties that have it defined, 48 | // but it doesn't guarantee that properties required by API are set 49 | func NewAlertmanagerStatusWithDefaults() *AlertmanagerStatus { 50 | this := AlertmanagerStatus{} 51 | return &this 52 | } 53 | 54 | // GetCluster returns the Cluster field value 55 | func (o *AlertmanagerStatus) GetCluster() ClusterStatus { 56 | if o == nil { 57 | var ret ClusterStatus 58 | return ret 59 | } 60 | 61 | return o.Cluster 62 | } 63 | 64 | // GetClusterOk returns a tuple with the Cluster field value 65 | // and a boolean to check if the value has been set. 66 | func (o *AlertmanagerStatus) GetClusterOk() (*ClusterStatus, bool) { 67 | if o == nil { 68 | return nil, false 69 | } 70 | return &o.Cluster, true 71 | } 72 | 73 | // SetCluster sets field value 74 | func (o *AlertmanagerStatus) SetCluster(v ClusterStatus) { 75 | o.Cluster = v 76 | } 77 | 78 | // GetVersionInfo returns the VersionInfo field value 79 | func (o *AlertmanagerStatus) GetVersionInfo() VersionInfo { 80 | if o == nil { 81 | var ret VersionInfo 82 | return ret 83 | } 84 | 85 | return o.VersionInfo 86 | } 87 | 88 | // GetVersionInfoOk returns a tuple with the VersionInfo field value 89 | // and a boolean to check if the value has been set. 90 | func (o *AlertmanagerStatus) GetVersionInfoOk() (*VersionInfo, bool) { 91 | if o == nil { 92 | return nil, false 93 | } 94 | return &o.VersionInfo, true 95 | } 96 | 97 | // SetVersionInfo sets field value 98 | func (o *AlertmanagerStatus) SetVersionInfo(v VersionInfo) { 99 | o.VersionInfo = v 100 | } 101 | 102 | // GetConfig returns the Config field value 103 | func (o *AlertmanagerStatus) GetConfig() AlertmanagerConfig { 104 | if o == nil { 105 | var ret AlertmanagerConfig 106 | return ret 107 | } 108 | 109 | return o.Config 110 | } 111 | 112 | // GetConfigOk returns a tuple with the Config field value 113 | // and a boolean to check if the value has been set. 114 | func (o *AlertmanagerStatus) GetConfigOk() (*AlertmanagerConfig, bool) { 115 | if o == nil { 116 | return nil, false 117 | } 118 | return &o.Config, true 119 | } 120 | 121 | // SetConfig sets field value 122 | func (o *AlertmanagerStatus) SetConfig(v AlertmanagerConfig) { 123 | o.Config = v 124 | } 125 | 126 | // GetUptime returns the Uptime field value 127 | func (o *AlertmanagerStatus) GetUptime() time.Time { 128 | if o == nil { 129 | var ret time.Time 130 | return ret 131 | } 132 | 133 | return o.Uptime 134 | } 135 | 136 | // GetUptimeOk returns a tuple with the Uptime field value 137 | // and a boolean to check if the value has been set. 138 | func (o *AlertmanagerStatus) GetUptimeOk() (*time.Time, bool) { 139 | if o == nil { 140 | return nil, false 141 | } 142 | return &o.Uptime, true 143 | } 144 | 145 | // SetUptime sets field value 146 | func (o *AlertmanagerStatus) SetUptime(v time.Time) { 147 | o.Uptime = v 148 | } 149 | 150 | func (o AlertmanagerStatus) MarshalJSON() ([]byte, error) { 151 | toSerialize,err := o.ToMap() 152 | if err != nil { 153 | return []byte{}, err 154 | } 155 | return json.Marshal(toSerialize) 156 | } 157 | 158 | func (o AlertmanagerStatus) ToMap() (map[string]interface{}, error) { 159 | toSerialize := map[string]interface{}{} 160 | toSerialize["cluster"] = o.Cluster 161 | toSerialize["versionInfo"] = o.VersionInfo 162 | toSerialize["config"] = o.Config 163 | toSerialize["uptime"] = o.Uptime 164 | return toSerialize, nil 165 | } 166 | 167 | func (o *AlertmanagerStatus) UnmarshalJSON(data []byte) (err error) { 168 | // This validates that all required properties are included in the JSON object 169 | // by unmarshalling the object into a generic map with string keys and checking 170 | // that every required field exists as a key in the generic map. 171 | requiredProperties := []string{ 172 | "cluster", 173 | "versionInfo", 174 | "config", 175 | "uptime", 176 | } 177 | 178 | allProperties := make(map[string]interface{}) 179 | 180 | err = json.Unmarshal(data, &allProperties) 181 | 182 | if err != nil { 183 | return err; 184 | } 185 | 186 | for _, requiredProperty := range(requiredProperties) { 187 | if _, exists := allProperties[requiredProperty]; !exists { 188 | return fmt.Errorf("no value given for required property %v", requiredProperty) 189 | } 190 | } 191 | 192 | varAlertmanagerStatus := _AlertmanagerStatus{} 193 | 194 | decoder := json.NewDecoder(bytes.NewReader(data)) 195 | decoder.DisallowUnknownFields() 196 | err = decoder.Decode(&varAlertmanagerStatus) 197 | 198 | if err != nil { 199 | return err 200 | } 201 | 202 | *o = AlertmanagerStatus(varAlertmanagerStatus) 203 | 204 | return err 205 | } 206 | 207 | type NullableAlertmanagerStatus struct { 208 | value *AlertmanagerStatus 209 | isSet bool 210 | } 211 | 212 | func (v NullableAlertmanagerStatus) Get() *AlertmanagerStatus { 213 | return v.value 214 | } 215 | 216 | func (v *NullableAlertmanagerStatus) Set(val *AlertmanagerStatus) { 217 | v.value = val 218 | v.isSet = true 219 | } 220 | 221 | func (v NullableAlertmanagerStatus) IsSet() bool { 222 | return v.isSet 223 | } 224 | 225 | func (v *NullableAlertmanagerStatus) Unset() { 226 | v.value = nil 227 | v.isSet = false 228 | } 229 | 230 | func NewNullableAlertmanagerStatus(val *AlertmanagerStatus) *NullableAlertmanagerStatus { 231 | return &NullableAlertmanagerStatus{value: val, isSet: true} 232 | } 233 | 234 | func (v NullableAlertmanagerStatus) MarshalJSON() ([]byte, error) { 235 | return json.Marshal(v.value) 236 | } 237 | 238 | func (v *NullableAlertmanagerStatus) UnmarshalJSON(src []byte) error { 239 | v.isSet = true 240 | return json.Unmarshal(src, &v.value) 241 | } 242 | 243 | 244 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/configuration.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "context" 15 | "fmt" 16 | "net/http" 17 | "strings" 18 | ) 19 | 20 | // contextKeys are used to identify the type of value in the context. 21 | // Since these are string, it is possible to get a short description of the 22 | // context key for logging and debugging using key.String(). 23 | 24 | type contextKey string 25 | 26 | func (c contextKey) String() string { 27 | return "auth " + string(c) 28 | } 29 | 30 | var ( 31 | // ContextServerIndex uses a server configuration from the index. 32 | ContextServerIndex = contextKey("serverIndex") 33 | 34 | // ContextOperationServerIndices uses a server configuration from the index mapping. 35 | ContextOperationServerIndices = contextKey("serverOperationIndices") 36 | 37 | // ContextServerVariables overrides a server configuration variables. 38 | ContextServerVariables = contextKey("serverVariables") 39 | 40 | // ContextOperationServerVariables overrides a server configuration variables using operation specific values. 41 | ContextOperationServerVariables = contextKey("serverOperationVariables") 42 | ) 43 | 44 | // BasicAuth provides basic http authentication to a request passed via context using ContextBasicAuth 45 | type BasicAuth struct { 46 | UserName string `json:"userName,omitempty"` 47 | Password string `json:"password,omitempty"` 48 | } 49 | 50 | // APIKey provides API key based authentication to a request passed via context using ContextAPIKey 51 | type APIKey struct { 52 | Key string 53 | Prefix string 54 | } 55 | 56 | // ServerVariable stores the information about a server variable 57 | type ServerVariable struct { 58 | Description string 59 | DefaultValue string 60 | EnumValues []string 61 | } 62 | 63 | // ServerConfiguration stores the information about a server 64 | type ServerConfiguration struct { 65 | URL string 66 | Description string 67 | Variables map[string]ServerVariable 68 | } 69 | 70 | // ServerConfigurations stores multiple ServerConfiguration items 71 | type ServerConfigurations []ServerConfiguration 72 | 73 | // Configuration stores the configuration of the API client 74 | type Configuration struct { 75 | Host string `json:"host,omitempty"` 76 | Scheme string `json:"scheme,omitempty"` 77 | DefaultHeader map[string]string `json:"defaultHeader,omitempty"` 78 | UserAgent string `json:"userAgent,omitempty"` 79 | Debug bool `json:"debug,omitempty"` 80 | Servers ServerConfigurations 81 | OperationServers map[string]ServerConfigurations 82 | HTTPClient *http.Client 83 | } 84 | 85 | // NewConfiguration returns a new Configuration object 86 | func NewConfiguration() *Configuration { 87 | cfg := &Configuration{ 88 | DefaultHeader: make(map[string]string), 89 | UserAgent: "OpenAPI-Generator/1.0.0/go", 90 | Debug: false, 91 | Servers: ServerConfigurations{ 92 | { 93 | URL: "/api/v2", 94 | Description: "No description provided", 95 | }, 96 | }, 97 | OperationServers: map[string]ServerConfigurations{ 98 | }, 99 | } 100 | return cfg 101 | } 102 | 103 | // AddDefaultHeader adds a new HTTP header to the default header in the request 104 | func (c *Configuration) AddDefaultHeader(key string, value string) { 105 | c.DefaultHeader[key] = value 106 | } 107 | 108 | // URL formats template on a index using given variables 109 | func (sc ServerConfigurations) URL(index int, variables map[string]string) (string, error) { 110 | if index < 0 || len(sc) <= index { 111 | return "", fmt.Errorf("index %v out of range %v", index, len(sc)-1) 112 | } 113 | server := sc[index] 114 | url := server.URL 115 | 116 | // go through variables and replace placeholders 117 | for name, variable := range server.Variables { 118 | if value, ok := variables[name]; ok { 119 | found := bool(len(variable.EnumValues) == 0) 120 | for _, enumValue := range variable.EnumValues { 121 | if value == enumValue { 122 | found = true 123 | } 124 | } 125 | if !found { 126 | return "", fmt.Errorf("the variable %s in the server URL has invalid value %v. Must be %v", name, value, variable.EnumValues) 127 | } 128 | url = strings.Replace(url, "{"+name+"}", value, -1) 129 | } else { 130 | url = strings.Replace(url, "{"+name+"}", variable.DefaultValue, -1) 131 | } 132 | } 133 | return url, nil 134 | } 135 | 136 | // ServerURL returns URL based on server settings 137 | func (c *Configuration) ServerURL(index int, variables map[string]string) (string, error) { 138 | return c.Servers.URL(index, variables) 139 | } 140 | 141 | func getServerIndex(ctx context.Context) (int, error) { 142 | si := ctx.Value(ContextServerIndex) 143 | if si != nil { 144 | if index, ok := si.(int); ok { 145 | return index, nil 146 | } 147 | return 0, reportError("Invalid type %T should be int", si) 148 | } 149 | return 0, nil 150 | } 151 | 152 | func getServerOperationIndex(ctx context.Context, endpoint string) (int, error) { 153 | osi := ctx.Value(ContextOperationServerIndices) 154 | if osi != nil { 155 | if operationIndices, ok := osi.(map[string]int); !ok { 156 | return 0, reportError("Invalid type %T should be map[string]int", osi) 157 | } else { 158 | index, ok := operationIndices[endpoint] 159 | if ok { 160 | return index, nil 161 | } 162 | } 163 | } 164 | return getServerIndex(ctx) 165 | } 166 | 167 | func getServerVariables(ctx context.Context) (map[string]string, error) { 168 | sv := ctx.Value(ContextServerVariables) 169 | if sv != nil { 170 | if variables, ok := sv.(map[string]string); ok { 171 | return variables, nil 172 | } 173 | return nil, reportError("ctx value of ContextServerVariables has invalid type %T should be map[string]string", sv) 174 | } 175 | return nil, nil 176 | } 177 | 178 | func getServerOperationVariables(ctx context.Context, endpoint string) (map[string]string, error) { 179 | osv := ctx.Value(ContextOperationServerVariables) 180 | if osv != nil { 181 | if operationVariables, ok := osv.(map[string]map[string]string); !ok { 182 | return nil, reportError("ctx value of ContextOperationServerVariables has invalid type %T should be map[string]map[string]string", osv) 183 | } else { 184 | variables, ok := operationVariables[endpoint] 185 | if ok { 186 | return variables, nil 187 | } 188 | } 189 | } 190 | return getServerVariables(ctx) 191 | } 192 | 193 | // ServerURLWithContext returns a new server URL given an endpoint 194 | func (c *Configuration) ServerURLWithContext(ctx context.Context, endpoint string) (string, error) { 195 | sc, ok := c.OperationServers[endpoint] 196 | if !ok { 197 | sc = c.Servers 198 | } 199 | 200 | if ctx == nil { 201 | return sc.URL(0, nil) 202 | } 203 | 204 | index, err := getServerOperationIndex(ctx, endpoint) 205 | if err != nil { 206 | return "", err 207 | } 208 | 209 | variables, err := getServerOperationVariables(ctx, endpoint) 210 | if err != nil { 211 | return "", err 212 | } 213 | 214 | return sc.URL(index, variables) 215 | } 216 | -------------------------------------------------------------------------------- /config/crd/bases/alertmanager.prometheus.io.alertmanager.prometheus.io_silences.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | controller-gen.kubebuilder.io/version: v0.15.0 7 | name: silences.alertmanager.prometheus.io.alertmanager.prometheus.io 8 | spec: 9 | group: alertmanager.prometheus.io.alertmanager.prometheus.io 10 | names: 11 | kind: Silence 12 | listKind: SilenceList 13 | plural: silences 14 | singular: silence 15 | scope: Namespaced 16 | versions: 17 | - name: v1alpha1 18 | schema: 19 | openAPIV3Schema: 20 | description: Silence is the Schema for the silences API 21 | properties: 22 | apiVersion: 23 | description: |- 24 | APIVersion defines the versioned schema of this representation of an object. 25 | Servers should convert recognized schemas to the latest internal value, and 26 | may reject unrecognized values. 27 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources 28 | type: string 29 | kind: 30 | description: |- 31 | Kind is a string value representing the REST resource this object represents. 32 | Servers may infer this from the endpoint the client submits requests to. 33 | Cannot be updated. 34 | In CamelCase. 35 | More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds 36 | type: string 37 | metadata: 38 | type: object 39 | spec: 40 | description: SilenceSpec defines the desired state of Silence 41 | properties: 42 | comment: 43 | type: string 44 | createdBy: 45 | type: string 46 | endsAt: 47 | format: date-time 48 | type: string 49 | matchLabels: 50 | additionalProperties: 51 | type: string 52 | description: 'TODO: CRD validation https://book.kubebuilder.io/reference/markers/crd-validation.html' 53 | type: object 54 | startsAt: 55 | description: MatchRegexes 56 | format: date-time 57 | type: string 58 | type: object 59 | status: 60 | description: SilenceStatus defines the observed state of Silence 61 | properties: 62 | conditions: 63 | items: 64 | description: "Condition contains details for one aspect of the current 65 | state of this API Resource.\n---\nThis struct is intended for 66 | direct use as an array at the field path .status.conditions. For 67 | example,\n\n\n\ttype FooStatus struct{\n\t // Represents the 68 | observations of a foo's current state.\n\t // Known .status.conditions.type 69 | are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // 70 | +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t 71 | \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" 72 | patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t 73 | \ // other fields\n\t}" 74 | properties: 75 | lastTransitionTime: 76 | description: |- 77 | lastTransitionTime is the last time the condition transitioned from one status to another. 78 | This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. 79 | format: date-time 80 | type: string 81 | message: 82 | description: |- 83 | message is a human readable message indicating details about the transition. 84 | This may be an empty string. 85 | maxLength: 32768 86 | type: string 87 | observedGeneration: 88 | description: |- 89 | observedGeneration represents the .metadata.generation that the condition was set based upon. 90 | For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date 91 | with respect to the current state of the instance. 92 | format: int64 93 | minimum: 0 94 | type: integer 95 | reason: 96 | description: |- 97 | reason contains a programmatic identifier indicating the reason for the condition's last transition. 98 | Producers of specific condition types may define expected values and meanings for this field, 99 | and whether the values are considered a guaranteed API. 100 | The value should be a CamelCase string. 101 | This field may not be empty. 102 | maxLength: 1024 103 | minLength: 1 104 | pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ 105 | type: string 106 | status: 107 | description: status of the condition, one of True, False, Unknown. 108 | enum: 109 | - "True" 110 | - "False" 111 | - Unknown 112 | type: string 113 | type: 114 | description: |- 115 | type of condition in CamelCase or in foo.example.com/CamelCase. 116 | --- 117 | Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be 118 | useful (see .node.status.conditions), the ability to deconflict is important. 119 | The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) 120 | maxLength: 316 121 | pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ 122 | type: string 123 | required: 124 | - lastTransitionTime 125 | - message 126 | - reason 127 | - status 128 | - type 129 | type: object 130 | type: array 131 | silenceID: 132 | description: SilenceId is the unique identifier for this silence (generated 133 | by Alertmanager) 134 | type: string 135 | type: object 136 | type: object 137 | served: true 138 | storage: true 139 | subresources: 140 | status: {} 141 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_silence.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "time" 16 | "bytes" 17 | "fmt" 18 | ) 19 | 20 | // checks if the Silence type satisfies the MappedNullable interface at compile time 21 | var _ MappedNullable = &Silence{} 22 | 23 | // Silence struct for Silence 24 | type Silence struct { 25 | Matchers []Matcher `json:"matchers"` 26 | StartsAt time.Time `json:"startsAt"` 27 | EndsAt time.Time `json:"endsAt"` 28 | CreatedBy string `json:"createdBy"` 29 | Comment string `json:"comment"` 30 | } 31 | 32 | type _Silence Silence 33 | 34 | // NewSilence instantiates a new Silence object 35 | // This constructor will assign default values to properties that have it defined, 36 | // and makes sure properties required by API are set, but the set of arguments 37 | // will change when the set of required properties is changed 38 | func NewSilence(matchers []Matcher, startsAt time.Time, endsAt time.Time, createdBy string, comment string) *Silence { 39 | this := Silence{} 40 | this.Matchers = matchers 41 | this.StartsAt = startsAt 42 | this.EndsAt = endsAt 43 | this.CreatedBy = createdBy 44 | this.Comment = comment 45 | return &this 46 | } 47 | 48 | // NewSilenceWithDefaults instantiates a new Silence object 49 | // This constructor will only assign default values to properties that have it defined, 50 | // but it doesn't guarantee that properties required by API are set 51 | func NewSilenceWithDefaults() *Silence { 52 | this := Silence{} 53 | return &this 54 | } 55 | 56 | // GetMatchers returns the Matchers field value 57 | func (o *Silence) GetMatchers() []Matcher { 58 | if o == nil { 59 | var ret []Matcher 60 | return ret 61 | } 62 | 63 | return o.Matchers 64 | } 65 | 66 | // GetMatchersOk returns a tuple with the Matchers field value 67 | // and a boolean to check if the value has been set. 68 | func (o *Silence) GetMatchersOk() ([]Matcher, bool) { 69 | if o == nil { 70 | return nil, false 71 | } 72 | return o.Matchers, true 73 | } 74 | 75 | // SetMatchers sets field value 76 | func (o *Silence) SetMatchers(v []Matcher) { 77 | o.Matchers = v 78 | } 79 | 80 | // GetStartsAt returns the StartsAt field value 81 | func (o *Silence) GetStartsAt() time.Time { 82 | if o == nil { 83 | var ret time.Time 84 | return ret 85 | } 86 | 87 | return o.StartsAt 88 | } 89 | 90 | // GetStartsAtOk returns a tuple with the StartsAt field value 91 | // and a boolean to check if the value has been set. 92 | func (o *Silence) GetStartsAtOk() (*time.Time, bool) { 93 | if o == nil { 94 | return nil, false 95 | } 96 | return &o.StartsAt, true 97 | } 98 | 99 | // SetStartsAt sets field value 100 | func (o *Silence) SetStartsAt(v time.Time) { 101 | o.StartsAt = v 102 | } 103 | 104 | // GetEndsAt returns the EndsAt field value 105 | func (o *Silence) GetEndsAt() time.Time { 106 | if o == nil { 107 | var ret time.Time 108 | return ret 109 | } 110 | 111 | return o.EndsAt 112 | } 113 | 114 | // GetEndsAtOk returns a tuple with the EndsAt field value 115 | // and a boolean to check if the value has been set. 116 | func (o *Silence) GetEndsAtOk() (*time.Time, bool) { 117 | if o == nil { 118 | return nil, false 119 | } 120 | return &o.EndsAt, true 121 | } 122 | 123 | // SetEndsAt sets field value 124 | func (o *Silence) SetEndsAt(v time.Time) { 125 | o.EndsAt = v 126 | } 127 | 128 | // GetCreatedBy returns the CreatedBy field value 129 | func (o *Silence) GetCreatedBy() string { 130 | if o == nil { 131 | var ret string 132 | return ret 133 | } 134 | 135 | return o.CreatedBy 136 | } 137 | 138 | // GetCreatedByOk returns a tuple with the CreatedBy field value 139 | // and a boolean to check if the value has been set. 140 | func (o *Silence) GetCreatedByOk() (*string, bool) { 141 | if o == nil { 142 | return nil, false 143 | } 144 | return &o.CreatedBy, true 145 | } 146 | 147 | // SetCreatedBy sets field value 148 | func (o *Silence) SetCreatedBy(v string) { 149 | o.CreatedBy = v 150 | } 151 | 152 | // GetComment returns the Comment field value 153 | func (o *Silence) GetComment() string { 154 | if o == nil { 155 | var ret string 156 | return ret 157 | } 158 | 159 | return o.Comment 160 | } 161 | 162 | // GetCommentOk returns a tuple with the Comment field value 163 | // and a boolean to check if the value has been set. 164 | func (o *Silence) GetCommentOk() (*string, bool) { 165 | if o == nil { 166 | return nil, false 167 | } 168 | return &o.Comment, true 169 | } 170 | 171 | // SetComment sets field value 172 | func (o *Silence) SetComment(v string) { 173 | o.Comment = v 174 | } 175 | 176 | func (o Silence) MarshalJSON() ([]byte, error) { 177 | toSerialize,err := o.ToMap() 178 | if err != nil { 179 | return []byte{}, err 180 | } 181 | return json.Marshal(toSerialize) 182 | } 183 | 184 | func (o Silence) ToMap() (map[string]interface{}, error) { 185 | toSerialize := map[string]interface{}{} 186 | toSerialize["matchers"] = o.Matchers 187 | toSerialize["startsAt"] = o.StartsAt 188 | toSerialize["endsAt"] = o.EndsAt 189 | toSerialize["createdBy"] = o.CreatedBy 190 | toSerialize["comment"] = o.Comment 191 | return toSerialize, nil 192 | } 193 | 194 | func (o *Silence) UnmarshalJSON(data []byte) (err error) { 195 | // This validates that all required properties are included in the JSON object 196 | // by unmarshalling the object into a generic map with string keys and checking 197 | // that every required field exists as a key in the generic map. 198 | requiredProperties := []string{ 199 | "matchers", 200 | "startsAt", 201 | "endsAt", 202 | "createdBy", 203 | "comment", 204 | } 205 | 206 | allProperties := make(map[string]interface{}) 207 | 208 | err = json.Unmarshal(data, &allProperties) 209 | 210 | if err != nil { 211 | return err; 212 | } 213 | 214 | for _, requiredProperty := range(requiredProperties) { 215 | if _, exists := allProperties[requiredProperty]; !exists { 216 | return fmt.Errorf("no value given for required property %v", requiredProperty) 217 | } 218 | } 219 | 220 | varSilence := _Silence{} 221 | 222 | decoder := json.NewDecoder(bytes.NewReader(data)) 223 | decoder.DisallowUnknownFields() 224 | err = decoder.Decode(&varSilence) 225 | 226 | if err != nil { 227 | return err 228 | } 229 | 230 | *o = Silence(varSilence) 231 | 232 | return err 233 | } 234 | 235 | type NullableSilence struct { 236 | value *Silence 237 | isSet bool 238 | } 239 | 240 | func (v NullableSilence) Get() *Silence { 241 | return v.value 242 | } 243 | 244 | func (v *NullableSilence) Set(val *Silence) { 245 | v.value = val 246 | v.isSet = true 247 | } 248 | 249 | func (v NullableSilence) IsSet() bool { 250 | return v.isSet 251 | } 252 | 253 | func (v *NullableSilence) Unset() { 254 | v.value = nil 255 | v.isSet = false 256 | } 257 | 258 | func NewNullableSilence(val *Silence) *NullableSilence { 259 | return &NullableSilence{value: val, isSet: true} 260 | } 261 | 262 | func (v NullableSilence) MarshalJSON() ([]byte, error) { 263 | return json.Marshal(v.value) 264 | } 265 | 266 | func (v *NullableSilence) UnmarshalJSON(src []byte) error { 267 | v.isSet = true 268 | return json.Unmarshal(src, &v.value) 269 | } 270 | 271 | 272 | -------------------------------------------------------------------------------- /api/v1alpha1/zz_generated.deepcopy.go: -------------------------------------------------------------------------------- 1 | //go:build !ignore_autogenerated 2 | 3 | /* 4 | Copyright 2024. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | // Code generated by controller-gen. DO NOT EDIT. 20 | 21 | package v1alpha1 22 | 23 | import ( 24 | "k8s.io/apimachinery/pkg/apis/meta/v1" 25 | runtime "k8s.io/apimachinery/pkg/runtime" 26 | ) 27 | 28 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 29 | func (in *Alert) DeepCopyInto(out *Alert) { 30 | *out = *in 31 | out.TypeMeta = in.TypeMeta 32 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 33 | out.Spec = in.Spec 34 | in.Status.DeepCopyInto(&out.Status) 35 | } 36 | 37 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Alert. 38 | func (in *Alert) DeepCopy() *Alert { 39 | if in == nil { 40 | return nil 41 | } 42 | out := new(Alert) 43 | in.DeepCopyInto(out) 44 | return out 45 | } 46 | 47 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 48 | func (in *Alert) DeepCopyObject() runtime.Object { 49 | if c := in.DeepCopy(); c != nil { 50 | return c 51 | } 52 | return nil 53 | } 54 | 55 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 56 | func (in *AlertList) DeepCopyInto(out *AlertList) { 57 | *out = *in 58 | out.TypeMeta = in.TypeMeta 59 | in.ListMeta.DeepCopyInto(&out.ListMeta) 60 | if in.Items != nil { 61 | in, out := &in.Items, &out.Items 62 | *out = make([]Alert, len(*in)) 63 | for i := range *in { 64 | (*in)[i].DeepCopyInto(&(*out)[i]) 65 | } 66 | } 67 | } 68 | 69 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertList. 70 | func (in *AlertList) DeepCopy() *AlertList { 71 | if in == nil { 72 | return nil 73 | } 74 | out := new(AlertList) 75 | in.DeepCopyInto(out) 76 | return out 77 | } 78 | 79 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 80 | func (in *AlertList) DeepCopyObject() runtime.Object { 81 | if c := in.DeepCopy(); c != nil { 82 | return c 83 | } 84 | return nil 85 | } 86 | 87 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 88 | func (in *AlertSpec) DeepCopyInto(out *AlertSpec) { 89 | *out = *in 90 | } 91 | 92 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertSpec. 93 | func (in *AlertSpec) DeepCopy() *AlertSpec { 94 | if in == nil { 95 | return nil 96 | } 97 | out := new(AlertSpec) 98 | in.DeepCopyInto(out) 99 | return out 100 | } 101 | 102 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 103 | func (in *AlertStatus) DeepCopyInto(out *AlertStatus) { 104 | *out = *in 105 | if in.Annotations != nil { 106 | in, out := &in.Annotations, &out.Annotations 107 | *out = make(map[string]string, len(*in)) 108 | for key, val := range *in { 109 | (*out)[key] = val 110 | } 111 | } 112 | if in.Labels != nil { 113 | in, out := &in.Labels, &out.Labels 114 | *out = make(map[string]string, len(*in)) 115 | for key, val := range *in { 116 | (*out)[key] = val 117 | } 118 | } 119 | } 120 | 121 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AlertStatus. 122 | func (in *AlertStatus) DeepCopy() *AlertStatus { 123 | if in == nil { 124 | return nil 125 | } 126 | out := new(AlertStatus) 127 | in.DeepCopyInto(out) 128 | return out 129 | } 130 | 131 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 132 | func (in *Silence) DeepCopyInto(out *Silence) { 133 | *out = *in 134 | out.TypeMeta = in.TypeMeta 135 | in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) 136 | in.Spec.DeepCopyInto(&out.Spec) 137 | in.Status.DeepCopyInto(&out.Status) 138 | } 139 | 140 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Silence. 141 | func (in *Silence) DeepCopy() *Silence { 142 | if in == nil { 143 | return nil 144 | } 145 | out := new(Silence) 146 | in.DeepCopyInto(out) 147 | return out 148 | } 149 | 150 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 151 | func (in *Silence) DeepCopyObject() runtime.Object { 152 | if c := in.DeepCopy(); c != nil { 153 | return c 154 | } 155 | return nil 156 | } 157 | 158 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 159 | func (in *SilenceList) DeepCopyInto(out *SilenceList) { 160 | *out = *in 161 | out.TypeMeta = in.TypeMeta 162 | in.ListMeta.DeepCopyInto(&out.ListMeta) 163 | if in.Items != nil { 164 | in, out := &in.Items, &out.Items 165 | *out = make([]Silence, len(*in)) 166 | for i := range *in { 167 | (*in)[i].DeepCopyInto(&(*out)[i]) 168 | } 169 | } 170 | } 171 | 172 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SilenceList. 173 | func (in *SilenceList) DeepCopy() *SilenceList { 174 | if in == nil { 175 | return nil 176 | } 177 | out := new(SilenceList) 178 | in.DeepCopyInto(out) 179 | return out 180 | } 181 | 182 | // DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. 183 | func (in *SilenceList) DeepCopyObject() runtime.Object { 184 | if c := in.DeepCopy(); c != nil { 185 | return c 186 | } 187 | return nil 188 | } 189 | 190 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 191 | func (in *SilenceSpec) DeepCopyInto(out *SilenceSpec) { 192 | *out = *in 193 | if in.MatchLabels != nil { 194 | in, out := &in.MatchLabels, &out.MatchLabels 195 | *out = make(map[string]string, len(*in)) 196 | for key, val := range *in { 197 | (*out)[key] = val 198 | } 199 | } 200 | in.StartsAt.DeepCopyInto(&out.StartsAt) 201 | in.EndsAt.DeepCopyInto(&out.EndsAt) 202 | } 203 | 204 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SilenceSpec. 205 | func (in *SilenceSpec) DeepCopy() *SilenceSpec { 206 | if in == nil { 207 | return nil 208 | } 209 | out := new(SilenceSpec) 210 | in.DeepCopyInto(out) 211 | return out 212 | } 213 | 214 | // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. 215 | func (in *SilenceStatus) DeepCopyInto(out *SilenceStatus) { 216 | *out = *in 217 | if in.Conditions != nil { 218 | in, out := &in.Conditions, &out.Conditions 219 | *out = make([]v1.Condition, len(*in)) 220 | for i := range *in { 221 | (*in)[i].DeepCopyInto(&(*out)[i]) 222 | } 223 | } 224 | } 225 | 226 | // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SilenceStatus. 227 | func (in *SilenceStatus) DeepCopy() *SilenceStatus { 228 | if in == nil { 229 | return nil 230 | } 231 | out := new(SilenceStatus) 232 | in.DeepCopyInto(out) 233 | return out 234 | } 235 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_version_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "bytes" 16 | "fmt" 17 | ) 18 | 19 | // checks if the VersionInfo type satisfies the MappedNullable interface at compile time 20 | var _ MappedNullable = &VersionInfo{} 21 | 22 | // VersionInfo struct for VersionInfo 23 | type VersionInfo struct { 24 | Version string `json:"version"` 25 | Revision string `json:"revision"` 26 | Branch string `json:"branch"` 27 | BuildUser string `json:"buildUser"` 28 | BuildDate string `json:"buildDate"` 29 | GoVersion string `json:"goVersion"` 30 | } 31 | 32 | type _VersionInfo VersionInfo 33 | 34 | // NewVersionInfo instantiates a new VersionInfo object 35 | // This constructor will assign default values to properties that have it defined, 36 | // and makes sure properties required by API are set, but the set of arguments 37 | // will change when the set of required properties is changed 38 | func NewVersionInfo(version string, revision string, branch string, buildUser string, buildDate string, goVersion string) *VersionInfo { 39 | this := VersionInfo{} 40 | this.Version = version 41 | this.Revision = revision 42 | this.Branch = branch 43 | this.BuildUser = buildUser 44 | this.BuildDate = buildDate 45 | this.GoVersion = goVersion 46 | return &this 47 | } 48 | 49 | // NewVersionInfoWithDefaults instantiates a new VersionInfo object 50 | // This constructor will only assign default values to properties that have it defined, 51 | // but it doesn't guarantee that properties required by API are set 52 | func NewVersionInfoWithDefaults() *VersionInfo { 53 | this := VersionInfo{} 54 | return &this 55 | } 56 | 57 | // GetVersion returns the Version field value 58 | func (o *VersionInfo) GetVersion() string { 59 | if o == nil { 60 | var ret string 61 | return ret 62 | } 63 | 64 | return o.Version 65 | } 66 | 67 | // GetVersionOk returns a tuple with the Version field value 68 | // and a boolean to check if the value has been set. 69 | func (o *VersionInfo) GetVersionOk() (*string, bool) { 70 | if o == nil { 71 | return nil, false 72 | } 73 | return &o.Version, true 74 | } 75 | 76 | // SetVersion sets field value 77 | func (o *VersionInfo) SetVersion(v string) { 78 | o.Version = v 79 | } 80 | 81 | // GetRevision returns the Revision field value 82 | func (o *VersionInfo) GetRevision() string { 83 | if o == nil { 84 | var ret string 85 | return ret 86 | } 87 | 88 | return o.Revision 89 | } 90 | 91 | // GetRevisionOk returns a tuple with the Revision field value 92 | // and a boolean to check if the value has been set. 93 | func (o *VersionInfo) GetRevisionOk() (*string, bool) { 94 | if o == nil { 95 | return nil, false 96 | } 97 | return &o.Revision, true 98 | } 99 | 100 | // SetRevision sets field value 101 | func (o *VersionInfo) SetRevision(v string) { 102 | o.Revision = v 103 | } 104 | 105 | // GetBranch returns the Branch field value 106 | func (o *VersionInfo) GetBranch() string { 107 | if o == nil { 108 | var ret string 109 | return ret 110 | } 111 | 112 | return o.Branch 113 | } 114 | 115 | // GetBranchOk returns a tuple with the Branch field value 116 | // and a boolean to check if the value has been set. 117 | func (o *VersionInfo) GetBranchOk() (*string, bool) { 118 | if o == nil { 119 | return nil, false 120 | } 121 | return &o.Branch, true 122 | } 123 | 124 | // SetBranch sets field value 125 | func (o *VersionInfo) SetBranch(v string) { 126 | o.Branch = v 127 | } 128 | 129 | // GetBuildUser returns the BuildUser field value 130 | func (o *VersionInfo) GetBuildUser() string { 131 | if o == nil { 132 | var ret string 133 | return ret 134 | } 135 | 136 | return o.BuildUser 137 | } 138 | 139 | // GetBuildUserOk returns a tuple with the BuildUser field value 140 | // and a boolean to check if the value has been set. 141 | func (o *VersionInfo) GetBuildUserOk() (*string, bool) { 142 | if o == nil { 143 | return nil, false 144 | } 145 | return &o.BuildUser, true 146 | } 147 | 148 | // SetBuildUser sets field value 149 | func (o *VersionInfo) SetBuildUser(v string) { 150 | o.BuildUser = v 151 | } 152 | 153 | // GetBuildDate returns the BuildDate field value 154 | func (o *VersionInfo) GetBuildDate() string { 155 | if o == nil { 156 | var ret string 157 | return ret 158 | } 159 | 160 | return o.BuildDate 161 | } 162 | 163 | // GetBuildDateOk returns a tuple with the BuildDate field value 164 | // and a boolean to check if the value has been set. 165 | func (o *VersionInfo) GetBuildDateOk() (*string, bool) { 166 | if o == nil { 167 | return nil, false 168 | } 169 | return &o.BuildDate, true 170 | } 171 | 172 | // SetBuildDate sets field value 173 | func (o *VersionInfo) SetBuildDate(v string) { 174 | o.BuildDate = v 175 | } 176 | 177 | // GetGoVersion returns the GoVersion field value 178 | func (o *VersionInfo) GetGoVersion() string { 179 | if o == nil { 180 | var ret string 181 | return ret 182 | } 183 | 184 | return o.GoVersion 185 | } 186 | 187 | // GetGoVersionOk returns a tuple with the GoVersion field value 188 | // and a boolean to check if the value has been set. 189 | func (o *VersionInfo) GetGoVersionOk() (*string, bool) { 190 | if o == nil { 191 | return nil, false 192 | } 193 | return &o.GoVersion, true 194 | } 195 | 196 | // SetGoVersion sets field value 197 | func (o *VersionInfo) SetGoVersion(v string) { 198 | o.GoVersion = v 199 | } 200 | 201 | func (o VersionInfo) MarshalJSON() ([]byte, error) { 202 | toSerialize,err := o.ToMap() 203 | if err != nil { 204 | return []byte{}, err 205 | } 206 | return json.Marshal(toSerialize) 207 | } 208 | 209 | func (o VersionInfo) ToMap() (map[string]interface{}, error) { 210 | toSerialize := map[string]interface{}{} 211 | toSerialize["version"] = o.Version 212 | toSerialize["revision"] = o.Revision 213 | toSerialize["branch"] = o.Branch 214 | toSerialize["buildUser"] = o.BuildUser 215 | toSerialize["buildDate"] = o.BuildDate 216 | toSerialize["goVersion"] = o.GoVersion 217 | return toSerialize, nil 218 | } 219 | 220 | func (o *VersionInfo) UnmarshalJSON(data []byte) (err error) { 221 | // This validates that all required properties are included in the JSON object 222 | // by unmarshalling the object into a generic map with string keys and checking 223 | // that every required field exists as a key in the generic map. 224 | requiredProperties := []string{ 225 | "version", 226 | "revision", 227 | "branch", 228 | "buildUser", 229 | "buildDate", 230 | "goVersion", 231 | } 232 | 233 | allProperties := make(map[string]interface{}) 234 | 235 | err = json.Unmarshal(data, &allProperties) 236 | 237 | if err != nil { 238 | return err; 239 | } 240 | 241 | for _, requiredProperty := range(requiredProperties) { 242 | if _, exists := allProperties[requiredProperty]; !exists { 243 | return fmt.Errorf("no value given for required property %v", requiredProperty) 244 | } 245 | } 246 | 247 | varVersionInfo := _VersionInfo{} 248 | 249 | decoder := json.NewDecoder(bytes.NewReader(data)) 250 | decoder.DisallowUnknownFields() 251 | err = decoder.Decode(&varVersionInfo) 252 | 253 | if err != nil { 254 | return err 255 | } 256 | 257 | *o = VersionInfo(varVersionInfo) 258 | 259 | return err 260 | } 261 | 262 | type NullableVersionInfo struct { 263 | value *VersionInfo 264 | isSet bool 265 | } 266 | 267 | func (v NullableVersionInfo) Get() *VersionInfo { 268 | return v.value 269 | } 270 | 271 | func (v *NullableVersionInfo) Set(val *VersionInfo) { 272 | v.value = val 273 | v.isSet = true 274 | } 275 | 276 | func (v NullableVersionInfo) IsSet() bool { 277 | return v.isSet 278 | } 279 | 280 | func (v *NullableVersionInfo) Unset() { 281 | v.value = nil 282 | v.isSet = false 283 | } 284 | 285 | func NewNullableVersionInfo(val *VersionInfo) *NullableVersionInfo { 286 | return &NullableVersionInfo{value: val, isSet: true} 287 | } 288 | 289 | func (v NullableVersionInfo) MarshalJSON() ([]byte, error) { 290 | return json.Marshal(v.value) 291 | } 292 | 293 | func (v *NullableVersionInfo) UnmarshalJSON(src []byte) error { 294 | v.isSet = true 295 | return json.Unmarshal(src, &v.value) 296 | } 297 | 298 | 299 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/utils.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "reflect" 16 | "time" 17 | ) 18 | 19 | // PtrBool is a helper routine that returns a pointer to given boolean value. 20 | func PtrBool(v bool) *bool { return &v } 21 | 22 | // PtrInt is a helper routine that returns a pointer to given integer value. 23 | func PtrInt(v int) *int { return &v } 24 | 25 | // PtrInt32 is a helper routine that returns a pointer to given integer value. 26 | func PtrInt32(v int32) *int32 { return &v } 27 | 28 | // PtrInt64 is a helper routine that returns a pointer to given integer value. 29 | func PtrInt64(v int64) *int64 { return &v } 30 | 31 | // PtrFloat32 is a helper routine that returns a pointer to given float value. 32 | func PtrFloat32(v float32) *float32 { return &v } 33 | 34 | // PtrFloat64 is a helper routine that returns a pointer to given float value. 35 | func PtrFloat64(v float64) *float64 { return &v } 36 | 37 | // PtrString is a helper routine that returns a pointer to given string value. 38 | func PtrString(v string) *string { return &v } 39 | 40 | // PtrTime is helper routine that returns a pointer to given Time value. 41 | func PtrTime(v time.Time) *time.Time { return &v } 42 | 43 | type NullableBool struct { 44 | value *bool 45 | isSet bool 46 | } 47 | 48 | func (v NullableBool) Get() *bool { 49 | return v.value 50 | } 51 | 52 | func (v *NullableBool) Set(val *bool) { 53 | v.value = val 54 | v.isSet = true 55 | } 56 | 57 | func (v NullableBool) IsSet() bool { 58 | return v.isSet 59 | } 60 | 61 | func (v *NullableBool) Unset() { 62 | v.value = nil 63 | v.isSet = false 64 | } 65 | 66 | func NewNullableBool(val *bool) *NullableBool { 67 | return &NullableBool{value: val, isSet: true} 68 | } 69 | 70 | func (v NullableBool) MarshalJSON() ([]byte, error) { 71 | return json.Marshal(v.value) 72 | } 73 | 74 | func (v *NullableBool) UnmarshalJSON(src []byte) error { 75 | v.isSet = true 76 | return json.Unmarshal(src, &v.value) 77 | } 78 | 79 | type NullableInt struct { 80 | value *int 81 | isSet bool 82 | } 83 | 84 | func (v NullableInt) Get() *int { 85 | return v.value 86 | } 87 | 88 | func (v *NullableInt) Set(val *int) { 89 | v.value = val 90 | v.isSet = true 91 | } 92 | 93 | func (v NullableInt) IsSet() bool { 94 | return v.isSet 95 | } 96 | 97 | func (v *NullableInt) Unset() { 98 | v.value = nil 99 | v.isSet = false 100 | } 101 | 102 | func NewNullableInt(val *int) *NullableInt { 103 | return &NullableInt{value: val, isSet: true} 104 | } 105 | 106 | func (v NullableInt) MarshalJSON() ([]byte, error) { 107 | return json.Marshal(v.value) 108 | } 109 | 110 | func (v *NullableInt) UnmarshalJSON(src []byte) error { 111 | v.isSet = true 112 | return json.Unmarshal(src, &v.value) 113 | } 114 | 115 | type NullableInt32 struct { 116 | value *int32 117 | isSet bool 118 | } 119 | 120 | func (v NullableInt32) Get() *int32 { 121 | return v.value 122 | } 123 | 124 | func (v *NullableInt32) Set(val *int32) { 125 | v.value = val 126 | v.isSet = true 127 | } 128 | 129 | func (v NullableInt32) IsSet() bool { 130 | return v.isSet 131 | } 132 | 133 | func (v *NullableInt32) Unset() { 134 | v.value = nil 135 | v.isSet = false 136 | } 137 | 138 | func NewNullableInt32(val *int32) *NullableInt32 { 139 | return &NullableInt32{value: val, isSet: true} 140 | } 141 | 142 | func (v NullableInt32) MarshalJSON() ([]byte, error) { 143 | return json.Marshal(v.value) 144 | } 145 | 146 | func (v *NullableInt32) UnmarshalJSON(src []byte) error { 147 | v.isSet = true 148 | return json.Unmarshal(src, &v.value) 149 | } 150 | 151 | type NullableInt64 struct { 152 | value *int64 153 | isSet bool 154 | } 155 | 156 | func (v NullableInt64) Get() *int64 { 157 | return v.value 158 | } 159 | 160 | func (v *NullableInt64) Set(val *int64) { 161 | v.value = val 162 | v.isSet = true 163 | } 164 | 165 | func (v NullableInt64) IsSet() bool { 166 | return v.isSet 167 | } 168 | 169 | func (v *NullableInt64) Unset() { 170 | v.value = nil 171 | v.isSet = false 172 | } 173 | 174 | func NewNullableInt64(val *int64) *NullableInt64 { 175 | return &NullableInt64{value: val, isSet: true} 176 | } 177 | 178 | func (v NullableInt64) MarshalJSON() ([]byte, error) { 179 | return json.Marshal(v.value) 180 | } 181 | 182 | func (v *NullableInt64) UnmarshalJSON(src []byte) error { 183 | v.isSet = true 184 | return json.Unmarshal(src, &v.value) 185 | } 186 | 187 | type NullableFloat32 struct { 188 | value *float32 189 | isSet bool 190 | } 191 | 192 | func (v NullableFloat32) Get() *float32 { 193 | return v.value 194 | } 195 | 196 | func (v *NullableFloat32) Set(val *float32) { 197 | v.value = val 198 | v.isSet = true 199 | } 200 | 201 | func (v NullableFloat32) IsSet() bool { 202 | return v.isSet 203 | } 204 | 205 | func (v *NullableFloat32) Unset() { 206 | v.value = nil 207 | v.isSet = false 208 | } 209 | 210 | func NewNullableFloat32(val *float32) *NullableFloat32 { 211 | return &NullableFloat32{value: val, isSet: true} 212 | } 213 | 214 | func (v NullableFloat32) MarshalJSON() ([]byte, error) { 215 | return json.Marshal(v.value) 216 | } 217 | 218 | func (v *NullableFloat32) UnmarshalJSON(src []byte) error { 219 | v.isSet = true 220 | return json.Unmarshal(src, &v.value) 221 | } 222 | 223 | type NullableFloat64 struct { 224 | value *float64 225 | isSet bool 226 | } 227 | 228 | func (v NullableFloat64) Get() *float64 { 229 | return v.value 230 | } 231 | 232 | func (v *NullableFloat64) Set(val *float64) { 233 | v.value = val 234 | v.isSet = true 235 | } 236 | 237 | func (v NullableFloat64) IsSet() bool { 238 | return v.isSet 239 | } 240 | 241 | func (v *NullableFloat64) Unset() { 242 | v.value = nil 243 | v.isSet = false 244 | } 245 | 246 | func NewNullableFloat64(val *float64) *NullableFloat64 { 247 | return &NullableFloat64{value: val, isSet: true} 248 | } 249 | 250 | func (v NullableFloat64) MarshalJSON() ([]byte, error) { 251 | return json.Marshal(v.value) 252 | } 253 | 254 | func (v *NullableFloat64) UnmarshalJSON(src []byte) error { 255 | v.isSet = true 256 | return json.Unmarshal(src, &v.value) 257 | } 258 | 259 | type NullableString struct { 260 | value *string 261 | isSet bool 262 | } 263 | 264 | func (v NullableString) Get() *string { 265 | return v.value 266 | } 267 | 268 | func (v *NullableString) Set(val *string) { 269 | v.value = val 270 | v.isSet = true 271 | } 272 | 273 | func (v NullableString) IsSet() bool { 274 | return v.isSet 275 | } 276 | 277 | func (v *NullableString) Unset() { 278 | v.value = nil 279 | v.isSet = false 280 | } 281 | 282 | func NewNullableString(val *string) *NullableString { 283 | return &NullableString{value: val, isSet: true} 284 | } 285 | 286 | func (v NullableString) MarshalJSON() ([]byte, error) { 287 | return json.Marshal(v.value) 288 | } 289 | 290 | func (v *NullableString) UnmarshalJSON(src []byte) error { 291 | v.isSet = true 292 | return json.Unmarshal(src, &v.value) 293 | } 294 | 295 | type NullableTime struct { 296 | value *time.Time 297 | isSet bool 298 | } 299 | 300 | func (v NullableTime) Get() *time.Time { 301 | return v.value 302 | } 303 | 304 | func (v *NullableTime) Set(val *time.Time) { 305 | v.value = val 306 | v.isSet = true 307 | } 308 | 309 | func (v NullableTime) IsSet() bool { 310 | return v.isSet 311 | } 312 | 313 | func (v *NullableTime) Unset() { 314 | v.value = nil 315 | v.isSet = false 316 | } 317 | 318 | func NewNullableTime(val *time.Time) *NullableTime { 319 | return &NullableTime{value: val, isSet: true} 320 | } 321 | 322 | func (v NullableTime) MarshalJSON() ([]byte, error) { 323 | return json.Marshal(v.value) 324 | } 325 | 326 | func (v *NullableTime) UnmarshalJSON(src []byte) error { 327 | v.isSet = true 328 | return json.Unmarshal(src, &v.value) 329 | } 330 | 331 | // IsNil checks if an input is nil 332 | func IsNil(i interface{}) bool { 333 | if i == nil { 334 | return true 335 | } 336 | switch reflect.TypeOf(i).Kind() { 337 | case reflect.Chan, reflect.Func, reflect.Map, reflect.Ptr, reflect.UnsafePointer, reflect.Interface, reflect.Slice: 338 | return reflect.ValueOf(i).IsNil() 339 | case reflect.Array: 340 | return reflect.ValueOf(i).IsZero() 341 | } 342 | return false 343 | } 344 | 345 | type MappedNullable interface { 346 | ToMap() (map[string]interface{}, error) 347 | } 348 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_postable_silence.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "time" 16 | "bytes" 17 | "fmt" 18 | ) 19 | 20 | // checks if the PostableSilence type satisfies the MappedNullable interface at compile time 21 | var _ MappedNullable = &PostableSilence{} 22 | 23 | // PostableSilence struct for PostableSilence 24 | type PostableSilence struct { 25 | Matchers []Matcher `json:"matchers"` 26 | StartsAt time.Time `json:"startsAt"` 27 | EndsAt time.Time `json:"endsAt"` 28 | CreatedBy string `json:"createdBy"` 29 | Comment string `json:"comment"` 30 | Id *string `json:"id,omitempty"` 31 | } 32 | 33 | type _PostableSilence PostableSilence 34 | 35 | // NewPostableSilence instantiates a new PostableSilence object 36 | // This constructor will assign default values to properties that have it defined, 37 | // and makes sure properties required by API are set, but the set of arguments 38 | // will change when the set of required properties is changed 39 | func NewPostableSilence(matchers []Matcher, startsAt time.Time, endsAt time.Time, createdBy string, comment string) *PostableSilence { 40 | this := PostableSilence{} 41 | this.Matchers = matchers 42 | this.StartsAt = startsAt 43 | this.EndsAt = endsAt 44 | this.CreatedBy = createdBy 45 | this.Comment = comment 46 | return &this 47 | } 48 | 49 | // NewPostableSilenceWithDefaults instantiates a new PostableSilence object 50 | // This constructor will only assign default values to properties that have it defined, 51 | // but it doesn't guarantee that properties required by API are set 52 | func NewPostableSilenceWithDefaults() *PostableSilence { 53 | this := PostableSilence{} 54 | return &this 55 | } 56 | 57 | // GetMatchers returns the Matchers field value 58 | func (o *PostableSilence) GetMatchers() []Matcher { 59 | if o == nil { 60 | var ret []Matcher 61 | return ret 62 | } 63 | 64 | return o.Matchers 65 | } 66 | 67 | // GetMatchersOk returns a tuple with the Matchers field value 68 | // and a boolean to check if the value has been set. 69 | func (o *PostableSilence) GetMatchersOk() ([]Matcher, bool) { 70 | if o == nil { 71 | return nil, false 72 | } 73 | return o.Matchers, true 74 | } 75 | 76 | // SetMatchers sets field value 77 | func (o *PostableSilence) SetMatchers(v []Matcher) { 78 | o.Matchers = v 79 | } 80 | 81 | // GetStartsAt returns the StartsAt field value 82 | func (o *PostableSilence) GetStartsAt() time.Time { 83 | if o == nil { 84 | var ret time.Time 85 | return ret 86 | } 87 | 88 | return o.StartsAt 89 | } 90 | 91 | // GetStartsAtOk returns a tuple with the StartsAt field value 92 | // and a boolean to check if the value has been set. 93 | func (o *PostableSilence) GetStartsAtOk() (*time.Time, bool) { 94 | if o == nil { 95 | return nil, false 96 | } 97 | return &o.StartsAt, true 98 | } 99 | 100 | // SetStartsAt sets field value 101 | func (o *PostableSilence) SetStartsAt(v time.Time) { 102 | o.StartsAt = v 103 | } 104 | 105 | // GetEndsAt returns the EndsAt field value 106 | func (o *PostableSilence) GetEndsAt() time.Time { 107 | if o == nil { 108 | var ret time.Time 109 | return ret 110 | } 111 | 112 | return o.EndsAt 113 | } 114 | 115 | // GetEndsAtOk returns a tuple with the EndsAt field value 116 | // and a boolean to check if the value has been set. 117 | func (o *PostableSilence) GetEndsAtOk() (*time.Time, bool) { 118 | if o == nil { 119 | return nil, false 120 | } 121 | return &o.EndsAt, true 122 | } 123 | 124 | // SetEndsAt sets field value 125 | func (o *PostableSilence) SetEndsAt(v time.Time) { 126 | o.EndsAt = v 127 | } 128 | 129 | // GetCreatedBy returns the CreatedBy field value 130 | func (o *PostableSilence) GetCreatedBy() string { 131 | if o == nil { 132 | var ret string 133 | return ret 134 | } 135 | 136 | return o.CreatedBy 137 | } 138 | 139 | // GetCreatedByOk returns a tuple with the CreatedBy field value 140 | // and a boolean to check if the value has been set. 141 | func (o *PostableSilence) GetCreatedByOk() (*string, bool) { 142 | if o == nil { 143 | return nil, false 144 | } 145 | return &o.CreatedBy, true 146 | } 147 | 148 | // SetCreatedBy sets field value 149 | func (o *PostableSilence) SetCreatedBy(v string) { 150 | o.CreatedBy = v 151 | } 152 | 153 | // GetComment returns the Comment field value 154 | func (o *PostableSilence) GetComment() string { 155 | if o == nil { 156 | var ret string 157 | return ret 158 | } 159 | 160 | return o.Comment 161 | } 162 | 163 | // GetCommentOk returns a tuple with the Comment field value 164 | // and a boolean to check if the value has been set. 165 | func (o *PostableSilence) GetCommentOk() (*string, bool) { 166 | if o == nil { 167 | return nil, false 168 | } 169 | return &o.Comment, true 170 | } 171 | 172 | // SetComment sets field value 173 | func (o *PostableSilence) SetComment(v string) { 174 | o.Comment = v 175 | } 176 | 177 | // GetId returns the Id field value if set, zero value otherwise. 178 | func (o *PostableSilence) GetId() string { 179 | if o == nil || IsNil(o.Id) { 180 | var ret string 181 | return ret 182 | } 183 | return *o.Id 184 | } 185 | 186 | // GetIdOk returns a tuple with the Id field value if set, nil otherwise 187 | // and a boolean to check if the value has been set. 188 | func (o *PostableSilence) GetIdOk() (*string, bool) { 189 | if o == nil || IsNil(o.Id) { 190 | return nil, false 191 | } 192 | return o.Id, true 193 | } 194 | 195 | // HasId returns a boolean if a field has been set. 196 | func (o *PostableSilence) HasId() bool { 197 | if o != nil && !IsNil(o.Id) { 198 | return true 199 | } 200 | 201 | return false 202 | } 203 | 204 | // SetId gets a reference to the given string and assigns it to the Id field. 205 | func (o *PostableSilence) SetId(v string) { 206 | o.Id = &v 207 | } 208 | 209 | func (o PostableSilence) MarshalJSON() ([]byte, error) { 210 | toSerialize,err := o.ToMap() 211 | if err != nil { 212 | return []byte{}, err 213 | } 214 | return json.Marshal(toSerialize) 215 | } 216 | 217 | func (o PostableSilence) ToMap() (map[string]interface{}, error) { 218 | toSerialize := map[string]interface{}{} 219 | toSerialize["matchers"] = o.Matchers 220 | toSerialize["startsAt"] = o.StartsAt 221 | toSerialize["endsAt"] = o.EndsAt 222 | toSerialize["createdBy"] = o.CreatedBy 223 | toSerialize["comment"] = o.Comment 224 | if !IsNil(o.Id) { 225 | toSerialize["id"] = o.Id 226 | } 227 | return toSerialize, nil 228 | } 229 | 230 | func (o *PostableSilence) UnmarshalJSON(data []byte) (err error) { 231 | // This validates that all required properties are included in the JSON object 232 | // by unmarshalling the object into a generic map with string keys and checking 233 | // that every required field exists as a key in the generic map. 234 | requiredProperties := []string{ 235 | "matchers", 236 | "startsAt", 237 | "endsAt", 238 | "createdBy", 239 | "comment", 240 | } 241 | 242 | allProperties := make(map[string]interface{}) 243 | 244 | err = json.Unmarshal(data, &allProperties) 245 | 246 | if err != nil { 247 | return err; 248 | } 249 | 250 | for _, requiredProperty := range(requiredProperties) { 251 | if _, exists := allProperties[requiredProperty]; !exists { 252 | return fmt.Errorf("no value given for required property %v", requiredProperty) 253 | } 254 | } 255 | 256 | varPostableSilence := _PostableSilence{} 257 | 258 | decoder := json.NewDecoder(bytes.NewReader(data)) 259 | decoder.DisallowUnknownFields() 260 | err = decoder.Decode(&varPostableSilence) 261 | 262 | if err != nil { 263 | return err 264 | } 265 | 266 | *o = PostableSilence(varPostableSilence) 267 | 268 | return err 269 | } 270 | 271 | type NullablePostableSilence struct { 272 | value *PostableSilence 273 | isSet bool 274 | } 275 | 276 | func (v NullablePostableSilence) Get() *PostableSilence { 277 | return v.value 278 | } 279 | 280 | func (v *NullablePostableSilence) Set(val *PostableSilence) { 281 | v.value = val 282 | v.isSet = true 283 | } 284 | 285 | func (v NullablePostableSilence) IsSet() bool { 286 | return v.isSet 287 | } 288 | 289 | func (v *NullablePostableSilence) Unset() { 290 | v.value = nil 291 | v.isSet = false 292 | } 293 | 294 | func NewNullablePostableSilence(val *PostableSilence) *NullablePostableSilence { 295 | return &NullablePostableSilence{value: val, isSet: true} 296 | } 297 | 298 | func (v NullablePostableSilence) MarshalJSON() ([]byte, error) { 299 | return json.Marshal(v.value) 300 | } 301 | 302 | func (v *NullablePostableSilence) UnmarshalJSON(src []byte) error { 303 | v.isSet = true 304 | return json.Unmarshal(src, &v.value) 305 | } 306 | 307 | 308 | -------------------------------------------------------------------------------- /internal/alertmanagerapi/model_postable_alert.go: -------------------------------------------------------------------------------- 1 | /* 2 | Alertmanager API 3 | 4 | API of the Prometheus Alertmanager (https://github.com/prometheus/alertmanager) 5 | 6 | API version: 0.0.1 7 | */ 8 | 9 | // Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. 10 | 11 | package alertmanagerapi 12 | 13 | import ( 14 | "encoding/json" 15 | "time" 16 | "bytes" 17 | "fmt" 18 | ) 19 | 20 | // checks if the PostableAlert type satisfies the MappedNullable interface at compile time 21 | var _ MappedNullable = &PostableAlert{} 22 | 23 | // PostableAlert struct for PostableAlert 24 | type PostableAlert struct { 25 | Labels map[string]string `json:"labels"` 26 | GeneratorURL *string `json:"generatorURL,omitempty"` 27 | StartsAt *time.Time `json:"startsAt,omitempty"` 28 | EndsAt *time.Time `json:"endsAt,omitempty"` 29 | Annotations *map[string]string `json:"annotations,omitempty"` 30 | } 31 | 32 | type _PostableAlert PostableAlert 33 | 34 | // NewPostableAlert instantiates a new PostableAlert object 35 | // This constructor will assign default values to properties that have it defined, 36 | // and makes sure properties required by API are set, but the set of arguments 37 | // will change when the set of required properties is changed 38 | func NewPostableAlert(labels map[string]string) *PostableAlert { 39 | this := PostableAlert{} 40 | this.Labels = labels 41 | return &this 42 | } 43 | 44 | // NewPostableAlertWithDefaults instantiates a new PostableAlert object 45 | // This constructor will only assign default values to properties that have it defined, 46 | // but it doesn't guarantee that properties required by API are set 47 | func NewPostableAlertWithDefaults() *PostableAlert { 48 | this := PostableAlert{} 49 | return &this 50 | } 51 | 52 | // GetLabels returns the Labels field value 53 | func (o *PostableAlert) GetLabels() map[string]string { 54 | if o == nil { 55 | var ret map[string]string 56 | return ret 57 | } 58 | 59 | return o.Labels 60 | } 61 | 62 | // GetLabelsOk returns a tuple with the Labels field value 63 | // and a boolean to check if the value has been set. 64 | func (o *PostableAlert) GetLabelsOk() (*map[string]string, bool) { 65 | if o == nil { 66 | return nil, false 67 | } 68 | return &o.Labels, true 69 | } 70 | 71 | // SetLabels sets field value 72 | func (o *PostableAlert) SetLabels(v map[string]string) { 73 | o.Labels = v 74 | } 75 | 76 | // GetGeneratorURL returns the GeneratorURL field value if set, zero value otherwise. 77 | func (o *PostableAlert) GetGeneratorURL() string { 78 | if o == nil || IsNil(o.GeneratorURL) { 79 | var ret string 80 | return ret 81 | } 82 | return *o.GeneratorURL 83 | } 84 | 85 | // GetGeneratorURLOk returns a tuple with the GeneratorURL field value if set, nil otherwise 86 | // and a boolean to check if the value has been set. 87 | func (o *PostableAlert) GetGeneratorURLOk() (*string, bool) { 88 | if o == nil || IsNil(o.GeneratorURL) { 89 | return nil, false 90 | } 91 | return o.GeneratorURL, true 92 | } 93 | 94 | // HasGeneratorURL returns a boolean if a field has been set. 95 | func (o *PostableAlert) HasGeneratorURL() bool { 96 | if o != nil && !IsNil(o.GeneratorURL) { 97 | return true 98 | } 99 | 100 | return false 101 | } 102 | 103 | // SetGeneratorURL gets a reference to the given string and assigns it to the GeneratorURL field. 104 | func (o *PostableAlert) SetGeneratorURL(v string) { 105 | o.GeneratorURL = &v 106 | } 107 | 108 | // GetStartsAt returns the StartsAt field value if set, zero value otherwise. 109 | func (o *PostableAlert) GetStartsAt() time.Time { 110 | if o == nil || IsNil(o.StartsAt) { 111 | var ret time.Time 112 | return ret 113 | } 114 | return *o.StartsAt 115 | } 116 | 117 | // GetStartsAtOk returns a tuple with the StartsAt field value if set, nil otherwise 118 | // and a boolean to check if the value has been set. 119 | func (o *PostableAlert) GetStartsAtOk() (*time.Time, bool) { 120 | if o == nil || IsNil(o.StartsAt) { 121 | return nil, false 122 | } 123 | return o.StartsAt, true 124 | } 125 | 126 | // HasStartsAt returns a boolean if a field has been set. 127 | func (o *PostableAlert) HasStartsAt() bool { 128 | if o != nil && !IsNil(o.StartsAt) { 129 | return true 130 | } 131 | 132 | return false 133 | } 134 | 135 | // SetStartsAt gets a reference to the given time.Time and assigns it to the StartsAt field. 136 | func (o *PostableAlert) SetStartsAt(v time.Time) { 137 | o.StartsAt = &v 138 | } 139 | 140 | // GetEndsAt returns the EndsAt field value if set, zero value otherwise. 141 | func (o *PostableAlert) GetEndsAt() time.Time { 142 | if o == nil || IsNil(o.EndsAt) { 143 | var ret time.Time 144 | return ret 145 | } 146 | return *o.EndsAt 147 | } 148 | 149 | // GetEndsAtOk returns a tuple with the EndsAt field value if set, nil otherwise 150 | // and a boolean to check if the value has been set. 151 | func (o *PostableAlert) GetEndsAtOk() (*time.Time, bool) { 152 | if o == nil || IsNil(o.EndsAt) { 153 | return nil, false 154 | } 155 | return o.EndsAt, true 156 | } 157 | 158 | // HasEndsAt returns a boolean if a field has been set. 159 | func (o *PostableAlert) HasEndsAt() bool { 160 | if o != nil && !IsNil(o.EndsAt) { 161 | return true 162 | } 163 | 164 | return false 165 | } 166 | 167 | // SetEndsAt gets a reference to the given time.Time and assigns it to the EndsAt field. 168 | func (o *PostableAlert) SetEndsAt(v time.Time) { 169 | o.EndsAt = &v 170 | } 171 | 172 | // GetAnnotations returns the Annotations field value if set, zero value otherwise. 173 | func (o *PostableAlert) GetAnnotations() map[string]string { 174 | if o == nil || IsNil(o.Annotations) { 175 | var ret map[string]string 176 | return ret 177 | } 178 | return *o.Annotations 179 | } 180 | 181 | // GetAnnotationsOk returns a tuple with the Annotations field value if set, nil otherwise 182 | // and a boolean to check if the value has been set. 183 | func (o *PostableAlert) GetAnnotationsOk() (*map[string]string, bool) { 184 | if o == nil || IsNil(o.Annotations) { 185 | return nil, false 186 | } 187 | return o.Annotations, true 188 | } 189 | 190 | // HasAnnotations returns a boolean if a field has been set. 191 | func (o *PostableAlert) HasAnnotations() bool { 192 | if o != nil && !IsNil(o.Annotations) { 193 | return true 194 | } 195 | 196 | return false 197 | } 198 | 199 | // SetAnnotations gets a reference to the given map[string]string and assigns it to the Annotations field. 200 | func (o *PostableAlert) SetAnnotations(v map[string]string) { 201 | o.Annotations = &v 202 | } 203 | 204 | func (o PostableAlert) MarshalJSON() ([]byte, error) { 205 | toSerialize,err := o.ToMap() 206 | if err != nil { 207 | return []byte{}, err 208 | } 209 | return json.Marshal(toSerialize) 210 | } 211 | 212 | func (o PostableAlert) ToMap() (map[string]interface{}, error) { 213 | toSerialize := map[string]interface{}{} 214 | toSerialize["labels"] = o.Labels 215 | if !IsNil(o.GeneratorURL) { 216 | toSerialize["generatorURL"] = o.GeneratorURL 217 | } 218 | if !IsNil(o.StartsAt) { 219 | toSerialize["startsAt"] = o.StartsAt 220 | } 221 | if !IsNil(o.EndsAt) { 222 | toSerialize["endsAt"] = o.EndsAt 223 | } 224 | if !IsNil(o.Annotations) { 225 | toSerialize["annotations"] = o.Annotations 226 | } 227 | return toSerialize, nil 228 | } 229 | 230 | func (o *PostableAlert) UnmarshalJSON(data []byte) (err error) { 231 | // This validates that all required properties are included in the JSON object 232 | // by unmarshalling the object into a generic map with string keys and checking 233 | // that every required field exists as a key in the generic map. 234 | requiredProperties := []string{ 235 | "labels", 236 | } 237 | 238 | allProperties := make(map[string]interface{}) 239 | 240 | err = json.Unmarshal(data, &allProperties) 241 | 242 | if err != nil { 243 | return err; 244 | } 245 | 246 | for _, requiredProperty := range(requiredProperties) { 247 | if _, exists := allProperties[requiredProperty]; !exists { 248 | return fmt.Errorf("no value given for required property %v", requiredProperty) 249 | } 250 | } 251 | 252 | varPostableAlert := _PostableAlert{} 253 | 254 | decoder := json.NewDecoder(bytes.NewReader(data)) 255 | decoder.DisallowUnknownFields() 256 | err = decoder.Decode(&varPostableAlert) 257 | 258 | if err != nil { 259 | return err 260 | } 261 | 262 | *o = PostableAlert(varPostableAlert) 263 | 264 | return err 265 | } 266 | 267 | type NullablePostableAlert struct { 268 | value *PostableAlert 269 | isSet bool 270 | } 271 | 272 | func (v NullablePostableAlert) Get() *PostableAlert { 273 | return v.value 274 | } 275 | 276 | func (v *NullablePostableAlert) Set(val *PostableAlert) { 277 | v.value = val 278 | v.isSet = true 279 | } 280 | 281 | func (v NullablePostableAlert) IsSet() bool { 282 | return v.isSet 283 | } 284 | 285 | func (v *NullablePostableAlert) Unset() { 286 | v.value = nil 287 | v.isSet = false 288 | } 289 | 290 | func NewNullablePostableAlert(val *PostableAlert) *NullablePostableAlert { 291 | return &NullablePostableAlert{value: val, isSet: true} 292 | } 293 | 294 | func (v NullablePostableAlert) MarshalJSON() ([]byte, error) { 295 | return json.Marshal(v.value) 296 | } 297 | 298 | func (v *NullablePostableAlert) UnmarshalJSON(src []byte) error { 299 | v.isSet = true 300 | return json.Unmarshal(src, &v.value) 301 | } 302 | 303 | 304 | --------------------------------------------------------------------------------