ã€ã³ã¿ãŒãããã§ã¯ãã€ã³ãã©ã¹ãã©ã¯ãã£ã«é¢ããå€ãã®èšäºãã³ãŒããSaltStackãKitchen-CIãŠãŒãã£ãªãã£ãªã©ãšããŠèŠã€ããããšãã§ããŸãããããŸããŸãªçš®é¡ã®IaCã®äŸãèŠãŠããªãã®ã§ãéåžžã¯VCSã®ãã©ã³ãã«åå²ãããã³ãŒãã®ã¿ã§ããç°å¢ã®ã¿ã€ãã®ååãããšãã°dev / intã¯ã¿ã°ã䜿çšããŠãå¯èœã§ãããŸããååãšããŠãæ¬æ Œçãªæ§æéçºãµã€ã¯ã«ã«ã€ããŠè©±ãå¿
èŠã¯ãããŸããã ãããã«ããããã®ç¶æ³ã«ç²ŸéããŠããäŒæ¥ã§ã¯ãèšäºã¯èŠã€ãããŸããã§ããã
å€åããã¯ç解ã§ãã-å
šäœçãªã¢ãžã£ã€ã«ãšãäžåºŠã ãã®çç£ãã
ãã®èšäºã§ç¶æ³ãä¿®æ£ããããšããŸãã
çãä»äºã®èª¬æ
ãã®èšäºã§ã¯ããã©ãããã©ãŒã ã®ãããžã§ã¯ãã®ã€ã³ãã©ã¹ãã©ã¯ãã£ãœãªã¥ãŒã·ã§ã³ã®æ§æãšç®¡çã®åéã§ã®ãœãªã¥ãŒã·ã§ã³ã«ã€ããŠèª¬æããŸãããã®ãœãªã¥ãŒã·ã§ã³ã¯ãåæãŠããããé€ã20ã®ç°ãªãã³ã³ããŒãã³ãã§æ§æãããåèš70ã®ããµãŒããŒãŠãããããåããŠããŸãã
æ£çŽã«èšããšãç¹ã«ããããã¹ãŠãèªåçã«å¶åŸ¡ããã³æ§æãããŠããå Žåãããã»ã©å€ãã¯ãããŸããã 倧èŠæš¡ãªã·ã¹ãã ã«ã€ããŠã¯èª¬æã§ããŸãããæ£çŽãªãšãããã»ãŒåãã§ããããã¯ãããå€ãã®ã€ã³ã¹ã¿ã³ã¹ã«åºãã£ãŠããã ãã§ããäŒæ¥ãã¯æŸèæã®ããã«èªã¿ãŸãã
å¹å°ã®äŸã¯ãçš®åçšã§ãã
説æãããã©ãããã©ãŒã ã¯ãSaltStackã¢ãžã¥ãŒã«ã«ãã£ãŠå®å šã«ç®¡çãããSaltStackã¢ãžã¥ãŒã«ã«ãã£ãŠæ°ããã€ã³ã¹ã¿ã³ã¹ãèªç¶ã«äœæããã³èµ·åããŸãã ãã¡ãããåãã©ãããã©ãŒã ãµãŒãã¹ãèšå®ããå¿ èŠããããŸãããã·ã¹ãã ãµãŒãã¹ã®èšå®ãå¿ããªãã§ãã ããã
ãã®ãããããšãã°ãæãäžè¬çãªWebãµãŒããŒã®æ§æã«ã¯ãnginx / httpdããã³ãµã€ãèªäœã®æ§æã ãã§ãªããã·ã¹ãã ãµãŒãã¹ãå«ãŸããŸãã
- ãããã¯ãŒã¯æ§æ
- sshããŒã¢ã³ã®æ§æ
- ãã¹ãèªèšŒ
- tcp_wrapperèšå®
- iptables
- selinux / apparmor
- æå»åæ
- ãã®ã³ã°
- ç£æ»
ãµã€ãã®DNSã¬ã³ãŒãã蚌ææžã®çºè¡ãšåçºè¡ãå¿ããªãã§ãã ããã
åãµãŒãã¹ã®æ§æãåå¥ã«èª¬æãããšãã³ããŒã¢ã³ãããŒã¹ãããã ãã§ã倢äžã«ãªããŸãã
幞ããªããšã«ãSaltStackã¯ãä»ã®ã»ãšãã©ã®æ§æ管çã·ã¹ãã ãšåæ§ã«ãFormulasãšåŒã°ããåçŸå¯èœãªæ§æãããã¯ãåããŠããŸãã ãã ããåŒãã³ããŒãããããªããžããªããçŽæ¥ãã«ãããããããšã¯ãäœããã®ã¿ã°ãŸãã¯ç¹å¥ãªãªãªãŒã¹ãã©ã³ãããã§ãã£ãŠããå®å®åãšåçŸæ§ã®èŠ³ç¹ããã¯å®å šã«æ£ãããããŸãã-ã¿ã°ãæžãæãããã©ã³ããæŽæ°ãããã§ãã¯ããã³æ€èšŒã§ããŸãé£ããããŸã ãªããžã§ã³ã«åºã¥ããæ°åŒéã®å¯Ÿå¿äŸåé¢ä¿ã®ãªã¹ããç¶æããå¿ èŠããããŸãã ãã®ããã«ãã¢ãžã¥ãŒã«ãšäŸåé¢ä¿ãããŒãžã§ã³ç®¡çããããã»ã¹ã¯ããªãåã«çºæãããŸããã ã¯ãããã¡ããããªããžã§ã³ãšãšãã«ããŒãžã§ã³ã®äŸåé¢ä¿ãè¿œå ã§ããŸãããVCSã¯ãã¡ã€ã«ã®å€æŽå±¥æŽãç¶æããããã«éçºããããã®ã§ããããªãªãŒã¹ã¢ãŒãã£ãã¡ã¯ããä¿®æ£ããããã§ã¯ãããŸããã
顧客ã®ç°å¢ã§æ°åŒã䜿çšããå¿
èŠãããç¶æ³ãå¿ããªãã§ãã ããã顧客ã®ç°å¢ããäŒç€Ÿã®ãªããžããªãµãŒããŒãžã®ã¢ã¯ã»ã¹ãéãããšã¯ããããããå®å
šã«ããããã€ããªã¢ãŒãã£ãã¡ã¯ããžã®ã¢ã¯ã»ã¹ãæäŸããæ¹ãã¯ããã«å®å
šã§ãã
SaltStackã¯ãããŒãžã§ã³ä»ãã®ãã€ããªããã±ãŒãžãæäœã§ããã³ã³ããŒãã³ããæäŸããŸãã
ãã®ã³ã³ããŒãã³ãã¯ã SaltStack Packet ManagerãŸãã¯ç¥ããŠSPMãšåŒã°ããŸãã æ¬è³ªçã«ãçµæã®ããã±ãŒãžã¯tarã§ãããbzipã«ãã£ãŠã¡ã¿æ å ±ãå§çž®ãããŠããã FORMULAãã¡ã€ã«ã責任ãè² ããŸãã ãªããžããªãç¶æããããã«ã¯ããªããžããªå ã«ä¿åããããã¹ãŠã®ã¢ãŒãã£ãã¡ã¯ããååšããå Žåã«çæãããã¡ã¿æ å ±ãã¡ã€ã«ãçæããå¿ èŠãããããšã«æ³šæããŠãã ãããååã¯Yumãªããžããªãšåãã§ãã SPMã«ã¯ããã®æ å ±ãå«ãã¡ã¿ããŒã¿ãã¡ã€ã«ããŸãšããŠãåŒã®äŸåé¢ä¿ã®ããŒãžã§ã³ãæå®ããã«ããããããããªããžããªã§äœ¿çšå¯èœãªåŒãäžèŠ§è¡šç€ºã§ããªããªã©ãSPMã«ããã€ãã®æ¬ ç¹ããããŸãããããã¯SPMèªäœã®è¥ãã«ãããã®ã§ããããŒãžã§ã³2016.3ã§ã¡ã¢ãªãå€æŽãããªãå Žåã
ãªãªãŒã¹ãªããžã§ã¯ã
ããžãã¹ã«åãæãããŸãããã ãããè¡ãã«ã¯ãç¥ãããŠããªãGitbucketãµãŒãã¹ã®æ§æãæ€èšããŠãã ãã-Scalaã§æžããããªãŒãã³ãœãŒã¹ã®gitãªããžããªç®¡çã·ã¹ãã ã¯ãããªãè¯ãAPIããã©ã°ã€ã³ã·ã¹ãã ãçŽ æµã§äŸ¿å©ãªWebã€ã³ã¿ãŒãã§ã€ã¹ãåããBitbucketãGitHubãGitLabãªã©ã®ãã¹ã¿ãŒãšå®å šã«æ¯èŒããŸãïŒCIãªãïŒããã³Beanstalkãšæ¯èŒããŠç¹ã«è±ªè¯ã§ãã
ã ãããç§ãèšã£ãããã«ãããã¯scalaã§æžãããŠãããWebã¢ããªã±ãŒã·ã§ã³ãªã®ã§ãå°ãªããšã次ã®æ§æãå¿
èŠã§ã-javaãtomcatãnginxã
Dockerãã¹ãã§Kitchen-Clãããã€ããŒãšããŠKitchen-CIã䜿çšããŠãã¹ãããŸãã
æ§æã®ãããã£ã¬ã¯ããªã®æ§é ãèæ ®ããŠã¿ãŸãããã
gitbucket-formula |-- gitbucket | |-- frontend | | |-- templates | | | |-- nginx-http.conf | | | |-- nginx-https.conf | | | `-- upstream.conf | | `-- init.sls | |-- plugins | | `-- init.sls | |-- templates | | |-- database.conf | | `-- gitbucket.conf | |-- init.sls | `-- settings.jinja |-- test | `-- integration | |-- fe | | `-- serverspec | | `-- frontend_spec.rb | |-- fe-ssl | | `-- serverspec | | `-- frontend_ssl_spec.rb | |-- gitbucket | | `-- serverspec | | `-- gitbucket_spec.rb | `-- helpers | `-- serverspec | |-- fe_shared_spec.rb | |-- fe_ssl_shared_spec.rb | `-- gitbucket_shared_spec.rb |-- .editorconfig |-- .gitattributes |-- .gitconfig |-- .gitignore |-- .kitchen.yml |-- pillar.example |-- FORMULA `-- README.md
ã芧ã®ããã«ãåŒã«ã¯ã¡ã€ã³ã®ãµãŒãã¹æ§æãã©ã¡ãŒã¿ãŒã ãã§ãªãããã¹ããã£ã¬ã¯ããªã®serverspecã«èšè¿°ããããã¹ããFORMULAã¡ã¿æ å ±ãã¡ã€ã«ããããã³ã®æ§æèšè¿°åãããã³gitãªããžããªãŒæ§æãµãŒãã¹ãã¡ã€ã«ãå«ãŸããŠããŸãã
çŸæç¹ã§ã¯ã.kitchen.ymlãã¡ã€ã«ã«èå³ããããŸãã
--- driver: name: docker use_sudo: false require_chef_omnibus: false socket: tcp://dckhub.platops.org:2375 volume: /sys/fs/cgroup cap_add: - SYS_ADMIN provisioner: name: salt_solo formula: gitbucket salt_bootstrap_options: 'stable 2016.11' dependencies: - path: ../tomcat-formula name: tomcat - path: ../oracle-jdk-formula name: oracle-jdk - path: ../nginx-formula name: nginx state_top: base: '*': - gitbucket pillars: top.sls: base: '*': - gitbucket gitbucket.sls: tomcat: instance: name: 'gitbucket' connport: '8080' sslport: '8443' xms: '512M' xmx: '1G' mdmsize: '256M' frontend.sls: gitbucket: frontend: enabled: False ssl: enabled: False external: False crt: | -----BEGIN CERTIFICATE----- C ssl localhost -----END CERTIFICATE----- key: | -----BEGIN RSA PRIVATE KEY----- -----END RSA PRIVATE KEY----- platforms: - name: debian driver_config: image: debian:8 run_command: /sbin/init provision_command: - apt-get install -y --no-install-recommends wget curl tar mc iproute apt-utils apt-transport-https locales - localedef --no-archive -c -i en_US -f UTF-8 en_US.UTF-8 && localedef --no-archive -c -i ru_RU -f UTF-8 ru_RU.UTF-8 - name: centos driver_config: image: dckreg.platops.org/centos-systemd:7.3.1611 run_command: /sbin/init provision_command: - yum install -y -q wget curl tar mc iproute - localedef --no-archive -c -i en_US -f UTF-8 en_US.UTF-8 && localedef --no-archive -c -i ru_RU -f UTF-8 ru_RU.UTF-8 - sed -i -r 's/^(.*pam_nologin.so)/#\1/' /etc/pam.d/sshd - sed -i 's/tsflags=nodocs//g' /etc/yum.conf suites: - name: gitbucket - name: fe provisioner: pillars: top.sls: base: '*': - gitbucket - frontend frontend.sls: gitbucket: frontend: enabled: True - name: fe-ssl provisioner: pillars: top.sls: base: '*': - gitbucket - frontend frontend.sls: gitbucket: frontend: enabled: True url: localhost ssl: enabled: True
Driverã»ã¯ã·ã§ã³ã§ã¯ãDockerãã¹ããæäœããããã®ãã©ã¡ãŒã¿ãŒãæå®ããŸããããŒã«ã«ã¢ãã¬ã¹ãæå®ã§ããŸãããŸããä»ã®ãã©ã€ããŒãããšãã°vagrant ã ec2ãªã©ã䜿çšã§ããŸãã
Provisionerã»ã¯ã·ã§ã³ã¯ãSaltStackãæ§æãããŒã«ããããã«å¿
èŠãªæ§æãæ
åœããŸããããã§ããã®åŒã®äžèšã®äŸåé¢ä¿ãæ±ãä»ããŠéä¿¡ããããµãŒãã¹ã®æ§æãã€ã³ã¹ããŒã«ããŸãã
ãã©ãããã©ãŒã ã»ã¯ã·ã§ã³ã§ã¯ããã¹ããå®è¡ããããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãšããŠèªã¿åããã©ãããã©ãŒã ãå®çŸ©ããŸãã
æåŸã«ãã¹ã€ãŒãããã®ã»ã¯ã·ã§ã³ã§ã¯ãäžèšã®ãã©ãããã©ãŒã ã§ãã¹ãããæ§æã®ã¿ã€ããæå®ããŸãã Kitchenã®æå®ãããèšè¿°åã§ã¯ã3çš®é¡ã®ãã¹ããæ§æãããŠããŸãã
- ã¯ãªãŒã³ãµãŒãã¹ã®ã»ããã¢ãã-Java + Tomcat 8 + Gitbucket
- HTTPçµç±ã§ã®ã¿nginxã§ã»ããã¢ãã
- HTTP / Sã§nginxã䜿çšããŠã»ããã¢ãããã
åèšã§ãOSããšã«3ã€ã®æ§æããã¹ããããŸã-Debian Jessieããã³CentOS 7ã
ãã£ã¬ã¯ããªãã¥ãŒãããããããã«ããã¹ãã¹ã€ãŒãããããŸã-gitbucketãfeãfe-sslã«ããåé¢ãå«ããã¹ããã©ã«ããŒããããŸãããã«ããŒãã©ã«ããŒã«ã泚æãæã£ãŠãã ããããã¹ãã®çš®é¡ããšã«shared_examplesãå«ãŸããåããã¹ããèšè¿°ããªãããã«ãªã£ãŠããŸãã
äŸåé¢ä¿
SaltStackã®æ±æ§æãšããŒãã¹ãã©ãããã©ã¡ãŒã¿ãŒã«å ããŠãProvisionerã»ã¯ã·ã§ã³ã«æ³šç®ããŸãããããã®ã»ã¯ã·ã§ã³ã«ã¯ãæ§æããã»ã¹äžã®çžå¯Ÿãã¹ãŸãã¯çµ¶å¯Ÿãã¹ã§å©çšã§ãããã®æ§æã®äŸåé¢ä¿ã«é¢ããæ
å ±ãå«ãŸããŠããŸãã ã芧ã®ãšããããã®ãµãŒãã¹ã®ãã¹ãã«çŽæ¥é¢ä¿ããæ§æã®ã¿ããªã¹ããããŠããŸãã
ãã¡ãããã€ã³ã¹ã¿ã³ã¹ã®æ§æãå®å
šã«ã«ããŒããããã«äžèšã®9ã€ã®ã·ã¹ãã ãµãŒãã¹ãè¿œå ã§ããŸããããŸãããã®ãããªãã¹ãã«ã¯æ°æéããããŸããããšãã°ã2ã€ã®OSãã¡ããªã«å¿
èŠãªãã¹ãŠã®ãã©ã°ã€ã³ãã€ã³ã¹ããŒã«ããJenkinsã®åŒã§ã¯ããããã3ã€ã®æ§æã§çŽ1æéããããŸã-第äºã«ãç¹å®ã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã«å¿ããŠããããã®ã»ããã¯ç°ãªãããã®ãããªã»ããã®æ°ã¯ç¡éã«ãªãåŸåããããŸãã第äžã«ãçµ±åç°å¢ã§ããŒã«ãããšãã«ãã®ãããªãã¹ããå®è¡ãããŸãã
ãªãªãŒã¹ã®äž»é¡ã«ç²Ÿéããã®ã§ãæ§æã®ãªãªãŒã¹ããã»ã¹ã®æ§ç¯ã«å®éã«é²ãããšãã§ããŸãã
ã¹ã¯ãŒã¿ãŒãšããŠããã¹ãŠã®äººã«éåžžã®Jenkinsã䜿çšããNexus OSS 2ã䜿çšããŠã¢ãŒãã£ãã¡ã¯ããä¿åããŸãã
ãªãªãŒã¹ãã€ãã©ã€ã³
å®è¡ã«å¿ èŠãªãã¹ãŠã®èª¬æãå«ãJenkinsfileãäœæãããã¹ãŠã®äººã«æãããŠããã¹ããŒãžã®ããçŸããåºå ŽãäœæããŸãã
èµ·åããŒããšããŠãDockerã¯ã©ãŠããã©ã°ã€ã³ã䜿çšããŠãå¿ èŠãªãã¹ãŠã®ã³ã³ããŒãã³ããã€ã³ã¹ããŒã«ãããŠããã³ã³ãããŒïŒRubyãtest-kitchenãkitchen-saltãkitchen-dockerãããã³å®éã«ã¯docker-engineèªäœïŒãèµ·åããŠã Dockerãã¹ãã§åäœããŸãã
æåã«ããªããžããªã®ååãä»ãããã£ã¬ã¯ããªã«ãã¡ã€ã³åŒã䜿çšããŠãªããžããªãããŠã³ããŒãããŸãã æ¢ã«è¿°ã¹ãããã«ãäŸåé¢ä¿ãšããŠä»ã®æ°åŒãå¿ èŠã§ããä»åºŠã¯ããããã®ãªã¹ããååŸããŠã¯ãŒã¯ã¹ããŒã¹ã«ãã«ããŸãã ãªããžããªã®ååã«ããäŸåé¢ä¿ãæã€ãã£ã¬ã¯ããªãžã®çžå¯Ÿãã¹ã䜿çšã§ãããããæšæºã®ãªããžããªåœåã䜿çšããŠããããšã«æ³šæããŠãã ããã
node("kitchen-ci") { try { stage('Checkout repository') { checkout changelog: false, poll: false, scm: [ $class : 'GitSCM', branches : [ [ name: "${branch}" ] ], doGenerateSubmoduleConfigurations: false, extensions : [ [ $class: 'RelativeTargetDirectory', relativeTargetDir: "${repository}" ] ], userRemoteConfigs : [ [ url: "${gitRepositoryUrl}/${repository}.git" ] ] ] dir("${repository}") { gitCommit = sh(returnStdout: true, script: "git rev-parse HEAD").trim() } currentBuild.displayName = "#${env.BUILD_NUMBER} ${repository}" currentBuild.description = "${branch}(${gitCommit.take(7)})" } } catch (err) { currentBuild.result = failedStatus } def kitchenConfig = readYaml(file: "${repository}/.kitchen.yml") def formulaMetadata = readYaml(file: "${repository}/FORMULA") def dependencies = kitchenConfig.provisioner.dependencies def platforms = kitchenConfig.platforms try { stage('Get formula dependencies') { for (dependency in dependencies) { depRepo = dependency['path'] - ~/\.{2}\// println "Prepare \"${depRepo}\" as dependency" checkout changelog: false, poll: false, scm: [ $class : 'GitSCM', branches : [ [ name: '*/master' ] ], doGenerateSubmoduleConfigurations: false, extensions : [ [ $class: 'RelativeTargetDirectory', relativeTargetDir: "${depRepo}" ] ], userRemoteConfigs : [ [ url: "${gitRepositoryUrl}/${depRepo}.git" ] ] ] } } } catch (err) { currentBuild.result = failedStatus }
ç°¡åã«ããããã«ãäŸåé¢ä¿ããŒãžã§ã³ãèšå®ããããŠã£ã¶ãŒãããæåŸã®å®å®ããŒãžã§ã³ãããŠã³ããŒãããŸããããã®ãã€ãã©ã€ã³ãæ£åžžã«å®äºãããšãã«ã€ã³ã¹ããŒã«ããããŒãžã§ã³ãã¡ã€ã«ã䜿çšããŠç°¡åã«å®è£ ããã¿ã°ãŸãã¯åããã€ããªãªããžããªãããã«ããŸãã
ãŸããçŸããåè§åœ¢ã®è¡šç€ºããªã»ããããªãããã«ã2çš®é¡ã®ãã©ãããã©ãŒã ã®ã¿ã®ãã¹ããå®è¡ããŸãã
次ã®ã¹ãããã¯ãå®éã«kitchen verify
ããŒã ãšã¿ãŒã²ãããã©ãããã©ãŒã ã®ãã¹ããéå§kitchen verify
ã§ãã ãã®ã³ãã³ãã¯ãã³ã³ããã¢ã»ã³ããªãèµ·åããSaltStackæ§æãããŒã«ã¢ããããŸãããã®åŸãKitchenã¯Serverspecã§èšè¿°ããããã¹ããå®è¡ããŸãã
for (targetPlatform in targetPlatforms) { try { stage("Test integration with ${targetPlatform}") { dir("${repository}") { if (platforms['name'].containsAll(targetPlatform.toLowerCase())) { ansiColor('xterm') { sh "kitchen verify ${targetPlatform.toLowerCase()}" } } else { println "Skipping checks for \"${targetPlatform}\" platform" } } } } catch (err) { currentBuild.result = failedStatus } }
fe-sslæ§æã§ã¯ã以äžã«ãªã¹ããããŠãããã®ãå«ã42ã®ãã¹ããå®è¡ãããŸãã
require 'serverspec' set :backend, :exec host_name = `cat /etc/hostname` instance_name = 'gitbucket' nginx_confd = '/etc/nginx/conf.d' nginx_keyd = '/etc/nginx/keys' status_host = '127.0.0.1' gitbucket_version = '4.10' ssl_vhost = nginx_confd + '/90-' + instance_name + '-https.conf' certs = [ nginx_keyd + '/' + host_name.chomp + '.crt', nginx_keyd + '/' + host_name.chomp + '.key', ] ports = %w[ 443 ] shared_examples_for 'gitbucket nginx ssl frontend' do describe '### Frontend SSL configuration ###' do describe file(ssl_vhost) do it { should be_file } it { should be_owned_by 'root' } it { should be_grouped_into 'root' } it { should be_mode 644 } end certs.each do |cert| describe file(cert) do it { should be_file } it { should be_owned_by 'root' } it { should be_grouped_into 'root' } it { should be_mode 600 } end end ports.each do |port| describe port(port) do it { should be_listening.with('tcp') } end end end describe '### Frontend SSL status ###' do describe command('curl -Iso /dev/null -w "%{http_code} %{redirect_url}" '+ status_host ) do its(:stdout) { should match '301 https://localhost/' } end describe command('curl -ILso /dev/null -w "%{http_code}" --insecure '+ status_host ) do its(:stdout) { should match '200' } end describe command('curl -sL --insecure ' +\ status_host +\ '|grep "header-version"|awk -F\'>|<\' \'{print $3}\'' ) do its(:stdout) { should match gitbucket_version } end end end
ãã®ããããã¹ãŠã®ãã¹ãã«åæ Œãããããããã±ãŒãžãåéããŠãã€ããªã¢ãŒãã£ãã¡ã¯ããªããžããªã«å±éããŸãã
ã¢ãŒãã£ãã¡ã¯ãã®ã¢ã»ã³ããªã¯spm build
ã«ãã£ãŠå®è¡ãããŸããããã§ã«ã·ã§ã«ã¹ããŒãžãèµ·åããŠãããããcurlã§ã¢ãŒãã£ãã¡ã¯ããæšå¥šããŸãã
try { stage('Build and deploy SPM artifact') { if (currentBuild.result != failedStatus) { withCredentials([[$class : 'UsernamePasswordMultiBinding', credentialsId : binaryRepoCredentials, usernameVariable: 'USERNAME', passwordVariable: 'PASSWORD']]) { dir("${repository}") { sh """#!/usr/bin/env bash sudo spm build . formula=\$(ls -1A ${spmBuildDir}|grep '.spm') if [[ -n \$formula ]]; then response=\$(curl --compressed \ -u ${env.USERNAME}:${env.PASSWORD} \ -s -o /dev/null -w "%{http_code}\n" \ -A 'Jenkins POST Invoker' \ --upload-file ${spmBuildDir}/\$formula \ ${binaryRepoUrl}); if [[ \$response -ne 201 ]]; then echo "Something goes wrong! HTTP_CODE: \$response"; exit 1; else echo "Formula \$formula deployed."; fi else echo "Couldn't find file"; exit 1; fi """ } } } else { println "We will not packing failed formulas" } } } catch (err) { currentBuild.result = failedStatus }
ããã¯ã»ãŒçµããã§ããçŸåšã®ã³ãããã«ã¿ã°ãä»ãã kitchen destroy
ãå®è¡ããŠãäœæããããã¹ãŠã®ã³ã³ãããåé€ããŸãã
try { stage('Tag version in SCM') { currentTag = formulaMetadata['version'] if (currentBuild.result != failedStatus) { dir("${repository}") { sh """#!/usr/bin/env bash if [[ \$(git tag -l|grep ${currentTag}) ]]; then if [[ "\$(git show-ref --tags|grep ${currentTag}|awk '{print \$1}'|cut -b-7)" != "${gitCommit.take(7)}" ]]; then echo "Tag \"${currentTag}\" will be updated." git tag -d ${currentTag} git push origin :${currentTag} else echo "Tag \"${currentTag}\" already exists. Skipping." fi else echo "Creating tag \"${currentTag}\"" git tag ${currentTag} git push origin --tags fi """ } } else { println "We will not tag revision for failed formulas" } } } catch (err) { currentBuild.result = failedStatus } try { stage('Cleanup after tests') { dir("${repository}") { sh "kitchen destr" } } } catch (err) { currentBuild.result = failedStatus }
äžè¬çã«ã destroy
ã create
ã converge
ã setup
ã verify
ã destroy
ãªã©ã®ã¹ããŒãžãèµ·åããtest
ã³ãã³ããKitchen-CIã«ããsetup
ããäžéšã®åŒã§ã¯ããã¹ãããã»ã¹äžã«ãªã³ã¯ã³ã³ãããŒã䜿çšããŸããããšãã°ããµãŒããŒæ§æãæåã«éå§ããFreeIPAãæ©èœããããšãæ€èšŒããŸããããŠãã¯ã©ã€ã¢ã³ãæ§æãæã€ã³ã³ãããèµ·åããããããªã³ã¯ãµãŒããŒã®ãã¡ã€ã³ã«å
¥åããŸã.testãå®è¡test
ãšããµãŒããŒãèµ·åãããã¹ããããã¯ã©ã€ã¢ã³ããèµ·åããåã«åé€ãããŸãã ãã®ããã verify
ã³ãã³ãã䜿çšãããã€ãã©ã€ã³ã®æåŸã®ã¹ããŒãžã¯destroy
ä»ããŠã¯ãªãŒãã³ã°ãdestroy
ãŸãã
ãªããžããªã§ã®äœæ¥
åŒããã¹ããããã¿ã°ããªããžããªã«é
眮ãããã¢ãŒãã£ãã¡ã¯ãããã€ããªãªããžããªã«åã蟌ãŸããŠããŸãããSaltStackã§ã¯ãŸã 䜿çšã§ããŸãã-ã¡ã¿æ
å ±ãæŽæ°ããå¿
èŠããããŸããããã«ã¯ããã¹ãŠã®åŒãå«ããªããžããªãã£ã¬ã¯ããªã®spm create_repo $DIR
ã³ãã³ããå¿
èŠã§ãã
ãŸããSaltStackãä»ããŠNexusãæ§æãããããSPMã¯ããŒã«ã«ã«ã€ã³ã¹ããŒã«ãããŸããããã䜿çšããŸãã
Nexusãåãããã¹ãã«python-inotifyã¢ãžã¥ãŒã«ãã€ã³ã¹ããŒã«ãããœã«ããããªã³çšã«SaltStack Beaconãèšå®ããŸããããã«ãããåŒã§ãã£ã¬ã¯ããªã®å€æŽã5ç§ããšã«ç£èŠããŸãã
#/etc/salt/minion.d/beacons.conf beacons: inotify: interval: 5 disable_during_state_run: True /opt/nexus/data/storage/org.platops.salt.formulas: mask: - create - modify - delete - attrib recurse: True auto_add: True exclude: - /opt/nexus/data/storage/org.platops.salt.formulas/SPM-METADATA - /opt/nexus/data/storage/org.platops.salt.formulas/.nexus/
ãã®æ®µéã§ãsalt-minionãåèµ·åããå¿ èŠããããŸãããã®åŸããã£ã¬ã¯ããªå ã®ãã¡ã€ã«ãå€æŽããå Žåãsalt-masterã¯ããã«é¢ããã€ãã³ããåãåããŸãã
salt/beacon/nexus.platops.org/inotify//opt/nexus/data/storage/org.platops.salt.formulas { "_stamp": "2017-07-09T10:31:11.283771", "change": "IN_ATTRIB", "id": "nexus.platops.org", "path": "/opt/nexus/data/storage/org.platops.salt.formulas/gitbucket-1.0.0-1.spm"
salt-masterã§ãæ§æãããããŒã³ã³ããã®ã€ãã³ããç£èŠããæ§æãããç¶æ ãèµ·åãããªã¢ã¯ã¿ãŒãã»ããã¢ããããŸãã
#/etc/salt/master.d/reactor.conf reactor: - 'salt/beacon/nexus.platops.org/inotify//opt/nexus/data/storage/org.platops.salt.formulas': - /srv/salt/reactor/update-spm-metadata.sls
ãããŠãå®éã«ç¶æ ã¯å¿ èŠãªã³ãã³ããéå§ããŸãïŒ
#/srv/salt/reactor/update-spm-metadata.sls update spm repository metadata: local.cmd.run: - tgt: {{ data['id'] }} - arg: - spm create_repo /opt/nexus/data/storage/org.platops.salt.formulas
salt-masterãsalt-minionãããã³å®éã«ã¯ãã¹ãŠã5ç§ããšã«åèµ·åããããšãå¿ããªãã§ãã ãããããŒã³ã³ã¯ãã£ã¬ã¯ããªå
ã®inotifyãéããŠã€ãã³ãããã§ãã¯ãããªããžããªã¡ã¿ããŒã¿ã®æŽæ°ãéå§ããŸãã
Nexus 3ã䜿çšããŠããå Žåã¯ããããå®è£
ããæ©äŒããããŸããNexuswebhookãšSalt-API㫠泚ç®ããŠãã ããã
æ°åŒãèšå®ãã
salt-masterã®/etc/salt/spm.repos.d/nexus.repoã§ãªããžããªãèšå®ããŸãããã¹ã¯ãŒãã¯ãã¬ãŒã³ããã¹ãã§èšå®ãããŠããããšã«æ³šæããŠãã ãããããšãã°ããã®ãã¡ã€ã«ã«é©åãªæš©éãèšå®ããããšãå¿ããªãã§ãã ãã400éãããæš©å©ã»ããããŸããSPMãè¿œå ããŠæå·åããããã¹ã¯ãŒãã䜿çšããïŒ
#/etc/salt/spm.repos.d/nexus.repo nexus.platops.org: url: https://nexus.platops.org/content/sites/org.platops.salt.formulas username: saltmaster password: supersecret
salt-masteräžã®åŒã®ããŒã¿ãæŽæ°ããåŒãèšå®ããŸãã
spm update_repo spm install gitbucket Installing packages: gitbucket Proceed? [N/y] y ... installing gitbucket
å®éã«ã¯ããã¹ãæžã¿ãã¿ã°ä»ããããã¯æžã¿ã®ãã¹ãŠã®æ°åŒãsalt-masterãã£ã¬ã¯ããªã«ã€ã³ã¹ããŒã«ãããŠããŸãã
ãã«ãªã¯ãšã¹ãã®ã¢ã»ã³ããªãšãšãã«ããã®ãããªããªãåçŽã§ããå¹æçãªæ§æã®ãªãªãŒã¹ãµã€ã¯ã«ãç·šæããŸãããããã¯ãåŒã®äŸåé¢ä¿ããµãŒãã¹ã®æ§æã®åé¡ãæ€åºããåæ段éã§åœ¹ç«ã¡ãç°ãªã顧客ç°å¢éã§æ§æãç°¡åã«é åžããããšãã§ããŸãã
å®ç§ã«å¶éã¯ãªãããœã«ããã¹ã¿ãŒã®ãªããžããªããŒã¿ã®æŽæ°ã®èªåèµ·åãšãã®æ°åŒã®èªåæŽæ°ãäºææ§ãé«ããããã«ããŒãã³ãŒããããããŒãžã§ã³ã§ã®äŸåé¢ä¿ã®ãã¹ããSPMãžã®ãã¹ã¯ãŒãæå·åãµããŒãã®è¿œå ãè¿œå ã SPM䜿çšå¯èœãªæ°åŒã®ãªã¹ãã衚瀺ããæ©èœãç¹å®ã®ããŒãžã§ã³ã®äŸåé¢ä¿ãã€ã³ã¹ããŒã«ããæ©èœãSPMã«è¿œå ããããã¹ãããããã©ãããã©ãŒã ã®æ°ãå¢ãããªã©ã
ãšããã§ãç§ãåŒçšãããã¹ãã§ã¯ããã¹ãå€ã¯ããŒãã³ãŒãã£ã³ã°ãããŠããŸããããã¯.kitchen.ymlã®æ±ã«ãèšå®ãããŠãããæ¬è³ªçã«æ å ±ã®è€è£œãäœæããŸããç§ã®ååã®Alexander Shevchenkoã®ãããã§ãç§ãã¡ã¯ãããã䜿çšããªããªããŸããããããã«ã€ããŠã¯ã圌ã¯èªåã§æžããŸãã
çæ§ãããããšãããããŸãããã®èšäºãããªãã®ä»äºã«åœ¹ç«ã€ããšãé¡ã£ãŠããŸãã