diff --git a/user-skel/.ace/ace b/user-skel/.ace/ace index 7df888f36..2b5e878d6 100755 --- a/user-skel/.ace/ace +++ b/user-skel/.ace/ace @@ -48,6 +48,7 @@ enable_targets = [ 'demo_monaco_gitops', 'demo_ar_workflows_gitlab', 'demo_release_validation_srg_gitlab', + 'demo_release_validation_srg_jenkins', 'demo_ar_workflows_ansible' ] diff --git a/user-skel/ansible_collections/ace_box/ace_box/playbooks/main_v2.yml b/user-skel/ansible_collections/ace_box/ace_box/playbooks/main_v2.yml index a361e13d1..ac90cd64b 100644 --- a/user-skel/ansible_collections/ace_box/ace_box/playbooks/main_v2.yml +++ b/user-skel/ansible_collections/ace_box/ace_box/playbooks/main_v2.yml @@ -47,6 +47,12 @@ - demo_release_validation_srg_gitlab - never + # Use case - Release Validation with Site Reliability Guardion via Jenkins + - role: demo-release-validation-srg-jenkins + tags: + - demo_release_validation_srg_jenkins + - never + # Use case - Auto Remediation Workflows with Ansible - role: demo-ar-workflows-ansible tags: diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/defaults/main.yml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/defaults/main.yml new file mode 100644 index 000000000..5ca05ea2c --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/defaults/main.yml @@ -0,0 +1,5 @@ +--- +demo_quality_gates_jenkins_org: "demo" +demo_quality_gates_jenkins_repo_name: "release-validation-jenkins" +demo_quality_gates_jenkins_folder: "demo-release-validation-jenkins" +monacoVersion: "2.9.2" diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/01_build_images.Jenkinsfile b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/01_build_images.Jenkinsfile new file mode 100644 index 000000000..2393df260 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/01_build_images.Jenkinsfile @@ -0,0 +1,129 @@ +pipeline { + agent { + label 'nodejs' + } + stages { + stage('Node build') { + steps { + checkout scm + container('nodejs') { + sh 'npm install' + } + } + } + stage('Docker build and push') { + parallel { + stage('Build 1') { + environment { + BUILD = '1' + GIT_COMMIT_SHORT = sh(returnStdout: true, script: "echo ${env.GIT_COMMIT} | cut -c1-6 | tr -d '\n'") + // Release product may not end in string, as Dynatrace won't merge + // services required to be merged for canary baselining + RELEASE_PRODUCT = 'simplenodeservice' + RELEASE_VERSION = "${env.BUILD}.0.0" + RELEASE_BUILD_VERSION = "${env.RELEASE_VERSION}-${env.GIT_COMMIT_SHORT}" + IMAGE_TAG = "${env.RELEASE_BUILD_VERSION}" + IMAGE_NAME = "${env.DOCKER_REGISTRY_URL}/${env.RELEASE_PRODUCT}" + IS_CANARY = false + CANARY_WEIGHT = '0' + // Usually, RELEASE_PRODUCT and HELM_RELEASE_NAME can be the same. For our demo, + // i.e. the NGINX canary feature, we need to deloy both Helm releases in the same + // namespace and therefore overwrite the release name. + HELM_RELEASE_NAME = 'simplenodeservice-0' + } + stages { + stage('Docker build') { + steps { + container('docker') { + sh "docker build --build-arg BUILD_NUMBER=${env.BUILD} -t ${env.IMAGE_NAME}:${env.IMAGE_TAG} ." + } + } + } + stage('Docker push') { + steps { + container('docker') { + sh "docker push ${env.IMAGE_NAME}:${env.IMAGE_TAG}" + } + } + } + stage('Deploy good build') { + steps { + build job: 'demo-ar-workflows-ansible/3. Deploy', + wait: false, + parameters: [ + string(name: 'RELEASE_PRODUCT', value: "${env.RELEASE_PRODUCT}"), + string(name: 'RELEASE_VERSION', value: "${env.RELEASE_VERSION}"), + string(name: 'RELEASE_BUILD_VERSION', value: "${env.RELEASE_BUILD_VERSION}"), + string(name: 'RELEASE_STAGE', value: 'canary-jenkins'), + string(name: 'IMAGE_TAG', value: "${env.IMAGE_TAG}"), + string(name: 'IMAGE_NAME', value: "${env.IMAGE_NAME}"), + booleanParam(name: 'IS_CANARY', value: "${env.IS_CANARY}"), + string(name: 'CANARY_WEIGHT', value: "${env.CANARY_WEIGHT}"), + string(name: 'HELM_RELEASE_NAME', value: "${env.HELM_RELEASE_NAME}") + ] + } + } + } + } + stage('Build 4') { + environment { + BUILD = '4' + GIT_COMMIT_SHORT = sh(returnStdout: true, script: "echo ${env.GIT_COMMIT} | cut -c1-6 | tr -d '\n'") + // Release product may not end in string, as Dynatrace won't merge + // services required to be merged for canary baselining + RELEASE_PRODUCT = 'simplenodeservice' + RELEASE_VERSION = "${env.BUILD}.0.0" + RELEASE_BUILD_VERSION = "${env.RELEASE_VERSION}-${env.GIT_COMMIT_SHORT}" + IMAGE_TAG = "${env.RELEASE_BUILD_VERSION}" + IMAGE_NAME = "${env.DOCKER_REGISTRY_URL}/${env.RELEASE_PRODUCT}" + IS_CANARY = true + CANARY_WEIGHT = '0' + // Usually, RELEASE_PRODUCT and HELM_RELEASE_NAME can be the same. For our demo, + // i.e. the NGINX canary feature, we need to deloy both Helm releases in the same + // namespace and therefore overwrite the release name. + HELM_RELEASE_NAME = 'simplenodeservice-1' + } + stages { + stage('Docker build') { + steps { + container('docker') { + sh "docker build --build-arg BUILD_NUMBER=${env.BUILD} -t ${env.IMAGE_NAME}:${env.IMAGE_TAG} ." + } + } + } + stage('Docker push') { + steps { + container('docker') { + sh "docker push ${env.IMAGE_NAME}:${env.IMAGE_TAG}" + } + } + } + stage('Deploy faulty build') { + steps { + build job: 'demo-ar-workflows-ansible/3. Deploy', + wait: false, + parameters: [ + string(name: 'RELEASE_PRODUCT', value: "${env.RELEASE_PRODUCT}"), + string(name: 'RELEASE_VERSION', value: "${env.RELEASE_VERSION}"), + string(name: 'RELEASE_BUILD_VERSION', value: "${env.RELEASE_BUILD_VERSION}"), + string(name: 'RELEASE_STAGE', value: 'canary-jenkins'), + string(name: 'IMAGE_TAG', value: "${env.IMAGE_TAG}"), + string(name: 'IMAGE_NAME', value: "${env.IMAGE_NAME}"), + booleanParam(name: 'IS_CANARY', value: "${env.IS_CANARY}"), + string(name: 'CANARY_WEIGHT', value: "${env.CANARY_WEIGHT}"), + string(name: 'HELM_RELEASE_NAME', value: "${env.HELM_RELEASE_NAME}") + ] + } + } + } + } + } + } + stage('Monaco') { + steps { + build job: 'demo-ar-workflows-ansible/2. Monaco', + wait: false + } + } + } +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/02_monaco.Jenkinsfile b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/02_monaco.Jenkinsfile new file mode 100644 index 000000000..f7ae33ead --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/02_monaco.Jenkinsfile @@ -0,0 +1,93 @@ +@Library('ace@v1.1') +def event = new com.dynatrace.ace.Event() + +pipeline { + agent { + label 'monaco-runner' + } + environment { + DT_API_TOKEN = credentials('DT_API_TOKEN') + DT_TENANT_URL = "${env.DYNATRACE_URL_GEN3}" + DT_OAUTH_CLIENT_ID = credentials('DT_OAUTH_CLIENT_ID') + DT_OAUTH_CLIENT_SECRET = credentials('DT_OAUTH_CLIENT_SECRET') + DT_OAUTH_SSO_ENDPOINT = credentials('DT_OAUTH_SSO_ENDPOINT') + AWX_BASIC_AUTH = credentials('AWX_BASIC_AUTH') + // As of June 2023, MONACO_FEAT_AUTOMATION_RESOURCES flag required as feature is in preview + MONACO_FEAT_AUTOMATION_RESOURCES = '1' + // Monaco variables + DT_OWNER_IDENTIFIER = 'demo-ar-workflows-ansible' + RELEASE_PRODUCT = 'simplenodeservice' + RELEASE_STAGE = 'canary-jenkins' + } + stages { + stage('Dynatrace global project - Validate') { + steps { + container('monaco') { + script { + sh 'monaco deploy monaco/manifest.yaml -p global -d' + } + } + } + } + stage('Dynatrace global project - Deploy') { + steps { + container('monaco') { + script { + sh 'monaco deploy monaco/manifest.yaml -p global' + } + } + } + } + stage('Dynatrace app project - Validate') { + steps { + container('monaco') { + script { + sh 'monaco deploy monaco/manifest.yaml -p app -d' + } + } + } + } + stage('Dynatrace app project - Deploy') { + steps { + container('monaco') { + script { + sh 'monaco deploy monaco/manifest.yaml -p app' + } + } + } + } + stage('Dynatrace configuration event') { + steps { + script { + // Give Dynatrace a couple seconds to tag host according to current config + sleep(time:120, unit:'SECONDS') + + event.pushDynatraceConfigurationEvent( + tagRule: getTagRulesForHostEvent('ace-demo-canary'), + description: 'Monaco deployment successful: ace-demo-canary', + configuration: 'ace-demo-canary', + customProperties: [ + 'Approved by': 'ACE' + ] + ) + } + } + } + } +} + +// +// Legacy tag rules function can be removed with availabilty of dta feature +// +def getTagRulesForHostEvent(hostTag) { + def tagMatchRules = [ + [ + 'meTypes': ['HOST'], + tags: [ + ['context': 'CONTEXTLESS', 'key': hostTag] + ] + ] + ] + + return tagMatchRules +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/03_deploy.Jenkinsfile b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/03_deploy.Jenkinsfile new file mode 100644 index 000000000..88abf1858 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/03_deploy.Jenkinsfile @@ -0,0 +1,133 @@ +@Library('ace@v1.1') +def event = new com.dynatrace.ace.Event() + +pipeline { + parameters { + string( + name: 'RELEASE_PRODUCT', + defaultValue: 'simplenodeservice', + description: 'The name of the service to deploy.', + trim: true + ) + string( + name: 'IMAGE_NAME', + defaultValue: '', + description: 'The image name of the service to deploy.', + trim: true + ) + string(name: 'IMAGE_TAG', defaultValue: '', description: 'The image tag of the service to deploy.', trim: true) + string(name: 'RELEASE_VERSION', defaultValue: '', description: 'SemVer release version.', trim: true) + string( + name: 'RELEASE_BUILD_VERSION', + defaultValue: '', + description: 'Release version, including build id.', + trim: true + ) + string( + name: 'RELEASE_STAGE', + defaultValue: 'canary-jenkins', + description: 'Namespace service will be deployed in.', + trim: true + ) + string( + name: 'CANARY_WEIGHT', + defaultValue: '0', + description: 'Weight of traffic that will be routed to service.', + trim: true + ) + booleanParam(name: 'IS_CANARY', defaultValue: false, description: 'Is canary version of service.') + string( + name: 'HELM_RELEASE_NAME', + defaultValue: 'simplenodeservice', + description: 'The name of the Helm release.', + trim: true + ) + } + agent { + label 'kubegit' + } + environment { + DT_API_TOKEN = credentials('DT_API_TOKEN') + DT_TENANT_URL = credentials('DT_TENANT_URL') + } + stages { + stage('Deploy') { + steps { + script { + env.DT_CUSTOM_PROP = generateMetaData() + env.DT_TAGS = "non-prod BUILD=${env.RELEASE_BUILD_VERSION}" + } + container('helm') { + sh "helm upgrade --install ${env.HELM_RELEASE_NAME} helm/simplenodeservice \ + --set image=\"${env.IMAGE_NAME}:${env.IMAGE_TAG}\" \ + --set domain=${env.INGRESS_DOMAIN} \ + --set version=${env.RELEASE_VERSION} \ + --set build_version=${env.RELEASE_BUILD_VERSION} \ + --set ingress.isCanary=${env.IS_CANARY} \ + --set ingress.canaryWeight=${env.CANARY_WEIGHT} \ + --set dt_release_product=\"${env.RELEASE_PRODUCT}\" \ + --set dt_owner=\"demo-ar-workflows-ansible\" \ + --set dt_tags=\"${env.DT_TAGS}\" \ + --set dt_custom_prop=\"${env.DT_CUSTOM_PROP}\" \ + --namespace ${env.RELEASE_STAGE} --create-namespace \ + --wait" + } + } + } + stage('Dynatrace deployment event') { + steps { + script { + sleep(time:120, unit:'SECONDS') + + event.pushDynatraceDeploymentEvent( + tagRule: getTagRulesForPGIEvent(), + deploymentName: "${env.RELEASE_PRODUCT} ${env.RELEASE_BUILD_VERSION} deployed", + deploymentVersion: "${env.RELEASE_BUILD_VERSION}", + deploymentProject: "${env.RELEASE_PRODUCT}", + customProperties : [ + 'Jenkins Build Number': "${env.BUILD_ID}", + 'Approved by':'ACE' + ] + ) + } + } + } + } +} + +def generateMetaData() { + String returnValue = '' + + returnValue += 'FriendlyName=simplenode ' + returnValue += 'SERVICE_TYPE=FRONTEND ' + returnValue += 'Project=simpleproject ' + returnValue += 'DesignDocument=https://simple-corp.com/stories/simplenodeservice ' + returnValue += 'Tier=1 ' + returnValue += 'Class=Gold ' + returnValue += 'Purpose=ACE ' + returnValue += "SCM=${env.GIT_URL} " + returnValue += "Branch=${env.GIT_BRANCH} " + returnValue += "Build=${env.RELEASE_BUILD_VERSION} " + returnValue += "Version=${env.RELEASE_VERSION} " + returnValue += "Image=${env.IMAGE_NAME}:${env.IMAGE_TAG} " + returnValue += "url=${env.RELEASE_PRODUCT}-${env.RELEASE_STAGE}.${env.INGRESS_DOMAIN}" + return returnValue +} + +// +// Legacy tag rules function can be removed with availabilty of dta feature +// +def getTagRulesForPGIEvent() { + def tagMatchRules = [ + [ + 'meTypes': ['PROCESS_GROUP_INSTANCE'], + tags: [ + ['context': 'ENVIRONMENT', 'key': 'DT_RELEASE_PRODUCT', 'value': "${env.RELEASE_PRODUCT}"], + ['context': 'ENVIRONMENT', 'key': 'DT_RELEASE_STAGE', 'value': "${env.RELEASE_STAGE}"], + ['context': 'ENVIRONMENT', 'key': 'DT_RELEASE_BUILD_VERSION', 'value': "${env.RELEASE_BUILD_VERSION}"] + ] + ] + ] + + return tagMatchRules +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/04_canary.Jenkinsfile b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/04_canary.Jenkinsfile new file mode 100644 index 000000000..ff4044ce3 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/jenkins/04_canary.Jenkinsfile @@ -0,0 +1,101 @@ +@Library('ace@v1.1') +def event = new com.dynatrace.ace.Event() + +pipeline { + agent { + label 'kubegit' + } + parameters { + string( + name: 'CANARY_WEIGHT', + defaultValue: '0', + description: 'Weight of traffic that will be routed to service.', + trim: true + ) + string( + name: 'REMEDIATION_URL', + defaultValue: '', + description: 'Remediation script to call if canary release fails', + trim: true + ) + string( + name: 'REMEDIATION_TYPE', + defaultValue: '', + description: 'Remediation type to target specific remediation handler', + trim: true + ) + string( + name: 'RELEASE_STAGE', + defaultValue: 'canary-jenkins', + description: 'Namespace service will be deployed in.', + trim: true + ) + string( + name: 'RELEASE_PRODUCT', + defaultValue: 'simplenodeservice', + description: 'The name of the service to deploy.', + trim: true + ) + } + environment { + DT_API_TOKEN = credentials('DT_API_TOKEN') + DT_TENANT_URL = credentials('DT_TENANT_URL') + // RELEASE_STAGE = 'canary-jenkins' + // RELEASE_PRODUCT = 'simplenodeservice' + } + stages { + stage('Retrieve canary metadata') { + steps { + container('kubectl') { + script { + env.CANARY_NAME = sh(returnStdout: true, script: "kubectl -n ${params.RELEASE_STAGE} get ingress -o=jsonpath='{.items[?(@.metadata.annotations.nginx\\.ingress\\.kubernetes\\.io/canary==\"true\")].metadata.name}'") + // env.NON_CANARY_NAME = sh(returnStdout: true, script: "kubectl -n ${env.RELEASE_STAGE} get ingress -o=jsonpath='{.items[?(@.metadata.annotations.nginx\\.ingress\\.kubernetes\\.io/canary==\"false\")].metadata.name}'") + } + } + } + } + stage('Shift traffic') { + steps { + container('kubectl') { + sh "kubectl -n ${params.RELEASE_STAGE} annotate ingress ${env.CANARY_NAME} nginx.ingress.kubernetes.io/canary-weight='${params.CANARY_WEIGHT}' --overwrite" + } + } + } + stage('Dynatrace configuration change event') { + steps { + script { + // env.RELEASE_BUILD_VERSION = sh(returnStdout: true, script: "kubectl -n ${env.RELEASE_STAGE} get deployment ${env.CANARY_NAME} -o=jsonpath='{.metadata.labels.app\\.kubernetes\\.io/version}'") + // sh "echo ${env.RELEASE_BUILD_VERSION}" + + event.pushDynatraceConfigurationEvent( + tagRule : getTagRulesForServiceEvent(), + description : "${params.RELEASE_PRODUCT} canary weight set to ${params.CANARY_WEIGHT}%", + source : 'Jenkins', + configuration : 'Load Balancer', + customProperties : [ + 'remediationAction': "${params.REMEDIATION_URL}", + 'remediationType': "${params.REMEDIATION_TYPE}" + ] + ) + } + } + } + } +} + +// +// Legacy tag rules function can be removed with availabilty of dta feature +// +def getTagRulesForServiceEvent() { + def tagMatchRules = [ + [ + 'meTypes': ['SERVICE'], + tags: [ + ['context': 'ENVIRONMENT', 'key': 'DT_RELEASE_PRODUCT', 'value': "${params.RELEASE_PRODUCT}"], + ['context': 'ENVIRONMENT', 'key': 'DT_RELEASE_STAGE', 'value': "${params.RELEASE_STAGE}"] + ] + ] + ] + + return tagMatchRules +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/_config.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/_config.yaml new file mode 100644 index 000000000..aa4b03de6 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/_config.yaml @@ -0,0 +1,333 @@ +configs: + # ownership + - id: owner_simplenode_rv_srg_staging + config: + name: + type: environment + name: DT_OWNER_IDENTIFIER + template: ownership.json + skip: false + parameters: + identifier: + type: environment + name: DT_OWNER_IDENTIFIER + email: ace@dynatrace.com + solution: ACE-Box + # As of May 2023 there is no Gitlab integration. We therefore repurpose + # the JIRA integration as it has the biggest overlap with what we need for + # integrating with Gitlab's issue tracker. + gitlabProjectId: + type: environment + name: GITLAB_PROJECT_ID + gitlabDefaultAssigneeId: + type: environment + name: GITLAB_DEFAULT_ASSIGNEE_ID + type: + settings: + schema: builtin:ownership.teams + schemaVersion: 1.0.6 + scope: environment + groupOverrides: + - group: production + override: + skip: true + + # auto-tag + - id: autoTagApp + type: + api: auto-tag + config: + template: auto-tag-app.json + name: + type: compound + format: "{{ .releaseStage }}-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + parameters: + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + releaseStage: + type: environment + name: RELEASE_STAGE + applicationName: ["application-web", "app", "name"] + hostGroup: + type: environment + name: HOST_GROUP + default: "ace-box" + + # application-web + - id: app + type: + api: application-web + config: + template: application.json + name: + type: compound + format: "{{ .releaseProduct }}-{{ .releaseStage }}-{{ .demoIdentifier }}" + references: + - releaseProduct + - releaseStage + - demoIdentifier + parameters: + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + skip: false + + # app-detection-rule + - id: appDetection + type: + settings: + schema: builtin:rum.web.app-detection + scope: environment + schemaVersion: "2.0.1" + config: + name: + type: compound + format: "{{ .releaseStage }}-app-detection-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + template: application-detection-rule.json + parameters: + applicationId: ["application-web", "app", "id"] + pattern: + type: compound + format: "{{ .ingressProtocol }}://{{ .releaseProduct }}-{{ .releaseStage }}.{{ .ingressDomain }}" + references: + - ingressProtocol + - releaseProduct + - releaseStage + - ingressDomain + ingressProtocol: + type: environment + name: INGRESS_PROTOCOL + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + ingressDomain: + type: environment + name: INGRESS_DOMAIN + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + skip: false + + #calculated metrics service + - id: csmFailureRate + type: + api: calculated-metrics-service + config: + name: + type: compound + format: "{{ .releaseStage }}-failure_rate_by_version-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + template: csm-failure-rate.json + skip: false + parameters: + metricKey: + type: compound + format: "calc:service.{{ .name }}" + references: + - name + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + + - id: csmResponseTime + type: + api: calculated-metrics-service + config: + name: + type: compound + format: "{{ .releaseStage }}-response_time_by_version-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + template: csm-response-time.json + skip: false + parameters: + metricKey: + type: compound + format: "calc:service.{{ .name }}" + references: + - name + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + + #slo + - id: slo_success_rate + type: + api: slo + config: + template: slo.json + name: + type: compound + format: "{{ .tag_stage }}_slo_success_rate_{{ .demoIdentifier }}" + references: + - tag_stage + - demoIdentifier + parameters: + description: "Service Errors Total SuccessCount / Service RequestCount Total" + metricNumerator: "builtin:service.errors.total.successCount:splitBy()" + metricDenominator: "builtin:service.requestCount.total:splitBy()" + filterType: "SERVICE" + target: 95 + warning: 99 + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + sloTimeFrame: + type: compound + format: "-{{ .timeFrame }}" + references: + - timeFrame + timeFrame: + type: environment + name: TEST_TIMEFRAME + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + tag_stage: + type: environment + name: SRG_EVALUATION_STAGE + skip: false + + - id: slo_availability + type: + api: slo + config: + template: slo.json + name: + type: compound + format: "{{ .tag_stage }}_slo_availability_{{ .demoIdentifier }}" + references: + - tag_stage + - demoIdentifier + parameters: + description: "Service Availability" + metricNumerator: "builtin:service.errors.server.successCount:splitBy()" + metricDenominator: "builtin:service.requestCount.server:splitBy()" + filterType: "SERVICE" + target: 95 + warning: 99 + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + sloTimeFrame: + type: compound + format: "-{{ .timeFrame }}" + references: + - timeFrame + timeFrame: + type: environment + name: TEST_TIMEFRAME + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + tag_stage: + type: environment + name: SRG_EVALUATION_STAGE + skip: false + + + # dashboard + - id: dashboard + type: + api: dashboard + config: + template: dashboard.json + name: + type: compound + format: "{{ .releaseStage }}-dashboard-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + skip: false + parameters: + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + sloId: ["slo", "slo_success_rate", "id"] + csmFailureRateMetricKey: ["calculated-metrics-service", "csmFailureRate", "metricKey"] + csmResponseTimeMetricKey: ["calculated-metrics-service", "csmResponseTime", "metricKey"] + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + + # synthetic-monitor + - id: health-simplenode + type: + api: synthetic-monitor + config: + name: + type: compound + format: "{{ .releaseStage }}-health-check-{{ .demoIdentifier }}" + references: + - releaseStage + - demoIdentifier + template: health-check-monitor.json + parameters: + description: Health check for simplenode in app-one + location: ["infrastructure","synthetic-location", "synthetic-location-ace-box", "id"] + tag: ["auto-tag", "autoTagApp", "name"] + frequencyMin: 5 + url: + type: compound + format: "{{ .ingressProtocol }}://{{ .releaseProduct }}-{{ .releaseStage }}.{{ .ingressDomain }}" + references: + - ingressProtocol + - releaseProduct + - releaseStage + - ingressDomain + ingressProtocol: + type: environment + name: INGRESS_PROTOCOL + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + ingressDomain: + type: environment + name: INGRESS_DOMAIN + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + skip: false diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application-detection-rule.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application-detection-rule.json new file mode 100644 index 000000000..6ed187654 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application-detection-rule.json @@ -0,0 +1,5 @@ +{ + "matcher":"URL_STARTS_WITH", + "pattern":"{{ .pattern }}", + "applicationId":"{{ .applicationId }}" +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application.json new file mode 100644 index 000000000..4b4dedd2d --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/application.json @@ -0,0 +1,123 @@ +{ + "name": "{{ .name }}", + "realUserMonitoringEnabled": true, + "costControlUserSessionPercentage": 10, + "loadActionKeyPerformanceMetric": "VISUALLY_COMPLETE", + "xhrActionKeyPerformanceMetric": "VISUALLY_COMPLETE", + "loadActionApdexSettings": { + "threshold": 1, + "toleratedThreshold": 1000, + "frustratingThreshold": 3000, + "toleratedFallbackThreshold": 1300, + "frustratingFallbackThreshold": 3300, + "considerJavaScriptErrors": true + }, + "xhrActionApdexSettings": { + "threshold": 3, + "toleratedThreshold": 3000, + "frustratingThreshold": 12000, + "toleratedFallbackThreshold": 3000, + "frustratingFallbackThreshold": 12000, + "considerJavaScriptErrors": true + }, + "customActionApdexSettings": { + "threshold": 3, + "toleratedThreshold": 3000, + "frustratingThreshold": 12000, + "toleratedFallbackThreshold": 3000, + "frustratingFallbackThreshold": 12000, + "considerJavaScriptErrors": true + }, + "waterfallSettings": { + "uncompressedResourcesThreshold": 860, + "resourcesThreshold": 100000, + "resourceBrowserCachingThreshold": 50, + "slowFirstPartyResourcesThreshold": 200000, + "slowThirdPartyResourcesThreshold": 200000, + "slowCdnResourcesThreshold": 200000, + "speedIndexVisuallyCompleteRatioThreshold": 50 + }, + "monitoringSettings": { + "fetchRequests": true, + "xmlHttpRequest": true, + "javaScriptFrameworkSupport": { + "angular": true, + "dojo": false, + "extJS": false, + "icefaces": false, + "jQuery": false, + "mooTools": false, + "prototype": false, + "activeXObject": false + }, + "contentCapture": { + "resourceTimingSettings": { + "w3cResourceTimings": true, + "nonW3cResourceTimings": false, + "nonW3cResourceTimingsInstrumentationDelay": 50, + "resourceTimingCaptureType": "CAPTURE_FULL_DETAILS", + "resourceTimingsDomainLimit": 10 + }, + "javaScriptErrors": true, + "timeoutSettings": { + "timedActionSupport": false, + "temporaryActionLimit": 0, + "temporaryActionTotalTimeout": 100 + }, + "visuallyCompleteAndSpeedIndex": true + }, + "excludeXhrRegex": "", + "injectionMode": "JAVASCRIPT_TAG", + "libraryFileLocation": "", + "monitoringDataPath": "", + "customConfigurationProperties": "", + "serverRequestPathId": "", + "secureCookieAttribute": false, + "cookiePlacementDomain": "", + "cacheControlHeaderOptimizations": true, + "advancedJavaScriptTagSettings": { + "syncBeaconFirefox": false, + "syncBeaconInternetExplorer": false, + "instrumentUnsupportedAjaxFrameworks": false, + "specialCharactersToEscape": "", + "maxActionNameLength": 100, + "maxErrorsToCapture": 10, + "additionalEventHandlers": { + "userMouseupEventForClicks": false, + "clickEventHandler": false, + "mouseupEventHandler": false, + "blurEventHandler": false, + "changeEventHandler": false, + "toStringMethod": false, + "maxDomNodesToInstrument": 5000 + }, + "eventWrapperSettings": { + "click": false, + "mouseUp": false, + "change": false, + "blur": false, + "touchStart": false, + "touchEnd": false + }, + "globalEventCaptureSettings": { + "mouseUp": true, + "mouseDown": true, + "click": true, + "doubleClick": true, + "keyUp": true, + "keyDown": true, + "scroll": true, + "additionalEventCapturedAsUserInput": "" + } + } + }, + "userActionNamingSettings": { + "placeholders": [], + "loadActionNamingRules": [], + "xhrActionNamingRules": [], + "ignoreCase": true, + "splitUserActionsByDomain": true + }, + "metaDataCaptureSettings": [], + "conversionGoals": [] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/auto-tag-app.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/auto-tag-app.json new file mode 100644 index 000000000..6af172d3c --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/auto-tag-app.json @@ -0,0 +1,92 @@ +{ + "name": "{{ .name }}", + "rules": [ + { + "type": "PROCESS_GROUP", + "enabled": true, + "valueFormat": null, + "propagationTypes": [ + "PROCESS_GROUP_TO_SERVICE" + ], + "conditions": [ + { + "key": { + "attribute": "PROCESS_GROUP_PREDEFINED_METADATA", + "dynamicKey": "KUBERNETES_NAMESPACE", + "type": "PROCESS_PREDEFINED_METADATA_KEY" + }, + "comparisonInfo": { + "type": "STRING", + "operator": "EQUALS", + "value": "{{ .releaseStage }}", + "negate": false, + "caseSensitive": true + } + } + ] + }, + { + "type": "SERVICE", + "enabled": true, + "valueFormat": null, + "propagationTypes": [], + "conditions": [ + { + "key": { + "attribute": "SERVICE_TYPE" + }, + "comparisonInfo": { + "type": "SERVICE_TYPE", + "operator": "EQUALS", + "value": "DATABASE_SERVICE", + "negate": false + } + } + ] + }, + { + "type": "APPLICATION", + "enabled": true, + "valueFormat": null, + "normalization": "LEAVE_TEXT_AS_IS", + "propagationTypes": [], + "conditions": [ + { + "key": { + "attribute": "WEB_APPLICATION_NAME", + "type": "STATIC" + }, + "comparisonInfo": { + "type": "STRING", + "operator": "EQUALS", + "value": "{{ .applicationName }}", + "negate": false, + "caseSensitive": true + } + } + ] + }, + { + "type": "HOST", + "enabled": true, + "valueFormat": null, + "normalization": "LEAVE_TEXT_AS_IS", + "propagationTypes": [], + "conditions": [ + { + "key": { + "attribute": "HOST_GROUP_NAME", + "type": "STATIC" + }, + "comparisonInfo": { + "type": "STRING", + "operator": "EQUALS", + "value": "{{ .hostGroup }}", + "negate": false, + "caseSensitive": true + } + } + ] + } + ] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-failure-rate.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-failure-rate.json new file mode 100644 index 000000000..74e896dc5 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-failure-rate.json @@ -0,0 +1,36 @@ +{ + "tsmMetricKey": "{{ .metricKey }}", + "name": "{{ .name }}", + "enabled": true, + "metricDefinition": { + "metric": "FAILURE_RATE", + "requestAttribute": null + }, + "unit": "PERCENT", + "unitDisplayName": "", + "entityId": null, + "managementZones": [], + "conditions": [ + { + "attribute": "SERVICE_TAG", + "comparisonInfo": { + "type": "TAG", + "comparison": "EQUALS", + "value": { + "context": "ENVIRONMENT", + "key": "DT_RELEASE_STAGE", + "value": "{{ .releaseStage }}" + }, + "negate": false + } + } + ], + "dimensionDefinition": { + "name": "version", + "dimension": "{Request:ApplicationBuildVersion}", + "placeholders": [], + "topX": 100, + "topXDirection": "DESCENDING", + "topXAggregation": "OF_INTEREST_RATIO" + } +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-response-time.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-response-time.json new file mode 100644 index 000000000..5e45c060d --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/csm-response-time.json @@ -0,0 +1,35 @@ +{ + "tsmMetricKey": "{{ .metricKey }}", + "name": "{{ .name }}", + "enabled": true, + "metricDefinition": { + "metric": "RESPONSE_TIME", + "requestAttribute": null + }, + "unit": "MICRO_SECOND", + "unitDisplayName": "", + "managementZones": [], + "conditions": [ + { + "attribute": "SERVICE_TAG", + "comparisonInfo": { + "type": "TAG", + "comparison": "EQUALS", + "value": { + "context": "ENVIRONMENT", + "key": "DT_RELEASE_STAGE", + "value": "{{ .releaseStage }}" + }, + "negate": false + } + } + ], + "dimensionDefinition": { + "name": "version", + "dimension": "{Request:ApplicationBuildVersion}", + "placeholders": [], + "topX": 100, + "topXDirection": "DESCENDING", + "topXAggregation": "AVERAGE" + } +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/dashboard.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/dashboard.json new file mode 100644 index 000000000..bfbee24f8 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/dashboard.json @@ -0,0 +1,300 @@ +{ + "dashboardMetadata": { + "name": "{{.name}}", + "shared": true, + "owner": "", + "dashboardFilter": { + "timeframe": "-30m" + } + }, + "tiles": [ + { + "name": "Service health", + "tileType": "SERVICES", + "configured": true, + "bounds": { + "top": 266, + "left": 1140, + "width": 152, + "height": 152 + }, + "tileFilter": {}, + "chartVisible": true + }, + { + "name": "Service-level objective", + "tileType": "SLO", + "configured": true, + "bounds": { + "top": 266, + "left": 684, + "width": 304, + "height": 152 + }, + "tileFilter": {}, + "assignedEntities": ["{{ .sloId }}"], + "metric": "METRICS=true;LEGEND=true;PROBLEMS=true;decimals=10;customTitle=ace-demo-canary;" + }, + { + "name": "Response time by version", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 266, + "left": 0, + "width": 684, + "height": 266 + }, + "tileFilter": {}, + "customName": "Response time by version", + "queries": [ + { + "id": "A", + "metric": "{{ .csmResponseTimeMetricKey }}", + "spaceAggregation": "AVG", + "timeAggregation": "DEFAULT", + "splitBy": ["version"], + "filterBy": { + "nestedFilters": [], + "criteria": [] + }, + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": {}, + "rules": [ + { + "matcher": "A:", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "visible": true + } + ] + } + }, + { + "name": "Load by version", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 532, + "left": 0, + "width": 684, + "height": 266 + }, + "tileFilter": {}, + "customName": "Data explorer results", + "queries": [ + { + "id": "A", + "metric": "{{ .csmResponseTimeMetricKey }}", + "spaceAggregation": "COUNT", + "timeAggregation": "DEFAULT", + "splitBy": ["version"], + "filterBy": { + "nestedFilters": [], + "criteria": [] + }, + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": {}, + "rules": [ + { + "matcher": "A:", + "properties": { + "color": "DEFAULT", + "seriesType": "AREA" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "columnId": "response_time_by_version", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "visible": true + } + ] + } + }, + { + "name": "Top failed versions", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 0, + "left": 684, + "width": 608, + "height": 266 + }, + "tileFilter": {}, + "customName": "Top failed versions", + "queries": [ + { + "id": "A", + "metric": "{{ .csmFailureRateMetricKey }}", + "spaceAggregation": "AVG", + "timeAggregation": "DEFAULT", + "splitBy": ["version"], + "filterBy": { + "nestedFilters": [], + "criteria": [] + }, + "enabled": true + } + ], + "visualConfig": { + "type": "TOP_LIST", + "global": {}, + "rules": [ + { + "matcher": "A:", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "thresholds": [ + { + "axisTarget": "LEFT", + "rules": [ + { + "color": "#7dc540" + }, + { + "color": "#f5d30f" + }, + { + "color": "#dc172a" + } + ], + "visible": true + } + ] + } + }, + { + "name": "Failure rate by version", + "tileType": "DATA_EXPLORER", + "configured": true, + "bounds": { + "top": 0, + "left": 0, + "width": 684, + "height": 266 + }, + "tileFilter": {}, + "customName": "Failure rate by version", + "queries": [ + { + "id": "A", + "metric": "{{ .csmFailureRateMetricKey }}", + "spaceAggregation": "AVG", + "timeAggregation": "DEFAULT", + "splitBy": ["version"], + "filterBy": { + "filterOperator": "AND", + "nestedFilters": [], + "criteria": [] + }, + "enabled": true + } + ], + "visualConfig": { + "type": "GRAPH_CHART", + "global": {}, + "rules": [ + { + "matcher": "A", + "properties": { + "seriesType": "LINE" + }, + "seriesOverrides": [] + }, + { + "matcher": "A:", + "properties": { + "color": "DEFAULT", + "seriesType": "LINE" + }, + "seriesOverrides": [] + } + ], + "axes": { + "xAxis": { + "visible": true + }, + "yAxes": [] + }, + "thresholds": [] + } + }, + { + "name": "Problems", + "tileType": "OPEN_PROBLEMS", + "configured": true, + "bounds": { + "top": 266, + "left": 988, + "width": 152, + "height": 152 + }, + "tileFilter": {} + } + ] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/health-check-monitor.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/health-check-monitor.json new file mode 100644 index 000000000..4f4b373b4 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/health-check-monitor.json @@ -0,0 +1,57 @@ +{ + "name": "{{ .name }}", + "frequencyMin": "{{ .frequencyMin }}", + "enabled": true, + "type": "HTTP", + "script": { + "version": "1.0", + "requests": [ + { + "description": "{{ .description }}", + "url": "{{ .url }}", + "method": "GET", + "requestBody": "", + "validation": { + "rules": [ + { + "value": ">=400", + "passIfFound": false, + "type": "regexConstraint" + } + ] + }, + "configuration": { + "requestHeaders": [ + { + "name": "accept", + "value": "application/json" + } + ], + "acceptAnyCertificate": false, + "followRedirects": true + } + } + ] + }, + "locations": ["{{ .location }}"], + "anomalyDetection": { + "outageHandling": { + "globalOutage": false, + "localOutage": true, + "localOutagePolicy": { + "affectedLocations": 1, + "consecutiveRuns": 3 + } + }, + "loadingTimeThresholds": { + "enabled": false, + "thresholds": [ + { + "type": "TOTAL", + "valueMs": 0 + } + ] + } + }, + "tags": ["{{ .tag }}"] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/ownership.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/ownership.json new file mode 100644 index 000000000..0c68c88f1 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/ownership.json @@ -0,0 +1,32 @@ +{ + "name": "{{ .name }}", + "identifier": "{{ .identifier }}", + "supplementaryIdentifiers": [], + "responsibilities": { + "development": true, + "security": true, + "operations": true, + "infrastructure": true, + "lineOfBusiness": true + }, + "contactDetails": [ + { + "integrationType": "EMAIL", + "email": "{{ .email }}" + }, + { + "jira": { + "project": "{{ .gitlabProjectId }}", + "defaultAssignee": "{{ .gitlabDefaultAssigneeId }}" + }, + "integrationType": "JIRA" + } + ], + "links": [], + "additionalInformation": [ + { + "key": "Solution", + "value": "{{ .solution }}" + } + ] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo-settings.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo-settings.json new file mode 100644 index 000000000..a90b285fd --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo-settings.json @@ -0,0 +1,15 @@ +{ + "enabled": true, + "name": "{{ .name }}", + "customDescription": "{{ .description }}", + "metricName": "{{ .metricName }}", + "metricExpression": "{{ .metricExpression }}", + "evaluationType": "AGGREGATE", + "filter": "type({{ .filterType }}),tag([Environment]DT_RELEASE_STAGE:{{ .releaseStage }}),tag([ENVIRONMENT]DT_RELEASE_VERSION:{{ .releaseVersion }})", + "evaluationWindow": "{{ .sloTimeFrame }}", + "targetSuccess": {{ .target }}, + "targetWarning": {{ .warning }}, + "errorBudgetBurnRate": { + "burnRateVisualizationEnabled": false + } +} \ No newline at end of file diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo.json new file mode 100644 index 000000000..748410088 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/app/slo.json @@ -0,0 +1,14 @@ +{ + "enabled": true, + "name": "{{ .name }}", + "customDescription": "{{ .description }}", + "useRateMetric": false, + "metricRate": "", + "metricNumerator": "{{ .metricNumerator }}", + "metricDenominator": "{{ .metricDenominator }}", + "evaluationType": "AGGREGATE", + "filter": "type(\"{{ .filterType }}\"),tag(\"[Environment]DT_RELEASE_PRODUCT:{{ .releaseProduct }}\",\"[Environment]DT_RELEASE_STAGE:{{ .releaseStage }}\")", + "target": "{{ .target }}", + "warning": "{{ .warning }}", + "timeframe": "{{ .sloTimeFrame }}" +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-app.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-app.yaml new file mode 100644 index 000000000..fe2593da0 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-app.yaml @@ -0,0 +1,41 @@ +delete: + + # project - srg + - project: srg + type: app:dynatrace.site.reliability.guardian:guardians + id: simplenodeguardian + - project: srg + type: workflow + id: simplenodeworkflow + + # project - app + - project: app + type: synthetic-monitor + name: $RELEASE_STAGE-health-check-$DEMO_IDENTIFIER + - project: app + type: auto-tag + name: $RELEASE_STAGE-$DEMO_IDENTIFIER + - project: app + type: builtin:rum.web.app-detection + id: appDetection + - project: app + type: application-web + name: $RELEASE_PRODUCT-$RELEASE_STAGE-$DEMO_IDENTIFIER + - project: app + type: calculated-metrics-service + name: $RELEASE_STAGE.failure_rate_by_version-$DEMO_IDENTIFIER + - project: app + type: calculated-metrics-service + name: $RELEASE_STAGE.response_time_by_version-$DEMO_IDENTIFIER + - project: app + type: slo + name: staging_slo_success_rate_$DEMO_IDENTIFIER + - project: app + type: slo + name: staging_slo_availability_$DEMO_IDENTIFIER + - project: app + type: dashboard + name: $RELEASE_STAGE-dashboard-$DEMO_IDENTIFIER + - project: app + type: builtin:ownership.teams + id: owner_simplenode_rv_srg_staging diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-infra.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-infra.yaml new file mode 100644 index 000000000..65c9c817b --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/delete-infra.yaml @@ -0,0 +1,18 @@ +delete: + + # project - infrastructure + - project: infrastructure + type: auto-tag + name: environment-$DEMO_IDENTIFIER + - project: infrastructure + type: auto-tag + name: app-$DEMO_IDENTIFIER + - project: infrastructure + type: request-attributes + name: LTN-$DEMO_IDENTIFIER + - project: infrastructure + type: request-attributes + name: TSN-$DEMO_IDENTIFIER + - project: infrastructure + type: request-attributes + name: LSN-$DEMO_IDENTIFIER diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/_config.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/_config.yaml new file mode 100644 index 000000000..c9fdac82d --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/_config.yaml @@ -0,0 +1,110 @@ +configs: + + # auto-tag + - id: autoTag-env + type: + api: auto-tag + config: + template: auto-tag-infra.json + name: + type: compound + format: "environment-{{ .demoIdentifier }}" + references: + - demoIdentifier + skip: false + parameters: + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + valueFormat: "{ProcessGroup:KubernetesNamespace}" + dynamicKey: "KUBERNETES_NAMESPACE" + + - id: autoTag-app + type: + api: auto-tag + config: + template: auto-tag-infra.json + name: + type: compound + format: "app-{{ .demoIdentifier }}" + references: + - demoIdentifier + skip: false + parameters: + demoIdentifier: + type: environment + name: DEMO_IDENTIFIER + valueFormat: "{ProcessGroup:KubernetesContainerName}" + dynamicKey: "KUBERNETES_CONTAINER_NAME" + + # private-sythetic-location + - id: synthetic-location-ace-box + type: + api: synthetic-location + config: + name: ACE-BOX + template: private-synthetic-location.json + parameters: + nodeId: + name: SYNTH_NODE_ID + type: environment + skip: false + + # request-attribute + - id: ltn-request-attribute + type: + api: request-attributes + config: + name: + type: compound + format: "LTN-{{ .demoIdentifier }}" + references: + - demoIdentifier + template: request-attribute.json + parameters: + delimiter: LTN= + endDelimiter: ; + headerName: x-dynatrace-test + demoIdentifier: + name: DEMO_IDENTIFIER + type: environment + skip: false + + - id: tsn-request-attribute + type: + api: request-attributes + config: + name: + type: compound + format: "TSN-{{ .demoIdentifier }}" + references: + - demoIdentifier + template: request-attribute.json + parameters: + delimiter: TSN= + endDelimiter: ; + headerName: x-dynatrace-test + demoIdentifier: + name: DEMO_IDENTIFIER + type: environment + skip: false + + - id: lsn-request-attribute + type: + api: request-attributes + config: + name: + type: compound + format: "LSN-{{ .demoIdentifier }}" + references: + - demoIdentifier + template: request-attribute.json + parameters: + delimiter: LSN= + endDelimiter: ; + headerName: x-dynatrace-test + demoIdentifier: + name: DEMO_IDENTIFIER + type: environment + skip: false + diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/auto-tag-infra.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/auto-tag-infra.json new file mode 100644 index 000000000..279606014 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/auto-tag-infra.json @@ -0,0 +1,29 @@ +{ + "name": "{{ .name }}", + "rules": [ + { + "type": "PROCESS_GROUP", + "enabled": true, + "valueFormat": "{{ .valueFormat }}", + "propagationTypes": [ + "PROCESS_GROUP_TO_SERVICE" + ], + "conditions": [ + { + "key": { + "attribute": "PROCESS_GROUP_PREDEFINED_METADATA", + "dynamicKey": "{{ .dynamicKey }}", + "type": "PROCESS_PREDEFINED_METADATA_KEY" + }, + "comparisonInfo": { + "type": "STRING", + "operator": "EXISTS", + "value": null, + "negate": false, + "caseSensitive": null + } + } + ] + } + ] +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/private-synthetic-location.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/private-synthetic-location.json new file mode 100644 index 000000000..63c81ae89 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/private-synthetic-location.json @@ -0,0 +1,12 @@ +{ + "type": "PRIVATE", + "name": "{{ .name }}", + "countryCode": "US", + "regionCode": "MI", + "city": "Detroit", + "latitude": 42.3673, + "longitude": -83.1329, + "nodes": [ + "{{ .nodeId }}" + ] + } \ No newline at end of file diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/request-attribute.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/request-attribute.json new file mode 100644 index 000000000..37988c12d --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/infrastructure/request-attribute.json @@ -0,0 +1,26 @@ +{ + "name": "{{ .name }}", + "enabled": true, + "dataType": "STRING", + "dataSources": [ + { + "enabled": true, + "source": "REQUEST_HEADER", + "valueProcessing": { + "splitAt": "", + "trim": false, + "extractSubstring": { + "position": "BETWEEN", + "delimiter": "{{ .delimiter }}", + "endDelimiter": "{{ .endDelimiter }}" + } + }, + "parameterName": "{{ .headerName }}", + "capturingAndStorageLocation": "CAPTURE_AND_STORE_ON_SERVER" + } + ], + "normalization": "ORIGINAL", + "aggregation": "FIRST", + "confidential": false, + "skipPersonalDataMasking": false + } \ No newline at end of file diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/manifest.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/manifest.yaml new file mode 100644 index 000000000..6f16c7b2d --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/manifest.yaml @@ -0,0 +1,45 @@ +manifestVersion: 1.0 + +projects: + - name: infrastructure + path: infrastructure + - name: app + path: app + - name: srg + path: srg + +environmentGroups: + - name: staging + environments: + - name: staging-environment + url: + type: environment + value: DT_PLATFORM_TENANT_URL + auth: + token: + name: DT_API_TOKEN + oAuth: + clientId: + name: DT_OAUTH_CLIENT_ID + clientSecret: + name: DT_OAUTH_CLIENT_SECRET + tokenEndpoint: + type: environment + value: DT_OAUTH_SSO_ENDPOINT + - name: production + environments: + - name: prod-environment + url: + type: environment + value: DT_PLATFORM_TENANT_URL + auth: + token: + name: DT_API_TOKEN + oAuth: + clientId: + name: DT_OAUTH_CLIENT_ID + clientSecret: + name: DT_OAUTH_CLIENT_SECRET + tokenEndpoint: + type: environment + value: DT_OAUTH_SSO_ENDPOINT \ No newline at end of file diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/_config.yaml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/_config.yaml new file mode 100644 index 000000000..557e8ebb1 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/_config.yaml @@ -0,0 +1,111 @@ +configs: + # srg + - id: simplenodeguardian + type: + settings: + schema: app:dynatrace.site.reliability.guardian:guardians + schemaVersion: "1.1.1" + scope: environment + config: + name: "Simplenode Guardian for ACE Demo" + template: srg.json + parameters: + description: "Simplenode Guardian for ACE Demo - created by Monaco" + tags: + type: list + values: + - "stage:staging" + - "owner:ace" + - "app:simplenode" + # objective - dql - response time + objective_name_dql: "Response Time of API Method" + dqlQuery: "fetch logs\n| filter dt.process.name == \"simplenodeservice.simplenode-gitlab-staging\"\n| filter k8s.namespace.name == \"simplenode-gitlab-staging\"\n| filter matchesPhrase(content, \"/api/invoke\")\n| parse content, \"DATA '/api/' DATA 'rt:' SPACE? FLOAT:responsetime \" \n| filter isNotNull(responsetime) \n| summarize median(responsetime), alias:response_time " + comparisonOperator: "LESS_THAN_OR_EQUAL" + failure_dql: 500 + warning_dql: 400 + # objective - slo - success rate + objective_name_slo_success_rate: "Success Rate" + reference_slo_success_rate: ["app", "slo", "slo_success_rate", "name"] + reference_slo_metric_success_rate: + type: compound + format: "func:slo.{{ .reference_slo_success_rate }}" + references: + - reference_slo_success_rate + failure_slo_success_rate: 98 + warning_slo_success_rate: 99 + # objective - slo - availability + objective_name_slo_availability: "Availability of Service" + reference_slo_availability: ["app", "slo", "slo_availability", "name"] + reference_slo_metric_availability: + type: compound + format: "func:slo.{{ .reference_slo_availability }}" + references: + - reference_slo_availability + failure_slo_availability: 98 + warning_slo_availability: 99 + # objective - slo - process cpu usage + objective_name_dql_cpu_usage: "Process Group Instance CPU Usage" + dqlQuery_cpu_usage: "timeseries cpu=avg(dt.process.cpu.usage), by:{dt.entity.process_group, host.name} \n| lookup [fetch dt.entity.process_group], sourceField:dt.entity.process_group, lookupField:id \n| filter matchesPhrase(lookup.entity.name,\"simplenode-gitlab-staging\") \n| fields usageCpuAvg = arrayAvg(cpu) \n| summarize cpuUsageAvg = max(usageCpuAvg) " + failure_dql_cpu_usage: 0.4 + warning_dql_cpu_usage: 0.3 + skip: false + # workflow + - id: simplenodeworkflow + config: + name: Simplenode SRG Evaluation + template: wf.json + skip: false + parameters: + #wf related + wf_description: "Simplenode Workflow with Guardians by Monaco for demo purposes" + wf_isPrivate: false + #trigger related + tag_service: + type: environment + name: SRG_EVALUATION_SERVICE + tag_stage: + type: environment + name: SRG_EVALUATION_STAGE + #srg related + srg_task_description: "Evaluate simplenode app guardian objectives" + guardian_id: + configType: app:dynatrace.site.reliability.guardian:guardians + property: id + type: reference + configId: simplenodeguardian + #gitlab related + gitlab_task_description: "Create a Gitlab Issue when SRG fails" + gitlab_url: + type: environment + name: GITLAB_EXTERNAL_ENDPOINT + gitlab_private_token: + type: environment + name: GITLAB_PRIVATE_TOKEN + gitlab_username: + type: environment + name: GITLAB_USERNAME + gitlab_passwd: + type: environment + name: GITLAB_PASSWORD + dt_url: + type: environment + name: DT_TENANT_URL + # Query service entities + releaseProduct: + type: environment + name: RELEASE_PRODUCT + releaseStage: + type: environment + name: RELEASE_STAGE + dql_service_entities_query: + type: compound + format: | + fetch dt.entity.service + | filter matchesValue(tags,"[Environment]DT_RELEASE_PRODUCT:{{ .releaseProduct }}") + and matchesValue(tags,"[Environment]DT_RELEASE_STAGE:{{ .releaseStage }}") + references: + - releaseProduct + - releaseStage + type: + automation: + resource: workflow diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/srg.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/srg.json new file mode 100644 index 000000000..3fe99d2ad --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/srg.json @@ -0,0 +1,41 @@ +{ + "name": "{{ .name }}", + "description": "{{ .description }}", + "tags": {{ .tags }}, + "objectives": [ + { + "name": "{{ .objective_name_dql }}", + "objectiveType": "DQL", + "dqlQuery": "{{ .dqlQuery }}", + "comparisonOperator": "{{ .comparisonOperator }}", + "target": {{ .failure_dql }}, + "warning": {{ .warning_dql }} + }, + { + "name": "{{ .objective_name_slo_success_rate }}", + "description": null, + "objectiveType": "REFERENCE_SLO", + "referenceSlo": "{{ .reference_slo_metric_success_rate }}", + "comparisonOperator": "GREATER_THAN_OR_EQUAL", + "target": {{ .failure_slo_success_rate }}, + "warning": {{ .warning_slo_success_rate }} + }, + { + "name": "{{ .objective_name_slo_availability }}", + "description": null, + "objectiveType": "REFERENCE_SLO", + "referenceSlo": "{{ .reference_slo_metric_availability }}", + "comparisonOperator": "GREATER_THAN_OR_EQUAL", + "target": {{ .failure_slo_availability }}, + "warning": {{ .warning_slo_availability }} + }, + { + "name": "{{ .objective_name_dql_cpu_usage }}", + "objectiveType": "DQL", + "dqlQuery": "{{ .dqlQuery_cpu_usage }}", + "comparisonOperator": "LESS_THAN_OR_EQUAL", + "target": {{ .failure_dql_cpu_usage }}, + "warning": {{ .warning_dql_cpu_usage }} + } + ] +} \ No newline at end of file diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/wf.json b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/wf.json new file mode 100644 index 000000000..d2182ec0b --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/files/monaco/srg/wf.json @@ -0,0 +1,108 @@ +{ + "title": "{{ .name }}", + "description": "{{ .wf_description }}", + "isPrivate": "{{ .wf_isPrivate }}", + "labels": {}, + "schemaVersion": 3, + "taskDefaults": {}, + "usages": [], + "version": 4, + "triggerType": "Event", + "trigger": { + "eventTrigger": { + "filterQuery": "event.type == \"guardian.validation.triggered\" AND tag.service==\"{{ .tag_service }}\" AND tag.stage==\"{{ .tag_stage }}\"", + "isActive": true, + "triggerConfiguration": { + "type": "event", + "value": { + "eventType": "bizevents", + "query": "event.type == \"guardian.validation.triggered\" AND tag.service==\"{{ .tag_service }}\" AND tag.stage==\"{{ .tag_stage }}\"" + } + }, + "uniqueExpression": null + } + }, + + "tasks": { + "evaluate_srg": { + "action": "dynatrace.site.reliability.guardian:validate-guardian-action", + "description": "{{ .srg_task_description }}", + "input": { + "executionId": "{{`{{`}} execution().id {{`}}`}}", + "objectId": "{{ .guardian_id }}", + "expressionFrom": "{{`{{`}} event()['timeframe.from'] {{`}}`}}", + "expressionTo": "{{`{{`}} event()['timeframe.to'] {{`}}`}}", + "timeframeInputType": "expression" + }, + "name": "evaluate_srg", + "position": { + "x": 0, + "y": 1 + }, + "predecessors": [] + }, + "query_service_entities": { + "name": "query_service_entities", + "input": { + "query": "{{ .dql_service_entities_query }}" + }, + "action": "dynatrace.automations:execute-dql-query", + "position": { + "x": 0, + "y": 2 + }, + "conditions": { + "custom": "{{ `{{` }} result(\"evaluate_srg\").validation_status != \"pass\" {{ `}}` }}", + "states": { + "evaluate_srg": "OK" + } + }, + "description": "Executes DQL query", + "predecessors": ["evaluate_srg"] + }, + "identify_ownership": { + "name": "identify_ownership", + "input": { + "entityIds": "{{ `{{` }} result(\"query_service_entities\").records[0].id {{ `}}` }}", + "responsibilities": [] + }, + "action": "dynatrace.ownership:get-ownership-from-entity", + "position": { + "x": 0, + "y": 3 + }, + "conditions": { + "states": { + "query_service_entities": "SUCCESS" + } + }, + "description": "Retrieves entity and extracts ownership data from it.", + "predecessors": ["query_service_entities"] + }, + "create_gitlab_issue": { + "action": "dynatrace.automations:http-function", + "conditions": { + "custom": "{{`{{`}} (result('identify_ownership').owners | length > 0) {{`}}`}}", + "states": { + "identify_ownership": "OK" + } + }, + "description": "{{ .gitlab_task_description }}", + "input": { + "headers": { + "Content-Type": "application/json", + "PRIVATE-TOKEN": "{{ .gitlab_private_token }}" + }, + "method": "POST", + "url": "{{ .gitlab_url }}/api/v4/projects/{{`{{`}} result(\"identify_ownership\").owners[0].contactDetails | selectattr('integrationType', 'equalto', 'JIRA') | map(attribute='jira.project') | first() {{`}}`}}/issues", + "payload": "{\n \"title\": \"Site Reliability Guardian validation failed\",\n \"description\": \"For the SRG validation details, go to {{`{{`}} result(\"evaluate_srg\").validation_url {{`}}`}}\"\n}" + }, + "name": "create_gitlab_issue", + "position": { + "x": 0, + "y": 4 + }, + "predecessors": ["identify_ownership"] + } + } +} diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/jenkins.yml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/jenkins.yml new file mode 100644 index 000000000..b205c183e --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/jenkins.yml @@ -0,0 +1,33 @@ +--- +- include_role: + name: gitea + tasks_from: source-secret + when: gitea_access_token is not defined or gitea_username is not defined or gitea_password is not defined + +- set_fact: + role_path_abs: "{{ role_path }}" + +- include_role: + name: jenkins + tasks_from: template-values-file + vars: + include_jenkins_value_file: "{{ role_path_abs }}/templates/demo-default-jobs.yml.j2" + git_username: "{{ gitea_username }}" + git_token: "{{ gitea_access_token }}" + demo_org: "{{ demo_quality_gates_jenkins_org }}" + demo_repo: "{{ demo_quality_gates_jenkins_repo_name }}" + demo_jenkins_folder: "{{ demo_quality_gates_jenkins_repo_name }}" + git_domain: "gitea.{{ ingress_domain }}" + +- set_fact: + role_path_abs: + +- include_role: + name: jenkins + vars: + jenkins_monaco_container_image: "dynatrace/dynatrace-configuration-as-code:{{ monacoVersion }}" + dt_oauth_sso_endpoint: "{{ extra_vars.dt_oauth_sso_endpoint.rstrip('/') }}" + dt_oauth_client_id: "{{ extra_vars.dt_oauth_client_id }}" + dt_oauth_client_secret: "{{ extra_vars.dt_oauth_client_secret }}" + dt_oauth_account_urn: "{{ extra_vars.dt_oauth_account_urn }}" + dt_environment_url_gen3: "{{ extra_vars.dt_environment_url_gen3.rstrip('/') }}" diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/main.yml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/main.yml new file mode 100644 index 000000000..9ac551e62 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/main.yml @@ -0,0 +1,77 @@ +--- +- include_role: + name: microk8s + +- include_role: + name: dt-activegate-classic + vars: + activegate_install_synthetic: true + +- include_role: + name: dt-operator + +- include_role: + name: otel-collector + + +- include_role: + name: monaco-v2 + +- include_role: + name: gitea + + +- include_role: + name: gitea + tasks_from: source-secret + when: gitea_access_token is not defined or gitea_username is not defined or gitea_password is not defined + +- include_role: + name: gitea + tasks_from: create-organization + vars: + gitea_org: "{{ demo_quality_gates_jenkins_org }}" + +- include_role: + name: gitea + tasks_from: create-repository + vars: + gitea_org: "{{ demo_quality_gates_jenkins_org }}" + gitea_repo: "{{ demo_quality_gates_jenkins_repo_name }}" + +- name: Source Gitea endpoint + include_role: + name: gitea + tasks_from: source-endpoints + +- ansible.builtin.include_tasks: simplenode.yml +- ansible.builtin.include_tasks: jenkins.yml + +# Include use case specific Jenkins values +# - set_fact: +# include_jenkins_value_file: "{{ role_path }}/templates/demo-default-jobs.yml.j2" + +# - include_role: +# name: jenkins +# tasks_from: template-values-file +# vars: +# git_username: "{{ gitea_username }}" +# git_token: "{{ gitea_access_token }}" +# demo_repo: "{{ demo_quality_gates_jenkins_repo_name }}" +# demo_org: "{{ demo_quality_gates_jenkins_org }}" +# demo_jenkins_folder: "{{ demo_quality_gates_jenkins_folder }}" +# git_domain: "gitea.{{ ingress_domain }}" + +# - include_role: +# name: jenkins + +# Include use case specific Dashboard values +- set_fact: + include_dashboard_value_file: "{{ role_path }}/templates/demo-release-validation-jenkins-dashboard.yml.j2" + +- include_role: + name: dashboard + tasks_from: template-values-file + +- include_role: + name: dashboard diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/simplenode.yml b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/simplenode.yml new file mode 100644 index 000000000..ca58ddef2 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/tasks/simplenode.yml @@ -0,0 +1,30 @@ +--- + +- set_fact: + role_path_abs: "{{ role_path }}" + +- include_role: + name: app-simplenode + vars: + app_simplenode_overwrites: + - dest: demo/ + - dest: README.md + - dest: docs/ + - dest: cloudautomation/ + - dest: jmeter/ + - dest: locust/ + - dest: monaco/ + src: "{{ role_path_abs }}/files/monaco/" + - dest: jenkins/ + src: "{{ role_path_abs }}/files/jenkins/" + - dest: load-gen/ + - dest: build_number.txt + - dest: .gitlab-ci.yml + git_username: "{{ gitea_username }}" + git_password: "{{ gitea_password }}" + git_endpoint: "{{ gitea_internal_endpoint | regex_replace(\"http://\") }}" + git_org_name: "{{ demo_quality_gates_jenkins_org }}" + repo_name: "{{ demo_quality_gates_jenkins_repo_name }}" + +- set_fact: + role_path_abs: diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-default-jobs.yml.j2 b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-default-jobs.yml.j2 new file mode 100644 index 000000000..063fdcc79 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-default-jobs.yml.j2 @@ -0,0 +1,140 @@ +controller: + JCasC: + configScripts: + demo-default-jobs-config: | + jobs: + - script: > + folder('{{ demo_jenkins_folder }}') + - script: > + multibranchPipelineJob('{{ demo_jenkins_folder }}/Detect SCM drift') { + branchSources { + git { + id('B8BE0E28-4D53-46B2-BB1C-3BD25CA36EA8') + remote('{{ ingress_protocol }}://{{ git_username }}:{{ git_token }}@{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}.git') + includes('main') + } + } + factory { + workflowBranchProjectFactory { + scriptPath('jenkins/triggerBuild.Jenkinsfile') + } + } + } + - script: > + pipelineJob('{{ demo_jenkins_folder }}/1. Build') { + parameters { + choiceParam('BUILD', ['1','2','3','4'], 'Select the build you want to deploy (affects application behavior, github.com/grabnerandi/simplenodeservice for more details)') + } + definition { + cpsScm { + scriptPath('jenkins/build.Jenkinsfile') + scm { + git { + remote { + url('{{ ingress_protocol }}://{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}') + credentials('git-creds-ace') + } + branch('*/main') + } + } + lightweight() + } + } + } + - script: > + pipelineJob('{{ demo_jenkins_folder }}/2. Deploy') { + parameters { + stringParam('RELEASE_PRODUCT') + stringParam('IMAGE_NAME') + stringParam('IMAGE_TAG') + stringParam('RELEASE_VERSION') + stringParam('RELEASE_BUILD_VERSION') + stringParam('RELEASE_STAGE') + } + definition { + cpsScm { + scriptPath('jenkins/deployStaging.Jenkinsfile') + scm { + git { + remote { + url('{{ ingress_protocol }}://{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}') + credentials('git-creds-ace') + } + branch('*/main') + } + } + lightweight() + } + } + } + - script: > + pipelineJob('{{ demo_jenkins_folder }}/3. Test') { + parameters { + stringParam('RELEASE_PRODUCT') + stringParam('IMAGE_NAME') + stringParam('IMAGE_TAG') + stringParam('RELEASE_VERSION') + stringParam('RELEASE_BUILD_VERSION') + stringParam('RELEASE_STAGE') + choiceParam('QG_MODE', ['yaml','dashboard'], 'Use yaml or dashboard for QG') + } + definition { + cpsScm { + scriptPath('jenkins/test.Jenkinsfile') + scm { + git { + remote { + url('{{ ingress_protocol }}://{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}') + credentials('git-creds-ace') + } + branch('*/main') + } + } + lightweight() + } + } + } + - script: > + pipelineJob('{{ demo_jenkins_folder }}/4. Deploy production') { + parameters { + stringParam('RELEASE_PRODUCT') + stringParam('IMAGE_NAME') + stringParam('IMAGE_TAG') + stringParam('RELEASE_VERSION') + stringParam('RELEASE_BUILD_VERSION') + stringParam('RELEASE_STAGE') + } + definition { + cpsScm { + scriptPath('jenkins/deployProd.Jenkinsfile') + scm { + git { + remote { + url('{{ ingress_protocol }}://{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}') + credentials('git-creds-ace') + } + branch('*/main') + } + } + lightweight() + } + } + } + - script: > + pipelineJob('{{ demo_jenkins_folder }}/Monitoring as Code') { + definition { + cpsScm { + scriptPath('jenkins/mac.Jenkinsfile') + scm { + git { + remote { + url('{{ ingress_protocol }}://{{ git_domain }}/{{ demo_org }}/{{ demo_repo }}') + credentials('git-creds-ace') + } + branch('*/main') + } + } + lightweight() + } + } + } diff --git a/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-quality-gates-jenkins-dashboard.yml.j2 b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-quality-gates-jenkins-dashboard.yml.j2 new file mode 100644 index 000000000..86299ebf2 --- /dev/null +++ b/user-skel/ansible_collections/ace_box/ace_box/roles/demo-release-validation-srg-jenkins/templates/demo-quality-gates-jenkins-dashboard.yml.j2 @@ -0,0 +1,13 @@ +--- +useCases: + demo-release-validation-jenkins: + previews: + - section: demo-release-validation-jenkins + description: Staging + url: "{{ ingress_protocol }}://simplenodeservice-staging-jenkins.{{ ingress_domain }}" + - section: demo-release-validation-jenkins + description: Production + url: "{{ ingress_protocol }}://simplenodeservice-prod-jenkins.{{ ingress_domain }}" + guides: + - description: "Quality Gates, Monitoring as a Service and Monitoring as Code - Demo using Jenkins, Gitea and Cloud Automation" + url: "{{ ingress_protocol }}://gitea.{{ ingress_domain }}/demo/release-validation-jenkins/src/branch/main/demo"