Jenkinsfile(Declarative Pipeline)を忘れたときに見て!なる早で思い出せるかも?

Jenkinsfileを忘れた時に見てほしい Jenkins
スポンサーリンク

今回は、Jenkinsfileを書く上で知っておきたい基礎知識を紹介します。

この記事では、「昔書いたことあるけど、忘れちゃった。。」って人が、なる早でJenkinsfileを思い出すことができる!を目指しています。

本ページはプロモーションが含まれています。

あなたの才能に、正当な価格を。転職ドラフトで見つける、次のステージ。
スポンサーリンク

実際にはどんな感じで書くの?

まずは全体像から。ここでイメージを掴んでもらい、後述の解説を確認してもらう方法が理解しやすいのではないかと思います。

pipeline {
  environment {
    AWS_ACCESS_KEY = credentials("AWS_ACCESS_KEY")
    AWS_SECRET_ACCESS_KEY = credentials("AWS_SECRET_ACCESS_KEY")
    DOCKER_IMAGE = 'terraform:latest'
    TERRAFORM_HOME = '003/rds-restore/terraform'
  }

  agent any

  parameters {
    string(name: 'SNAPSHOT_ID', defaultValue: '', description: 'リストアするスナップショットIDを入力してください。')
    choice(
      choices: ['apply', 'destroy', 'state list', 'state show'],
      description: '実行するTerraformのアクションを選択して下さい。',
      name: 'ACTION'
    )
    string(name: 'TARGET', defaultValue: '', description: 'Stateを確認したいターゲットを指定してください。')
  }

  stages {
    stage('Image Build') {
      steps {
        script {
          docker.build(DOCKER_IMAGE, '--build-arg AWS_ACCESS_KEY=$AWS_ACCESS_KEY --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY ./003/rds-restore')
        }
      }
    }
    stage('terraform init'){
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform init'
        }
      }
    }
    stage('terraform plan') {
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      when {
        expression {params.ACTION == 'apply' || params.ACTION == 'destroy'}
      }
      steps {
        script {
          dir(TERRAFORM_HOME){
            if(params.ACTION == 'apply'){
              sh 'terraform plan -var-file=variables.tfvars'
            } else if (params.ACTION == 'destroy') {
              sh 'terraform plan -destroy -var-file=variables.tfvars'
            } else {
              return
            }
          }
        }
      }
    }
    stage('terraform apply') {
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      when {
        beforeInput true
        expression {params.ACTION == 'apply'}
      }
      input {
          message 'applyを実行しますか?'
          ok 'Yes'
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform apply -var-file=variables.tfvars -auto-approve'
        }
      }
    }
    stage('terraform destroy') {
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      when {
        beforeInput true
        expression {params.ACTION == 'destroy'}
      }
      input {
          message 'destroyを実行しますか?'
          ok 'Yes'
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform apply -destroy -var-file=variables.tfvars -auto-approve'
        }
      }
    }
    stage('terraform state list') {
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      when {
        beforeInput true
        expression {params.ACTION == 'state list'}
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform state list'
        }
      }
    }
    stage('terraform state show') {
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      when {
        beforeInput true
        expression {params.ACTION == 'state show' && params.TARGET != ''}
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh "terraform state show $params.TARGET"
        }
      }
    }
  }
}
転職エージェントなら「レバテック」!
レバテックキャリア

求人数も多く、完全無料で利用することができます。すぐに退会もすることもできるので、1度登録して、相談に乗ってもらうことがオススメです。

Declarative Pipelineとは?

Jenkinsの構文は2種類あります。

1つ目が上でも使用している「Scripted Pipeline」。node {}で書き始める構文になります。古くからある書き方ですが、Groovy言語を使用して処理を記載することができるので自由度が高いです。ただ、自由度が高い一方、複雑になってしまい保守性が下がったりもすることもあるかと思います。

