Bypass หน้า Setup Wizard ของ Jenkins

ความตั้งใจจริง ๆ แค่อยากได้ jenkins ที่เป็น docker แล้วมี go install ไว้ให้แล้วเท่านั้น พอลอง compose up (ด้วย docker compose) jenkins ขึ้นมาก็เจอหน้าอย่างที่เคย ๆ เจอ คือ หน้า setup wizard พอลอง compose up ตัว jenkins บ่อย ๆ ก็รู้สึกว่า ต้องมานั่ง unlock jenkins ทุกครั้งด้วนยการเอา initialAdminPassword มากรอก เสร็จแล้วต้องไปเลือก plugin ที่อยากลงอีก ซึ่งกว่าจะลงเสร็จก็ใช้เวลาสักพัก ถัดมาต้องมาสร้าง account อีก กว่าจะเสร็จทุกขั้นตอนนี่โคตรเสียเวลาเลย เลยคิดว่า มันมีวิธีไหนมั่งที่สามารถข้ามขั้นตอนพวกนี้ไปได้ เป็นแบบ compose up เสร็จปุ๊บ พร้อมใช้เลย เลยกลายมาเป็นที่มาของการ bypass หน้า setup wizard ของ jenkins

หน้า unlock jenkins
หน้า unlock jenkins

หน้าเลือกวิธีการลง plugin
หน้าเลือกวิธีการลง plugin

หน้าสร้าง user
หน้าสร้าง user

jenkins พร้อมใช้งานแล้ว
jenkins พร้อมใช้งานแล้ว

แรก ๆ ใช้วิธีตรงไปตรงมาคือ ใช้ curl ส่ง POST ไปหา jenkins หลังจาก jenkins start แล้วเพื่อที่จะ simulate action ไปทีละหน้า ปัญหาที่เจอคือ

  • เมื่อไหร่ jenkins จะ start เสร็จนะ เพราะว่าตอน jenkins start กว่ามันจะสร้าง file และ directory ที่มันต้องใช้เสร็จ ก็ใช้เวลา จะใช้ loop แล้ว sleep รอไปเรื่อย ๆ ลองแล้วก็กลายเป็นว่า jenkins มันไม่ start เลยทีนี้ (ทำไมก็ไม่รู้)
  • install plugin ลำบากมาก ต่อเนื่องจากอันแรกคือ กว่า jenkins จะพร้อมก็นาน กว่าจะเข้าไปใช้ script install-plugin.sh ที่ jenkins มี ก็ลำบากมาก ต้องมาคอยเช็คว่า script ตัวนี้โผล่มาให้ใช้แล้วหรือยังนะ
  • initial admin password file เหมือนกับข้อข้างบน ไฟล์นี้จะเก็บ unlock code ไว้ให้ ซึ่งกว่าจะโผล่มาให้ใช้ก็ต้องรอ
  • crumb form บน jenkins ทุกอย่างใช้ crumb ซึ่งเป็น token แปลว่าเราต้องเขียน script ไปดึง crumb มาก่อน แล้วค่อยยิง request ไปหา jenkins อีกที

ปัญหาข้างบน ทำให้ตอนพยายามสร้าง jenkins ลำบากและวุ่นวายโคตร เลยไปหาวิธีเพิ่มเติม จนไปเจอวิธีที่น่าสนใจ

Groovy

เนื่องจาก jenkins เขียนด้วย java ทำมาเป็น war file, jenkins มัน support groovy และ jenkins มี init.groovy.d directory เพื่อเอาไว้ใส่ของที่จะถูกทำตอน jenkins start ขึ้นมา เพียงแค่ต้องเขียนด้วย groovy นั่นคือ เราแค่ต้องทำ groovy เพื่อ create user และ bypass หน้า setup wizard

สิ่งที่ทำคือ สร้างไฟล์ groovy ไปวางไว้ที่ /var/home/jenkins/init.groovy.d ชื่ออะไรก็ได้ นามสกุลเป็น .groovy มีรายละเอียดตามนี้

#!/usr/bin/env groovy
import jenkins.model.*
import hudson.security.*
import jenkins.install.InstallState

def instance = Jenkins.getInstance()

println "--> creating local user from environment variable"

def env = System.getenv()
def username = env['JENKINS_USERNAME']
def password = env['JENKINS_PASSWORD']

// Create user with custom pass
def realm = new HudsonPrivateSecurityRealm(false, false, null)
instance.setSecurityRealm(realm)
def user = realm.createAccount(username, password)
user.save()

def strategy = new FullControlOnceLoggedInAuthorizationStrategy()
strategy.setAllowAnonymousRead(false)
instance.setAuthorizationStrategy(strategy)

if (!instance.installState.isSetupComplete()) {
  println '--> Neutering SetupWizard'
  InstallState.INITIAL_SETUP_COMPLETED.initializeState()
}

instance.save()

จาก script จะเห็นว่า มันเอา default user/password มาจาก environment variable เราก็แค่ไปกำหนดไว้ใน docker compose หรือ ENV ใน Dockerfile

ในตอนท้าย ๆ ก็มีการเซ็ตให้มันกระโดดข้าม setup wizard โดยการหลอกมันว่า setup เสร็จแล้ว

ทีนี้เพื่อความชัวร์ใน docker-compose.yml ก็ประกาศ JAVA_OPTS="-Djenkins.install.runSetupWizard=false" ไว้ใน environment ด้วย เพื่อที่จะบอกว่าเฮ้ย ไม่ต้อง run wizard นะ

Install plugins

ตัว jenkins มี plugin installation script มาให้ อยู่ที่ /usr/local/bin/install-plugins.sh เราแค่ส่งชื่อ plugin ที่จะ install ให้มันเท่านั้น ดังนั้นถ้าเรามีรายชื่อ plugin เป็นไฟล์ ก็แค่ใช้ /usr/local/bin/install-plugins.sh < plugins.txt ก็จบ

ที่เหลือ

เนื่องจากตอนต้นสุด สิ่งที่อยากได้คือ jenkins ที่ unlock แล้ว พร้อมกับ plugin และมี go install ไว้ให้ด้วย ก็เหลือแค่ install go เท่านั้น อันนี้ก็ตรงไปตรงมา แค่เพิ่ม script ข้างล่างนี้ลงไปใน Dockerfile

USER root
RUN curl -O https://dl.google.com/go/go1.10.3.linux-amd64.tar.gz \
    && tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
USER jenkins

ENV PATH="${PATH}:/usr/local/go/bin"

เท่านี้ก็มี go ให้ใช้แล้ว

ตัวอย่าง

ดูตัวอย่างอันที่ทำเสร็จแล้ว ที่ https://github.com/chonla/jenkins-docker-with-go

อ้างอิง

Leave a Reply

Your email address will not be published. Required fields are marked *