Friday, 4 March 2022

Setting Up Cd Pipeline for Terraform

 

  • Go back to Jenkins and select your terraform pipeline and click  Configure
  • Scroll down to Pipeline and click on the drop down to select Pipeline Script From SCM
  • Enter credentials for Bitbucket, Leave the Branch master as the default, Make sure script path is Jenkinsfile
  • Right click on Pipeline Syntax and open in a new tab. 
  • Choose Checkout from Version Control in the Sample Step field
  • Enter Bitbucket Repository URL and Credentials, leave the branches blank
  • Click GENERATE PIPELINE SCRIPT, copy credentialsId and url (This is required for Jenkinsfile script)



Create Workspace for Terraform Pipeline
  • Open File Explorer, navigate to Desktop and create a folder cd_pipeline

  • Once folder has been created, open Visual Code Studio and add folder to workspace







  • Open a New Terminal
  • Run the command before cloning repo: git init
  • Navigate to terraform-pipeline repo in Bitbucket
  • Clone the repo with SSH or HTTPS
  • Create a new file main.tf and copy the below code in yellow color



















terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 5.0"
    }
  }
}

provider "aws" {
  region = var.region
}

data "aws_vpc" "default" {
  default = true
}

data "aws_subnets" "default" {
  filter {
    name   = "vpc-id"
    values = [data.aws_vpc.default.id]
  }
}

resource "aws_instance" "ec2" {
  ami                    = "ami-0782e9ee97725263d" # MUST be Ubuntu 22 if using deploy.sh
  instance_type           = var.instance_type
  subnet_id               = data.aws_subnets.default.ids[0]
  vpc_security_group_ids  = [aws_security_group.ec2_SecurityGroups.id]

  user_data = file("deploy.sh")

  root_block_device {
    volume_type           = "gp3"
    volume_size           = 200
    delete_on_termination = true
    encrypted             = true
  }

  tags = {
    Name        = "u2-${var.environment}-${var.application}"
    CreatedBy   = var.launched_by
    Application = var.application
    OS          = var.os
    Environment = var.environment
  }
}

output "ec2_private_ip"  { value = aws_instance.ec2.private_ip }
output "ec2_public_ip"   { value = aws_instance.ec2.public_ip }
output "ec2_name"        { value = aws_instance.ec2.tags["Name"] }
output "ec2_instance_id" { value = aws_instance.ec2.id }



  • Create a new file security.tf and copy the below code in yellow color

resource "aws_security_group" "ec2_SecurityGroups" {
name = "u2-${var.environment}-sg-${var.application}"
description = "EC2 SG"
  vpc_id      = data.aws_vpc.default.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
     from_port   = 8081
to_port     = 8081
protocol    = "tcp"
cidr_blocks = ["0.0.0.0/0"]
   }
ingress {
     from_port   = 8082
to_port     = 8082
protocol    = "tcp"
cidr_blocks = ["0.0.0.0/0"]
   }
   ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
#Allow all outbound
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}

  • Create a new file variable.tf and copy the below code in yellow color. 

variable "region" {
  type    = string
  default = "us-east-2"
}
variable "os" {
    type = string
    default = "Ubuntu" 
    }
variable "launched_by"  {
     type = string
     default = "USER"
      }
variable "instance_type" { type = string }
variable "application"   { type = string }
variable "environment"   { type = string }


############## end tags


Bash Script to Deploy Artifactory

  • Create a new file deploy.sh and copy the below code in yellow color. 
#!/usr/bin/env bash
set -euo pipefail

# Log user-data output
exec > >(tee /var/log/user-data-artifactory.log | logger -t user-data -s 2>/dev/console) 2>&1

ART_VERSION="7.21.5"
ART_TGZ="jfrog-artifactory-oss-${ART_VERSION}-linux.tar.gz"
ART_URL="https://releases.jfrog.io/artifactory/bintray-artifactory/org/artifactory/oss/jfrog-artifactory-oss/${ART_VERSION}/${ART_TGZ}"

BASE_DIR="/opt/artifactory"
APP_DIR="${BASE_DIR}/app"     # final target
RUN_USER="artifactory"

echo "==== Installing prerequisites ===="
apt-get update -y
apt-get install -y curl tar gzip unzip jq

echo "==== Installing OpenJDK 17 ===="
apt-get install -y openjdk-17-jdk
java -version || true

echo "==== Creating artifactory user (if needed) ===="
if ! id "${RUN_USER}" >/dev/null 2>&1; then
  useradd --system --create-home --home-dir /var/opt/jfrog --shell /usr/sbin/nologin "${RUN_USER}"
fi

echo "==== Creating directories ===="
mkdir -p "${BASE_DIR}"
cd "${BASE_DIR}"

echo "==== Downloading Artifactory OSS ${ART_VERSION} ===="
# download only if not already present
if [ ! -f "${BASE_DIR}/${ART_TGZ}" ]; then
  curl -fL "${ART_URL}" -o "${BASE_DIR}/${ART_TGZ}"
fi

echo "==== Extracting ===="
# Clean previous extract folder if exists (safe for fresh builds)
rm -rf "${BASE_DIR}/artifactory-oss-${ART_VERSION}" || true
tar -xzf "${BASE_DIR}/${ART_TGZ}"

