diff --git a/azure-pipelines-example.yaml b/azure-pipelines-example.yaml index 6311eb8..a3a5506 100644 --- a/azure-pipelines-example.yaml +++ b/azure-pipelines-example.yaml @@ -89,6 +89,7 @@ stages: - script: | yq eval '.spec.template.spec.containers[0].env += [{"name": "AZURE_LOG_LEVEL", "value": "verbose"}, {"name": "AZURE_CLIENT_ID", "value": "$(AZURE_CLIENT_ID)"}, {"name": "AZURE_CLIENT_SECRET", "value": "$(AZURE_CLIENT_SECRET)"}, {"name": "AZURE_TENANT_ID", "value": "$(AZURE_TENANT_ID)"}]' -i $(Pipeline.Workspace)/manifests/deployment.yml displayName: 'Add Environment Variable with yq' + - task: KubernetesManifest@0 displayName: Deploy to Kubernetes cluster inputs: @@ -101,3 +102,12 @@ stages: containers: | $(containerRegistry)/$(imageRepository):$(tag) + - task: Kubernetes@1 + displayName: Deploy ServiceMonitor + inputs: + connectionType: Kubernetes Service Connection + kubernetesServiceEndpoint: $(kubernetesServiceConnection) + namespace: default + command: apply + useConfigurationFile: true + configuration: $(Pipeline.Workspace)/manifests/servicemonitor.yaml diff --git a/azure-pipelines-liquibase-example.yaml b/azure-pipelines-liquibase-snippet.yaml similarity index 57% rename from azure-pipelines-liquibase-example.yaml rename to azure-pipelines-liquibase-snippet.yaml index 67b9fcc..cdd017e 100644 --- a/azure-pipelines-liquibase-example.yaml +++ b/azure-pipelines-liquibase-snippet.yaml @@ -1,71 +1,9 @@ -# Deploy to Azure Kubernetes Service -# Build and push image to Azure Container Registry; Deploy to Azure Kubernetes Service -# https://docs.microsoft.com/azure/devops/pipelines/languages/docker - -trigger: - - main - -resources: - - repo: self - -variables: - - # Container registry service connection established during pipeline creation - dockerRegistryServiceConnection: 'ba554595-2da8-4cf6-88c4-a57c75966491' - imageRepository: 'multicloudapp' - containerRegistry: 'multicloud.azurecr.io' - dockerfilePath: '**/Dockerfile' - tag: '$(Build.BuildId)' - imagePullSecret: 'multicloud2012b828-auth' - - # Agent VM image name - vmImageName: 'ubuntu-latest' - - # Name of the new namespace being created to deploy the PR changes. - k8sNamespaceForPR: 'review-app-$(System.PullRequest.PullRequestId)' - -stages: - - stage: Build - displayName: Build stage - jobs: - - job: Build - displayName: Build - pool: - vmImage: $(vmImageName) - steps: - - task: JavaToolInstaller@0 - inputs: - versionSpec: '17' - jdkArchitectureOption: 'x64' - jdkSourceOption: 'PreInstalled' - - task: Maven@4 - inputs: - mavenPomFile: 'pom.xml' - publishJUnitResults: true - testResultsFiles: '**/surefire-reports/TEST-*.xml' - javaHomeOption: 'JDKVersion' - mavenVersionOption: '1.17' - mavenAuthenticateFeed: false - effectivePomSkip: false - sonarQubeRunAnalysis: false - - task: Docker@2 - displayName: Build and push an image to container registry - inputs: - command: buildAndPush - repository: $(imageRepository) - dockerfile: $(dockerfilePath) - containerRegistry: $(dockerRegistryServiceConnection) - tags: | - $(tag) - - - upload: manifests - artifact: manifests - - script: | +#As part of build... - script: | echo Downloading Liquibase and Oracle JDBC driver wget https://github.com/liquibase/liquibase/releases/download/v4.4.3/liquibase-4.4.3.tar.gz tar -xzf liquibase-4.4.3.tar.gz - wget https://path/to/ojdbc8.jar + wget https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc8.jar displayName: 'Install Liquibase and Oracle JDBC' @@ -124,3 +62,12 @@ stages: DB_USERNAME: $(DB_USERNAME) DB_PASSWORD: $(DB_PASSWORD) + - task: Kubernetes@1 + displayName: Deploy ServiceMonitor + inputs: + connectionType: Kubernetes Service Connection + kubernetesServiceEndpoint: $(kubernetesServiceConnection + namespace: default + command: apply + useConfigurationFile: true + configuration: $(Pipeline.Workspace)/manifests/servicemonitor.yaml diff --git a/azure-pipelines-observability-snippet.yaml b/azure-pipelines-observability-snippet.yaml new file mode 100644 index 0000000..98a97f0 --- /dev/null +++ b/azure-pipelines-observability-snippet.yaml @@ -0,0 +1,12 @@ + + + +- task: Kubernetes@1 + displayName: Deploy ServiceMonitor + inputs: + connectionType: Kubernetes Service Connection + kubernetesServiceEndpoint: $(kubernetesServiceConnection) + namespace: default + command: apply + useConfigurationFile: true + configuration: $(Pipeline.Workspace)/manifests/servicemonitor.yaml \ No newline at end of file diff --git a/azure-pipelines.yml b/azure-pipelines.yml index f5573ad..21faf49 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -60,7 +60,15 @@ stages: - upload: manifests artifact: manifests - + - script: | + echo Downloading Liquibase and Oracle JDBC driver + wget https://github.com/liquibase/liquibase/releases/download/v4.4.3/liquibase-4.4.3.tar.gz + tar -xzf liquibase-4.4.3.tar.gz + wget https://download.oracle.com/otn-pub/otn_software/jdbc/233/ojdbc8.jar + wget https://download.oracle.com/otn_software/java/sqldeveloper/sqlcl-latest.zip + sudo apt-get install unzip + unzip sqlcl-latest.zip + displayName: 'Install Liquibase and Oracle JDBC' - stage: Deploy @@ -102,3 +110,12 @@ stages: containers: | $(containerRegistry)/$(imageRepository):$(tag) + - task: Kubernetes@1 + displayName: Deploy ServiceMonitor + inputs: + connectionType: Kubernetes Service Connection + kubernetesServiceEndpoint: $(kubernetesServiceConnection) + namespace: default + command: apply + useConfigurationFile: true + configuration: $(Pipeline.Workspace)/manifests/servicemonitor.yaml diff --git a/db/changelog/db.changelog-master.xml b/db/changelog/db.changelog-master.xml index b6dc748..5c733b3 100644 --- a/db/changelog/db.changelog-master.xml +++ b/db/changelog/db.changelog-master.xml @@ -5,11 +5,9 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"> - - diff --git a/manifests/service.yml b/manifests/service.yml index 5848217..3732963 100644 --- a/manifests/service.yml +++ b/manifests/service.yml @@ -1,10 +1,15 @@ apiVersion: v1 kind: Service metadata: - name: multicloudapp + name: multicloudapp + labels: + app: multicloudapp + release: stable spec: - type: LoadBalancer - ports: - - port: 8080 - selector: - app: multicloudapp \ No newline at end of file + type: LoadBalancer + ports: + - port: 8080 + name: http + targetPort: 8080 + selector: + app: multicloudapp diff --git a/manifests/servicemonitor.yaml b/manifests/servicemonitor.yaml new file mode 100644 index 0000000..0a6fa08 --- /dev/null +++ b/manifests/servicemonitor.yaml @@ -0,0 +1,17 @@ +## Copyright (c) 2024 Oracle and/or its affiliates. +## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: multicloudapp-monitor + labels: + app: multicloudapp + release: prometheus +spec: + selector: + matchLabels: + app: multicloudapp + endpoints: + - interval: 20s + port: http + path: /actuator/prometheus diff --git a/observability/dashboards/multicloudapp-dashboard.json b/observability/dashboards/multicloudapp-dashboard.json new file mode 100644 index 0000000..a6bc26b --- /dev/null +++ b/observability/dashboards/multicloudapp-dashboard.json @@ -0,0 +1,242 @@ +{ + "annotations": { + "list": [ + { + "builtIn": 1, + "datasource": { + "type": "grafana", + "uid": "-- Grafana --" + }, + "enable": true, + "hide": true, + "iconColor": "rgba(0, 211, 255, 1)", + "name": "Annotations & Alerts", + "type": "dashboard" + } + ] + }, + "editable": true, + "fiscalYearStartMonth": 0, + "graphTooltip": 0, + "id": 28, + "links": [], + "liveNow": false, + "panels": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 0 + }, + "id": 1, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "jvm_threads_started_threads_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Microservice Running in Kubernetes(AKS)", + "type": "timeseries" + }, + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "fieldConfig": { + "defaults": { + "color": { + "mode": "palette-classic" + }, + "custom": { + "axisBorderShow": false, + "axisCenteredZero": false, + "axisColorMode": "text", + "axisLabel": "", + "axisPlacement": "auto", + "barAlignment": 0, + "drawStyle": "line", + "fillOpacity": 0, + "gradientMode": "none", + "hideFrom": { + "legend": false, + "tooltip": false, + "viz": false + }, + "insertNulls": false, + "lineInterpolation": "linear", + "lineWidth": 1, + "pointSize": 5, + "scaleDistribution": { + "type": "linear" + }, + "showPoints": "auto", + "spanNulls": false, + "stacking": { + "group": "A", + "mode": "none" + }, + "thresholdsStyle": { + "mode": "off" + } + }, + "mappings": [], + "thresholds": { + "mode": "absolute", + "steps": [ + { + "color": "green", + "value": null + }, + { + "color": "red", + "value": 80 + } + ] + }, + "unitScale": true + }, + "overrides": [] + }, + "gridPos": { + "h": 8, + "w": 12, + "x": 0, + "y": 8 + }, + "id": 2, + "options": { + "legend": { + "calcs": [], + "displayMode": "list", + "placement": "bottom", + "showLegend": true + }, + "tooltip": { + "mode": "single", + "sort": "none" + } + }, + "targets": [ + { + "datasource": { + "type": "prometheus", + "uid": "prometheus" + }, + "disableTextWrap": false, + "editorMode": "builder", + "expr": "oracledb_exporter_scrapes_total", + "fullMetaSearch": false, + "includeNullMetadata": true, + "instant": false, + "legendFormat": "__auto", + "range": true, + "refId": "A", + "useBackend": false + } + ], + "title": "Oracle Database Used By AKS Microservice", + "type": "timeseries" + } + ], + "refresh": "", + "schemaVersion": 39, + "tags": [], + "templating": { + "list": [] + }, + "time": { + "from": "now-6h", + "to": "now" + }, + "timepicker": {}, + "timezone": "", + "title": "MultiCloud Azure DevOps Oracle Database Dashboard", + "uid": "ec188762-611c-41f8-967d-0f4406e448c7", + "version": 2, + "weekStart": "" +} \ No newline at end of file diff --git a/observability/db-metrics-exporter/createDBExporterResources.sh b/observability/db-metrics-exporter/createDBExporterResources.sh new file mode 100644 index 0000000..b038450 --- /dev/null +++ b/observability/db-metrics-exporter/createDBExporterResources.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# Copyright (c) 2024 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +kubectl create secret generic db-secret \ +--from-literal=username=admin \ +--from-literal=password=Welcome12345 + +kubectl apply -f metrics-exporter-deployment.yaml + +kubectl apply -f metrics-exporter-service.yaml + +kubectl apply -f metrics-exporter-servicemonitor.yaml + +#kubectl port-forward deployment/prometheus-grafana 3000 +#kubectl port-forward service/prometheus-operated 9090 +#kubectl port-forward deployment/metrics-exporter 9161 +#kubectl port-forward deployment/multicloudapp 8080 diff --git a/observability/db-metrics-exporter/createWalletConfigMap.sh b/observability/db-metrics-exporter/createWalletConfigMap.sh new file mode 100755 index 0000000..64f5517 --- /dev/null +++ b/observability/db-metrics-exporter/createWalletConfigMap.sh @@ -0,0 +1,13 @@ +#!/bin/bash +# Copyright (c) 2024 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +kubectl create cm db-metrics-tns-admin \ + --from-file=cwallet.sso \ + --from-file=ewallet.p12 \ + --from-file=ewallet.pem \ + --from-file=keystore.jks \ + --from-file=ojdbc.properties \ + --from-file=sqlnet.ora \ + --from-file=tnsnames.ora \ + --from-file=truststore.jks diff --git a/observability/db-metrics-exporter/metrics-exporter-deployment.yaml b/observability/db-metrics-exporter/metrics-exporter-deployment.yaml new file mode 100644 index 0000000..518fec7 --- /dev/null +++ b/observability/db-metrics-exporter/metrics-exporter-deployment.yaml @@ -0,0 +1,68 @@ +## Copyright (c) 2021, 2023, Oracle and/or its affiliates. +## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: metrics-exporter +spec: + replicas: 1 + selector: + matchLabels: + app: metrics-exporter + template: + metadata: + labels: + app: metrics-exporter + spec: + containers: + - name: metrics-exporter + image: container-registry.oracle.com/database/observability-exporter:1.0.0 + imagePullPolicy: Always + env: + # uncomment and customize the next item if you want to provide custom metrics definitions + #- name: CUSTOM_METRICS + # value: /oracle/observability/txeventq-metrics.toml + - name: TNS_ADMIN + value: "/oracle/tns_admin" + - name: DB_USERNAME + valueFrom: + secretKeyRef: + name: db-secret + key: username + optional: false + - name: DB_PASSWORD + valueFrom: + secretKeyRef: + name: db-secret + key: password + optional: false + # update the connect string below for your database - can be simple format, or use a tns name as shown: + - name: DB_CONNECT_STRING + value: "DEVDB_TP?TNS_ADMIN=$(TNS_ADMIN)" + - name: DB_CONNECT_STRING + value: "DEVDB_TP?TNS_ADMIN=$(TNS_ADMIN)" + volumeMounts: + - name: tns-admin + mountPath: /oracle/tns_admin + # uncomment and customize the next item if you want to provide custom metrics definitions + #- name: config-volume + # mountPath: /oracle/observability/txeventq-metrics.toml + # subPath: txeventq-metrics.toml + resources: + requests: + memory: "64Mi" + cpu: "250m" + limits: + memory: "128Mi" + cpu: "500m" + ports: + - containerPort: 8080 + restartPolicy: Always + volumes: + - name: tns-admin + configMap: + name: db-metrics-tns-admin + # uncomment and customize the next item if you want to provide custom metrics definitions + #- name: config-volume + # configMap: + # name: db-metrics-txeventq-exporter-config diff --git a/observability/db-metrics-exporter/metrics-exporter-service.yaml b/observability/db-metrics-exporter/metrics-exporter-service.yaml new file mode 100644 index 0000000..67ecd3b --- /dev/null +++ b/observability/db-metrics-exporter/metrics-exporter-service.yaml @@ -0,0 +1,18 @@ +## Copyright (c) 2021, 2023, Oracle and/or its affiliates. +## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ +apiVersion: v1 +kind: Service +metadata: + name: metrics-exporter-svc + labels: + app: metrics-exporter + release: stable +spec: + type: ClusterIP + ports: + - port: 9161 + name: metrics + targetPort: 9161 + selector: + app: metrics-exporter + diff --git a/observability/db-metrics-exporter/metrics-exporter-servicemonitor.yaml b/observability/db-metrics-exporter/metrics-exporter-servicemonitor.yaml new file mode 100644 index 0000000..eadfa2f --- /dev/null +++ b/observability/db-metrics-exporter/metrics-exporter-servicemonitor.yaml @@ -0,0 +1,16 @@ +## Copyright (c) 20214 Oracle and/or its affiliates. +## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ +apiVersion: monitoring.coreos.com/v1 +kind: ServiceMonitor +metadata: + name: prometheus-metrics-exporter + labels: + app: metrics-exporter + release: prometheus +spec: + endpoints: + - interval: 20s + port: metrics + selector: + matchLabels: + app: metrics-exporter diff --git a/observability/delete_k8s_observability.sh b/observability/delete_k8s_observability.sh new file mode 100644 index 0000000..d5fa40b --- /dev/null +++ b/observability/delete_k8s_observability.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Copyright (c) 2024 Oracle and/or its affiliates. +# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. + +helm uninstall prometheus \ No newline at end of file diff --git a/observability/installPrometheusAndGrafana.sh b/observability/installPrometheusAndGrafana.sh new file mode 100755 index 0000000..a54e321 --- /dev/null +++ b/observability/installPrometheusAndGrafana.sh @@ -0,0 +1,12 @@ +#!/bin/bash +## Copyright (c) 2021 Oracle and/or its affiliates. +## Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ + +# Fail on error +set -e + +echo Installing Prometheus and Grafana ... +helm repo add prometheus-community https://prometheus-community.github.io/helm-charts +helm repo add stable https://charts.helm.sh/stable +helm repo update +helm install prometheus prometheus-community/kube-prometheus-stack diff --git a/pom.xml b/pom.xml index 793d245..5553082 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,19 @@ ${spring.boot.version} test + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-actuator + + + io.micrometer + micrometer-registry-prometheus + runtime + com.oracle.database.jdbc diff --git a/sql/createtable.sql b/sql/createtable.sql new file mode 100644 index 0000000..e07d041 --- /dev/null +++ b/sql/createtable.sql @@ -0,0 +1 @@ +CREATE TABLE cicd_test_table (testvalue varchar2(64)) diff --git a/sql/createuser.sql b/sql/createuser.sql new file mode 100644 index 0000000..6f35a03 --- /dev/null +++ b/sql/createuser.sql @@ -0,0 +1,5 @@ +CREATE USER aiuser identified BY [Yourpassword]; +GRANT CREATE session TO aiuser; +GRANT RESOURCE TO aiuser; +GRANT unlimited tablespace TO aiuser; +GRANT execute on DBMS_CLOUD to aiuser; \ No newline at end of file diff --git a/src/main/java/oraclemulticloud/MultiCloudController.java b/src/main/java/oraclemulticloud/MultiCloudController.java index bfa1660..4f0f00e 100644 --- a/src/main/java/oraclemulticloud/MultiCloudController.java +++ b/src/main/java/oraclemulticloud/MultiCloudController.java @@ -34,7 +34,8 @@ public String test() throws Exception { Connection cn = ds.getConnection(); Statement st = cn.createStatement(); String returnString = cn + " "; -// Replace with "SELECT 'Hello, db' FROM sys.dual" if cicd_test_table doesn't exist or any other applicable SQL + //Replace with "SELECT 'Hello, db' FROM sys.dual" or any other applicable SQL if cicd_test_table doesn't exist + //Command here can be used to test database changes and liquibase, ie db/changelog/db.changelog-master.xml - eg rollback, etc. ResultSet rs = st.executeQuery("SELECT * FROM cicd_test_table"); if (rs.next()) returnString+= "value = " + rs.getString(1) + " : "; return "got the conn :" + returnString; diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 4a06365..969be04 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -11,3 +11,8 @@ spring: logging: level: org.springframework.web.cors: DEBUG +management: + endpoints: + web: + exposure: + include: [ "prometheus" ] \ No newline at end of file