Copy
template:
name: "Golden K8s "
identifier: Golden_K8s
type: Stage
projectIdentifier: Operations
orgIdentifier: Harness
tags:
regulated: ""
ops_owned: ""
bt_managed: ""
spec:
type: Deployment
spec:
deploymentType: Kubernetes
services:
values: <+input>
metadata:
parallel: true
environments:
metadata:
parallel: false
values: <+input>
execution:
steps:
- stepGroup:
name: PRE_REQUISITE
identifier: pre_requisite
steps:
- step:
type: ShellScript
name: Check_namespace_env_mapping
identifier: Check_namespace_env_mapping
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |-
set -x
if [ "<+infra.namespace>" == "NOT_SET_CHECK_WITH_SRE" ]
then
echo " Error!! For the current Env: <+env.name> is not mapped a namespace, as it not an existing deployment"
exit 1
fi
environmentVariables: []
outputVariables: []
timeout: 10m
when:
stageStatus: Success
failureStrategies: []
- step:
type: Http
name: check_image_deployed_in_qa
identifier: check_image_deployed_in_qa
spec:
url: https://stage.harness.io/gateway/pipeline/api/pipelines/execution/summary?routingId=wFHXHD0RRQWoO8tIZT5YVw&accountIdentifier=wFHXHD0RRQWoO8tIZT5YVw&projectIdentifier=Operations&orgIdentifier=Harness&page=0&size=100&sort=startTs%2CDESC&module=cd
method: POST
headers:
- key: x-api-key
value: <+secrets.getValue('qa_image_check_token')>
- key: content-type
value: application/json
outputVariables:
- name: qaLastStatus
value: <+json.select("data.content[0].status",httpResponseBody)>
type: String
requestBody: "{ \"moduleProperties\": { \"cd\": { \"serviceIdentifiers\": \"<+service.identifier>\", \"artifactDisplayNames\": \"<+artifacts.primary.imagePath>:<+artifacts.primary.tag>\", \"envIdentifiers\": \"qa\" } }, \"filterType\": \"PipelineExecution\"}"
assertion: <+json.select("data.content[0].status",httpResponseBody)>=='Success' || <+json.select("data.content[0].status",httpResponseBody)>=='IgnoreFailed'
timeout: 30s
when:
stageStatus: Success
condition: <+env.type> == "NA"
failureStrategies: []
- step:
type: ShellScript
name: set_availability_type
identifier: set_availability_type
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: "#!/bin/bash\n##########################################################\n# To set the Availability Type to primary or failover\n# based on the Infra Connector type\n##########################################################\nset -x\navailType=\"NULL\"\necho \" Connector : <+infra.connectorRef> \"\ncase <+infra.connectorRef> in\n\tqaprivate|prodprivateprimary|freeprivateprimary|compprivateprimary|uatprivate|qastress|genai_qa_k8s|genai_prod_k8s|prodcidlite|proddliteselfmanaged) availType=\"primary\" \n\t;;\n\tprodprivatefailover|freeprivatefailover|compprivatefailover|uatfailoverprivate|prodcidlitefailover) availType=\"failover\"\n\t;;\nesac\n\nif [ \"$availType\" == \"NULL\" ]\nthen\n echo \"availType cannot be NULL\"\n exit 1\nfi \necho \"Availability Type: $availType\""
environmentVariables: []
outputVariables:
- name: infraType
type: String
value: availType
timeout: 10m
- step:
name: get_deployed_version
identifier: get_deployed_version
template:
templateRef: Get_Deployed_Version
versionLabel: v2
templateInputs:
type: ShellScript
spec:
environmentVariables:
- name: deploymentName
type: String
value: <+input>
- name: versionedNs
type: String
value: <+input>
- name: isStatefulSet
type: String
value: <+input>
- stepGroup:
name: MANDATORY
identifier: mandatory
steps:
- step:
type: ShellScript
name: validate_inputs
identifier: validate_inputs
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |+
set -x
change_list=$(echo <+stage.variables.ChangeList> | sed -e 's/null//' | sed -e 's/ //g')
if [[ -z ${change_list} ]]
then
echo "Mandatory pipeline variable: ChangeList is empty."
exit 1
fi
environmentVariables: []
outputVariables: []
timeout: 10m
when:
stageStatus: Success
condition: <+env.type> == "Production"
failureStrategies: []
- stepGroup:
name: STO_SCAN
identifier: STO_SCAN
steps:
- step:
type: Http
name: trig_sto_scan_pipeline
identifier: trig_sto_scan_pipeline
spec:
url: https://stage.harness.io/pipeline/api/webhook/custom/v2?accountIdentifier=wFHXHD0RRQWoO8tIZT5YVw&orgIdentifier=Harness&projectIdentifier=Operations&pipelineIdentifier=STO_scan_for_svc_artifact&triggerIdentifier=goldenPipelineTrigger
method: POST
headers:
- key: Content-Type
value: application/json
- key: X-Api-Key
value: <+secrets.getValue("failover_sa_token")>
outputVariables:
- name: apiUrl
value: <+json.object(httpResponseBody).data.apiUrl>
type: String
requestBody: "{\"imagePath\": \"<+artifact.imagePath>\",\"tag\": \"<+artifact.tag>\"}"
assertion: httpResponseCode == 200
timeout: 10s
when:
stageStatus: Success
condition: <+env.identifier> == "qa"
failureStrategies: []
- step:
type: Http
name: poll_scan_status
identifier: poll_scan_status
spec:
method: GET
headers:
- key: Content-Type
value: application/json
outputVariables:
- name: pollingStatus
value: <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>
type: String
- name: accountId
value: <+json.object(httpResponseBody).data.webhookProcessingDetails.accountIdentifier>
type: String
- name: orgId
value: <+json.object(httpResponseBody).data.webhookProcessingDetails.orgIdentifier>
type: String
- name: projectId
value: <+json.object(httpResponseBody).data.webhookProcessingDetails.projectIdentifier>
type: String
- name: pipelineId
value: <+json.object(httpResponseBody).data.webhookProcessingDetails.pipelineIdentifier>
type: String
- name: executionId
value: <+json.object(httpResponseBody).data.webhookProcessingDetails.pipelineExecutionId>
type: String
requestBody: ""
url: <+steps.trig_sto_scan_pipeline.output.outputVariables.apiUrl>
assertion: <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>!="Running" && <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>!="QueuedLicenseLimitReached"
timeout: 2h
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Retry
spec:
retryCount: 120
retryIntervals:
- 1m
onRetryFailure:
action:
type: Ignore
- step:
type: ShellScript
name: get_execution_url
identifier: get_execution_url
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |-
set -x
accountId=<+steps.poll_scan_status.output.outputVariables.accountId>
orgId=<+steps.poll_scan_status.output.outputVariables.orgId>
projectId=<+steps.poll_scan_status.output.outputVariables.projectId>
pipelineId=<+steps.poll_scan_status.output.outputVariables.pipelineId>
planExecutionId=<+steps.poll_scan_status.output.outputVariables.executionId>
link="https://stage.harness.io/ng/#/account/$accountId/cd/orgs/$orgId/projects/$projectId/pipelines/$pipelineId/executions/$planExecutionId/pipeline"
environmentVariables: []
outputVariables:
- name: execution_link
type: String
value: link
timeout: 10m
when:
stageStatus: All
failureStrategies: []
- step:
type: ShellScript
name: verify_poll_status
identifier: verify_poll_status
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |+
set -x
echo "STO Pipeline : <+steps.get_execution_url.output.outputVariables.execution_link>"
actualFailedTestsStatus=<+steps.poll_scan_status.output.outputVariables.pollingStatus>
if [[ "$actualFailedTestsStatus" = "Success" || "$actualFailedTestsStatus" = "IgnoreFailed" ]]
then
echo "STO Scan Pipeline return SUCCESS"
exit 0
else
echo "STO Scan Pipeline return FAILED"
echo "Please kindly consult the troubleshooting document by following this link: https://harness.atlassian.net/l/cp/5A0Bukdg"
exit 1
fi
environmentVariables: []
outputVariables: []
timeout: 10m
- step:
type: K8sDryRun
name: DryRun
identifier: DryRun
spec: {}
timeout: 20m
when:
stageStatus: Success
condition: <+execution.steps.pre_requisite.steps.get_deployed_version.output.outputVariables.STO_SCAN> && <+env.identifier> == "qa" && <+service.identifier> != "lwredis" && <+service.identifier> != "lwpostgres" && <+service.identifier> != "assessmentservice" && <+service.identifier> != "assessmentui" && <+service.identifier> != "LightwingFaktory"
spec: {}
- step:
type: HarnessApproval
name: manager_approval
identifier: manager_approval
spec:
approvalMessage: "Please review if the details provided as inputs are valid like ChangeList does it correspond to the current deployment for Prod (and not QA page). "
includePipelineExecutionHistory: true
approvers:
userGroups:
- GoldenApprovalGroup
- OPSApproval_Group
minimumCount: 1
disallowPipelineExecutor: false
approverInputs: []
timeout: 1d
when:
stageStatus: All
condition: <+env.type> == "Production"
failureStrategies: []
when:
stageStatus: Success
condition: <+stage.spec.execution.steps.pre_requisite.steps.set_availability_type.output.outputVariables.infraType> == "primary"
failureStrategies: []
spec: {}
- step:
name: Rollout Deployment
identifier: rolloutDeployment
type: K8sRollingDeploy
timeout: 15m
spec:
skipDryRun: false
pruningEnabled: false
when:
stageStatus: Success
failureStrategies: []
- step:
type: K8sApply
name: hpa
identifier: hpa
spec:
filePaths:
- templates/apply-only/hpa.yaml
skipDryRun: false
skipSteadyStateCheck: false
skipRendering: false
overrides: []
timeout: 10m
when:
stageStatus: Success
condition: <+input>
failureStrategies: []
- step:
name: Nprd Slack Notify
identifier: Nprd_Slack_Notify
template:
templateRef: Slack_Notify_Single_Service
versionLabel: golden_nprd_only
templateInputs:
type: ShellScript
spec:
environmentVariables:
- name: WEBHOOK_LIST_COMMA_SEP
type: String
value: <+stage.variables.WEBHOOK_LIST_COMMA_SEP>
- stepGroup:
name: POST_REQUISITE
identifier: post_steps_primary
steps:
- stepGroup:
name: trigger_sanity
identifier: trigger_sanity
steps:
- step:
type: Http
name: trigger_webhook_urls
identifier: trigger_webhook_urls
spec:
url: <+matrix.triggerdata.url>
method: POST
headers:
- key: Content-Type
value: application/json
outputVariables:
- name: apiUrl
value: <+json.object(httpResponseBody).data.apiUrl>
type: String
requestBody: <+matrix.triggerdata.body>
assertion: httpResponseCode == 200
timeout: 10m
- step:
type: Http
name: poll_sanity_urls
identifier: poll_sanity_urls
spec:
method: GET
headers:
- key: Content-Type
value: application/json
outputVariables:
- name: pollingStatus
value: <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>
type: String
url: <+steps.trigger_webhook_urls.output.outputVariables.apiUrl>
assertion: <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>!="Running" && <+json.object(httpResponseBody).data.executionDetails.pipelineExecutionSummary.status>!="QueuedLicenseLimitReached"
inputVariables: []
timeout: 2h
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Retry
spec:
retryCount: 120
retryIntervals:
- 1m
onRetryFailure:
action:
type: ManualIntervention
spec:
timeout: 2h
onTimeout:
action:
type: MarkAsFailure
when:
stageStatus: Success
condition: <+steps.trigger_webhook_urls.output.httpResponseCode>!=400
- step:
name: collect_metrics
identifier: collect_metrics
template:
templateRef: Dora
versionLabel: "0.1"
templateInputs:
type: ShellScript
spec:
environmentVariables:
- name: sanity
type: String
value: <+steps.poll_sanity_urls.output.outputVariables.pollingStatus>
- name: prev_ver
type: String
value: <+stage.spec.execution.steps.pre_requisite.steps.get_deployed_version.output.outputVariables.PREV_VER>
- step:
type: ShellScript
name: verify_poll_urls_status
identifier: verify_poll_urls_status
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |-
set -x
actualFailedTestsStatus=<+steps.poll_sanity_urls.output.outputVariables.pollingStatus>
if [[ "$actualFailedTestsStatus" = "Success" || "$actualFailedTestsStatus" = "IgnoreFailed" ]]
then
echo "Sanity return SUCCESS"
exit 0
else
echo "Sanity return FAILED"
echo "Please manually abort the pipeline!"
exit 0
fi
environmentVariables: []
outputVariables: []
timeout: 1d
failureStrategies: []
strategy:
matrix:
triggerdata: <+json.list("$", <+stage.variables.sanity_urls>)>
spec: {}
- parallel:
- step:
type: ShellScript
name: mark_jira_deployed
identifier: mark_jira_deployed
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: <+input>.default("Please fill in if applicable script here")
environmentVariables: []
outputVariables: []
timeout: 10m
when:
stageStatus: Success
condition: <+input>
failureStrategies: []
- step:
type: JiraCreate
name: jira_create
identifier: jira_create
spec:
connectorRef: JiraOperations
projectKey: OPS
issueType: Deployment
fields:
- name: Deployed By
value: <+pipeline.triggeredBy.name>
- name: Deployment Approved By
value: "<+stage.spec.execution.steps.mandatory.steps.manager_approval.output.approvalActivities[0].user.name> "
- name: Deployment Change List URL
value: <+stage.variables.ChangeList>
- name: Deployment Current Artifact
value: <+artifact.tag>
- name: Deployment Execution URL
value: <+pipeline.executionUrl>
- name: Deployment Previous Artifact
value: <+stage.spec.execution.steps.pre_requisite.steps.get_deployed_version.output.outputVariables.PREV_VER>
- name: Deployment QA Sign-Off Page
value: <+stage.variables.QASignOffPage>
- name: Deployment Sanity
value: NA
- name: Deployment Service
value: <+service.name>
- name: Deployment Type
value: <+stage.variables.DeploymentType>
- name: Environment
value: <+env.identifier>
- name: Description
value: |-
Service Name : <+service.name>
Environment : <+env.identifier>
Artifact Version (Current) : <+artifact.tag>
Artifact Version (Previous) : <+stage.spec.execution.steps.pre_requisite.steps.get_deployed_version.output.outputVariables.PREV_VER>
Strategy : <+stage.variables.DeploymentStrategy>
- name: Summary
value: Deploying <+service.name> for <+env.identifier> with <+artifact.tag>
timeout: 1d
when:
stageStatus: Success
condition: <+env.type> == "Production"
- step:
type: ShellScript
name: sanity_result
identifier: sanity_result
spec:
shell: Bash
onDelegate: true
source:
type: Inline
spec:
script: |-
sanity_result=<+stage.spec.execution.steps.post_steps_primary.steps.trigger_sanity.status>
echo ${sanity_result}
environmentVariables: []
outputVariables: []
timeout: 10m
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: MarkAsSuccess
- parallel:
- step:
name: slack_notify
identifier: slack_notify
template:
templateRef: Slack_Notify_Single_Service
versionLabel: golden
templateInputs:
type: ShellScript
spec:
environmentVariables:
- name: WEBHOOK_LIST_COMMA_SEP
type: String
value: <+stage.variables.WEBHOOK_LIST_COMMA_SEP>
- name: sanity_result
type: String
value: <+stage.spec.execution.steps.post_steps_primary.steps.trigger_sanity_0.steps.poll_sanity_urls.output.outputVariables.pollingStatus>
- step:
type: JiraUpdate
name: jira_close
identifier: jira_close
spec:
connectorRef: JiraOperations
issueKey: <+stage.spec.execution.steps.post_steps_primary.steps.jira_create.issue.key>
transitionTo:
transitionName: ""
status: Done
fields: []
timeout: 1d
when:
stageStatus: Success
condition: <+env.type> == "Production"
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Ignore
when:
stageStatus: Success
condition: <+stage.spec.execution.steps.pre_requisite.steps.set_availability_type.output.outputVariables.infraType> == "primary"
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: Ignore
spec: {}
rollbackSteps:
- step:
name: Rollback Rollout Deployment
identifier: rollbackRolloutDeployment
type: K8sRollingRollback
timeout: 15m
spec:
pruningEnabled: false
failureStrategies:
- onFailure:
errors:
- AllErrors
action:
type: StageRollback
variables:
- name: ChangeList
type: String
description: ""
required: true
value: <+input>
- name: QASignOffPage
type: String
description: ""
required: true
value: <+input>
- name: DeploymentStrategy
type: String
default: rollout
description: ""
required: true
value: rollout
- name: DeploymentType
type: String
description: ""
required: true
value: <+input>.allowedValues(new-rel,hf-feature,hf-regression,rollback,bounce)
- name: If_Regression_Choose_TicketPriority
type: String
description: ""
required: true
value: <+input>.allowedValues(P0,P1,NA)
- name: sanity_urls
type: String
description: ""
required: true
value: <+input>
- name: WEBHOOK_LIST_COMMA_SEP
type: String
description: ""
required: true
value: <+input>
delegateSelectors:
- <+env.variables.delegate>
versionLabel: "0.8"