echo "==== Normalizing folder layout to /opt/artifactory/app ===="
# The tarball extracts as: artifactory-oss-7.21.5/{app,var}
# We'll move that folder to /opt/artifactory/app so you end up with:
# /opt/artifactory/app/app/bin/artifactory.sh (matches your confirmed structure)
rm -rf "${APP_DIR}" || true
mv "${BASE_DIR}/artifactory-oss-${ART_VERSION}" "${APP_DIR}"

echo "==== Setting ownership ===="
chown -R "${RUN_USER}:${RUN_USER}" "${BASE_DIR}"

echo "==== Creating systemd unit ===="
cat >/etc/systemd/system/artifactory.service <<'EOF'
[Unit]
Description=JFrog Artifactory OSS
After=network.target

[Service]
Type=forking
User=artifactory
Group=artifactory
WorkingDirectory=/opt/artifactory/app
ExecStart=/opt/artifactory/app/app/bin/artifactory.sh start
ExecStop=/opt/artifactory/app/app/bin/artifactory.sh stop
TimeoutStartSec=180
TimeoutStopSec=180
Restart=on-failure
RestartSec=10
LimitNOFILE=65536

[Install]
WantedBy=multi-user.target
EOF

echo "==== Enabling and starting Artifactory ===="
systemctl daemon-reload
systemctl enable artifactory.service
systemctl restart artifactory.service

echo "==== Status (last 20 lines) ===="
systemctl --no-pager --full status artifactory.service | tail -n 40 || true

echo "==== Done. Access Artifactory on port 8081 (default) ===="





  • Create a new file Jenkinsfile and copy the below code in yellow color. 



pipeline {
    agent any
    parameters {
        string(name: 'AppName', defaultValue: 'Enter App Name', description: 'Name of application', )
        choice(choices: ['main', 'dev', 'qa', 'prod'], description: 'Select lifecycle to Deploy', name: 'Branch')
        choice(choices: ['t3.micro', 't2.small', 't2.medium'], description: 'Select Instance Size', name: 'InstanceSize')
        booleanParam(name: 'autoApprove', defaultValue: false, description: 'Automatically run apply after generating plan?')
    }


     environment {
        AWS_ACCESS_KEY_ID     = credentials('AWS_ACCESS_KEY_ID')
        AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
        TF_VAR_instance_type = "${params.InstanceSize}"
        TF_VAR_environment = "${params.Branch}"
        TF_VAR_application = "${params.AppName}"
    }
// 

    stages {
      stage('checkout') {
        steps {
            echo "Pulling changes from the branch ${params.Branch}"
            git credentialsId: '3eb34bc6-f086-49b6-bf20-8ca407bf2063', url: 'https://maworld9284@bitbucket.org/maworld9284/terraform.git' , branch: "${params.Branch}"
        }
      }

        stage('terraform plan') {
            steps {
                sh "pwd ; terraform init -input=true"
                sh "terraform plan -input=true -out tfplan"
                sh 'terraform show -no-color tfplan > tfplan.txt'
}
            }
        
        stage('terraform apply approval') {
           when {
               not {
                   equals expected: true, actual: params.autoApprove
               }
           }

           steps {
               script {
                    def plan = readFile 'tfplan.txt'
                    input message: "Do you want to apply the plan?",
                    parameters: [text(name: 'Plan', description: 'Please review the plan', defaultValue: plan)]
               }
           }
       }

        stage('terraform apply') {
            steps {
                sh "terraform apply -input=true tfplan"
            }
        }
        
        stage('terraform destroy approval') {
            steps {
                input 'Run terraform destroy?'
            }
        }
        stage('terraform destroy') {
            steps {
                sh 'terraform destroy -auto-approve'
            }
        }
    }

  }

  • Commit and push code changes to Repo with the following:
    • In Vscode, navigate to Source Code Icon on the right tabs on the side
    • Enter commit message
    • Click the + icon to stage changes 

    • Push changes by clicking on the ðŸ”„0 ⬇️ 1 ⬆️ as shown below

Run Pipeline Job

  • Go to terraform-pipeline on Jenkins and run build 
Note: The pipeline job will fail the first time to capture the parameters in Jenkinsfile

  • The next time you run a build you should see as shown below





  • Enter Artifactory in the AppName field
  • Select a Branch/Lifecycle to deploy server
  • Choose t2.small or t2.medium for Artifactory server.
  • Go to Console Output to track progress
Note: You can abort the destroy step and rerun the step by installing Blue Ocean Plugin on Jenkins to delete the resources created.


Install Proper Graph Plugin

If graph still doesn’t show, install:

Recommended Modern Plugin:

Pipeline: Stage View

Plugin ID:

pipeline-stage-view

Go to:

Manage Jenkins → Plugins → Available

Search:

Pipeline Stage View

Install and restart.

No comments:

Post a Comment

Bash Script To Install Ansible Automation Platform ( AWX)

#!/bin/bash # --- Configuration --- AWX_OPERATOR_VERSION="2.19.1" NAMESPACE="awx" KUBECONFIG_PATH="/etc/rancher/k3s...