2つ目が上でも使用している「Declarative Pipeline」。こちらは比較的新しい構文になります。「Scripted Pipeline」と比べてシンプルな構文になっています。シンプルですが、やれることは多く現在の主流になっているかと思います。script {}のディレクティブを使用することで、「Scripted Pipeline」の記述方法も使えるので基本的にこちらの使用をオススメします。

それでは、以降で細かい部分を解説していきます。

環境変数の使い方は?

environment {}の中で環境変数を使用することができます。(当然ながら、ここで設定した変数は、以降の処理で使用することができます。以下の例では、「DOCKER_IMAGE」を環境変数として宣言しており、ビルドコマンドのオプションにその変数を使用しています。)

  ...
  environment {
    AWS_ACCESS_KEY = credentials("AWS_ACCESS_KEY")
    AWS_SECRET_ACCESS_KEY = credentials("AWS_SECRET_ACCESS_KEY")
    DOCKER_IMAGE = 'terraform:latest'
    TERRAFORM_HOME = '003/rds-restore/terraform'
  }
  ...
  stages {
    stage('Image Build') {
      steps {
        script {
          docker.build(DOCKER_IMAGE, '--build-arg AWS_ACCESS_KEY=$AWS_ACCESS_KEY --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY ./003/rds-restore')
        }
      }
    }
   ...
あなたの才能に、正当な価格を。転職ドラフトで見つける、次のステージ。

Jenkinsに登録されたクレデンシャルの参照方法は?

credentials('登録されたキー')で取得することができます。

以下の例では、事前にAWSの認証情報をJenkinsのクレデンシャルに登録しておき、Pipelineの中で取得しています。

pipeline {
  environment {
   AWS_ACCESS_KEY = credentials('AWS_ACCESS_KEY')
   AWS_SECRET_ACCESS_KEY = credentials('AWS_SECRET_ACCESS_KEY')
  }
  ... //←後は通常の変数として利用することが可能。
}

ジョブ開始時のパラメータの設定方法は?

parameters {}で各種パラメータを設定することができます。

いくつか指定することができるのですが、その中でもよく使いそうなパラメータを紹介します。

string(文字列の入力をさせたい場合)

string(name: 'SNAPSHOT_ID', defaultValue: '', description: 'スナップショットIDを入力してください。')

choice(予め用意した選択肢から選ばせたい場合)

choice(
  name: 'ENVIRONMENT',
  choices: ['dev', 'stg', 'prd'],
  description: '環境を選択してください。'
)

boolean(チェックボックスで有効/無効を切り替えたい場合)

boolean(name: 'OUTPUT_LOG', defaultValue: false, description: '')

また、上述したパラメータはparams.[name]で取得することができます。

以下は例です。

  ...
  parameters {
    string(name: 'SNAPSHOT_ID', defaultValue: '', description: 'リストアするスナップショットIDを入力してください。')
    choice(
      choices: ['apply', 'destroy', 'state list', 'state show'],
      description: '実行するTerraformのアクションを選択して下さい。',
      name: 'ACTION'
    )
    string(name: 'TARGET', defaultValue: '', description: 'Stateを確認したいターゲットを指定してください。')
  }
  ...
      when {
        beforeInput true
        expression {params.ACTION == 'apply'}
      }
  ...

dockerを使いたい場合は?

Using Docker with Pipeline
Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy...

pipeline内でdockerイメージをビルドする

いくつかやり方はあるのですが、今回はscript {}(Scripted Pipeline)を利用します(ビルド時の引数で色々渡したかったため。)

docker.build([イメージ名], [ビルド時のオプション])

今回は、Terraformが実行できるイメージを作成したかったため、ビルド時のオプションでAWSクレデンシャルを渡しています。

  ...
    stage('Image Build') {
      steps {
        script {
          docker.build(DOCKER_IMAGE, '--build-arg AWS_ACCESS_KEY=$AWS_ACCESS_KEY --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY ./003/rds-restore')
        }
      }
    }
   ...

ビルドしたイメージの中でstepsの処理を行う

イメージをビルドしたら、それ以降のstage(){}ではそのビルドしたイメージを使用して処理を行いたいことがよくあると思います。そんなときに活躍するのがこれ。

  ...
  agent any
  ...
  stages {
    stage('Image Build') {
      steps {
        script {
          docker.build(DOCKER_IMAGE, '--build-arg AWS_ACCESS_KEY=$AWS_ACCESS_KEY --build-arg AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY ./003/rds-restore')
        }
      }
    }
    stage('terraform init'){
      agent {
        docker {
          image DOCKER_IMAGE
          reuseNode true
        }
      }
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform init'
        }
      }
    }
  ...

