From dfacf50f1b21ba6c82b57e476d3d1ae5341a1f6d Mon Sep 17 00:00:00 2001 From: jetzlstorfer Date: Fri, 3 Sep 2021 15:31:58 +0200 Subject: [PATCH] initial commit Signed-off-by: jetzlstorfer --- .ci_env | 2 +- .gitignore | 2 +- ..._example_com_keptn_service_template_go.xml | 6 +- CODEOWNERS | 1 + Dockerfile | 17 +- README.md | 56 +-- deploy/service.yaml | 88 +++- eventhandlers.go | 450 ++++++++++++------ go.mod | 3 +- helm/Chart.yaml | 4 +- helm/README.md | 10 +- helm/values.yaml | 4 +- helmValues.go | 61 +++ main.go | 403 +++------------- skaffold.yaml | 2 +- test-events/get-sli.triggered.json | 2 +- 16 files changed, 571 insertions(+), 540 deletions(-) create mode 100644 helmValues.go diff --git a/.ci_env b/.ci_env index 9ffe598..a5811c0 100644 --- a/.ci_env +++ b/.ci_env @@ -1,2 +1,2 @@ DOCKER_ORGANIZATION="keptnsandbox" -IMAGE="keptn-service-template-go" \ No newline at end of file +IMAGE="crossplane-service" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 57d2be8..c3c1e5e 100644 --- a/.gitignore +++ b/.gitignore @@ -16,7 +16,7 @@ vendor/* # binaries (created by go build on Linux/OSX) main -keptn-service-template-go +crossplane-service # IDE specific folders .vscode diff --git a/.idea/runConfigurations/go_build_example_com_keptn_service_template_go.xml b/.idea/runConfigurations/go_build_example_com_keptn_service_template_go.xml index 4948018..81c8e32 100644 --- a/.idea/runConfigurations/go_build_example_com_keptn_service_template_go.xml +++ b/.idea/runConfigurations/go_build_example_com_keptn_service_template_go.xml @@ -1,9 +1,9 @@ - - + + - + diff --git a/CODEOWNERS b/CODEOWNERS index c291844..0f3891d 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -8,3 +8,4 @@ # https://help.github.com/en/articles/about-code-owners # +@jetzlstorfer diff --git a/Dockerfile b/Dockerfile index f2dfd25..19c1f0f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,7 +5,7 @@ FROM golang:1.16.2-alpine as builder RUN apk add --no-cache gcc libc-dev git -WORKDIR /src/keptn-service-template-go +WORKDIR /src/crossplane-service ARG version=develop ENV VERSION="${version}" @@ -32,7 +32,7 @@ COPY . . # Build the command inside the container. # (You may fetch or manage dependencies here, either manually or with a tool like "godep".) -RUN GOOS=linux go build -ldflags '-linkmode=external' $BUILDFLAGS -v -o keptn-service-template-go +RUN GOOS=linux go build -ldflags '-linkmode=external' $BUILDFLAGS -v -o crossplane-service # Use a Docker multi-stage build to create a lean production image. # https://docs.docker.com/develop/develop-images/multistage-build/#use-multi-stage-builds @@ -42,6 +42,15 @@ ENV ENV=production # Install extra packages # See https://github.com/gliderlabs/docker-alpine/issues/136#issuecomment-272703023 +ARG KUBE_VERSION=1.20.0 +RUN wget -q https://storage.googleapis.com/kubernetes-release/release/v$KUBE_VERSION/bin/linux/amd64/kubectl -O /bin/kubectl && \ + chmod +x /bin/kubectl + +ARG HELM_VERSION=3.6.3 +RUN wget -q https://get.helm.sh/helm-v$HELM_VERSION-linux-amd64.tar.gz && \ + tar -zxvf helm-v$HELM_VERSION-linux-amd64.tar.gz && \ + mv linux-amd64/helm /bin/helm + RUN apk update && apk upgrade \ && apk add ca-certificates libc6-compat \ && update-ca-certificates \ @@ -51,7 +60,7 @@ ARG version=develop ENV VERSION="${version}" # Copy the binary to the production image from the builder stage. -COPY --from=builder /src/keptn-service-template-go/keptn-service-template-go /keptn-service-template-go +COPY --from=builder /src/crossplane-service/crossplane-service /crossplane-service EXPOSE 8080 @@ -64,4 +73,4 @@ ENV GOTRACEBACK=all #build-uncomment ENTRYPOINT ["/entrypoint.sh"] # Run the web service on container startup. -CMD ["/keptn-service-template-go"] +CMD ["/crossplane-service"] diff --git a/README.md b/README.md index 9851796..4950eb1 100644 --- a/README.md +++ b/README.md @@ -1,13 +1,15 @@ # README +# WORK IN PROGRESS + This is a Keptn Service Template written in GoLang. Follow the instructions below for writing your own Keptn integration. Quick start: 1. In case you want to contribute your service to keptn-sandbox or keptn-contrib, make sure you have read and understood the [Contributing Guidelines](https://github.com/keptn-sandbox/contributing). -1. Click [Use this template](https://github.com/keptn-sandbox/keptn-service-template-go/generate) on top of the repository, or download the repo as a zip-file, extract it into a new folder named after the service you want to create (e.g., simple-service) -1. Replace every occurrence of (docker) image names and tags from `keptnsandbox/keptn-service-template-go` to your docker organization and image name (e.g., `yourorganization/simple-service`) -1. Replace every occurrence of `keptn-service-template-go` with the name of your service (e.g., `simple-service`) +1. Click [Use this template](https://github.com/keptn-sandbox/crossplane-service/generate) on top of the repository, or download the repo as a zip-file, extract it into a new folder named after the service you want to create (e.g., simple-service) +1. Replace every occurrence of (docker) image names and tags from `keptnsandbox/crossplane-service` to your docker organization and image name (e.g., `yourorganization/simple-service`) +1. Replace every occurrence of `crossplane-service` with the name of your service (e.g., `simple-service`) 1. Optional (but recommended): Create a git repo (e.g., on `github.com/your-username/simple-service`) 1. Àdapt the [go.mod](go.mod) file and change `example.com/` to the actual package name (e.g., `github.com/your-username/simple-service`) 1. Add yourself to the [CODEOWNERS](CODEOWNERS) file @@ -21,39 +23,39 @@ Quick start: --- -# keptn-service-template-go -![GitHub release (latest by date)](https://img.shields.io/github/v/release/keptn-sandbox/keptn-service-template-go) -[![Go Report Card](https://goreportcard.com/badge/github.com/keptn-sandbox/keptn-service-template-go)](https://goreportcard.com/report/github.com/keptn-sandbox/keptn-service-template-go) +# crossplane-service +![GitHub release (latest by date)](https://img.shields.io/github/v/release/keptn-sandbox/crossplane-service) +[![Go Report Card](https://goreportcard.com/badge/github.com/keptn-sandbox/crossplane-service)](https://goreportcard.com/report/github.com/keptn-sandbox/crossplane-service) -This implements a keptn-service-template-go for Keptn. If you want to learn more about Keptn visit us on [keptn.sh](https://keptn.sh) +This implements a crossplane-service for Keptn. If you want to learn more about Keptn visit us on [keptn.sh](https://keptn.sh) ## Compatibility Matrix *Please fill in your versions accordingly* -| Keptn Version | [Keptn-Service-Template-Go Docker Image](https://hub.docker.com/r/keptnsandbox/keptn-service-template-go/tags) | +| Keptn Version | [crossplane-service Docker Image](https://hub.docker.com/r/keptnsandbox/crossplane-service/tags) | |:----------------:|:----------------------------------------:| -| 0.6.1 | keptnsandbox/keptn-service-template-go:0.1.0 | -| 0.7.1 | keptnsandbox/keptn-service-template-go:0.1.1 | -| 0.7.2 | keptnsandbox/keptn-service-template-go:0.1.2 | +| 0.6.1 | keptnsandbox/crossplane-service:0.1.0 | +| 0.7.1 | keptnsandbox/crossplane-service:0.1.1 | +| 0.7.2 | keptnsandbox/crossplane-service:0.1.2 | ## Installation -The *keptn-service-template-go* can be installed as a part of [Keptn's uniform](https://keptn.sh). +The *crossplane-service* can be installed as a part of [Keptn's uniform](https://keptn.sh). ### Deploy in your Kubernetes cluster -To deploy the current version of the *keptn-service-template-go* in your Keptn Kubernetes cluster, apply the [`deploy/service.yaml`](deploy/service.yaml) file: +To deploy the current version of the *crossplane-service* in your Keptn Kubernetes cluster, apply the [`deploy/service.yaml`](deploy/service.yaml) file: ```console kubectl apply -f deploy/service.yaml ``` -This should install the `keptn-service-template-go` together with a Keptn `distributor` into the `keptn` namespace, which you can verify using +This should install the `crossplane-service` together with a Keptn `distributor` into the `keptn` namespace, which you can verify using ```console -kubectl -n keptn get deployment keptn-service-template-go -o wide -kubectl -n keptn get pods -l run=keptn-service-template-go +kubectl -n keptn get deployment crossplane-service -o wide +kubectl -n keptn get pods -l run=crossplane-service ``` ### Up- or Downgrading @@ -61,12 +63,12 @@ kubectl -n keptn get pods -l run=keptn-service-template-go Adapt and use the following command in case you want to up- or downgrade your installed version (specified by the `$VERSION` placeholder): ```console -kubectl -n keptn set image deployment/keptn-service-template-go keptn-service-template-go=keptnsandbox/keptn-service-template-go:$VERSION --record +kubectl -n keptn set image deployment/crossplane-service crossplane-service=keptnsandbox/crossplane-service:$VERSION --record ``` ### Uninstall -To delete a deployed *keptn-service-template-go*, use the file `deploy/*.yaml` files from this repository and delete the Kubernetes resources: +To delete a deployed *crossplane-service*, use the file `deploy/*.yaml` files from this repository and delete the Kubernetes resources: ```console kubectl delete -f deploy/service.yaml @@ -99,16 +101,16 @@ If you want to get more insights into processing those CloudEvents or even defin ### Common tasks -* Build the binary: `go build -ldflags '-linkmode=external' -v -o keptn-service-template-go` +* Build the binary: `go build -ldflags '-linkmode=external' -v -o crossplane-service` * Run tests: `go test -race -v ./...` -* Build the docker image: `docker build . -t keptnsandbox/keptn-service-template-go:dev` (Note: Ensure that you use the correct DockerHub account/organization) -* Run the docker image locally: `docker run --rm -it -p 8080:8080 keptnsandbox/keptn-service-template-go:dev` -* Push the docker image to DockerHub: `docker push keptnsandbox/keptn-service-template-go:dev` (Note: Ensure that you use the correct DockerHub account/organization) +* Build the docker image: `docker build . -t keptnsandbox/crossplane-service:dev` (Note: Ensure that you use the correct DockerHub account/organization) +* Run the docker image locally: `docker run --rm -it -p 8080:8080 keptnsandbox/crossplane-service:dev` +* Push the docker image to DockerHub: `docker push keptnsandbox/crossplane-service:dev` (Note: Ensure that you use the correct DockerHub account/organization) * Deploy the service using `kubectl`: `kubectl apply -f deploy/` * Delete/undeploy the service using `kubectl`: `kubectl delete -f deploy/` -* Watch the deployment using `kubectl`: `kubectl -n keptn get deployment keptn-service-template-go -o wide` -* Get logs using `kubectl`: `kubectl -n keptn logs deployment/keptn-service-template-go -f` -* Watch the deployed pods using `kubectl`: `kubectl -n keptn get pods -l run=keptn-service-template-go` +* Watch the deployment using `kubectl`: `kubectl -n keptn get deployment crossplane-service -o wide` +* Get logs using `kubectl`: `kubectl -n keptn logs deployment/crossplane-service -f` +* Watch the deployed pods using `kubectl`: `kubectl -n keptn get pods -l run=crossplane-service` * Deploy the service using [Skaffold](https://skaffold.dev/): `skaffold run --default-repo=your-docker-registry --tail` (Note: Replace `your-docker-registry` with your DockerHub username; also make sure to adapt the image name in [skaffold.yaml](skaffold.yaml)) @@ -134,7 +136,7 @@ You can find the details in [.github/workflows/tests.yml](.github/workflows/test This repo uses GH Actions and Workflows to test the code and automatically build docker images. -Docker Images are automatically pushed based on the configuration done in [.ci_env](.ci_env) and the two [GitHub Secrets](https://github.com/keptn-sandbox/keptn-service-template-go/settings/secrets/actions) +Docker Images are automatically pushed based on the configuration done in [.ci_env](.ci_env) and the two [GitHub Secrets](https://github.com/keptn-sandbox/crossplane-service/settings/secrets/actions) * `REGISTRY_USER` - your DockerHub username * `REGISTRY_PASSWORD` - a DockerHub [access token](https://hub.docker.com/settings/security) (alternatively, your DockerHub password) @@ -155,7 +157,7 @@ If any problems occur, fix them in the release branch and test them again. Once you have confirmed that everything works and your version is ready to go, you should -* create a new release on the release branch using the [GitHub releases page](https://github.com/keptn-sandbox/keptn-service-template-go/releases), and +* create a new release on the release branch using the [GitHub releases page](https://github.com/keptn-sandbox/crossplane-service/releases), and * merge any changes from the release branch back to the master branch. ## License diff --git a/deploy/service.yaml b/deploy/service.yaml index 8a39c30..6ba86e8 100644 --- a/deploy/service.yaml +++ b/deploy/service.yaml @@ -1,30 +1,67 @@ --- -# Deployment of our keptn-service-template-go +apiVersion: v1 +kind: ServiceAccount +metadata: + name: keptn-crossplane-service + namespace: keptn + labels: + name: keptn-crossplane-service +--- +# Source: openebs/templates/clusterrole.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: keptn-crossplane-service + labels: + name: keptn-crossplane-service +rules: +- apiGroups: ["","cluster.civo.crossplane.io","devopstoolkitseries.com"] + resources: ["*"] + verbs: ["create","delete","get","list","patch","update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: keptn-crossplane-service + labels: + name: keptn-crossplane-service +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: keptn-crossplane-service +subjects: +- kind: ServiceAccount + name: keptn-crossplane-service + namespace: keptn +--- +# Deployment of our crossplane-service apiVersion: apps/v1 kind: Deployment metadata: - name: keptn-service-template-go + name: crossplane-service namespace: keptn spec: selector: matchLabels: - run: keptn-service-template-go + run: crossplane-service replicas: 1 template: metadata: labels: - run: keptn-service-template-go + run: crossplane-service + app.kubernetes.io/name: crossplane-service + app.kubernetes.io/version: dev spec: containers: - - name: keptn-service-template-go - image: keptnsandbox/keptn-service-template-go:latest # Todo: Replace this with your image name + - name: crossplane-service + image: keptnsandbox/crossplane-service # Todo: Replace this with your image name ports: - containerPort: 8080 env: - name: CONFIGURATION_SERVICE value: 'http://configuration-service:8080' - name: distributor - image: keptn/distributor:0.8.3 + image: keptn/distributor:0.8.7 livenessProbe: httpGet: path: /health @@ -45,23 +82,48 @@ spec: - name: PUBSUB_URL value: 'nats://keptn-nats-cluster' - name: PUBSUB_TOPIC - value: 'sh.keptn.>' + value: 'sh.keptn.event.environment-setup.>,sh.keptn.event.environment-teardown.>' - name: PUBSUB_RECIPIENT value: '127.0.0.1' - serviceAccountName: keptn-default + - name: VERSION + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: 'metadata.labels[''app.kubernetes.io/version'']' + - name: K8S_DEPLOYMENT_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: 'metadata.labels[''app.kubernetes.io/name'']' + - name: K8S_POD_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.name + - name: K8S_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + - name: K8S_NODE_NAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + serviceAccountName: keptn-crossplane-service --- -# Expose keptn-service-template-go via Port 8080 within the cluster +# Expose crossplane-service via Port 8080 within the cluster apiVersion: v1 kind: Service metadata: - name: keptn-service-template-go + name: crossplane-service namespace: keptn labels: - run: keptn-service-template-go + run: crossplane-service spec: ports: - port: 8080 protocol: TCP selector: - run: keptn-service-template-go + run: crossplane-service diff --git a/eventhandlers.go b/eventhandlers.go index 8cb5419..02e2914 100644 --- a/eventhandlers.go +++ b/eventhandlers.go @@ -1,13 +1,20 @@ package main import ( + "encoding/base64" "fmt" + "io" + "io/ioutil" "log" + "net/http" + "os" + "os/exec" + "strings" "time" cloudevents "github.com/cloudevents/sdk-go/v2" // make sure to use v2 cloudevents here - keptn "github.com/keptn/go-utils/pkg/lib" keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0" + "gopkg.in/yaml.v2" ) /** @@ -15,6 +22,8 @@ import ( * See https://github.com/keptn/spec/blob/0.8.0-alpha/cloudevents.md for details on the payload **/ +const helmVersion = "0.8.7" + // GenericLogKeptnCloudEventHandler is a generic handler for Keptn Cloud Events that logs the CloudEvent func GenericLogKeptnCloudEventHandler(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data interface{}) error { log.Printf("Handling %s Event: %s", incomingEvent.Type(), incomingEvent.Context.GetID()) @@ -23,150 +32,296 @@ func GenericLogKeptnCloudEventHandler(myKeptn *keptnv2.Keptn, incomingEvent clou return nil } -// OldHandleConfigureMonitoringEvent handles old configure-monitoring events -// TODO: add in your handler code -func OldHandleConfigureMonitoringEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptn.ConfigureMonitoringEventData) error { - log.Printf("Handling old configure-monitoring Event: %s", incomingEvent.Context.GetID()) +func HandleEnvironmentSetupTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *EnvironmentsetupTriggeredEventData) error { + log.Printf("Handling environment-setup.triggered Event: %s", incomingEvent.Context.GetID()) - return nil -} + _, err := myKeptn.SendTaskStartedEvent(data, ServiceName) -// HandleConfigureMonitoringTriggeredEvent handles configure-monitoring.triggered events -// TODO: add in your handler code -func HandleConfigureMonitoringTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ConfigureMonitoringTriggeredEventData) error { - log.Printf("Handling configure-monitoring.triggered Event: %s", incomingEvent.Context.GetID()) + if err != nil { + errMsg := fmt.Sprintf("Failed to send task started CloudEvent (%s), aborting...", err.Error()) + log.Println(errMsg) + return err + } - return nil -} + log.Printf("Looking for Crossplane cluster %s file in Keptn git repo...", CrossPlaneFilename) -// HandleDeploymentTriggeredEvent handles deployment.triggered events -// TODO: add in your handler code -func HandleDeploymentTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.DeploymentTriggeredEventData) error { - log.Printf("Handling deployment.triggered Event: %s", incomingEvent.Context.GetID()) + // load crossplane file + keptnResourceContent, err := myKeptn.GetKeptnResource(CrossPlaneFilename) - return nil -} + if err != nil { + logMessage := fmt.Sprintf("No %s file found for service %s in stage %s in project %s", CrossPlaneFilename, data.Service, data.Stage, data.Project) + log.Printf(logMessage) -// HandleTestTriggeredEvent handles test.triggered events -// TODO: add in your handler code -func HandleTestTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.TestTriggeredEventData) error { - log.Printf("Handling test.triggered Event: %s", incomingEvent.Context.GetID()) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) - return nil -} + return err + } + log.Printf("Crossplane file found.") -// HandleApprovalTriggeredEvent handles approval.triggered events -// TODO: add in your handler code -func HandleApprovalTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ApprovalTriggeredEventData) error { - log.Printf("Handling approval.triggered Event: %s", incomingEvent.Context.GetID()) + // store crossplane file locally + _ = os.Mkdir("crossplane", 0644) + err = ioutil.WriteFile(CrossPlaneFilename, []byte(keptnResourceContent), 0644) + if err != nil { + logMessage := fmt.Sprintf("Could not store crossplane file locally: %s", err.Error()) + log.Printf(logMessage) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) - return nil -} + return err + } + log.Printf("Crossplane file stored locally.") -// HandleEvaluationTriggeredEvent handles evaluation.triggered events -// TODO: add in your handler code -func HandleEvaluationTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.EvaluationTriggeredEventData) error { - log.Printf("Handling evaluation.triggered Event: %s", incomingEvent.Context.GetID()) + log.Printf("Now applying crossplane file.") + // now execute crossplane + kubectlresult, err := ExecuteCommand("kubectl", []string{"apply", "-f", CrossPlaneFilename}) + log.Printf(kubectlresult) + if err != nil { + logMessage := fmt.Sprintf("Error while applying crossplane cluster manifest: %s", err.Error()) + log.Printf(logMessage) - return nil -} + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) -// HandleReleaseTriggeredEvent handles release.triggered events -// TODO: add in your handler code -func HandleReleaseTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ReleaseTriggeredEventData) error { - log.Printf("Handling release.triggered Event: %s", incomingEvent.Context.GetID()) + return err + } + log.Printf("Crossplane file applied.") + + // waiting for cluster to be ready + // wait for secret + var secretName string + secretDefaultName := "kubeconfig-keptn-crossplane" + secretNamespace := "crossplane-system" + // wait as usually the secret is not immediately available + time.Sleep(10 * time.Second) + for secretName != secretDefaultName { + log.Printf("Checking availability of secret %s in namespace %s", secretDefaultName, secretNamespace) + secretName, err = CheckAvailabilityOfSecret(secretDefaultName, secretNamespace) + log.Printf("Retrieved secret name: %s", secretName) + + if err != nil { + logMessage := fmt.Sprintf("Could not retrieve secret %s yet - waiting for 30 seconds", secretDefaultName) + log.Printf(logMessage) + + // we will consider this a + _, err = myKeptn.SendTaskStatusChangedEvent(&keptnv2.EventData{ + Message: logMessage, + }, ServiceName) + if err != nil { + log.Printf("Error: %", err) + } + // interval before we check the chaosengine status again + time.Sleep(30 * time.Second) + } - return nil -} + } + log.Printf("Secret found. Continuing...") -// HandleGetSliTriggeredEvent handles get-sli.triggered events if SLIProvider == keptn-service-template-go -// This function acts as an example showing how to handle get-sli events by sending .started and .finished events -// TODO: adapt handler code to your needs -func HandleGetSliTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.GetSLITriggeredEventData) error { - log.Printf("Handling get-sli.triggered Event: %s", incomingEvent.Context.GetID()) + // first getting the kubeconfig + // kubectl get secrets cluster-details-keptn-crossplane -n default -o jsonpath={'.data.kubeconfig'} | base64 -d > kubeconfig + kubeconfigEncoded, err := ExecuteCommand("kubectl", []string{"get", "secrets", secretName, "-n", secretNamespace, "-o", "jsonpath={.data.kubeconfig}"}) + if err != nil { + logMessage := fmt.Sprintf("Error while getting kubeconfig: %s", err.Error()) + log.Printf(logMessage) + } + log.Printf(kubeconfigEncoded) - // Step 1 - Do we need to do something? - // Lets make sure we are only processing an event that really belongs to our SLI Provider - if data.GetSLI.SLIProvider != "keptn-service-template-go" { - log.Printf("Not handling get-sli event as it is meant for %s", data.GetSLI.SLIProvider) - return nil + kubeconfig, err := base64.StdEncoding.DecodeString(kubeconfigEncoded) + if err != nil { + logMessage := fmt.Sprintf("Could not base64 decode the Kubeconfig: %s", err.Error()) + log.Printf(logMessage) + return err } + err = ioutil.WriteFile("kubeconfig", kubeconfig, 0644) + if err != nil { + logMessage := fmt.Sprintf("Could not store kubeconfig file locally: %s", err.Error()) + log.Printf(logMessage) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) - // Step 2 - Send out a get-sli.started CloudEvent - // The get-sli.started cloud-event is new since Keptn 0.8.0 and is required to be send when the task is started - _, err := myKeptn.SendTaskStartedEvent(data, ServiceName) + return err + } + + if string(kubeconfig) == "" { + logMessage := "KubeConfig is empty" + log.Printf(logMessage) + } + // k get nodes --kubeconfig kubeconfig + nodes, err := ExecuteCommand("kubectl", []string{"get", "nodes", "--kubeconfig", "kubeconfig"}) if err != nil { - errMsg := fmt.Sprintf("Failed to send task started CloudEvent (%s), aborting...", err.Error()) + logMessage := fmt.Sprintf("Error while getting kubeconfig: %s", err.Error()) + log.Printf(logMessage) + } + logMessage := nodes + log.Printf(logMessage) + + _, err = myKeptn.SendTaskStatusChangedEvent(&keptnv2.EventData{ + Message: logMessage, + }, ServiceName) + if err != nil { + log.Printf("Error: %", err) + } + + // fetch values.yaml for helm-service + //helmVersion := "0.8.7" + fileUrl := "https://raw.githubusercontent.com/keptn/keptn/release-" + helmVersion + "/helm-service/chart/values.yaml" + err = DownloadFile("values.yaml", fileUrl) + if err != nil { + logMessage := fmt.Sprintf("Error while getting Helm values.yaml file: %s", err.Error()) + log.Printf(logMessage) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) + } + fmt.Println("Downloaded: " + fileUrl) + _, err = myKeptn.SendTaskStatusChangedEvent(&keptnv2.EventData{ + Message: "Downloaded Helm-service values.yaml file", + }, ServiceName) + + var helmValues helmValues + helmValues.getHelmValues("values.yaml") + helmValues.Helmservice.Image.Tag = helmVersion + helmValues.RemoteControlPlane.Enabled = true + helmValues.RemoteControlPlane.API.Protocol = "http" + helmValues.RemoteControlPlane.API.Hostname = "34.67.191.73.nip.io" + helmValues.RemoteControlPlane.API.Token = "wcw3YyJRBrS2OzziQKIZt3zzUSQMC4oSessgPhgPnwNIy" + + // now write the file + helmData, err := yaml.Marshal(&helmValues) + + if err != nil { + log.Fatal(err) + } + + err = ioutil.WriteFile("values.yaml", helmData, 0) + if err != nil { + logMessage := fmt.Sprintf("Error while writing Helm values.yaml file: %s", err.Error()) + log.Printf(logMessage) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) + } + log.Printf("Helm values.yaml stored locally.") + + // now apply helm chart with values file + // helm install helm-service https://github.com/keptn/keptn/releases/download/0.8.7/helm-service-0.8.7.tgz -n keptn-exec --create-namespace --values=values.yaml --kubeconfig kubeconfig + // TEMP DISABLE + log.Printf("Now installing Helm service.") + helmRelease := "https://github.com/keptn/keptn/releases/download/" + helmVersion + "/helm-service-" + helmVersion + ".tgz" + helmInstall, err := ExecuteCommand("helm", []string{"install", "helm-service", helmRelease, "-n", "keptn-exec", "--create-namespace", "--values=values.yaml", "--kubeconfig", "kubeconfig"}) + if err != nil { + logMessage := fmt.Sprintf("Error while installing Keptn helm-service: %s", err.Error()) + log.Printf(logMessage) + } + logMessage = helmInstall + log.Printf(logMessage) + + _, err = myKeptn.SendTaskStatusChangedEvent(&keptnv2.EventData{ + Message: logMessage, + }, ServiceName) + if err != nil { + log.Printf("Error: %", err) + } + // END TEMP DISABLE + + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusSucceeded, + Result: keptnv2.ResultPass, + }, ServiceName) + + if err != nil { + errMsg := fmt.Sprintf("Failed to send task finished CloudEvent (%s), aborting...", err.Error()) log.Println(errMsg) return err } - // Step 4 - prep-work - // Get any additional input / configuration data - // - Labels: get the incoming labels for potential config data and use it to pass more labels on result, e.g: links - // - SLI.yaml: if your service uses SLI.yaml to store query definitions for SLIs get that file from Keptn - labels := data.Labels - if labels == nil { - labels = make(map[string]string) - } - testRunID := labels["testRunId"] + return nil +} - // Step 5 - get SLI Config File - // Get SLI File from keptn-service-template-go subdirectory of the config repo - to add the file use: - // keptn add-resource --project=PROJECT --stage=STAGE --service=SERVICE --resource=my-sli-config.yaml --resourceUri=keptn-service-template-go/sli.yaml - sliFile := "keptn-service-template-go/sli.yaml" - sliConfigFileContent, err := myKeptn.GetKeptnResource(sliFile) +func HandleEnvironmentTeardownTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *EnvironmentTeardownTriggeredEventData) error { + log.Printf("Handling environment-teardown.triggered Event: %s", incomingEvent.Context.GetID()) - // FYI you do not need to "fail" if sli.yaml is missing, you can also assume smart defaults like we do - // in keptn-contrib/dynatrace-service and keptn-contrib/prometheus-service + _, err := myKeptn.SendTaskStartedEvent(data, ServiceName) if err != nil { - // failed to fetch sli config file - errMsg := fmt.Sprintf("Failed to fetch SLI file %s from config repo: %s", sliFile, err.Error()) + errMsg := fmt.Sprintf("Failed to send task started CloudEvent (%s), aborting...", err.Error()) log.Println(errMsg) - // send a get-sli.finished event with status=error and result=failed back to Keptn + return err + } + + log.Printf("Looking for Crossplane cluster %s file in Keptn git repo...", CrossPlaneFilename) + + // load crossplane file + keptnResourceContent, err := myKeptn.GetKeptnResource(CrossPlaneFilename) + + if err != nil { + logMessage := fmt.Sprintf("No %s file found for service %s in stage %s in project %s", CrossPlaneFilename, data.Service, data.Stage, data.Project) + log.Printf(logMessage) _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ - Status: keptnv2.StatusErrored, - Result: keptnv2.ResultFailed, + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, }, ServiceName) return err } + log.Printf("Crossplane file found.") - fmt.Println(sliConfigFileContent) - - // Step 6 - do your work - iterate through the list of requested indicators and return their values - // Indicators: this is the list of indicators as requested in the SLO.yaml - // SLIResult: this is the array that will receive the results - indicators := data.GetSLI.Indicators - sliResults := []*keptnv2.SLIResult{} + // store crossplane file locally + _ = os.Mkdir("crossplane", 0644) + err = ioutil.WriteFile(CrossPlaneFilename, []byte(keptnResourceContent), 0644) + if err != nil { + logMessage := fmt.Sprintf("Could not store crossplane file locally: %s", err.Error()) + log.Printf(logMessage) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) - for _, indicatorName := range indicators { - sliResult := &keptnv2.SLIResult{ - Metric: indicatorName, - Value: 123.4, // ToDo: Fetch the values from your monitoring tool here - } - sliResults = append(sliResults, sliResult) + return err } + log.Printf("Crossplane file stored locally.") + + log.Printf("Now starting to delete cluster based on crossplane file.") + // now execute crossplane + kubectlresult, err := ExecuteCommand("kubectl", []string{"delete", "-f", CrossPlaneFilename}) + log.Printf(kubectlresult) + if err != nil { + logMessage := fmt.Sprintf("Error while deleting crossplane cluster manifest: %s", err.Error()) + log.Printf(logMessage) - // Step 7 - add additional context via labels (e.g., a backlink to the monitoring or CI tool) - labels["Link to Data Source"] = "https://mydatasource/myquery?testRun=" + testRunID + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusErrored, + Result: keptnv2.ResultFailed, + Message: logMessage, + }, ServiceName) - // Step 8 - Build get-sli.finished event data - getSliFinishedEventData := &keptnv2.GetSLIFinishedEventData{ - EventData: keptnv2.EventData{ - Status: keptnv2.StatusSucceeded, - Result: keptnv2.ResultPass, - }, - GetSLI: keptnv2.GetSLIFinished{ - IndicatorValues: sliResults, - Start: data.GetSLI.Start, - End: data.GetSLI.End, - }, + return err } + log.Printf("Crossplane cluster deleted.") - _, err = myKeptn.SendTaskFinishedEvent(getSliFinishedEventData, ServiceName) + _, err = myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ + Status: keptnv2.StatusSucceeded, + Result: keptnv2.ResultPass, + }, ServiceName) if err != nil { errMsg := fmt.Sprintf("Failed to send task finished CloudEvent (%s), aborting...", err.Error()) @@ -177,48 +332,57 @@ func HandleGetSliTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevent return nil } -// HandleProblemEvent handles two problem events: -// - ProblemOpenEventType = "sh.keptn.event.problem.open" -// - ProblemEventType = "sh.keptn.events.problem" -// TODO: add in your handler code -func HandleProblemEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptn.ProblemEventData) error { - log.Printf("Handling Problem Event: %s", incomingEvent.Context.GetID()) +// ExecuteCommand exectues the command using the args +func ExecuteCommand(command string, args []string) (string, error) { + cmd := exec.Command(command, args...) + out, err := cmd.CombinedOutput() + if err != nil { + return string(out), fmt.Errorf("Error executing command %s %s: %s\n%s", command, strings.Join(args, " "), err.Error(), string(out)) + } + return string(out), nil +} - // Deprecated since Keptn 0.7.0 - use the HandleActionTriggeredEvent instead +func DownloadFile(filepath string, url string) error { - return nil + // Get the data + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + // Create the file + out, err := os.Create(filepath) + if err != nil { + return err + } + defer out.Close() + + // Write the body to file + _, err = io.Copy(out, resp.Body) + return err } -// HandleActionTriggeredEvent handles action.triggered events -// TODO: add in your handler code -func HandleActionTriggeredEvent(myKeptn *keptnv2.Keptn, incomingEvent cloudevents.Event, data *keptnv2.ActionTriggeredEventData) error { - log.Printf("Handling Action Triggered Event: %s", incomingEvent.Context.GetID()) - log.Printf("Action=%s\n", data.Action.Action) - - // check if action is supported - if data.Action.Action == "action-xyz" { - // ----------------------------------------------------- - // 1. Send Action.Started Cloud-Event - // ----------------------------------------------------- - myKeptn.SendTaskStartedEvent(data, ServiceName) - - // ----------------------------------------------------- - // 2. Implement your remediation action here - // ----------------------------------------------------- - time.Sleep(5 * time.Second) // Example: Wait 5 seconds. Maybe the problem fixes itself. - - // ----------------------------------------------------- - // 3. Send Action.Finished Cloud-Event - // ----------------------------------------------------- - myKeptn.SendTaskFinishedEvent(&keptnv2.EventData{ - Status: keptnv2.StatusSucceeded, // alternative: keptnv2.StatusErrored - Result: keptnv2.ResultPass, // alternative: keptnv2.ResultFailed - Message: "Successfully sleeped!", - }, ServiceName) +func CheckAvailabilityOfSecret(secretname string, namespace string) (string, error) { + secretname, err := ExecuteCommand("kubectl", []string{"get", "secrets", secretname, "-n", namespace, "-o", "jsonpath='{.metadata.name}'"}) - } else { - log.Printf("Retrieved unknown action %s, skipping...", data.Action.Action) - return nil + if err != nil { + return "", err } - return nil + + return strings.Trim(secretname, "'"), nil +} + +func (hv *helmValues) getHelmValues(filename string) *helmValues { + + yamlFile, err := ioutil.ReadFile(filename) + if err != nil { + log.Printf("yamlFile.Get err #%v ", err) + } + err = yaml.Unmarshal(yamlFile, hv) + if err != nil { + log.Fatalf("Unmarshal: %v", err) + } + + return hv } diff --git a/go.mod b/go.mod index 6d01b29..bb31573 100644 --- a/go.mod +++ b/go.mod @@ -1,4 +1,4 @@ -module example.com/keptn-service-template-go +module keptn.sh/keptnsandbox/crossplane-service go 1.16 @@ -9,4 +9,5 @@ require ( github.com/mitchellh/mapstructure v1.2.2 // indirect github.com/onsi/ginkgo v1.12.0 // indirect github.com/onsi/gomega v1.9.0 // indirect + gopkg.in/yaml.v2 v2.4.0 ) diff --git a/helm/Chart.yaml b/helm/Chart.yaml index 23f555d..ad03390 100644 --- a/helm/Chart.yaml +++ b/helm/Chart.yaml @@ -1,6 +1,6 @@ apiVersion: v2 appVersion: 0.8.0 -description: Helm Chart for the keptn keptn-service-template-go -name: keptn-service-template-go +description: Helm Chart for the keptn crossplane-service +name: crossplane-service type: application version: 0.8.0 diff --git a/helm/README.md b/helm/README.md index a841961..7ce1584 100644 --- a/helm/README.md +++ b/helm/README.md @@ -1,20 +1,20 @@ -keptn-service-template-go +crossplane-service =========== -Helm Chart for the keptn keptn-service-template-go +Helm Chart for the keptn crossplane-service ## Configuration -The following table lists the configurable parameters of the keptn-service-template-go chart and their default values. +The following table lists the configurable parameters of the crossplane-service chart and their default values. | Parameter | Description | Default | | ------------------------ | ----------------------- | -------------- | -| `keptnservice.image.repository` | Container image name | `"docker.io/keptnsandbox/keptn-service-template-go"` | +| `keptnservice.image.repository` | Container image name | `"docker.io/keptnsandbox/crossplane-service"` | | `keptnservice.image.pullPolicy` | Kubernetes image pull policy | `"IfNotPresent"` | | `keptnservice.image.tag` | Container tag | `""` | -| `keptnservice.service.enabled` | Creates a kubernetes service for the keptn-service-template-go | `true` | +| `keptnservice.service.enabled` | Creates a kubernetes service for the crossplane-service | `true` | | `distributor.stageFilter` | Sets the stage this helm service belongs to | `""` | | `distributor.serviceFilter` | Sets the service this helm service belongs to | `""` | | `distributor.projectFilter` | Sets the project this helm service belongs to | `""` | diff --git a/helm/values.yaml b/helm/values.yaml index 0bd1f67..b682897 100644 --- a/helm/values.yaml +++ b/helm/values.yaml @@ -1,10 +1,10 @@ keptnservice: image: - repository: docker.io/keptnsandbox/keptn-service-template-go # Container Image Name + repository: docker.io/keptnsandbox/crossplane-service # Container Image Name pullPolicy: Always # Kubernetes Image Pull Policy tag: "dev" # Container Tag service: - enabled: true # Creates a Kubernetes Service for the keptn-service-template-go + enabled: true # Creates a Kubernetes Service for the crossplane-service distributor: stageFilter: "" # Sets the stage this helm service belongs to diff --git a/helmValues.go b/helmValues.go new file mode 100644 index 0000000..1fb13cb --- /dev/null +++ b/helmValues.go @@ -0,0 +1,61 @@ +package main + +type helmValues struct { + Helmservice struct { + Image struct { + Repository string `yaml:"repository"` + PullPolicy string `yaml:"pullPolicy"` + Tag string `yaml:"tag"` + } `yaml:"image"` + Service struct { + Enabled bool `yaml:"enabled"` + } `yaml:"service"` + } `yaml:"helmservice"` + Distributor struct { + StageFilter string `yaml:"stageFilter"` + ServiceFilter string `yaml:"serviceFilter"` + ProjectFilter string `yaml:"projectFilter"` + Image struct { + Repository string `yaml:"repository"` + PullPolicy string `yaml:"pullPolicy"` + Tag string `yaml:"tag"` + } `yaml:"image"` + } `yaml:"distributor"` + RemoteControlPlane struct { + Enabled bool `yaml:"enabled"` + API struct { + Protocol string `yaml:"protocol"` + Hostname string `yaml:"hostname"` + APIValidateTLS bool `yaml:"apiValidateTls"` + Token string `yaml:"token"` + } `yaml:"api"` + } `yaml:"remoteControlPlane"` + ImagePullSecrets []interface{} `yaml:"imagePullSecrets"` + ServiceAccount struct { + Create bool `yaml:"create"` + Annotations struct { + } `yaml:"annotations"` + Name string `yaml:"name"` + } `yaml:"serviceAccount"` + PodAnnotations struct { + } `yaml:"podAnnotations"` + PodSecurityContext struct { + } `yaml:"podSecurityContext"` + SecurityContext struct { + } `yaml:"securityContext"` + Resources struct { + Limits struct { + CPU string `yaml:"cpu"` + Memory string `yaml:"memory"` + } `yaml:"limits"` + Requests struct { + CPU string `yaml:"cpu"` + Memory string `yaml:"memory"` + } `yaml:"requests"` + } `yaml:"resources"` + NodeSelector struct { + } `yaml:"nodeSelector"` + Tolerations []interface{} `yaml:"tolerations"` + Affinity struct { + } `yaml:"affinity"` +} diff --git a/main.go b/main.go index 85f8421..2ff532f 100644 --- a/main.go +++ b/main.go @@ -9,7 +9,6 @@ import ( cloudevents "github.com/cloudevents/sdk-go/v2" // make sure to use v2 cloudevents here "github.com/kelseyhightower/envconfig" - keptnlib "github.com/keptn/go-utils/pkg/lib" keptn "github.com/keptn/go-utils/pkg/lib/keptn" keptnv2 "github.com/keptn/go-utils/pkg/lib/v0_2_0" ) @@ -28,7 +27,47 @@ type envConfig struct { } // ServiceName specifies the current services name (e.g., used as source when sending CloudEvents) -const ServiceName = "keptn-service-template-go" +const ServiceName = "crossplane-service" + +const CrossPlaneFilename = "crossplane/preview-env.yaml" + +// EnvironemtsetupFinishedEventData is the name of an echo triggered event +const EnvironmentsetupEventTriggeredType = "sh.keptn.event.environment-setup.triggered" + +// EnvironemtsetupFinishedEventData is the name of an echo started event +const EnvironmentsetupStartedEventType = "sh.keptn.event.environment-setup.started" + +// EnvironemtsetupFinishedEventData is the name of an echo finished event +const EnvironmentsetupFinishedEventType = "sh.keptn.event.environment-setup.finished" + +// EnvironemtsetupFinishedEventData is the data of an echo triggered event +type EnvironmentsetupTriggeredEventData struct { + keptnv2.EventData +} + +// EnvironemtsetupFinishedEventData is the data of an echo started event +type EnvironmentsetupStartedEventData struct { + keptnv2.EventData +} + +// EnvironemtsetupFinishedEventData is the data of an echo finished event +type EnvironmentsetupFinishedEventData struct { + keptnv2.EventData +} + +const EnvironmentTeardownTriggeredEventType = "sh.keptn.event.environment-teardown.triggered" +const EnvironmentTeardownStartedEventType = "sh.keptn.event.environment-teardown.started" +const EnvironmentTeardownFinishedEventType = "sh.keptn.event.environment-teardown.finished" + +type EnvironmentTeardownTriggeredEventData struct { + keptnv2.EventData +} +type EnvironmentTeardownStartedEventData struct { + keptnv2.EventData +} +type EnvironmentTeardownFinishedEventData struct { + keptnv2.EventData +} /** * Parses a Keptn Cloud Event payload (data attribute) @@ -106,358 +145,50 @@ func processKeptnCloudEvent(ctx context.Context, event cloudevents.Event) error switch event.Type() { // ------------------------------------------------------- - // sh.keptn.event.project.create - Note: This is due to change - case keptnv2.GetStartedEventType(keptnv2.ProjectCreateTaskName): // sh.keptn.event.project.create.started - log.Printf("Processing Project.Create.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ProjectCreateStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ProjectCreateTaskName): // sh.keptn.event.project.create.finished - log.Printf("Processing Project.Create.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ProjectCreateFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - // ------------------------------------------------------- - // sh.keptn.event.service.create - Note: This is due to change - case keptnv2.GetStartedEventType(keptnv2.ServiceCreateTaskName): // sh.keptn.event.service.create.started - log.Printf("Processing Service.Create.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ServiceCreateStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ServiceCreateTaskName): // sh.keptn.event.service.create.finished - log.Printf("Processing Service.Create.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ServiceCreateFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.approval - case keptnv2.GetTriggeredEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.triggered - log.Printf("Processing Approval.Triggered Event") - - eventData := &keptnv2.ApprovalTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleApprovalTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.started - log.Printf("Processing Approval.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ApprovalStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ApprovalTaskName): // sh.keptn.event.approval.finished - log.Printf("Processing Approval.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ApprovalFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.deployment - case keptnv2.GetTriggeredEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.triggered - log.Printf("Processing Deployment.Triggered Event") - - eventData := &keptnv2.DeploymentTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleDeploymentTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.started - log.Printf("Processing Deployment.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.DeploymentStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.DeploymentTaskName): // sh.keptn.event.deployment.finished - log.Printf("Processing Deployment.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.DeploymentFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.test - case keptnv2.GetTriggeredEventType(keptnv2.TestTaskName): // sh.keptn.event.test.triggered - log.Printf("Processing Test.Triggered Event") - - eventData := &keptnv2.TestTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleTestTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.TestTaskName): // sh.keptn.event.test.started - log.Printf("Processing Test.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.TestStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.TestTaskName): // sh.keptn.event.test.finished - log.Printf("Processing Test.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.TestFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.evaluation - case keptnv2.GetTriggeredEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.triggered - log.Printf("Processing Evaluation.Triggered Event") - - eventData := &keptnv2.EvaluationTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleEvaluationTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.started - log.Printf("Processing Evaluation.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.EvaluationStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.EvaluationTaskName): // sh.keptn.event.evaluation.finished - log.Printf("Processing Evaluation.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.EvaluationFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.release - case keptnv2.GetTriggeredEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.triggered - log.Printf("Processing Release.Triggered Event") - - eventData := &keptnv2.ReleaseTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleReleaseTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.started - log.Printf("Processing Release.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ReleaseStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetStatusChangedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.status.changed - log.Printf("Processing Release.Status.Changed Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ReleaseStatusChangedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ReleaseTaskName): // sh.keptn.event.release.finished - log.Printf("Processing Release.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.ReleaseFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.get-action (sent by shipyard-controller to extract a remediation action from remediations.yaml) - case keptnv2.GetTriggeredEventType(keptnv2.GetActionTaskName): // sh.keptn.event.action.triggered - log.Printf("Processing Get-Action.Triggered Event") - - eventData := &keptnv2.GetActionTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.GetActionTaskName): // sh.keptn.event.action.started - log.Printf("Processing Get-Action.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.GetActionStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.GetActionTaskName): // sh.keptn.event.action.finished - log.Printf("Processing Get-Action.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). - - eventData := &keptnv2.GetActionFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.action (sent by shipyard-controller to execute a remediation action) - case keptnv2.GetTriggeredEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.triggered - log.Printf("Processing Action.Triggered Event") - - eventData := &keptnv2.ActionTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleActionTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.started - log.Printf("Processing Action.Started Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). + // your custom cloud event, e.g., sh.keptn.your-event + // see https://github.com/keptn-sandbox/echo-service/blob/a90207bc119c0aca18368985c7bb80dea47309e9/pkg/events.go + // for an example on how to generate your own CloudEvents and structs + case keptnv2.GetTriggeredEventType("environment-setup"): // sh.keptn.event.your-event.triggered + log.Printf("Processing environment-setup.triggered Event") - eventData := &keptnv2.ActionStartedEventData{} + eventData := &EnvironmentsetupTriggeredEventData{} parseKeptnCloudEventPayload(event, eventData) - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ActionTaskName): // sh.keptn.event.action.finished - log.Printf("Processing Action.Finished Event") - // Please note: Processing .started, .status.changed and .finished events is only recommended when you want to - // notify an external service (e.g., for logging purposes). + return HandleEnvironmentSetupTriggeredEvent(myKeptn, event, eventData) - eventData := &keptnv2.ActionFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) + break + case keptnv2.GetStartedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.your-event.started + log.Printf("Processing your-event.started Event") + // eventData := &keptnv2.YourEventStartedEventData{} + // parseKeptnCloudEventPayload(event, eventData) // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.problem / problem.open - // Please Note: This is deprecated; Use Action.Triggered instead - case keptnlib.ProblemEventType: // sh.keptn.event.problem - e.g., sent by Dynatrace to Keptn Api - log.Printf("Processing problem Event") - log.Printf("Subscribing to a problem.open or problem event is not recommended since Keptn 0.7. Please subscribe to event of type: sh.keptn.event.action.triggered") - - eventData := &keptnlib.ProblemEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleProblemEvent(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.get-sli (sent by lighthouse-service to fetch SLIs from the sli provider) - case keptnv2.GetTriggeredEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.triggered - log.Printf("Processing Get-SLI.Triggered Event") - - eventData := &keptnv2.GetSLITriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleGetSliTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.started - log.Printf("Processing Get-SLI.Started Event") - - eventData := &keptnv2.GetSLIStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) + // return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.GetSLITaskName): // sh.keptn.event.get-sli.finished - log.Printf("Processing Get-SLI.Finished Event") + break + case keptnv2.GetFinishedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.your-event.finished + log.Printf("Processing your-event.finished Event") - eventData := &keptnv2.GetSLIFinishedEventData{} - parseKeptnCloudEventPayload(event, eventData) + // eventData := &keptnv2.YourEventFinishedEventData{} + // parseKeptnCloudEventPayload(event, eventData) // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // sh.keptn.event.configure-monitoring - case keptnlib.ConfigureMonitoringEventType: // old configure-monitoring CE; compatibility with 0.8.0-alpha - log.Printf("Processing old configure-monitoring Event") - log.Printf("Note: This will be deprecated with Keptn 0.8.0") - - eventData := &keptnlib.ConfigureMonitoringEventData{} - parseKeptnCloudEventPayload(event, eventData) - - // Handle old configure-monitoring event - return OldHandleConfigureMonitoringEvent(myKeptn, event, eventData) - - case keptnv2.GetTriggeredEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.triggered - log.Printf("Processing configure-monitoring.Triggered Event") - - eventData := &keptnv2.ConfigureMonitoringTriggeredEventData{} - parseKeptnCloudEventPayload(event, eventData) - - return HandleConfigureMonitoringTriggeredEvent(myKeptn, event, eventData) - case keptnv2.GetStartedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.started - log.Printf("Processing configure-monitoring.Started Event") + // return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - eventData := &keptnv2.ConfigureMonitoringStartedEventData{} - parseKeptnCloudEventPayload(event, eventData) + break - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - case keptnv2.GetFinishedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.configure-monitoring.finished - log.Printf("Processing configure-monitoring.Finished Event") + // environment teardown event + case keptnv2.GetTriggeredEventType("environment-teardown"): // sh.keptn.event.your-event.triggered + log.Printf("Processing environment-teardown.triggered Event") - eventData := &keptnv2.ConfigureMonitoringFinishedEventData{} + eventData := &EnvironmentTeardownTriggeredEventData{} parseKeptnCloudEventPayload(event, eventData) - // Just log this event - return GenericLogKeptnCloudEventHandler(myKeptn, event, eventData) - - // ------------------------------------------------------- - // your custom cloud event, e.g., sh.keptn.your-event - // see https://github.com/keptn-sandbox/echo-service/blob/a90207bc119c0aca18368985c7bb80dea47309e9/pkg/events.go - // for an example on how to generate your own CloudEvents and structs - case keptnv2.GetTriggeredEventType("your-event"): // sh.keptn.event.your-event.triggered - log.Printf("Processing your-event.triggered Event") - - // eventData := &keptnv2.YourEventTriggeredEventData{} - // parseKeptnCloudEventPayload(event, eventData) + return HandleEnvironmentTeardownTriggeredEvent(myKeptn, event, eventData) break case keptnv2.GetStartedEventType(keptnv2.ConfigureMonitoringTaskName): // sh.keptn.event.your-event.started log.Printf("Processing your-event.started Event") - // eventData := &keptnv2.YourEventStartedEventData{} // parseKeptnCloudEventPayload(event, eventData) @@ -513,7 +244,7 @@ func _main(args []string, env envConfig) int { keptnOptions.ConfigurationServiceURL = env.ConfigurationServiceUrl - log.Println("Starting keptn-service-template-go...") + log.Println("Starting crossplane-service...") log.Printf(" on Port = %d; Path=%s", env.Port, env.Path) ctx := context.Background() diff --git a/skaffold.yaml b/skaffold.yaml index 59e36ad..edf2c70 100644 --- a/skaffold.yaml +++ b/skaffold.yaml @@ -2,7 +2,7 @@ apiVersion: skaffold/v1beta13 kind: Config build: artifacts: - - image: keptnsandbox/keptn-service-template-go # Todo: Replace this with your image name + - image: keptnsandbox/crossplane-service # Todo: Replace this with your image name docker: dockerfile: Dockerfile buildArgs: diff --git a/test-events/get-sli.triggered.json b/test-events/get-sli.triggered.json index f32b2e7..ee40214 100644 --- a/test-events/get-sli.triggered.json +++ b/test-events/get-sli.triggered.json @@ -7,7 +7,7 @@ "response_time_p95", "some_other_metric" ], - "sliProvider": "keptn-service-template-go", + "sliProvider": "crossplane-service", "start": "2021-01-15T15:04:45.000Z" }, "labels": null,