1つ目のポイントは「agent any」。今回は事前に用意されたDockerイメージではなく、処理の中でビルドしたイメージを使いたかっためanyを指定しています。(anyを指定すると各stageの処理は任意のagentを指定することが可能になります。

2つ目のポイントは、stateの中でagentにDockerイメージを指定していること。このようにすることで、このstageに含まれるstepsの処理は、そのコンテナ内で処理が行われます。

3つ目のポイントは、「reuseNode true」。これを指定することで既存のワークスペースを使い続けます。falseにするとチェックアウトが再度走るため、今回は処理時間を短くしたかったためtrueにしています。

柔軟性と高収入を両立。Midworkで、理想のワークスタイルを実現
Midworks

Midworkはフリーランスエンジニアのために、高単価からフルリモートまで、多様な働き方をサポートするプロジェクトマッチングサービスです。専任カウンセラーによる手厚いキャリアサポートも、特徴の一つ。これらのサービスを通じて、あなたのキャリアを次のレベルへ。

パラメータの値で処理をするかどうか決めたい!

「XXXのパラメータが指定された時だけ、処理を行いたい!」とかよくあると思います。

そんな時に使えるのがこちら。

  ...
      when {
        beforeInput true
        expression {params.ACTION == 'apply'}
      }
  ...

赤字の部分が、「パラメータのACTIONにapplyが指定された時だけ以降の処理を実行する」という意味になります。これとは逆に「apply以外が指定された時に処理を実行する」としたい場合は、条件の部分をparams.ACTION != 'apply'とすることでできます。

ディレクトリを移動してコマンドを実行したい!

デフォルトだとWorkSpaceで処理が実行されます。ディレクトリを移動して、コマンドを実行したい場合はdir([移動したいディレクトリ]){}を使用することで実現可能です。

  ...
      steps {
        dir(TERRAFORM_HOME) {
          sh 'terraform apply -var-file=variables.tfvars -auto-approve' // ←このコマンドはTERRAFORM_HOMEに設定されたパスで実行されます。
        }
      }
  ...

処理を実行する前に「Yes or No」を入力して実施の有無を決めたい!

input {}を使用することで実現可能!

  ...
      when {
        beforeInput true
        expression {params.ACTION == 'destroy'}
      }
      input {
          message 'destroyを実行しますか?'
          ok 'Yes'
      }
  ...

when { beforeInput true }を利用することで、inputの前にwhenで始まる処理を入れることができます。上記の例だと、params.ACTION == 'destroy'でパラメーターのチェックを入れた後に、inputで実行有無を確認しています。

(「destroyを実行しますか?」というポップアップが表示され、「Yes」ボタンをクリックすると処理が続きます。「Abort」も合わせて表示され、これをクリックすると処理が中断され終了します。)

以上です。参考になりました?

転職エージェントなら「レバテック」!
レバテックキャリア

求人数も多く、完全無料で利用することができます。すぐに退会もすることもできるので、1度登録して、相談に乗ってもらうことがオススメです。

プロフィール
この記事を書いた人
katsuya

SESからキャリアをスタートし、現在はフリーランスとして活動しています。フリーランスになってから6年で年収1,000万円を達成しました。「Study Infra」では、今までの経験やITインフラに関する情報を発信中です。

katsuyaをフォローする
Jenkins
スポンサーリンク
シェアする
katsuyaをフォローする

コメント

タイトルとURLをコピーしました