├── .gitignore
├── .travis.yml
├── README.org
├── Scenario-101
├── README.md
├── config
│ ├── node.json
│ └── solo.rb
├── cookbooks
│ └── example
│ │ └── recipes
│ │ └── default.rb
└── docker-compose.yml
├── Scenario-102
├── README.md
├── Vagrantfile
├── config
│ ├── node.json
│ └── solo.rb
└── cookbooks
│ └── example
│ ├── .rubocop.yml
│ ├── .travis.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── metadata.rb
│ └── recipes
│ └── default.rb
├── Scenario-103
├── README.md
├── config
│ ├── node.json
│ └── solo.rb
├── cookbooks
│ └── example
│ │ ├── .rubocop.yml
│ │ ├── .travis.yml
│ │ ├── Berksfile
│ │ ├── Gemfile
│ │ ├── README.md
│ │ ├── metadata.rb
│ │ └── recipes
│ │ └── default.rb
└── docker-compose.yml
├── Scenario-201
├── README.md
└── cookbooks
│ └── example
│ ├── .kitchen.yml
│ ├── .rubocop.yml
│ ├── .travis.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ └── default.rb
│ ├── metadata.rb
│ ├── recipes
│ └── default.rb
│ ├── templates
│ └── default
│ │ └── version.txt.erb
│ └── test
│ └── integration
│ └── default
│ └── serverspec
│ └── server_spec.rb
├── Scenario-202
├── README.md
└── cookbooks
│ └── example
│ ├── .kitchen.yml
│ ├── .kitchen_digitalocean.yml
│ ├── .kitchen_ec2.yml
│ ├── .kitchen_vagrant.yml
│ ├── .rubocop.yml
│ ├── .travis.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ └── default.rb
│ ├── chefignore
│ ├── metadata.rb
│ ├── recipes
│ └── default.rb
│ ├── templates
│ └── default
│ │ └── version.txt.erb
│ └── test
│ └── integration
│ └── default
│ └── serverspec
│ └── server_spec.rb
├── Scenario-301
├── README.md
└── cookbooks
│ └── jenkins-demo
│ ├── .kitchen.yml
│ ├── .kitchen_digitalocean.yml
│ ├── .kitchen_ec2.yml
│ ├── .kitchen_vagrant.yml
│ ├── .rubocop.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ ├── conf_job.rb
│ └── default.rb
│ ├── files
│ └── default
│ │ └── serverspec_check.sh
│ ├── metadata.rb
│ ├── recipes
│ ├── conf_job.rb
│ ├── default.rb
│ └── master.rb
│ ├── templates
│ └── default
│ │ └── CommonServerCheckRepo
│ │ └── config.xml
│ └── test
│ ├── integration
│ └── default
│ │ └── serverspec
│ │ └── server_spec.rb
│ └── shared
│ └── verify_job_config.rb
├── Scenario-302
├── README.md
└── cookbooks
│ └── jenkins-demo
│ ├── .kitchen.yml
│ ├── .kitchen_digitalocean.yml
│ ├── .kitchen_ec2.yml
│ ├── .kitchen_vagrant.yml
│ ├── .rubocop.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ ├── conf_job.rb
│ └── default.rb
│ ├── files
│ └── default
│ │ └── serverspec_check.sh
│ ├── metadata.rb
│ ├── recipes
│ ├── backup.rb
│ ├── conf_job.rb
│ ├── default.rb
│ ├── master.rb
│ └── security.rb
│ ├── templates
│ └── default
│ │ └── CommonServerCheckRepo
│ │ └── config.xml
│ └── test
│ ├── integration
│ └── default
│ │ └── serverspec
│ │ └── server_spec.rb
│ └── shared
│ └── verify_job_config.rb
├── Scenario-303
├── README.md
└── cookbooks
│ └── jenkins-demo
│ ├── .kitchen.yml
│ ├── .kitchen_digitalocean.yml
│ ├── .kitchen_ec2.yml
│ ├── .kitchen_vagrant.yml
│ ├── .rubocop.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ ├── conf_test_job.rb
│ └── default.rb
│ ├── files
│ └── default
│ │ └── serverspec_check.sh
│ ├── metadata.rb
│ ├── recipes
│ ├── backup.rb
│ ├── conf_test_job.rb
│ ├── default.rb
│ ├── master.rb
│ ├── security.rb
│ └── test_pipeline.rb
│ ├── templates
│ └── default
│ │ ├── CommonServerCheckRepo
│ │ └── config.xml
│ │ ├── JenkinsFileExample1
│ │ ├── Jenkinsfile.groovy
│ │ └── config.xml
│ │ └── JenkinsFileExample2
│ │ ├── Jenkinsfile.groovy
│ │ └── config.xml
│ └── test
│ ├── integration
│ └── default
│ │ └── serverspec
│ │ └── server_spec.rb
│ └── shared
│ └── verify_job_config.rb
├── Scenario-401
├── README.md
└── cookbooks
│ └── jenkins-demo
│ ├── .kitchen.yml
│ ├── .rubocop.yml
│ ├── Berksfile
│ ├── Gemfile
│ ├── README.md
│ ├── attributes
│ └── default.rb
│ ├── metadata.rb
│ ├── recipes
│ ├── conf_job.rb
│ ├── default.rb
│ └── master.rb
│ ├── templates
│ └── default
│ │ └── CollectFiles.xml.erb
│ └── test
│ └── integration
│ └── default
│ └── serverspec
│ └── server_spec.rb
└── images
├── chef-study.graffle
├── chef_icon.png
├── scenario-101-screenshot.jpg
├── scenario-102-screenshot.jpg
├── scenario-103-design.png
├── scenario-201-design.png
├── scenario-202-design.png
└── scenario-401-design.png
/.gitignore:
--------------------------------------------------------------------------------
1 | local-mode-cache
2 | .vagrant
3 | *.deb
4 | Berksfile.lock
5 | .kitchen
6 | Gemfile.lock
7 | Dockerfile-kitchen*
8 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 | rvm:
3 | - 2.2
4 | # command to install dependencies
5 | install:
6 | - gem install rubocop -v "0.48.1"
7 | # command to run tests
8 | script:
9 | - find . -name cookbooks | xargs rubocop
10 |
--------------------------------------------------------------------------------
/Scenario-101/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirements](#requirements)
11 | * [Procedure](#procedure)
12 |
13 |
14 |
15 |
16 | # Requirements
17 | ```
18 | 1. Use docker container to start a env with chef pre-installed
19 | 2. Create a dummy cookbook and apply it
20 | ```
21 |
22 | # Procedure
23 |
24 | - Start docker-compose env
25 |
26 | docker-compose up -d
27 |
28 | - Login to the container, and run procedure
29 | ```
30 | docker exec -it my_chef sh
31 | apt-get -y update
32 |
33 | cd /tmp
34 |
35 | - Before chef apply, jq package is missing
36 | which jq
37 |
38 | - From config/node.json, we specify to apply example cookbook
39 | chef-solo -c config/solo.rb -j config/node.json
40 |
41 | - After chef apply, jq package is installed
42 | which jq
43 | ```
44 |
45 | - Destroy docker-compose env after testing
46 |
47 | ```
48 | docker-compose down -v
49 | ```
50 |
51 |
--------------------------------------------------------------------------------
/Scenario-101/config/node.json:
--------------------------------------------------------------------------------
1 | {
2 | "run_list": [ "recipe[example]" ]
3 | }
4 |
--------------------------------------------------------------------------------
/Scenario-101/config/solo.rb:
--------------------------------------------------------------------------------
1 | cookbook_path File.expand_path(File.join(File.dirname(__FILE__), '..', "cookbooks"))
--------------------------------------------------------------------------------
/Scenario-101/cookbooks/example/recipes/default.rb:
--------------------------------------------------------------------------------
1 | package 'jq'
2 |
--------------------------------------------------------------------------------
/Scenario-101/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | my_chef:
4 | container_name: my_chef
5 | hostname: my_chef
6 | # https://hub.docker.com/r/chef/chefdk/
7 | image: chef/chefdk
8 | entrypoint: ["tail", "-f", "/dev/null"]
9 | volumes:
10 | - ./config:/tmp/config
11 | - ./cookbooks:/tmp/cookbooks
12 |
--------------------------------------------------------------------------------
/Scenario-102/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirements](#requirements)
11 | * [Procedure](#procedure)
12 | * [Test in public cloud?](#test-in-public-cloud)
13 |
14 |
15 |
16 |
17 | # Requirements
18 | 1. Start a VM, install chef facility
19 | 2. Create a dummy cookbook to install jq package
20 | 3. Before install jq, run "apt-get update" by chef. So you need berkshelf.
21 | 4. Enforce rubocop and foodcritic for code static check
22 |
23 | # Procedure
24 | - Start VM via vagrant
25 | ```
26 | vagrant up
27 | ```
28 | More about virtualbox: https://www.virtualbox.org/wiki/Downloads
29 |
30 | More about vagrant: https://www.vagrantup.com/docs/providers/basic_usage.html
31 |
32 | - Login and install chef-dk
33 | ```
34 | ssh vagrant@192.168.50.10
35 | # password: vagrant
36 |
37 | # https://downloads.chef.io/chefdk
38 | wget -O /tmp/chefdk.deb \
39 | https://packages.chef.io/files/stable/chefdk/2.3.4/ubuntu/16.04/chefdk_2.3.4-1_amd64.deb
40 |
41 | sudo dpkg -i /tmp/chefdk*.deb
42 |
43 | # chef-solo version: 13.4.19
44 | chef-solo -verison
45 | ```
46 |
47 | - Upload chef cookbook code
48 | ```
49 | scp -r Scenario-102 vagrant@192.168.50.10:/tmp/
50 | ```
51 |
52 | - Get cookbooks dependency
53 | ```
54 | ssh vagrant@192.168.50.10
55 | mkdir -p /tmp/berks_cookbooks
56 | cd /tmp/Scenario-102/cookbooks/example/
57 | berks vendor /tmp/berks_cookbooks
58 | ls -lth /tmp/berks_cookbooks
59 |
60 | cd /tmp/Scenario-102/
61 | ```
62 |
63 | - Apply Chef update
64 | ```
65 | ssh vagrant@192.168.50.10
66 | cd /tmp/Scenario-102
67 |
68 | # Before chef deployment, our VM doesn't have jq package
69 | which jq
70 | sudo chef-solo -c config/solo.rb -j config/node.json
71 |
72 | # After deployment, we should see jq package installed
73 | which jq
74 | ```
75 |
76 | - Run code static check
77 | rubocop:
78 | ```
79 | gem install rubocop -v "0.44.1"
80 | cd cookbooks/example
81 | rubocop .
82 | ```
83 | Check more about rubocop: https://www.dennyzhang.com/rubocop_errors
84 |
85 | foodcritic:
86 | ```
87 | gem install foodcritic -v "4.0.0"
88 | cd cookbooks/
89 | foodcritic example
90 | ```
91 |
92 | TODO: how to install foodcritic in mac OSX
93 |
94 | - Destroy local vm
95 | ```
96 | vagrant destroy -f
97 | ```
98 |
99 | # Test in public cloud?
100 |
101 | Now you have finished local VM deployment. Congratulations!
102 |
103 | Why not move to public cloud? AWS, AZure, or whatever. Should be easy for you, right?
104 |
105 |
--------------------------------------------------------------------------------
/Scenario-102/Vagrantfile:
--------------------------------------------------------------------------------
1 | # -*- mode: ruby -*-
2 | Vagrant.configure("2") do |config|
3 | config.vm.box = "ubuntu/trusty64"
4 | config.vm.provider "virtualbox" do |vb|
5 | vb.name = "chef-sandbox"
6 | vb.customize ["modifyvm", :id, "--memory", 512, "--cpus", 2]
7 | end
8 | # host-only network
9 | config.vm.network :private_network, ip: "192.168.50.10"
10 | end
11 |
--------------------------------------------------------------------------------
/Scenario-102/config/node.json:
--------------------------------------------------------------------------------
1 | {
2 | "run_list": [ "recipe[example]" ]
3 | }
4 |
--------------------------------------------------------------------------------
/Scenario-102/config/solo.rb:
--------------------------------------------------------------------------------
1 | cookbook_path [File.expand_path(File.join(File.dirname(__FILE__), '..', "cookbooks")), '/tmp/berks_cookbooks/']
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Excludes:
3 |
4 | Metrics/LineLength:
5 | Max: 100
6 |
7 | Style/Next:
8 | Enabled: false
9 |
10 | BlockLength:
11 | Max: 90
12 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 |
3 | rvm:
4 | - 2.1.1
5 |
6 | script:
7 | - bundle exec rspec --color --format progress
8 | - bundle exec foodcritic -f any .
9 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'foodcritic', '~> 4.0.0'
5 | gem 'rubocop', '~> 0.48.1'
6 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/README.md:
--------------------------------------------------------------------------------
1 | A chef cookbook template:
2 | - Run apt-get update
3 | - Install jq package
4 | - Enforce rubocop and foodcritic code static check
5 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/metadata.rb:
--------------------------------------------------------------------------------
1 | name 'example'
2 | maintainer 'DennyZhang.com'
3 | maintainer_email 'contact@dennyzhang.com'
4 | license 'All rights reserved'
5 | description 'Dummy chef cookbook'
6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
7 | version '0.0.1'
8 | issues_url 'https://www.dennyzhang.com'
9 | source_url 'https://www.dennyzhang.com'
10 |
11 | supports 'ubuntu'
12 |
13 | depends 'apt'
14 |
--------------------------------------------------------------------------------
/Scenario-102/cookbooks/example/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # Run apt-get update first
2 | include_recipe 'apt::default'
3 |
4 | package 'jq'
5 |
--------------------------------------------------------------------------------
/Scenario-103/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirements](#requirements)
11 | * [Procedures](#procedures)
12 |
13 |
14 |
15 |
16 |
17 | # Requirements
18 | 1. Start 3 containers to run chef server, knife workstation and chef client
19 | 2. Install and configure knife
20 | 3. From knife node run chef deployment in chef client node
21 |
22 | # Procedures
23 | - Start docker-compose env
24 | ```
25 | docker-compose up -d
26 | docker-compose ps
27 | ```
28 |
29 | - Setup chef server in docker container
30 |
31 | In docker-compose.yml, chef_server is using a dedicated chef server image.
32 |
33 | ```
34 | # https://hub.docker.com/r/base/chef-server/~/dockerfile/
35 |
36 | # Verify chef server
37 | curl -k -I https://localhost/users/login
38 | ```
39 |
40 | - Use chef_client as both client and knife workstation
41 |
42 | - Get certificate from chef server to chef knife
43 |
44 | To configure knife, we need admin.pem and chef-validator.pem from chef server node
45 |
46 | ```
47 | docker cp chef_server:/etc/chef-server/admin.pem /tmp/admin.pem
48 | docker cp chef_server:/etc/chef-server/chef-validator.pem /tmp/chef-validator.pem
49 |
50 | docker cp /tmp/admin.pem chef_knife:/tmp/
51 | docker cp /tmp/chef-validator.pem chef_knife:/tmp/
52 |
53 | rm -rf /tmp/admin.pem /tmp/chef-validator.pem
54 | ```
55 |
56 | - Configure knife workstation
57 | ```
58 | docker exec -it chef_knife bash
59 |
60 | mkdir -p /root/chef-server/.chef
61 | mv /tmp/*.pem /root/chef-server/
62 | chmod 600 -R /root/chef-server/*.pem
63 | ls -lth /root/chef-server/
64 |
65 | which knife
66 |
67 | curl -k -I https://chef_server/organizations/digitalocean
68 |
69 | knife configure --initial
70 |
71 | # Please enter the chef server URL:
72 | # https://chef_server/organizations/myorg
73 | #
74 | # Please enter a name for the new user:
75 | # dennykitchen
76 | #
77 | # Please enter a password for the new user:
78 | # password1
79 | #
80 |
81 | cat > ~/.ssh/knife.rb <
111 |
--------------------------------------------------------------------------------
/Scenario-103/config/node.json:
--------------------------------------------------------------------------------
1 | {
2 | "run_list": [ "recipe[example]" ]
3 | }
4 |
--------------------------------------------------------------------------------
/Scenario-103/config/solo.rb:
--------------------------------------------------------------------------------
1 | cookbook_path [File.expand_path(File.join(File.dirname(__FILE__), '..', "cookbooks")), '/tmp/cookbooks/']
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Excludes:
3 |
4 | Metrics/LineLength:
5 | Max: 100
6 |
7 | Style/Next:
8 | Enabled: false
9 |
10 | BlockLength:
11 | Max: 90
12 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 |
3 | rvm:
4 | - 2.1.1
5 |
6 | script:
7 | - bundle exec rspec --color --format progress
8 | - bundle exec foodcritic -f any .
9 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'foodcritic', '~> 4.0.0'
5 | gem 'rubocop', '~> 0.48.1'
6 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/README.md:
--------------------------------------------------------------------------------
1 | A chef cookbook template:
2 | - Run apt-get update
3 | - Install jq package
4 | - Enforce rubocop and foodcritic code static check
5 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/metadata.rb:
--------------------------------------------------------------------------------
1 | name 'example'
2 | maintainer 'DennyZhang.com'
3 | maintainer_email 'contact@dennyzhang.com'
4 | license 'All rights reserved'
5 | description 'Dummy chef cookbook'
6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
7 | version '0.0.1'
8 | issues_url 'https://www.dennyzhang.com'
9 | source_url 'https://www.dennyzhang.com'
10 |
11 | supports 'ubuntu'
12 |
13 | depends 'apt'
14 |
--------------------------------------------------------------------------------
/Scenario-103/cookbooks/example/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # Run apt-get update first
2 | include_recipe 'apt::default'
3 |
4 | package 'jq'
5 |
--------------------------------------------------------------------------------
/Scenario-103/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '2'
2 | services:
3 | chef_server:
4 | container_name: chef_server
5 | hostname: chef_server
6 | # https://hub.docker.com/r/base/chef-server/~/dockerfile/
7 | image: base/chef-server
8 | # entrypoint: ["tail", "-f", "/dev/null"]
9 | privileged: true
10 | ports:
11 | - "443:443"
12 | chef_knife:
13 | container_name: chef_knife
14 | hostname: chef_knife
15 | # https://hub.docker.com/r/chef/chefdk/
16 | image: chef/chefdk
17 | entrypoint: ["tail", "-f", "/dev/null"]
18 | chef_client:
19 | container_name: chef_client
20 | hostname: chef_client
21 | # https://hub.docker.com/r/chef/chefdk/
22 | image: chef/chefdk
23 | entrypoint: ["tail", "-f", "/dev/null"]
24 | volumes:
25 | - ./config:/tmp/config
26 | - ./cookbooks:/tmp/cookbooks
27 |
--------------------------------------------------------------------------------
/Scenario-201/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirements](#requirements)
11 | * [Procedure](#procedure)
12 |
13 |
14 |
15 |
16 |
17 | # Requirements
18 | Run kitchen docker in your laptop.
19 | 1. Use kitchen to test your cookbook: start a container and test the logic
20 | 2. Enforce kitchen verify logic via serverspec
21 |
22 | # Procedure
23 | - Install bundle
24 | ```
25 | apt-get install ruby-dev
26 |
27 | ruby --version
28 | # https://github.com/bundler/bundler/issues/4065
29 | sudo gem install bundler -n /usr/local/bin
30 |
31 | bundle --version
32 | ```
33 |
34 | - Install gem depenencies
35 | ```
36 | cd cookbooks/example
37 | bundle install
38 | ```
39 |
40 | - Run kitchen test
41 | ```
42 | # https://github.com/test-kitchen/kitchen-docker
43 | kitchen converge
44 | kitchen list
45 | kitchen verify
46 | kitchen destroy
47 | ```
48 |
49 |
50 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "example") %>
7 | hostname: <%= ENV.fetch('INSTANCE_NAME', "example") %>
8 | use_sudo: false
9 | privileged: true
10 | remove_images: false
11 | image: <%= ENV.fetch('IMAGE_NAME', "chef/chefdk") %>
12 | # tls_verify: true
13 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
14 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
15 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
16 | # socket: tcp://172.17.0.1:4243
17 | transport:
18 | username: kitchen
19 |
20 | provisioner:
21 | name: chef_zero
22 | require_chef_omnibus: 12.17.44
23 | data_path: test/shared
24 | client_rb:
25 | file_cache_path: "/var/chef/cache"
26 |
27 | platforms:
28 | - name: ubuntu-14.04
29 |
30 | suites:
31 | - name: default
32 | run_list:
33 | - recipe[apt::default]
34 | - recipe[example::default]
35 | attributes:
36 | {example:
37 | {update_version: '1.1'
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Excludes:
3 |
4 | Metrics/LineLength:
5 | Max: 100
6 |
7 | Style/Next:
8 | Enabled: false
9 |
10 | BlockLength:
11 | Max: 90
12 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 |
3 | rvm:
4 | - 2.1.1
5 |
6 | script:
7 | - bundle exec rspec --color --format progress
8 | - bundle exec foodcritic -f any .
9 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-docker', '>= 2.5.0'
5 | gem 'test-kitchen', '>= 1.4.1'
6 |
7 | gem 'berkshelf', '>= 5.2.0'
8 |
9 | gem 'foodcritic', '~> 4.0.0'
10 | gem 'rubocop', '~> 0.48.1'
11 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/README.md:
--------------------------------------------------------------------------------
1 | A chef cookbook template:
2 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | default['example']['update_version'] = '1.0'
4 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/metadata.rb:
--------------------------------------------------------------------------------
1 | name 'example'
2 | maintainer 'DennyZhang.com'
3 | maintainer_email 'contact@dennyzhang.com'
4 | license 'All rights reserved'
5 | description 'Dummy chef cookbook'
6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
7 | version '0.0.1'
8 | issues_url 'https://www.dennyzhang.com'
9 | source_url 'https://www.dennyzhang.com'
10 |
11 | supports 'ubuntu'
12 |
13 | depends 'apt'
14 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: example
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | %w[jq].each do |x|
13 | package 'jq' do
14 | action :install
15 | not_if "dpkg -l #{x} | grep -E '^ii'"
16 | end
17 | end
18 |
19 | directory '/etc/ec2-user/' do
20 | owner 'root'
21 | group 'root'
22 | mode 0o755
23 | action :create
24 | end
25 |
26 | template '/etc/ec2-user/version.txt' do
27 | source 'version.txt.erb'
28 | mode 0o700
29 | end
30 |
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/templates/default/version.txt.erb:
--------------------------------------------------------------------------------
1 | Update version: <%= node['example']['update_version'] %>
--------------------------------------------------------------------------------
/Scenario-201/cookbooks/example/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 | require 'socket'
5 | require 'json'
6 |
7 | # Required by serverspec
8 | set :backend, :exec
9 |
10 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
11 |
12 | update_version = \
13 | chef_data.fetch('example').fetch('update_version')
14 |
15 | # TODO: verify the specific version '1.5-1-a5b5cbe'
16 | describe package('jq') do
17 | it { should be_installed }
18 | end
19 |
20 | describe command('cat /etc/ec2-user/version.txt') do
21 | its(:stdout) { should contain update_version }
22 | end
23 |
--------------------------------------------------------------------------------
/Scenario-202/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirements](#requirements)
11 | * [Procedure](#procedure)
12 | * [Common Setup](#common-setup)
13 | * [kitchen docker deployment](#kitchen-docker-deployment)
14 | * [kitchen digitalocean deployment](#kitchen-digitalocean-deployment)
15 | * [kitchen ec2 deployment](#kitchen-ec2-deployment)
16 | * [kitchen vagrant deployment](#kitchen-vagrant-deployment)
17 |
18 |
19 |
20 |
21 |
22 | # Requirements
23 | 1. Use Kitchen to test local vm deployment
24 | 2. Use Kitchen to test docker deployment
25 | 3. Use Kitchen to test cloud VM deployment
26 |
27 | # Procedure
28 | ## Common Setup
29 | - Install bundle
30 | ```
31 | apt-get install ruby-dev
32 |
33 | ruby --version
34 | # https://github.com/bundler/bundler/issues/4065
35 | sudo gem install bundler -n /usr/local/bin
36 |
37 | bundle --version
38 | ```
39 |
40 | - Install gem depenencies
41 | ```
42 | cd cookbooks/example
43 | bundle install
44 | ```
45 |
46 | ## kitchen docker deployment
47 | - Run kitchen test
48 | ```
49 | # https://github.com/test-kitchen/kitchen-docker
50 | kitchen converge
51 | kitchen list
52 | kitchen verify
53 | kitchen destroy
54 | ```
55 |
56 | ## kitchen digitalocean deployment
57 | ```
58 | # https://github.com/test-kitchen/kitchen-digitalocean
59 | cd cookbooks/example
60 | export KITCHEN_YAML=".kitchen_digitalocean.yml"
61 |
62 | # Customize this with your credential
63 | export DIGITALOCEAN_ACCESS_TOKEN="1234"
64 | export DIGITALOCEAN_SSH_KEY_IDS="1234, 5678"
65 |
66 | kitchen converge
67 | kitchen list
68 | kitchen verify
69 | kitchen destroy
70 |
71 | - TODO: how does the ssh key work? With which OS user, and where the key is?
72 | ```
73 |
74 | ## kitchen ec2 deployment
75 | - Install AWS cli and configure aws credential
76 | ```
77 | # http://docs.aws.amazon.com/cli/latest/userguide/installing.html
78 | pip install awscli
79 | aws configure
80 |
81 | # Customize this
82 | export KEY_USER="denny-kitchen-test"
83 | aws ec2 create-key-pair --key-name $KEY_USER | ruby -e "require 'json'; puts JSON.parse(STDIN.read)['KeyMaterial']" > ~/.ssh/$KEY_USER
84 |
85 | chmod 600 ~/.ssh/$KEY_USER
86 |
87 | export AWS_SSH_KEY_ID="$KEY_USER"
88 |
89 | ```
90 |
91 | - Install and run kitchen-ec2
92 | ```
93 | # https://github.com/test-kitchen/kitchen-ec2
94 | # https://github.com/test-kitchen/kitchen-ec2/blob/master/lib/kitchen/driver/ec2.rb
95 | # http://kg4giy.com/2015/12/11/test-kitchen-to-support-amazon-web-service-aws-amis/
96 |
97 | cd cookbooks/example
98 | export KITCHEN_YAML=".kitchen_ec2.yml"
99 | # TODO: customize this
100 | export AWS_SSH_KEY_ID="$KEY_USER"
101 |
102 | # Update bundle: https://github.com/chef/chef-provisioning/issues/151
103 | bundle update
104 |
105 | kitchen converge
106 | kitchen list
107 | kitchen verify
108 | kitchen destroy
109 | ```
110 |
111 | ## kitchen vagrant deployment
112 | ```
113 | # https://github.com/test-kitchen/kitchen-vagrant
114 | cd cookbooks/example
115 | export KITCHEN_YAML=".kitchen_vagrant.yml"
116 |
117 | bundle install
118 |
119 | kitchen converge
120 | kitchen list
121 | kitchen verify
122 | kitchen destroy
123 | ```
124 |
125 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "example") %>
7 | hostname: <%= ENV.fetch('INSTANCE_NAME', "example") %>
8 | use_sudo: false
9 | privileged: true
10 | remove_images: false
11 | image: <%= ENV.fetch('IMAGE_NAME', "chef/chefdk") %>
12 | # tls_verify: true
13 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
14 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
15 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
16 | # socket: tcp://172.17.0.1:4243
17 | transport:
18 | username: kitchen
19 |
20 | provisioner:
21 | name: chef_zero
22 | require_chef_omnibus: 13.6.4
23 | data_path: test/shared
24 | client_rb:
25 | file_cache_path: "/var/chef/cache"
26 |
27 | platforms:
28 | - name: ubuntu-14.04
29 |
30 | suites:
31 | - name: default
32 | run_list:
33 | - recipe[apt::default]
34 | - recipe[example::default]
35 | attributes:
36 | {example:
37 | {update_version: '1.1'
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.kitchen_digitalocean.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: digitalocean
4 |
5 | provisioner:
6 | name: chef_zero
7 | require_chef_omnibus: 13.6.4
8 | data_path: test/shared
9 |
10 | platforms:
11 | - name: example
12 | driver_config:
13 | region: sfo2
14 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
15 | private_networking: false
16 | image: ubuntu-14-04-x64
17 | server_name: <%= ENV.fetch('INSTANCE_NAME', "example") %>
18 |
19 | suites:
20 | - name: default
21 | run_list:
22 | - recipe[apt::default]
23 | - recipe[example::default]
24 | attributes:
25 | {example:
26 | {update_version: '1.1'
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.kitchen_ec2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: ec2
4 | region: us-east-1
5 |
6 | transport:
7 | ssh_key: ~/.ssh/<%= ENV.fetch('KEY_USER', "") %>
8 | username: ["ec2-user"]
9 |
10 | provisioner:
11 | name: chef_zero
12 | require_chef_omnibus: 13.6.4
13 | data_path: test/shared
14 |
15 | platforms:
16 | - name: ubuntu-14.04
17 | driver:
18 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-6869aa05") %>
19 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
20 |
21 | suites:
22 | - name: default
23 | run_list:
24 | - recipe[apt::default]
25 | - recipe[example::default]
26 | attributes:
27 | {example:
28 | {update_version: '1.1'
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.kitchen_vagrant.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: vagrant
4 |
5 | driver_config:
6 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "example") %>
7 | hostname: <%= ENV.fetch('INSTANCE_NAME', "example") %>
8 | transport:
9 | username: kitchen
10 |
11 | provisioner:
12 | name: chef_zero
13 | require_chef_omnibus: 13.6.4
14 | data_path: test/shared
15 | client_rb:
16 | file_cache_path: "/var/chef/cache"
17 |
18 | platforms:
19 | - name: ubuntu-14.04
20 |
21 | suites:
22 | - name: default
23 | run_list:
24 | - recipe[apt::default]
25 | - recipe[example::default]
26 | attributes:
27 | {example:
28 | {update_version: '1.1'
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Excludes:
3 |
4 | Metrics/LineLength:
5 | Max: 100
6 |
7 | Style/Next:
8 | Enabled: false
9 |
10 | BlockLength:
11 | Max: 90
12 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/.travis.yml:
--------------------------------------------------------------------------------
1 | language: ruby
2 |
3 | rvm:
4 | - 2.1.1
5 |
6 | script:
7 | - bundle exec rspec --color --format progress
8 | - bundle exec foodcritic -f any .
9 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-digitalocean', '= 0.9.8'
5 | gem 'kitchen-docker', '= 2.6.0'
6 | gem 'kitchen-ec2', '= 1.3.2'
7 | gem 'kitchen-vagrant', '= 1.2.1'
8 |
9 | gem 'test-kitchen', '= 1.19.1'
10 |
11 | gem 'berkshelf', '= 6.3.1'
12 |
13 | gem 'foodcritic', '~> 4.0.0'
14 | gem 'rubocop', '~> 0.48.1'
15 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/README.md:
--------------------------------------------------------------------------------
1 | A chef cookbook template:
2 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | default['example']['update_version'] = '1.0'
4 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/chefignore:
--------------------------------------------------------------------------------
1 | .kitchen
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/metadata.rb:
--------------------------------------------------------------------------------
1 | name 'example'
2 | maintainer 'DennyZhang.com'
3 | maintainer_email 'contact@dennyzhang.com'
4 | license 'All rights reserved'
5 | description 'Dummy chef cookbook'
6 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
7 | version '0.0.1'
8 | issues_url 'https://www.dennyzhang.com'
9 | source_url 'https://www.dennyzhang.com'
10 |
11 | supports 'ubuntu'
12 |
13 | depends 'apt'
14 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: example
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | %w[jq].each do |x|
13 | package x do
14 | action :install
15 | not_if "dpkg -l #{x} | grep -E '^ii'"
16 | end
17 | end
18 |
19 | directory '/etc/ec2-user/' do
20 | owner 'root'
21 | group 'root'
22 | mode 0o755
23 | action :create
24 | end
25 |
26 | template '/etc/ec2-user/version.txt' do
27 | source 'version.txt.erb'
28 | mode 0o700
29 | end
30 |
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/templates/default/version.txt.erb:
--------------------------------------------------------------------------------
1 | Update version: <%= node['example']['update_version'] %>
--------------------------------------------------------------------------------
/Scenario-202/cookbooks/example/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 | require 'socket'
5 | require 'json'
6 |
7 | # Required by serverspec
8 | set :backend, :exec
9 |
10 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
11 |
12 | update_version = \
13 | chef_data.fetch('example').fetch('update_version')
14 |
15 | # TODO: verify the specific version '1.5-1-a5b5cbe'
16 | describe package('jq') do
17 | it { should be_installed }
18 | end
19 |
20 | describe command('cat /etc/ec2-user/version.txt') do
21 | its(:stdout) { should contain update_version }
22 | end
23 |
--------------------------------------------------------------------------------
/Scenario-301/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirement](#requirement)
11 | * [Procedure](#procedure)
12 | * [More Resources](#more-resources)
13 |
14 |
15 |
16 | # Requirement
17 |
18 | 1. Deploy a standalone jenkins by chef
19 | 2. Chef shall add one jenkins user
20 | 3. Chef shall add a dummy job with slack notification enabled
21 | 4. Run deployment in docker, vagrant and EC2
22 | 5. Test both Ubuntu 14.04 and Centos 7
23 |
24 | # Procedure
25 | ## Common Setup
26 | - Install bundle
27 | ```
28 | apt-get install ruby-dev
29 |
30 | ruby --version
31 | # https://github.com/bundler/bundler/issues/4065
32 | sudo gem install bundler -n /usr/local/bin
33 |
34 | bundle --version
35 | ```
36 |
37 | - Install gem depenencies
38 | ```
39 | cd cookbooks/jenkins-demo
40 | bundle install
41 | ```
42 |
43 | ## kitchen docker deployment
44 | - Run kitchen test
45 | ```
46 | # https://github.com/test-kitchen/kitchen-docker
47 |
48 | # Customize this, if you need to enable jenkins slack notification
49 | export SLACK_TOKEN="XXXX"
50 | kitchen list
51 | kitchen test
52 | ```
53 |
54 | ## kitchen digitalocean deployment
55 | ```
56 | # https://github.com/test-kitchen/kitchen-digitalocean
57 | cd cookbooks/jenkins-demo
58 | export KITCHEN_YAML=".kitchen_digitalocean.yml"
59 |
60 | # Customize this with your credential
61 | export DIGITALOCEAN_ACCESS_TOKEN="1234"
62 | export DIGITALOCEAN_SSH_KEY_IDS="1234, 5678"
63 |
64 | # Customize this, if you need to enable jenkins slack notification
65 | export SLACK_TOKEN="XXXX"
66 | kitchen list
67 | kitchen test
68 |
69 | - TODO: how does the ssh key work? With which OS user, and where the key is?
70 | ```
71 |
72 | ## kitchen ec2 deployment
73 | - Install AWS cli and configure aws credential
74 | ```
75 | # http://docs.aws.amazon.com/cli/latest/userguide/installing.html
76 | pip install awscli
77 | aws configure
78 |
79 | # Customize this
80 | export KEY_USER="denny-kitchen-test"
81 | aws ec2 create-key-pair --key-name $KEY_USER | ruby -e "require 'json'; puts JSON.parse(STDIN.read)['KeyMaterial']" > ~/.ssh/$KEY_USER
82 |
83 | chmod 600 ~/.ssh/$KEY_USER
84 |
85 | export AWS_SSH_KEY_ID="$KEY_USER"
86 | ```
87 |
88 | - Install and run kitchen-ec2
89 | ```
90 | # https://github.com/test-kitchen/kitchen-ec2
91 | # https://github.com/test-kitchen/kitchen-ec2/blob/master/lib/kitchen/driver/ec2.rb
92 | # http://kg4giy.com/2015/12/11/test-kitchen-to-support-amazon-web-service-aws-amis/
93 |
94 | cd cookbooks/jenkins-demo
95 | export KITCHEN_YAML=".kitchen_ec2.yml"
96 | # TODO: customize this
97 | export AWS_SSH_KEY_ID="$KEY_USER"
98 |
99 | # Update bundle: https://github.com/chef/chef-provisioning/issues/151
100 | bundle update
101 |
102 | # Customize this, if you need to enable jenkins slack notification
103 | export SLACK_TOKEN="XXXX"
104 | kitchen list
105 | kitchen test
106 | ```
107 |
108 | ## kitchen vagrant deployment
109 | ```
110 | # https://github.com/test-kitchen/kitchen-vagrant
111 | cd cookbooks/jenkins-demo
112 | export KITCHEN_YAML=".kitchen_vagrant.yml"
113 |
114 | bundle install
115 |
116 | # Customize this, if you need to enable jenkins slack notification
117 | export SLACK_TOKEN="XXXX"
118 | kitchen list
119 | kitchen test
120 | ```
121 |
122 | # More Resources
123 | - jenkins cookbook: https://github.com/chef-cookbooks/jenkins
124 |
125 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | use_sudo: false
7 | # because Docker and SystemD/Upstart
8 | privileged: true
9 | remove_images: false
10 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
11 | # tls_verify: true
12 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
13 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
14 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
15 | # socket: tcp://172.17.0.1:4243
16 | transport:
17 | username: kitchen
18 |
19 | provisioner:
20 | name: chef_zero
21 | require_chef_omnibus: 13.6.4
22 | data_path: test/shared
23 | client_rb:
24 | file_cache_path: "/var/chef/cache"
25 |
26 | platforms:
27 | - name: centos-7
28 | driver_config:
29 | # https://hub.docker.com/r/dokken/centos-7/
30 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
31 | image: <%= ENV.fetch('IMAGE_NAME', "dokken/centos-7") %>
32 | pid_one_command: /usr/lib/systemd/systemd
33 | forward:
34 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80:8080
35 | - name: ubuntu-14.04
36 | driver_config:
37 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
38 | image: <%= ENV.fetch('IMAGE_NAME', "ubuntu:14.04") %>
39 | forward:
40 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "280") %>80:8080
41 |
42 | suites:
43 | - name: default
44 | run_list:
45 | - recipe[apt::default]
46 | - recipe[jenkins-demo::default]
47 | - recipe[jenkins-demo::conf_job]
48 | attributes:
49 | {jenkins_demo:
50 | {jenkins_jobs: 'CommonServerCheckRepo',
51 | slack_teamdomain: 'mywechat',
52 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
53 | # TODO different env use different port
54 | # TODO use server ip
55 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
56 | slack_room: '#denny-alerts',
57 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
58 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/.kitchen_digitalocean.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: digitalocean
4 |
5 | provisioner:
6 | name: chef_zero
7 | require_chef_omnibus: 13.6.4
8 | data_path: test/shared
9 |
10 | platforms:
11 | - name: jenkins-demo-centos7
12 | driver_config:
13 | region: sfo2
14 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
15 | private_networking: false
16 | # https://github.com/test-kitchen/kitchen-digitalocean
17 | image: centos-7-x64
18 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
19 | - name: jenkins-demo-ubuntu1404
20 | driver_config:
21 | region: sfo2
22 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
23 | private_networking: false
24 | image: ubuntu-14-04-x64
25 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
26 |
27 | suites:
28 | - name: default
29 | run_list:
30 | - recipe[apt::default]
31 | - recipe[jenkins-demo::default]
32 | - recipe[jenkins-demo::conf_job]
33 | attributes:
34 | {jenkins_demo:
35 | {jenkins_jobs: 'CommonServerCheckRepo',
36 | slack_teamdomain: 'mywechat',
37 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
38 | # TODO different env use different port
39 | # TODO use server ip
40 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
41 | slack_room: '#denny-alerts',
42 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
43 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/.kitchen_ec2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: ec2
4 | region: us-east-1
5 |
6 | transport:
7 | ssh_key: ~/.ssh/<%= ENV.fetch('KEY_USER', "") %>
8 | username: ec2-user
9 |
10 | provisioner:
11 | name: chef_zero
12 | require_chef_omnibus: 13.6.4
13 | data_path: test/shared
14 |
15 | platforms:
16 | - name: ubuntu-1404
17 | driver:
18 | # https://cloud-images.ubuntu.com/releases/14.04/release-20150506/
19 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-8d9e1cf7") %>
20 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
21 | transport:
22 | username: ubuntu
23 | - name: centos-7
24 | driver:
25 | # https://wiki.centos.org/Cloud/AWS
26 | # https://stackoverflow.com/questions/40835953/how-to-find-ami-id-of-centos-7-image-in-aws-marketplace
27 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-ae7bfdb8") %>
28 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
29 | transport:
30 | username: centos
31 | - name: centos-ami
32 | driver:
33 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-6869aa05") %>
34 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
35 |
36 | suites:
37 | - name: default
38 | run_list:
39 | - recipe[apt::default]
40 | - recipe[jenkins-demo::default]
41 | - recipe[jenkins-demo::conf_job]
42 | attributes:
43 | {jenkins_demo:
44 | {jenkins_jobs: 'CommonServerCheckRepo',
45 | slack_teamdomain: 'mywechat',
46 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
47 | # TODO different env use different port
48 | # TODO use server ip
49 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
50 | slack_room: '#denny-alerts',
51 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
52 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/.kitchen_vagrant.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: vagrant
4 |
5 | driver_config:
6 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
7 | # https://github.com/test-kitchen/kitchen-vagrant
8 | memory: 1024
9 | transport:
10 | username: kitchen
11 |
12 | provisioner:
13 | name: chef_zero
14 | require_chef_omnibus: 13.6.4
15 | data_path: test/shared
16 | client_rb:
17 | file_cache_path: "/var/chef/cache"
18 |
19 | platforms:
20 | - name: centos-7
21 | driver_config:
22 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
23 | network:
24 | - ["forwarded_port", {guest: 8080, host: 18080}]
25 | - name: ubuntu-14.04
26 | # https://stackoverflow.com/questions/38677059/port-forwarding-not-working-with-test-kitchen-and-vagrant
27 | driver_config:
28 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
29 | network:
30 | - ["forwarded_port", {guest: 8080, host: 28080}]
31 |
32 | suites:
33 | - name: default
34 | run_list:
35 | - recipe[apt::default]
36 | - recipe[jenkins-demo::default]
37 | - recipe[jenkins-demo::conf_job]
38 | attributes:
39 | {jenkins_demo:
40 | {jenkins_jobs: 'CommonServerCheckRepo',
41 | slack_teamdomain: 'mywechat',
42 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
43 | # TODO different env use different port
44 | # TODO use server ip
45 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
46 | slack_room: '#denny-alerts',
47 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
48 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - Berksfile
4 |
5 | Style/Next:
6 | Enabled: false
7 |
8 | Metrics/LineLength:
9 | Max: 90
10 |
11 | MethodLength:
12 | Max: 20
13 |
14 | Metrics/AbcSize:
15 | Enabled: false
16 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-digitalocean', '= 0.9.8'
5 | gem 'kitchen-docker', '= 2.6.0'
6 | gem 'kitchen-ec2', '= 1.3.2'
7 | gem 'kitchen-vagrant', '= 1.2.1'
8 |
9 | gem 'test-kitchen', '= 1.19.1'
10 |
11 | gem 'berkshelf', '= 6.3.1'
12 |
13 | gem 'foodcritic', '~> 4.0.0'
14 | gem 'rubocop', '~> 0.48.1'
15 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/README.md:
--------------------------------------------------------------------------------
1 | jenkins-demo Cookbook
2 | ================
3 | Setup and configure demo jenkins
4 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/attributes/conf_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 |
9 | default['jenkins_demo']['jenkins_jobs'] = ''
10 | # slack notification
11 | default['jenkins_demo']['slack_teamdomain'] = ''
12 | default['jenkins_demo']['slack_authtoken'] = ''
13 | default['jenkins_demo']['slack_buildserverurl'] = ''
14 | default['jenkins_demo']['slack_room'] = ''
15 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 |
9 | default['jenkins_demo']['jenkins_plugins'] = {
10 | 'thinBackup' => '1.9',
11 | # 'command-launcher' => '1.0',
12 | 'bouncycastle-api' => '2.16.2',
13 | 'credentials' => '2.1.16',
14 | 'plain-credentials' => '1.4',
15 | 'slack' => '2.3',
16 | 'script-security' => '1.35'
17 | }
18 |
19 | ########################################
20 | default['jenkins_demo']['default_username'] = ''
21 | default['jenkins_demo']['default_password'] = ''
22 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/files/default/serverspec_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | function setup_serverspec() {
3 | working_dir=${1?}
4 | cd "$working_dir"
5 | if [ ! -f spec/spec_helper.rb ]; then
6 | echo "Setup Serverspec Test case"
7 | cat > spec/spec_helper.rb < Rakefile < 'spec:all'
18 | task :default => :spec
19 |
20 | namespace :spec do
21 | targets = []
22 | Dir.glob('./spec/*').each do |dir|
23 | next unless File.directory?(dir)
24 | target = File.basename(dir)
25 | target = "_#{target}" if target == "default"
26 | targets << target
27 | end
28 |
29 | task :all => targets
30 | task :default => :all
31 |
32 | targets.each do |target|
33 | original_target = target == "_default" ? target[1..-1] : target
34 | desc "Run serverspec tests to #{original_target}"
35 | RSpec::Core::RakeTask.new(target.to_sym) do |t|
36 | ENV['TARGET_HOST'] = original_target
37 | t.pattern = "spec/#{original_target}/*_spec.rb"
38 | end
39 | end
40 | end
41 | EOF
42 | fi
43 | }
44 |
45 | #########################################################
46 | [ -n "$working_dir" ] || working_dir="$WORKSPACE"
47 |
48 | mkdir -p "$working_dir/spec/localhost"
49 | cd "$working_dir"
50 |
51 | setup_serverspec "$working_dir"
52 |
53 | cat > spec/localhost/sample_spec.rb <= 14.04'
14 | depends 'apt', '=2.6.1'
15 | depends 'java'
16 | depends 'jenkins', '=5.0.4'
17 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/recipes/conf_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: conf_job
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | jenkins_jobs = node['jenkins_demo']['jenkins_jobs']
13 |
14 | # Install Jenkins jobs
15 | jenkins_jobs.split(',').each do |job_name|
16 | config = File.join(Chef::Config[:file_cache_path], "#{job_name}.xml")
17 |
18 | template config do
19 | source "#{job_name}/config.xml"
20 | end
21 |
22 | # Create a jenkins job (default action is `:create`)
23 | jenkins_job job_name do
24 | config config
25 | end
26 | end
27 |
28 | # Install required facilities
29 | if jenkins_jobs.index('CommonServerCheckRepo')
30 | if platform_family?('debian')
31 |
32 | # https://www.brightbox.com/blog/2017/01/13/ruby-2-4-ubuntu-packages/
33 | apt_repository 'ruby-repo' do
34 | uri 'ppa:brightbox/ruby-ng'
35 | distribution node['lsb']['codename']
36 | key 'C3173AA6'
37 | keyserver 'keyserver.ubuntu.com'
38 | retries 3
39 | retry_delay 3
40 | not_if { ::File.exist?('/etc/apt/sources.list.d/ruby-repo.list') }
41 | end
42 |
43 | %w[ruby2.4 ruby2.4-dev netcat gem rake].each do |x|
44 | package x do
45 | action :install
46 | not_if "dpkg -l #{x} | grep -E '^ii'"
47 | end
48 | end
49 | else
50 | %w[nc gem rake].each do |x|
51 | package x do
52 | action :install
53 | # TODO: change this
54 | # not_if "dpkg -l #{x} | grep -E '^ii'"
55 | end
56 | end
57 | end
58 |
59 | # keep the gem installation minimal: --no-ri --no-rdoc
60 | # https://coderwall.com/p/spo6bq/default-no-ri-no-rdoc-on-ruby-gem-installation
61 | file '/root/.gemrc' do
62 | content 'gem: --no-ri --no-rdoc'
63 | mode 0o755
64 | owner 'root'
65 | group 'root'
66 | end
67 |
68 | gem_package 'serverspec' do
69 | action :install
70 | version '2.41.3'
71 | end
72 |
73 | cookbook_file '/var/lib/jenkins/script/serverspec_check.sh' do
74 | source 'serverspec_check.sh'
75 | mode 0o755
76 | user 'jenkins'
77 | group 'jenkins'
78 | end
79 | end
80 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | include_recipe 'jenkins-demo::master'
13 |
14 | if platform_family?('debian')
15 | # Install iproute2 for ss package
16 | %w[lsof iproute2].each do |x|
17 | package x do
18 | action :install
19 | not_if "dpkg -l #{x} | grep -E '^ii'"
20 | end
21 | end
22 | else
23 | %w[lsof].each do |x|
24 | package x do
25 | action :install
26 | # TODO: change this
27 | # not_if "dpkg -l #{x} | grep -E '^ii'"
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/recipes/master.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: master
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | apt_update 'update' if platform_family?('debian')
13 |
14 | node.default['java']['install_flavor'] = 'oracle'
15 | node.default['java']['jdk_version'] = '8'
16 | node.default['java']['set_etc_environment'] = true
17 | node.default['java']['oracle']['accept_oracle_download_terms'] = true
18 |
19 | if %w[debian ubuntu].include?(node['platform_family'])
20 | node.default['jenkins']['master']['repository'] = \
21 | 'http://pkg.jenkins-ci.org/debian'
22 | node.default['jenkins']['master']['repository_key'] = \
23 | 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key'
24 | end
25 |
26 | node.default['jenkins']['executor']['timeout'] = 360
27 |
28 | include_recipe 'java::default'
29 | include_recipe 'jenkins::master'
30 |
31 | # Install some plugins needed, but not installed on jenkins2 by default
32 | node['jenkins_demo']['jenkins_plugins'].each do |plugin|
33 | jenkins_plugin plugin[0] do
34 | version plugin[1]
35 | notifies :execute, 'jenkins_command[safe-restart]', :immediately
36 | end
37 | end
38 |
39 | jenkins_command 'safe-restart' do
40 | action :nothing
41 | end
42 |
43 | %w[/var/lib/jenkins/script].each do |x|
44 | directory x do
45 | owner 'jenkins'
46 | group 'jenkins'
47 | mode 0o755
48 | action :create
49 | end
50 | end
51 |
52 | # Create password credentials
53 | username = node['jenkins_demo']['default_username']
54 | password = node['jenkins_demo']['default_password']
55 | if username != ''
56 | # https://gist.github.com/hayderimran7/50cb1244cc1e856873a4
57 | jenkins_script "add_user #{username}" do
58 | command <<-EOH.gsub(/^ {4}/, '')
59 | import jenkins.model.*
60 | import hudson.security.*
61 |
62 | def instance = Jenkins.getInstance()
63 |
64 | def hudsonRealm = new HudsonPrivateSecurityRealm(false)
65 | hudsonRealm.createAccount("#{username}", "#{password}")
66 | instance.setSecurityRealm(hudsonRealm)
67 | instance.save()
68 | EOH
69 | not_if "test -d /var/lib/jenkins/users/#{username}"
70 | end
71 | end
72 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/templates/default/CommonServerCheckRepo/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 |
8 | -1
9 | 50
10 | -1
11 | -1
12 |
13 |
14 |
15 | false
16 |
17 |
18 |
19 |
20 | test_spec
21 |
22 | # ping check
23 | ["www.github.com"].each do |item|
24 | describe command("ping -c3 #{item}") do
25 | its(:exit_status) { should eq 0 }
26 | end
27 | end
28 |
29 | # Check anonymous http links
30 | ["http://www.dennyzhang.com/",
31 | "https://www.dennyzhang.com/",
32 | "https://code.dennyzhang.com/",
33 | "http://slack.dennyzhang.com/",
34 | ].each do |url|
35 | describe command('curl -I --connect-timeout 10 -k %s 2>&1' %[url]) do
36 | its(:stdout) { should match /HTTP\/1.1 200 OK/ }
37 | end
38 | end
39 |
40 | describe service('jenkins') do
41 | it { should be_running }
42 | end
43 |
44 | # Check at least 2 GB free disk
45 | describe command("[ $(df -h / | tail -n1 |awk -F' ' '{print $4}' | awk -F'G' '{print $1}' | awk -F'.' '{print $1}') -gt 2 ]") do
46 | its(:exit_status) { should eq 0 }
47 | end
48 |
49 | # TODO: enable this
50 | # # Check at least 2 GB free memory
51 | # describe command("[ $(free -ml | grep 'buffers/cache' | awk -F' ' '{print $4}') -gt 2048 ]") do
52 | # its(:exit_status) { should eq 0 }
53 | # end
54 |
55 | # TODO: enable this
56 | # # Check remote tcp port
57 | # ["vpn.dennyzhang.com:6188", # vpn
58 | # "www.dennyzhang.com:443", # ssl
59 | # ].each do |ip_port|
60 | # (ip, port) = ip_port.split(':')
61 | # describe command("nc -z -v -w5 #{ip} #{port} 2>&1") do
62 | # its(:stdout) { should match /open/ }
63 | # end
64 | # end
65 |
66 | # # check cpu loadavg in latest one min
67 | # ["172.17.0.1:2702:10"].each do |item|
68 | # (ip, port, cpu_load) = item.split(':')
69 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s cat /proc/loadavg | awk '{print int($1+0.99)}'` -lt %s ]" \
70 | # % [port, ip, cpu_load]
71 | # describe command(command_str) do
72 | # its(:exit_status) { should eq 0 }
73 | # end
74 | # end
75 |
76 | # # check docker container number
77 | # ["172.17.0.1:2702:15"].each do |item|
78 | # (ip, port, container_count) = item.split(':')
79 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s docker ps | sed 1d | wc -l` -lt %s ]" \
80 | # % [port, ip, container_count]
81 | # describe command(command_str) do
82 | # its(:exit_status) { should eq 0 }
83 | # end
84 | # end
85 |
86 |
87 |
88 |
89 |
90 |
91 | true
92 | false
93 | false
94 | false
95 |
96 |
97 | H H/5 * * *
98 |
99 |
100 | false
101 |
102 |
103 | #!/bin/bash -ex
104 | bash -e /var/lib/jenkins/script/serverspec_check.sh
105 |
106 |
107 |
108 |
109 |
110 | false
111 | false
112 | false
113 | TestParent
114 |
115 | 3
116 |
117 | 1
118 |
119 |
120 | <%= node['jenkins_demo']['slack_teamdomain'] %>
121 | <%= node['jenkins_demo']['slack_authtoken'] %>
122 | <%= node['jenkins_demo']['slack_buildserverurl'] %>
123 | <%= node['jenkins_demo']['slack_room'] %>
124 | false
125 | false
126 | false
127 | false
128 | false
129 | true
130 | true
131 | true
132 | false
133 | NONE
134 | false
135 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 |
8 | #############################################################################
9 | require 'json'
10 |
11 | describe command('java -version') do
12 | its(:stderr) { should contain '1.8' }
13 | end
14 |
15 | describe command('chef-solo --version') do
16 | its(:stdout) { should contain '13.6.4' }
17 | end
18 |
19 | if %w[redhat centos].include?(os[:family])
20 | describe command('yum info jenkins') do
21 | its(:stdout) { should contain '2.73.3' }
22 | end
23 | elsif %w[debian ubuntu].include?(os[:family])
24 | # debian related environment spec
25 | describe command('dpkg -l | grep jenkins') do
26 | its(:stdout) { should contain '2.90' }
27 | end
28 | end
29 |
30 | #############################################################################
31 | # If extra jenkins jobs have been triggered, verify the logic
32 | require_relative '../../../kitchen/data/verify_job_config'
33 |
34 | #############################################################################
35 | port = 8080
36 | # Wait for service slow start/restart
37 | describe port(port), wait: { timeout: 60 } do
38 | it { should be_listening }
39 | end
40 |
--------------------------------------------------------------------------------
/Scenario-301/cookbooks/jenkins-demo/test/shared/verify_job_config.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 |
8 | #############################################################################
9 | require 'json'
10 |
11 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
12 | jenkins_jobs = \
13 | chef_data.fetch('jenkins_demo').fetch('jenkins_jobs')
14 |
15 | if jenkins_jobs.index('CommonServerCheckRepo')
16 |
17 | describe file('/var/lib/jenkins/script/serverspec_check.sh') do
18 | it { should be_file }
19 | end
20 |
21 | describe command('which nc') do
22 | its(:exit_status) { should eq 0 }
23 | end
24 |
25 | describe command('gem list | grep serverspec') do
26 | its(:stdout) { should contain '2.41.3' }
27 | end
28 |
29 | if %w[redhat centos].include?(os[:family])
30 | describe command('gem --version') do
31 | its(:stdout) { should contain '2.0.14' }
32 | end
33 |
34 | describe command('rake --version') do
35 | its(:stdout) { should contain '0.9.6' }
36 | end
37 | elsif %w[debian ubuntu].include?(os[:family])
38 | # debian related environment spec
39 | describe command('gem --version') do
40 | its(:stdout) { should contain '2.6.13' }
41 | end
42 |
43 | describe command('rake --version') do
44 | its(:stdout) { should contain '10.0.4' }
45 | end
46 | end
47 |
48 | end
49 |
--------------------------------------------------------------------------------
/Scenario-302/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirement](#requirement)
11 | * [Procedure](#procedure)
12 | * [More Resources](#more-resources)
13 |
14 |
15 |
16 | # Requirement
17 |
18 | 1. For better security, only registered user can login
19 | 2. For better security, Jenkins listen on port 18080, instead of 8080
20 | 3. When Jenkins is down, get alerts
21 |
22 | Quiz:
23 | - Once I have enabled Jenkins security, how my chef update will work?
24 |
25 | # Procedure
26 | ## Common Setup
27 | - Install bundle
28 | ```
29 | apt-get install ruby-dev
30 |
31 | ruby --version
32 | # https://github.com/bundler/bundler/issues/4065
33 | sudo gem install bundler -n /usr/local/bin
34 |
35 | bundle --version
36 | ```
37 |
38 | - Install gem depenencies
39 | ```
40 | cd cookbooks/jenkins-demo
41 | bundle install
42 | ```
43 |
44 | ## kitchen docker deployment
45 | - Run kitchen test
46 | ```
47 | # https://github.com/test-kitchen/kitchen-docker
48 | kitchen converge
49 | kitchen list
50 | kitchen verify
51 | kitchen destroy
52 | ```
53 |
54 | ## kitchen digitalocean deployment
55 | ```
56 | # https://github.com/test-kitchen/kitchen-digitalocean
57 | cd cookbooks/jenkins-demo
58 | export KITCHEN_YAML=".kitchen_digitalocean.yml"
59 |
60 | # Customize this with your credential
61 | export DIGITALOCEAN_ACCESS_TOKEN="1234"
62 | export DIGITALOCEAN_SSH_KEY_IDS="1234, 5678"
63 |
64 | kitchen converge
65 | kitchen list
66 | kitchen verify
67 | kitchen destroy
68 |
69 | - TODO: how does the ssh key work? With which OS user, and where the key is?
70 | ```
71 |
72 | ## kitchen ec2 deployment
73 | - Install AWS cli and configure aws credential
74 | ```
75 | # http://docs.aws.amazon.com/cli/latest/userguide/installing.html
76 | pip install awscli
77 | aws configure
78 |
79 | # Customize this
80 | export KEY_USER="denny-kitchen-test"
81 | aws ec2 create-key-pair --key-name $KEY_USER | ruby -e "require 'json'; puts JSON.parse(STDIN.read)['KeyMaterial']" > ~/.ssh/$KEY_USER
82 |
83 | chmod 600 ~/.ssh/$KEY_USER
84 |
85 | export AWS_SSH_KEY_ID="$KEY_USER"
86 |
87 | ```
88 |
89 | - Install and run kitchen-ec2
90 | ```
91 | # https://github.com/test-kitchen/kitchen-ec2
92 | # https://github.com/test-kitchen/kitchen-ec2/blob/master/lib/kitchen/driver/ec2.rb
93 | # http://kg4giy.com/2015/12/11/test-kitchen-to-support-amazon-web-service-aws-amis/
94 |
95 | cd cookbooks/jenkins-demo
96 | export KITCHEN_YAML=".kitchen_ec2.yml"
97 | # TODO: customize this
98 | export AWS_SSH_KEY_ID="$KEY_USER"
99 |
100 | # Update bundle: https://github.com/chef/chef-provisioning/issues/151
101 | bundle update
102 |
103 | kitchen converge
104 | kitchen list
105 | kitchen verify
106 | kitchen destroy
107 | ```
108 |
109 | ## kitchen vagrant deployment
110 | ```
111 | # https://github.com/test-kitchen/kitchen-vagrant
112 | cd cookbooks/jenkins-demo
113 | export KITCHEN_YAML=".kitchen_vagrant.yml"
114 |
115 | bundle install
116 |
117 | kitchen converge
118 | kitchen list
119 | kitchen verify
120 | kitchen destroy
121 | ```
122 |
123 | # More Resources
124 | - TODO: security improvement for the built-in chef user: attributes/default.rb
125 |
126 | - Critical Info
127 | ```
128 | CentOS Jenkins conf: /etc/sysconfig/jenkins
129 | ```
130 |
131 |
132 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | use_sudo: false
7 | # because Docker and SystemD/Upstart
8 | privileged: true
9 | remove_images: false
10 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
11 | # tls_verify: true
12 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
13 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
14 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
15 | # socket: tcp://172.17.0.1:4243
16 | transport:
17 | username: kitchen
18 |
19 | provisioner:
20 | name: chef_zero
21 | require_chef_omnibus: 13.6.4
22 | data_path: test/shared
23 | client_rb:
24 | file_cache_path: "/var/chef/cache"
25 |
26 | platforms:
27 | - name: centos-7
28 | driver_config:
29 | # https://hub.docker.com/r/dokken/centos-7/
30 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
31 | image: <%= ENV.fetch('IMAGE_NAME', "dokken/centos-7") %>
32 | pid_one_command: /usr/lib/systemd/systemd
33 | forward:
34 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>83:8081
35 | - name: ubuntu-14.04
36 | driver_config:
37 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
38 | image: <%= ENV.fetch('IMAGE_NAME', "ubuntu:14.04") %>
39 | forward:
40 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "280") %>83:8081
41 |
42 | suites:
43 | - name: default
44 | run_list:
45 | - recipe[apt::default]
46 | - recipe[jenkins-demo::default]
47 | - recipe[jenkins-demo::conf_job]
48 | attributes:
49 | {jenkins_demo:
50 | {jenkins_port: '8081',
51 | jenkins_jobs: 'CommonServerCheckRepo',
52 | slack_teamdomain: 'mywechat',
53 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
54 | # TODO different env use different port
55 | # TODO use server ip
56 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
57 | slack_room: '#denny-alerts',
58 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
59 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/.kitchen_digitalocean.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: digitalocean
4 |
5 | provisioner:
6 | name: chef_zero
7 | require_chef_omnibus: 13.6.4
8 | data_path: test/shared
9 |
10 | platforms:
11 | - name: jenkins-demo-centos7
12 | driver_config:
13 | region: sfo2
14 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
15 | private_networking: false
16 | # https://github.com/test-kitchen/kitchen-digitalocean
17 | image: centos-7-x64
18 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
19 | - name: jenkins-demo-ubuntu1404
20 | driver_config:
21 | region: sfo2
22 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
23 | private_networking: false
24 | image: ubuntu-14-04-x64
25 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
26 |
27 | suites:
28 | - name: default
29 | run_list:
30 | - recipe[apt::default]
31 | - recipe[jenkins-demo::default]
32 | - recipe[jenkins-demo::conf_job]
33 | attributes:
34 | {jenkins_demo:
35 | {jenkins_port: '8081',
36 | jenkins_jobs: 'CommonServerCheckRepo',
37 | slack_teamdomain: 'mywechat',
38 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
39 | # TODO different env use different port
40 | # TODO use server ip
41 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
42 | slack_room: '#denny-alerts',
43 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
44 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/.kitchen_ec2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: ec2
4 | region: us-east-1
5 |
6 | transport:
7 | ssh_key: ~/.ssh/<%= ENV.fetch('KEY_USER', "") %>
8 | username: ec2-user
9 |
10 | provisioner:
11 | name: chef_zero
12 | require_chef_omnibus: 13.6.4
13 | data_path: test/shared
14 |
15 | platforms:
16 | - name: ubuntu-1404
17 | driver:
18 | # https://cloud-images.ubuntu.com/releases/14.04/release-20150506/
19 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-8d9e1cf7") %>
20 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
21 | transport:
22 | username: ubuntu
23 | - name: centos-7
24 | driver:
25 | # https://wiki.centos.org/Cloud/AWS
26 | # https://stackoverflow.com/questions/40835953/how-to-find-ami-id-of-centos-7-image-in-aws-marketplace
27 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-ae7bfdb8") %>
28 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
29 | transport:
30 | username: centos
31 | - name: centos-ami
32 | driver:
33 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-6869aa05") %>
34 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
35 |
36 | suites:
37 | - name: default
38 | run_list:
39 | - recipe[apt::default]
40 | - recipe[jenkins-demo::default]
41 | - recipe[jenkins-demo::conf_job]
42 | attributes:
43 | {jenkins_demo:
44 | {jenkins_port: '8081',
45 | jenkins_jobs: 'CommonServerCheckRepo',
46 | slack_teamdomain: 'mywechat',
47 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
48 | # TODO different env use different port
49 | # TODO use server ip
50 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
51 | slack_room: '#denny-alerts',
52 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
53 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/.kitchen_vagrant.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: vagrant
4 |
5 | driver_config:
6 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
7 | # https://github.com/test-kitchen/kitchen-vagrant
8 | memory: 1024
9 | transport:
10 | username: kitchen
11 |
12 | provisioner:
13 | name: chef_zero
14 | require_chef_omnibus: 13.6.4
15 | data_path: test/shared
16 | client_rb:
17 | file_cache_path: "/var/chef/cache"
18 |
19 | platforms:
20 | - name: centos-7
21 | driver_config:
22 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
23 | network:
24 | - ["forwarded_port", {guest: 8080, host: 18080}]
25 | - name: ubuntu-14.04
26 | # https://stackoverflow.com/questions/38677059/port-forwarding-not-working-with-test-kitchen-and-vagrant
27 | driver_config:
28 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
29 | network:
30 | - ["forwarded_port", {guest: 8080, host: 28080}]
31 |
32 | suites:
33 | - name: default
34 | run_list:
35 | - recipe[apt::default]
36 | - recipe[jenkins-demo::default]
37 | - recipe[jenkins-demo::conf_job]
38 | attributes:
39 | {jenkins_demo:
40 | {jenkins_port: '8081',
41 | jenkins_jobs: 'CommonServerCheckRepo',
42 | slack_teamdomain: 'mywechat',
43 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
44 | # TODO different env use different port
45 | # TODO use server ip
46 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
47 | slack_room: '#denny-alerts',
48 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
49 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - Berksfile
4 |
5 | Style/Next:
6 | Enabled: false
7 |
8 | Metrics/LineLength:
9 | Max: 90
10 |
11 | MethodLength:
12 | Max: 20
13 |
14 | Metrics/AbcSize:
15 | Enabled: false
16 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-digitalocean', '= 0.9.8'
5 | gem 'kitchen-docker', '= 2.6.0'
6 | gem 'kitchen-ec2', '= 1.3.2'
7 | gem 'kitchen-vagrant', '= 1.2.1'
8 |
9 | gem 'test-kitchen', '= 1.19.1'
10 |
11 | gem 'berkshelf', '= 6.3.1'
12 |
13 | gem 'foodcritic', '~> 4.0.0'
14 | gem 'rubocop', '~> 0.48.1'
15 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/README.md:
--------------------------------------------------------------------------------
1 | jenkins-demo Cookbook
2 | ================
3 | Setup and configure demo jenkins
4 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/attributes/conf_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 |
9 | default['jenkins_demo']['jenkins_jobs'] = ''
10 | # slack notification
11 | default['jenkins_demo']['slack_teamdomain'] = ''
12 | default['jenkins_demo']['slack_authtoken'] = ''
13 | default['jenkins_demo']['slack_buildserverurl'] = ''
14 | default['jenkins_demo']['slack_room'] = ''
15 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 | default['jenkins_demo']['jenkins_port'] = 8080
9 |
10 | default['jenkins_demo']['jenkins_plugins'] = {
11 | 'thinBackup' => '1.9',
12 | # TODO
13 | # 'command-launcher' => '1.0',
14 | 'bouncycastle-api' => '2.16.2',
15 | 'credentials' => '2.1.16',
16 | 'plain-credentials' => '1.4',
17 | 'slack' => '2.3',
18 | 'script-security' => '1.35',
19 | 'matrix-auth' => '2.2'
20 | }
21 |
22 | ########################################
23 | default['jenkins_demo']['default_username'] = ''
24 | default['jenkins_demo']['default_password'] = ''
25 |
26 | # TODO: improve the security
27 | default['jenkins_demo']['chef_private_key'] = \
28 | '-----BEGIN RSA PRIVATE KEY-----
29 | MIIEpgIBAAKCAQEA6fIwUKxZXgKqEE6HCM94eEEeQ+n9mGpKn+CiKExI97mQtio4
30 | uzB/4A7qVXfBYaa2jbPZzD6bDvGco88vgeDuRB5tNh/sRBD3T7L9CxNIGp9gMMsu
31 | tRprwI5MEUsDDFXMKo5ZinpRe9fud5UBOmEHK0vjRVSgLVCGYdv/iXaBKY3feH8a
32 | 4gUuTzkdbUtoUMAUTfNyevhUfLRKSWjr5+f7krYYTqJpM7KUAL9e2dYMjkj3He7g
33 | iM4uiPtAQnMYcsyevNgpM0uKnp6+pPzTMSkSNp3uIK6aQ4lR80lEfq8fRwqzsIuJ
34 | dRT/+iJpd6XF8+GSyOt/tEh1RPiEKiGHLpmZGQIDAQABAoIBAQDFsipuIhcrQKki
35 | OpoWMe0mAjFnRtdM85W4YYXm9AA9h4zow+lJFoUZfME+FINQ2CcwvClzVfyGtlqe
36 | ezk0UjZHTkcQFA3+vy+fJCx+LX8jMEeDNFB2Lqub/yP9ARzEUcTEuaKlSRSOyTz1
37 | xO9SvCfoyKp4Ljll0cSd8eGR8pjX2TSfJ85aFAcP1CHGa/qGdxhSrbL2PMXaNFIT
38 | 27ZEUo4FVqcwRFN6JuO4sAlnyg8axXlXNLpwPzW1Zi7auS9nAO9bDEIhP4YfFwWs
39 | /iV7KBs/bryez94XS68b3MUXoZWS+1nP8ivBSOCH0mWy5/PhR4esih2EhXk/hi3P
40 | dp6aX4p5AoGBAPrmS+4lrvnvk2EOj3vqSergd31XBTM6NRKSsIYCtlaXsVjMym/i
41 | UdqcLqha4IEW3mucmpD3MBsTqshHGTI+67+tU/G23kThV/3U3a+jSR10FjgACPRd
42 | 8VhxrhTBvKjcw0uKeMl9uE0eb/2q8uVtX/8InOCvEfNGFCcszLsYFBr3AoGBAO6z
43 | qhWt8y/HkqWgBcbDJKx+T050nM9fkkBk1ILZn/GMEU828aEvKSwa8wzcx1gPo8Uu
44 | TP2SS0K0vnQv75UfyafgxFMVlELQrRTLHJqFQrCGikgBLNwHjRdvHfNujoBXbv+9
45 | g4LVFqHv0/kVRc1kXhdEwBCZm29rCDVusKK0C1hvAoGBAOAY4qkLL4Y93j1KbA4Z
46 | 7XvEkfV5zEM9Mjosm06XDZW6V8Ug5Y+ZbdL8vQ/SW8PxUSh87/GbV3RX1KqeFnsy
47 | iA7kGZ5D37NWMumdP4SpK50LGu1Z2qWpYu/EWeBgSsnopObL/6a4i+0VyqGgFuOl
48 | FaENaFGnDTlk1otHEHXrw8lxAoGBAITL11fwSlbOhLs3537ImeKM8roHDiYgWVER
49 | x1h0khLjhc24F31Aq3sqEwWY3h4TtVzBgXugo9Ycj8g70uH3qUyIMzC11KHHTkM/
50 | LE6azJtAfjXI0Zgna0saOmNvoj+sZMhKOpvSyKCWuCrettKpf98aFHAnxN2bghmX
51 | 1xTtbVJpAoGBAKnqvADsNFaI1Ak7tdfJJ+chxnxXd1k6Mly44Jsp6oako4Nl2Uiw
52 | 3xL4JGed+QBmjFh+n4hR9T7J65fUFvBixBEAhDSXcRHWL84xTQWLtdHK4+zDWGJt
53 | n2DMrFzhp1H6neUFMBeNOw+fQuhPj6OcLrs4dRdyQhVRp0ZOJyLMS39e
54 | -----END RSA PRIVATE KEY-----'
55 |
56 | default['jenkins_demo']['chef_public_key'] = \
57 | 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDp8jBQrFleAqoQTocIz3h4QR5'\
58 | 'D6f2Yakqf4KIoTEj3uZC2Kji7MH/gDupVd8FhpraNs9nMPpsO8Zyjzy+B4O5EHm'\
59 | '02H+xEEPdPsv0LE0gan2Awyy61GmvAjkwRSwMMVcwqjlmKelF71+53lQE6YQcrS'\
60 | '+NFVKAtUIZh2/+JdoEpjd94fxriBS5POR1tS2hQwBRN83J6+FR8tEpJaOvn5/uS'\
61 | 'thhOomkzspQAv17Z1gyOSPcd7uCIzi6I+0BCcxhyzJ682CkzS4qenr6k/NMxKRI'\
62 | '2ne4grppDiVHzSUR+rx9HCrOwi4l1FP/6Iml3pcXz4ZLI63+0SHVE+IQqIYcumZ'\
63 | 'kZ chef@mytest.com'
64 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/files/default/serverspec_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | function setup_serverspec() {
3 | working_dir=${1?}
4 | cd "$working_dir"
5 | if [ ! -f spec/spec_helper.rb ]; then
6 | echo "Setup Serverspec Test case"
7 | cat > spec/spec_helper.rb < Rakefile < 'spec:all'
18 | task :default => :spec
19 |
20 | namespace :spec do
21 | targets = []
22 | Dir.glob('./spec/*').each do |dir|
23 | next unless File.directory?(dir)
24 | target = File.basename(dir)
25 | target = "_#{target}" if target == "default"
26 | targets << target
27 | end
28 |
29 | task :all => targets
30 | task :default => :all
31 |
32 | targets.each do |target|
33 | original_target = target == "_default" ? target[1..-1] : target
34 | desc "Run serverspec tests to #{original_target}"
35 | RSpec::Core::RakeTask.new(target.to_sym) do |t|
36 | ENV['TARGET_HOST'] = original_target
37 | t.pattern = "spec/#{original_target}/*_spec.rb"
38 | end
39 | end
40 | end
41 | EOF
42 | fi
43 | }
44 |
45 | #########################################################
46 | [ -n "$working_dir" ] || working_dir="$WORKSPACE"
47 |
48 | mkdir -p "$working_dir/spec/localhost"
49 | cd "$working_dir"
50 |
51 | setup_serverspec "$working_dir"
52 |
53 | cat > spec/localhost/sample_spec.rb <= 14.04'
14 | depends 'apt', '=2.6.1'
15 | depends 'java'
16 | depends 'jenkins', '=5.0.4'
17 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/recipes/backup.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: backup
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/recipes/conf_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: conf_job
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | jenkins_jobs = node['jenkins_demo']['jenkins_jobs']
13 |
14 | # Install Jenkins jobs
15 | jenkins_jobs.split(',').each do |job_name|
16 | config = File.join(Chef::Config[:file_cache_path], "#{job_name}.xml")
17 |
18 | template config do
19 | source "#{job_name}/config.xml"
20 | end
21 |
22 | # Create a jenkins job (default action is `:create`)
23 | jenkins_job job_name do
24 | config config
25 | end
26 | end
27 |
28 | # Install required facilities
29 | if jenkins_jobs.index('CommonServerCheckRepo')
30 | # keep the gem installation minimal: --no-ri --no-rdoc
31 | # https://coderwall.com/p/spo6bq/default-no-ri-no-rdoc-on-ruby-gem-installation
32 | file '/root/.gemrc' do
33 | content 'gem: --no-ri --no-rdoc'
34 | mode 0o755
35 | owner 'root'
36 | group 'root'
37 | end
38 |
39 | if platform_family?('debian')
40 |
41 | # https://www.brightbox.com/blog/2017/01/13/ruby-2-4-ubuntu-packages/
42 | apt_repository 'ruby-repo' do
43 | uri 'ppa:brightbox/ruby-ng'
44 | distribution node['lsb']['codename']
45 | key 'C3173AA6'
46 | keyserver 'keyserver.ubuntu.com'
47 | retries 3
48 | retry_delay 3
49 | not_if { ::File.exist?('/etc/apt/sources.list.d/ruby-repo.list') }
50 | end
51 |
52 | %w[ruby2.4 ruby2.4-dev netcat gem rake].each do |x|
53 | package x do
54 | action :install
55 | not_if "dpkg -l #{x} | grep -E '^ii'"
56 | end
57 | end
58 | else
59 | %w[nc gem yum zlib-devel gcc gcc-c++ ruby-devel rubygems].each do |x|
60 | package x do
61 | action :install
62 | # TODO: change this
63 | # not_if "dpkg -l #{x} | grep -E '^ii'"
64 | end
65 | end
66 |
67 | gem_package 'rake' do
68 | action :install
69 | version '12.3.0'
70 | end
71 |
72 | # gem_package 'io-console' do
73 | # action :install
74 | # version '0.4.6'
75 | # end
76 | execute 'Install io-console' do
77 | command 'gem install io-console'
78 | action :run
79 | not_if 'gem list | grep io-console'
80 | end
81 | end
82 |
83 | gem_package 'serverspec' do
84 | action :install
85 | version '2.41.3'
86 | end
87 |
88 | cookbook_file '/var/lib/jenkins/script/serverspec_check.sh' do
89 | source 'serverspec_check.sh'
90 | mode 0o755
91 | user 'jenkins'
92 | group 'jenkins'
93 | end
94 | end
95 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | include_recipe 'jenkins-demo::master'
13 |
14 | if platform_family?('debian')
15 | # Install iproute2 for ss package
16 | %w[lsof iproute2].each do |x|
17 | package x do
18 | action :install
19 | not_if "dpkg -l #{x} | grep -E '^ii'"
20 | end
21 | end
22 | else
23 | %w[lsof].each do |x|
24 | package x do
25 | action :install
26 | # TODO: change this
27 | # not_if "dpkg -l #{x} | grep -E '^ii'"
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/recipes/master.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: master
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | apt_update 'update' if platform_family?('debian')
13 |
14 | node.default['java']['install_flavor'] = 'oracle'
15 | node.default['java']['jdk_version'] = '8'
16 | node.default['java']['set_etc_environment'] = true
17 | node.default['java']['oracle']['accept_oracle_download_terms'] = true
18 |
19 | if %w[debian ubuntu].include?(node['platform_family'])
20 | node.default['jenkins']['master']['repository'] = \
21 | 'http://pkg.jenkins-ci.org/debian'
22 | node.default['jenkins']['master']['repository_key'] = \
23 | 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key'
24 | end
25 |
26 | node.default['jenkins']['executor']['timeout'] = 360
27 |
28 | node.default['jenkins']['master']['port'] = node['jenkins_demo']['jenkins_port']
29 | node.default['jenkins']['master']['endpoint'] = \
30 | "http://#{node['jenkins']['master']['host']}:#{node['jenkins']['master']['port']}"
31 |
32 | include_recipe 'java::default'
33 | include_recipe 'jenkins::master'
34 |
35 | # Install some plugins needed, but not installed on jenkins2 by default
36 | node['jenkins_demo']['jenkins_plugins'].each do |plugin|
37 | jenkins_plugin plugin[0] do
38 | version plugin[1]
39 | notifies :execute, 'jenkins_command[safe-restart]', :immediately
40 | end
41 | end
42 |
43 | jenkins_command 'safe-restart' do
44 | action :nothing
45 | end
46 |
47 | %w[/var/lib/jenkins/script].each do |x|
48 | directory x do
49 | owner 'jenkins'
50 | group 'jenkins'
51 | mode 0o755
52 | action :create
53 | end
54 | end
55 |
56 | include_recipe 'jenkins-demo::security'
57 | include_recipe 'jenkins-demo::backup'
58 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/recipes/security.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: security
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | require 'openssl'
13 | require 'net/ssh'
14 | # key = OpenSSL::PKey::RSA.new(jenkins['private_key'])
15 | # private_key = key.to_pem
16 | # public_key = "#{key.ssh_type} #{[key.to_blob].pack('m0')}"
17 |
18 | # https://goo.gl/jvn5TN
19 | # Jenkins itself login the server
20 |
21 | private_key = node['jenkins_demo']['chef_private_key']
22 | public_key = node['jenkins_demo']['chef_public_key']
23 |
24 | # Set the private key on the executor
25 | node.run_state[:jenkins_private_key] = private_key
26 |
27 | # Create a default Chef user with the public key
28 | jenkins_user 'chef' do
29 | full_name 'Chef Client'
30 | public_keys [public_key]
31 | end
32 |
33 | # Turn on basic authentication
34 | jenkins_script 'setup authentication' do
35 | command <<-EOH.gsub(/^ {4}/, '')
36 | import jenkins.model.*
37 | def instance = Jenkins.getInstance()
38 |
39 | import hudson.security.*
40 | def realm = new HudsonPrivateSecurityRealm(false)
41 | instance.setSecurityRealm(realm)
42 |
43 | def strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
44 | instance.setAuthorizationStrategy(strategy)
45 |
46 | instance.save()
47 | EOH
48 | # TODO: add not_if
49 | end
50 |
51 | ################################################################################
52 | username = node['jenkins_demo']['default_username']
53 | password = node['jenkins_demo']['default_password']
54 | if username != ''
55 | # Create a dummy user
56 | # https://gist.github.com/hayderimran7/50cb1244cc1e856873a4
57 | jenkins_script "add_user #{username}" do
58 | command <<-EOH.gsub(/^ {4}/, '')
59 | import jenkins.model.*
60 | import hudson.security.*
61 |
62 | def instance = Jenkins.getInstance()
63 |
64 | def hudsonRealm = new HudsonPrivateSecurityRealm(false)
65 | hudsonRealm.createAccount("#{username}", "#{password}")
66 | instance.setSecurityRealm(hudsonRealm)
67 | instance.save()
68 | EOH
69 | not_if "test -d /var/lib/jenkins/users/#{username}"
70 | end
71 | end
72 |
73 | # Use matrix authorization model
74 | # Gives all authenticated users admin access
75 | # https://github.com/glenjamin/jenkins-groovy-examples/blob/master/README.md
76 | jenkins_script 'all authenticated users admin access' do
77 | command <<-EOH.gsub(/^ {4}/, '')
78 | import jenkins.model.*
79 | def instance = Jenkins.getInstance()
80 |
81 | import hudson.security.*
82 | def realm = new HudsonPrivateSecurityRealm(false)
83 | instance.setSecurityRealm(realm)
84 |
85 | def strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
86 | strategy.add(Jenkins.ADMINISTER, 'authenticated')
87 | instance.setAuthorizationStrategy(strategy)
88 |
89 | instance.save()
90 | EOH
91 | # TODO: add not_if
92 | end
93 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/templates/default/CommonServerCheckRepo/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 |
8 | -1
9 | 50
10 | -1
11 | -1
12 |
13 |
14 |
15 | false
16 |
17 |
18 |
19 |
20 | test_spec
21 |
22 | # ping check
23 | ["www.github.com"].each do |item|
24 | describe command("ping -c3 #{item}") do
25 | its(:exit_status) { should eq 0 }
26 | end
27 | end
28 |
29 | # Check anonymous http links
30 | ["http://www.dennyzhang.com/",
31 | "https://www.dennyzhang.com/",
32 | "https://code.dennyzhang.com/",
33 | "http://slack.dennyzhang.com/",
34 | ].each do |url|
35 | describe command('curl -I --connect-timeout 10 -k %s 2>&1' %[url]) do
36 | its(:stdout) { should match /HTTP\/1.1 200 OK/ }
37 | end
38 | end
39 |
40 | describe service('jenkins') do
41 | it { should be_running }
42 | end
43 |
44 | # Check at least 2 GB free disk
45 | describe command("[ $(df -h / | tail -n1 |awk -F' ' '{print $4}' | awk -F'G' '{print $1}' | awk -F'.' '{print $1}') -gt 2 ]") do
46 | its(:exit_status) { should eq 0 }
47 | end
48 |
49 | # TODO: enable this
50 | # # Check at least 2 GB free memory
51 | # describe command("[ $(free -ml | grep 'buffers/cache' | awk -F' ' '{print $4}') -gt 2048 ]") do
52 | # its(:exit_status) { should eq 0 }
53 | # end
54 |
55 | # TODO: support for both CentOS and Ubuntu OS
56 | # # Check remote tcp port
57 | # ["vpn.dennyzhang.com:6188", # vpn
58 | # "www.dennyzhang.com:443", # ssl
59 | # ].each do |ip_port|
60 | # (ip, port) = ip_port.split(':')
61 | # describe command("nc -z -v -w5 #{ip} #{port} 2>&1") do
62 | # its(:stdout) { should match /open/ }
63 | # end
64 | # end
65 |
66 | # # check cpu loadavg in latest one min
67 | # ["172.17.0.1:2702:10"].each do |item|
68 | # (ip, port, cpu_load) = item.split(':')
69 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s cat /proc/loadavg | awk '{print int($1+0.99)}'` -lt %s ]" \
70 | # % [port, ip, cpu_load]
71 | # describe command(command_str) do
72 | # its(:exit_status) { should eq 0 }
73 | # end
74 | # end
75 |
76 | # # check docker container number
77 | # ["172.17.0.1:2702:15"].each do |item|
78 | # (ip, port, container_count) = item.split(':')
79 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s docker ps | sed 1d | wc -l` -lt %s ]" \
80 | # % [port, ip, container_count]
81 | # describe command(command_str) do
82 | # its(:exit_status) { should eq 0 }
83 | # end
84 | # end
85 |
86 |
87 |
88 |
89 |
90 |
91 | true
92 | false
93 | false
94 | false
95 |
96 |
97 | H H/5 * * *
98 |
99 |
100 | false
101 |
102 |
103 | #!/bin/bash -ex
104 | export PATH=$PATH:/usr/local/bin/
105 | bash -e /var/lib/jenkins/script/serverspec_check.sh
106 |
107 |
108 |
109 |
110 |
111 | false
112 | false
113 | false
114 | TestParent
115 |
116 | 3
117 |
118 | 1
119 |
120 |
121 | <%= node['jenkins_demo']['slack_teamdomain'] %>
122 | <%= node['jenkins_demo']['slack_authtoken'] %>
123 | <%= node['jenkins_demo']['slack_buildserverurl'] %>
124 | <%= node['jenkins_demo']['slack_room'] %>
125 | false
126 | false
127 | false
128 | false
129 | false
130 | true
131 | true
132 | true
133 | false
134 | NONE
135 | false
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 |
8 | #############################################################################
9 | require 'json'
10 |
11 | describe command('java -version') do
12 | its(:stderr) { should contain '1.8' }
13 | end
14 |
15 | describe command('chef-solo --version') do
16 | its(:stdout) { should contain '13.6.4' }
17 | end
18 |
19 | if %w[redhat centos].include?(os[:family])
20 | describe command('yum info jenkins') do
21 | its(:stdout) { should contain '2.73.3' }
22 | end
23 | elsif %w[debian ubuntu].include?(os[:family])
24 | # debian related environment spec
25 | describe command('dpkg -l | grep jenkins') do
26 | its(:stdout) { should contain '2.91' }
27 | end
28 | end
29 |
30 | #############################################################################
31 | # If extra jenkins jobs have been triggered, verify the logic
32 | require_relative '../../../kitchen/data/verify_job_config'
33 |
34 | #############################################################################
35 | require 'json'
36 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
37 |
38 | jenkins_port = chef_data.fetch('jenkins_demo').fetch('jenkins_port')
39 | # Wait for service slow start/restart
40 | describe port(jenkins_port), wait: { timeout: 60 } do
41 | it { should be_listening }
42 | end
43 |
44 | #############################################################################
45 | username = chef_data.fetch('jenkins_demo').fetch('default_username')
46 |
47 | if username != ''
48 | describe file("/var/lib/jenkins/users/#{username}") do
49 | it { should be_directory }
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/Scenario-302/cookbooks/jenkins-demo/test/shared/verify_job_config.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 | # https://github.com/test-kitchen/test-kitchen/issues/469
8 | set :path, '/sbin:/usr/local/sbin:/usr/local/bin:$PATH'
9 |
10 | #############################################################################
11 | require 'json'
12 |
13 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
14 | jenkins_jobs = \
15 | chef_data.fetch('jenkins_demo').fetch('jenkins_jobs')
16 |
17 | if jenkins_jobs.index('CommonServerCheckRepo')
18 |
19 | describe file('/var/lib/jenkins/script/serverspec_check.sh') do
20 | it { should be_file }
21 | end
22 |
23 | describe command('which nc') do
24 | its(:exit_status) { should eq 0 }
25 | end
26 |
27 | describe command('gem list | grep serverspec') do
28 | its(:stdout) { should contain '2.41.3' }
29 | end
30 |
31 | if %w[redhat centos].include?(os[:family])
32 | describe command('gem --version') do
33 | its(:stdout) { should contain '2.0.14' }
34 | end
35 |
36 | describe command('rake --version') do
37 | its(:stdout) { should contain '12.3.0' }
38 | end
39 | elsif %w[debian ubuntu].include?(os[:family])
40 | # debian related environment spec
41 | describe command('gem --version') do
42 | its(:stdout) { should contain '2.6.13' }
43 | end
44 |
45 | describe command('rake --version') do
46 | its(:stdout) { should contain '10.0.4' }
47 | end
48 | end
49 |
50 | end
51 |
--------------------------------------------------------------------------------
/Scenario-303/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirement](#requirement)
11 | * [Procedure](#procedure)
12 | * [More Resources](#more-resources)
13 |
14 |
15 |
16 | # Requirement
17 |
18 | 1. Use Jenkinsfile to create a Jenkins pipeline
19 | 2. Enable and configure ThinBackup
20 |
21 | Quiz:
22 | - Once I have enabled Jenkins security, how my chef update will work?
23 |
24 | # Procedure
25 | ## Common Setup
26 | - Install bundle
27 | ```
28 | apt-get install ruby-dev
29 |
30 | ruby --version
31 | # https://github.com/bundler/bundler/issues/4065
32 | sudo gem install bundler -n /usr/local/bin
33 |
34 | bundle --version
35 | ```
36 |
37 | - Install gem depenencies
38 | ```
39 | cd cookbooks/jenkins-demo
40 | bundle install
41 | ```
42 |
43 | ## kitchen docker deployment
44 | - Run kitchen test
45 | ```
46 | # https://github.com/test-kitchen/kitchen-docker
47 | kitchen converge
48 | kitchen list
49 | kitchen verify
50 | kitchen destroy
51 | ```
52 |
53 | ## kitchen digitalocean deployment
54 | ```
55 | # https://github.com/test-kitchen/kitchen-digitalocean
56 | cd cookbooks/jenkins-demo
57 | export KITCHEN_YAML=".kitchen_digitalocean.yml"
58 |
59 | # Customize this with your credential
60 | export DIGITALOCEAN_ACCESS_TOKEN="1234"
61 | export DIGITALOCEAN_SSH_KEY_IDS="1234, 5678"
62 |
63 | kitchen converge
64 | kitchen list
65 | kitchen verify
66 | kitchen destroy
67 |
68 | - TODO: how does the ssh key work? With which OS user, and where the key is?
69 | ```
70 |
71 | ## kitchen ec2 deployment
72 | - Install AWS cli and configure aws credential
73 | ```
74 | # http://docs.aws.amazon.com/cli/latest/userguide/installing.html
75 | pip install awscli
76 | aws configure
77 |
78 | # Customize this
79 | export KEY_USER="denny-kitchen-test"
80 | aws ec2 create-key-pair --key-name $KEY_USER | ruby -e "require 'json'; puts JSON.parse(STDIN.read)['KeyMaterial']" > ~/.ssh/$KEY_USER
81 |
82 | chmod 600 ~/.ssh/$KEY_USER
83 |
84 | export AWS_SSH_KEY_ID="$KEY_USER"
85 |
86 | ```
87 |
88 | - Install and run kitchen-ec2
89 | ```
90 | # https://github.com/test-kitchen/kitchen-ec2
91 | # https://github.com/test-kitchen/kitchen-ec2/blob/master/lib/kitchen/driver/ec2.rb
92 | # http://kg4giy.com/2015/12/11/test-kitchen-to-support-amazon-web-service-aws-amis/
93 |
94 | cd cookbooks/jenkins-demo
95 | export KITCHEN_YAML=".kitchen_ec2.yml"
96 | # TODO: customize this
97 | export AWS_SSH_KEY_ID="$KEY_USER"
98 |
99 | # Update bundle: https://github.com/chef/chef-provisioning/issues/151
100 | bundle update
101 |
102 | kitchen converge
103 | kitchen list
104 | kitchen verify
105 | kitchen destroy
106 | ```
107 |
108 | ## kitchen vagrant deployment
109 | ```
110 | # https://github.com/test-kitchen/kitchen-vagrant
111 | cd cookbooks/jenkins-demo
112 | export KITCHEN_YAML=".kitchen_vagrant.yml"
113 |
114 | bundle install
115 |
116 | kitchen converge
117 | kitchen list
118 | kitchen verify
119 | kitchen destroy
120 | ```
121 |
122 | # More Resources
123 | - TODO: security improvement for the built-in chef user: attributes/default.rb
124 |
125 | - Critical Info
126 | ```
127 | CentOS Jenkins conf: /etc/sysconfig/jenkins
128 | ```
129 |
130 |
131 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | use_sudo: false
7 | # because Docker and SystemD/Upstart
8 | privileged: true
9 | remove_images: false
10 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
11 | # tls_verify: true
12 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
13 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
14 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
15 | # socket: tcp://172.17.0.1:4243
16 | transport:
17 | username: kitchen
18 |
19 | provisioner:
20 | name: chef_zero
21 | require_chef_omnibus: 13.6.4
22 | data_path: test/shared
23 | client_rb:
24 | file_cache_path: "/var/chef/cache"
25 |
26 | platforms:
27 | - name: centos-7
28 | driver_config:
29 | # https://hub.docker.com/r/dokken/centos-7/
30 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
31 | image: <%= ENV.fetch('IMAGE_NAME', "dokken/centos-7") %>
32 | pid_one_command: /usr/lib/systemd/systemd
33 | forward:
34 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>83:8081
35 | - name: ubuntu-14.04
36 | driver_config:
37 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
38 | image: <%= ENV.fetch('IMAGE_NAME', "ubuntu:14.04") %>
39 | forward:
40 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "280") %>83:8081
41 |
42 | suites:
43 | - name: default
44 | run_list:
45 | - recipe[apt::default]
46 | - recipe[jenkins-demo::default]
47 | - recipe[jenkins-demo::conf_test_job]
48 | attributes:
49 | {jenkins_demo:
50 | {jenkins_port: '8081',
51 | slack_teamdomain: 'mywechat',
52 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
53 | # TODO different env use different port
54 | # TODO use server ip
55 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>80/',
56 | slack_room: '#denny-alerts',
57 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
58 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/.kitchen_digitalocean.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: digitalocean
4 |
5 | provisioner:
6 | name: chef_zero
7 | require_chef_omnibus: 13.6.4
8 | data_path: test/shared
9 |
10 | platforms:
11 | - name: jenkins-demo-centos7
12 | driver_config:
13 | region: sfo2
14 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
15 | private_networking: false
16 | # https://github.com/test-kitchen/kitchen-digitalocean
17 | image: centos-7-x64
18 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
19 | - name: jenkins-demo-ubuntu1404
20 | driver_config:
21 | region: sfo2
22 | size: <%= ENV.fetch('DIGITALOCEAN_FLAVOR', "1gb") %>
23 | private_networking: false
24 | image: ubuntu-14-04-x64
25 | server_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
26 |
27 | suites:
28 | - name: default
29 | run_list:
30 | - recipe[apt::default]
31 | - recipe[jenkins-demo::default]
32 | - recipe[jenkins-demo::conf_test_job]
33 | attributes:
34 | {jenkins_demo:
35 | {jenkins_port: '8081',
36 | slack_teamdomain: 'mywechat',
37 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
38 | # TODO different env use different port
39 | # TODO use server ip
40 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
41 | slack_room: '#denny-alerts',
42 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
43 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/.kitchen_ec2.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: ec2
4 | region: us-east-1
5 |
6 | transport:
7 | ssh_key: ~/.ssh/<%= ENV.fetch('KEY_USER', "") %>
8 | username: ec2-user
9 |
10 | provisioner:
11 | name: chef_zero
12 | require_chef_omnibus: 13.6.4
13 | data_path: test/shared
14 |
15 | platforms:
16 | - name: ubuntu-1404
17 | driver:
18 | # https://cloud-images.ubuntu.com/releases/14.04/release-20150506/
19 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-8d9e1cf7") %>
20 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
21 | transport:
22 | username: ubuntu
23 | - name: centos-7
24 | driver:
25 | # https://wiki.centos.org/Cloud/AWS
26 | # https://stackoverflow.com/questions/40835953/how-to-find-ami-id-of-centos-7-image-in-aws-marketplace
27 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-ae7bfdb8") %>
28 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
29 | transport:
30 | username: centos
31 | - name: centos-ami
32 | driver:
33 | image_id: <%= ENV.fetch('EC2_IMAGE_ID', "ami-6869aa05") %>
34 | instance_type: <%= ENV.fetch('EC2_INSTANCE_TYPE', "t2.micro") %>
35 |
36 | suites:
37 | - name: default
38 | run_list:
39 | - recipe[apt::default]
40 | - recipe[jenkins-demo::default]
41 | - recipe[jenkins-demo::conf_test_job]
42 | attributes:
43 | {jenkins_demo:
44 | {jenkins_port: '8081',
45 | slack_teamdomain: 'mywechat',
46 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
47 | # TODO different env use different port
48 | # TODO use server ip
49 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
50 | slack_room: '#denny-alerts',
51 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
52 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/.kitchen_vagrant.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: vagrant
4 |
5 | driver_config:
6 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
7 | # https://github.com/test-kitchen/kitchen-vagrant
8 | memory: 1024
9 | transport:
10 | username: kitchen
11 |
12 | provisioner:
13 | name: chef_zero
14 | require_chef_omnibus: 13.6.4
15 | data_path: test/shared
16 | client_rb:
17 | file_cache_path: "/var/chef/cache"
18 |
19 | platforms:
20 | - name: centos-7
21 | driver_config:
22 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-centos7") %>
23 | network:
24 | - ["forwarded_port", {guest: 8080, host: 18080}]
25 | - name: ubuntu-14.04
26 | # https://stackoverflow.com/questions/38677059/port-forwarding-not-working-with-test-kitchen-and-vagrant
27 | driver_config:
28 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo-ubuntu1404") %>
29 | network:
30 | - ["forwarded_port", {guest: 8080, host: 28080}]
31 |
32 | suites:
33 | - name: default
34 | run_list:
35 | - recipe[apt::default]
36 | - recipe[jenkins-demo::default]
37 | - recipe[jenkins-demo::conf_test_job]
38 | attributes:
39 | {jenkins_demo:
40 | {jenkins_port: '8081',
41 | slack_teamdomain: 'mywechat',
42 | slack_authtoken: '<%= ENV.fetch('SLACK_TOKEN', "") %>',
43 | # TODO different env use different port
44 | # TODO use server ip
45 | slack_buildserverurl: 'http://localhost:<%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "180") %>81/',
46 | slack_room: '#denny-alerts',
47 | default_username: '<%= ENV.fetch('JENKINS_DEFAULT_USERNAME', "usertest123") %>',
48 | default_password: '<%= ENV.fetch('JENKINS_DEFAULT_PASSWORD', "password123") %>'
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - Berksfile
4 |
5 | Style/Next:
6 | Enabled: false
7 |
8 | Metrics/LineLength:
9 | Max: 90
10 |
11 | MethodLength:
12 | Max: 20
13 |
14 | Metrics/AbcSize:
15 | Enabled: false
16 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-digitalocean', '= 0.9.8'
5 | gem 'kitchen-docker', '= 2.6.0'
6 | gem 'kitchen-ec2', '= 1.3.2'
7 | gem 'kitchen-vagrant', '= 1.2.1'
8 |
9 | gem 'test-kitchen', '= 1.19.1'
10 |
11 | gem 'berkshelf', '= 6.3.1'
12 |
13 | gem 'foodcritic', '~> 4.0.0'
14 | gem 'rubocop', '~> 0.48.1'
15 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/README.md:
--------------------------------------------------------------------------------
1 | jenkins-demo Cookbook
2 | ================
3 | Setup and configure demo jenkins
4 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/attributes/conf_test_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 |
9 | # slack notification
10 | default['jenkins_demo']['slack_teamdomain'] = ''
11 | default['jenkins_demo']['slack_authtoken'] = ''
12 | default['jenkins_demo']['slack_buildserverurl'] = ''
13 | default['jenkins_demo']['slack_room'] = ''
14 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Copyright 2017, DennyZhang.com
5 | #
6 | # All rights reserved - Do Not Redistribute
7 | #
8 | default['jenkins_demo']['jenkins_port'] = 8080
9 |
10 | # TODO: speed up the deployment process
11 | default['jenkins_demo']['jenkins_plugins'] = {
12 | 'icon-shim' => '2.0.3',
13 | 'credentials' => '2.1.16',
14 | 'thinBackup' => '1.9',
15 | # 'command-launcher' => '1.0',
16 | 'bouncycastle-api' => '2.16.2',
17 | 'plain-credentials' => '1.4',
18 | 'slack' => '2.3',
19 | 'script-security' => '1.35',
20 | 'matrix-auth' => '2.2',
21 | 'ssh-credentials' => '1.13'
22 | }
23 |
24 | ########################################
25 | default['jenkins_demo']['default_username'] = ''
26 | default['jenkins_demo']['default_password'] = ''
27 |
28 | # TODO: improve the security
29 | default['jenkins_demo']['chef_private_key'] = \
30 | '-----BEGIN RSA PRIVATE KEY-----
31 | MIIEpgIBAAKCAQEA6fIwUKxZXgKqEE6HCM94eEEeQ+n9mGpKn+CiKExI97mQtio4
32 | uzB/4A7qVXfBYaa2jbPZzD6bDvGco88vgeDuRB5tNh/sRBD3T7L9CxNIGp9gMMsu
33 | tRprwI5MEUsDDFXMKo5ZinpRe9fud5UBOmEHK0vjRVSgLVCGYdv/iXaBKY3feH8a
34 | 4gUuTzkdbUtoUMAUTfNyevhUfLRKSWjr5+f7krYYTqJpM7KUAL9e2dYMjkj3He7g
35 | iM4uiPtAQnMYcsyevNgpM0uKnp6+pPzTMSkSNp3uIK6aQ4lR80lEfq8fRwqzsIuJ
36 | dRT/+iJpd6XF8+GSyOt/tEh1RPiEKiGHLpmZGQIDAQABAoIBAQDFsipuIhcrQKki
37 | OpoWMe0mAjFnRtdM85W4YYXm9AA9h4zow+lJFoUZfME+FINQ2CcwvClzVfyGtlqe
38 | ezk0UjZHTkcQFA3+vy+fJCx+LX8jMEeDNFB2Lqub/yP9ARzEUcTEuaKlSRSOyTz1
39 | xO9SvCfoyKp4Ljll0cSd8eGR8pjX2TSfJ85aFAcP1CHGa/qGdxhSrbL2PMXaNFIT
40 | 27ZEUo4FVqcwRFN6JuO4sAlnyg8axXlXNLpwPzW1Zi7auS9nAO9bDEIhP4YfFwWs
41 | /iV7KBs/bryez94XS68b3MUXoZWS+1nP8ivBSOCH0mWy5/PhR4esih2EhXk/hi3P
42 | dp6aX4p5AoGBAPrmS+4lrvnvk2EOj3vqSergd31XBTM6NRKSsIYCtlaXsVjMym/i
43 | UdqcLqha4IEW3mucmpD3MBsTqshHGTI+67+tU/G23kThV/3U3a+jSR10FjgACPRd
44 | 8VhxrhTBvKjcw0uKeMl9uE0eb/2q8uVtX/8InOCvEfNGFCcszLsYFBr3AoGBAO6z
45 | qhWt8y/HkqWgBcbDJKx+T050nM9fkkBk1ILZn/GMEU828aEvKSwa8wzcx1gPo8Uu
46 | TP2SS0K0vnQv75UfyafgxFMVlELQrRTLHJqFQrCGikgBLNwHjRdvHfNujoBXbv+9
47 | g4LVFqHv0/kVRc1kXhdEwBCZm29rCDVusKK0C1hvAoGBAOAY4qkLL4Y93j1KbA4Z
48 | 7XvEkfV5zEM9Mjosm06XDZW6V8Ug5Y+ZbdL8vQ/SW8PxUSh87/GbV3RX1KqeFnsy
49 | iA7kGZ5D37NWMumdP4SpK50LGu1Z2qWpYu/EWeBgSsnopObL/6a4i+0VyqGgFuOl
50 | FaENaFGnDTlk1otHEHXrw8lxAoGBAITL11fwSlbOhLs3537ImeKM8roHDiYgWVER
51 | x1h0khLjhc24F31Aq3sqEwWY3h4TtVzBgXugo9Ycj8g70uH3qUyIMzC11KHHTkM/
52 | LE6azJtAfjXI0Zgna0saOmNvoj+sZMhKOpvSyKCWuCrettKpf98aFHAnxN2bghmX
53 | 1xTtbVJpAoGBAKnqvADsNFaI1Ak7tdfJJ+chxnxXd1k6Mly44Jsp6oako4Nl2Uiw
54 | 3xL4JGed+QBmjFh+n4hR9T7J65fUFvBixBEAhDSXcRHWL84xTQWLtdHK4+zDWGJt
55 | n2DMrFzhp1H6neUFMBeNOw+fQuhPj6OcLrs4dRdyQhVRp0ZOJyLMS39e
56 | -----END RSA PRIVATE KEY-----'
57 |
58 | default['jenkins_demo']['chef_public_key'] = \
59 | 'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDp8jBQrFleAqoQTocIz3h4QR5'\
60 | 'D6f2Yakqf4KIoTEj3uZC2Kji7MH/gDupVd8FhpraNs9nMPpsO8Zyjzy+B4O5EHm'\
61 | '02H+xEEPdPsv0LE0gan2Awyy61GmvAjkwRSwMMVcwqjlmKelF71+53lQE6YQcrS'\
62 | '+NFVKAtUIZh2/+JdoEpjd94fxriBS5POR1tS2hQwBRN83J6+FR8tEpJaOvn5/uS'\
63 | 'thhOomkzspQAv17Z1gyOSPcd7uCIzi6I+0BCcxhyzJ682CkzS4qenr6k/NMxKRI'\
64 | '2ne4grppDiVHzSUR+rx9HCrOwi4l1FP/6Iml3pcXz4ZLI63+0SHVE+IQqIYcumZ'\
65 | 'kZ chef@mytest.com'
66 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/files/default/serverspec_check.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash -e
2 | function setup_serverspec() {
3 | working_dir=${1?}
4 | cd "$working_dir"
5 | if [ ! -f spec/spec_helper.rb ]; then
6 | echo "Setup Serverspec Test case"
7 | cat > spec/spec_helper.rb < Rakefile < 'spec:all'
18 | task :default => :spec
19 |
20 | namespace :spec do
21 | targets = []
22 | Dir.glob('./spec/*').each do |dir|
23 | next unless File.directory?(dir)
24 | target = File.basename(dir)
25 | target = "_#{target}" if target == "default"
26 | targets << target
27 | end
28 |
29 | task :all => targets
30 | task :default => :all
31 |
32 | targets.each do |target|
33 | original_target = target == "_default" ? target[1..-1] : target
34 | desc "Run serverspec tests to #{original_target}"
35 | RSpec::Core::RakeTask.new(target.to_sym) do |t|
36 | ENV['TARGET_HOST'] = original_target
37 | t.pattern = "spec/#{original_target}/*_spec.rb"
38 | end
39 | end
40 | end
41 | EOF
42 | fi
43 | }
44 |
45 | #########################################################
46 | [ -n "$working_dir" ] || working_dir="$WORKSPACE"
47 |
48 | mkdir -p "$working_dir/spec/localhost"
49 | cd "$working_dir"
50 |
51 | setup_serverspec "$working_dir"
52 |
53 | cat > spec/localhost/sample_spec.rb <= 14.04'
14 | depends 'apt', '=2.6.1'
15 | depends 'java'
16 | depends 'jenkins', '=5.0.4'
17 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/backup.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: backup
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/conf_test_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: conf_test_job
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | ################################################################################
13 | # Install simple jobs
14 | %w[CommonServerCheckRepo].each do |job_name|
15 | config = File.join(Chef::Config[:file_cache_path], "#{job_name}.xml")
16 | template config do
17 | source "#{job_name}/config.xml"
18 | end
19 |
20 | jenkins_job job_name do
21 | config config
22 | end
23 | end
24 |
25 | # Install facilities related to the jobs
26 |
27 | # keep the gem installation minimal: --no-ri --no-rdoc
28 | # https://coderwall.com/p/spo6bq/default-no-ri-no-rdoc-on-ruby-gem-installation
29 | file '/root/.gemrc' do
30 | content 'gem: --no-ri --no-rdoc'
31 | mode 0o755
32 | owner 'root'
33 | group 'root'
34 | end
35 |
36 | if platform_family?('debian')
37 |
38 | # https://www.brightbox.com/blog/2017/01/13/ruby-2-4-ubuntu-packages/
39 | apt_repository 'ruby-repo' do
40 | uri 'ppa:brightbox/ruby-ng'
41 | distribution node['lsb']['codename']
42 | key 'C3173AA6'
43 | keyserver 'keyserver.ubuntu.com'
44 | retries 3
45 | retry_delay 3
46 | not_if { ::File.exist?('/etc/apt/sources.list.d/ruby-repo.list') }
47 | end
48 |
49 | %w[ruby2.4 ruby2.4-dev netcat gem rake].each do |x|
50 | package x do
51 | action :install
52 | not_if "dpkg -l #{x} | grep -E '^ii'"
53 | end
54 | end
55 | else
56 | %w[nc gem yum zlib-devel gcc gcc-c++ ruby-devel rubygems].each do |x|
57 | package x do
58 | action :install
59 | # TODO: change this
60 | # not_if "dpkg -l #{x} | grep -E '^ii'"
61 | end
62 | end
63 |
64 | gem_package 'rake' do
65 | action :install
66 | version '12.3.0'
67 | end
68 |
69 | # TODO: better way to install io-console gem
70 | execute 'Install io-console' do
71 | command 'gem install io-console'
72 | action :run
73 | not_if 'gem list | grep io-console'
74 | end
75 | end
76 |
77 | gem_package 'serverspec' do
78 | action :install
79 | version '2.41.3'
80 | end
81 |
82 | cookbook_file '/var/lib/jenkins/script/serverspec_check.sh' do
83 | source 'serverspec_check.sh'
84 | mode 0o755
85 | user 'jenkins'
86 | group 'jenkins'
87 | end
88 | ################################################################################
89 | include_recipe 'jenkins-demo::test_pipeline'
90 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | include_recipe 'jenkins-demo::master'
13 |
14 | if platform_family?('debian')
15 | # Install iproute2 for ss package
16 | %w[lsof iproute2].each do |x|
17 | package x do
18 | action :install
19 | not_if "dpkg -l #{x} | grep -E '^ii'"
20 | end
21 | end
22 | else
23 | %w[lsof].each do |x|
24 | package x do
25 | action :install
26 | # TODO: change this
27 | # not_if "dpkg -l #{x} | grep -E '^ii'"
28 | end
29 | end
30 | end
31 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/master.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: master
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | apt_update 'update' if platform_family?('debian')
13 |
14 | node.default['java']['install_flavor'] = 'oracle'
15 | node.default['java']['jdk_version'] = '8'
16 | node.default['java']['set_etc_environment'] = true
17 | node.default['java']['oracle']['accept_oracle_download_terms'] = true
18 | # Avoid unecessary change to /etc/sysconfig/jenkins in CentOS
19 | node.default['jenkins']['java'] = 'java'
20 |
21 | if %w[debian ubuntu].include?(node['platform_family'])
22 | node.default['jenkins']['master']['repository'] = \
23 | 'http://pkg.jenkins-ci.org/debian'
24 | node.default['jenkins']['master']['repository_key'] = \
25 | 'http://pkg.jenkins-ci.org/debian/jenkins-ci.org.key'
26 | end
27 |
28 | node.default['jenkins']['executor']['timeout'] = 480
29 |
30 | node.default['jenkins']['master']['port'] = node['jenkins_demo']['jenkins_port']
31 | node.default['jenkins']['master']['endpoint'] = \
32 | "http://#{node['jenkins']['master']['host']}:#{node['jenkins']['master']['port']}"
33 |
34 | include_recipe 'java::default'
35 | include_recipe 'jenkins::master'
36 |
37 | # Install some plugins needed, but not installed on jenkins2 by default
38 | node['jenkins_demo']['jenkins_plugins'].each do |plugin|
39 | jenkins_plugin plugin[0] do
40 | version plugin[1]
41 | notifies :execute, 'jenkins_command[safe-restart]', :delayed
42 | end
43 | end
44 |
45 | # force restart, since critical jenkins plugin installed
46 | # TODO: When re-run chef update, avoid this extra blind jenkins restart
47 | jenkins_command 'safe-restart' do
48 | action :execute
49 | end
50 |
51 | %w[/var/lib/jenkins/script].each do |x|
52 | directory x do
53 | owner 'jenkins'
54 | group 'jenkins'
55 | mode 0o755
56 | action :create
57 | end
58 | end
59 |
60 | include_recipe 'jenkins-demo::security'
61 | include_recipe 'jenkins-demo::backup'
62 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/security.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: security
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | require 'openssl'
13 | require 'net/ssh'
14 | # key = OpenSSL::PKey::RSA.new(jenkins['private_key'])
15 | # private_key = key.to_pem
16 | # public_key = "#{key.ssh_type} #{[key.to_blob].pack('m0')}"
17 |
18 | # https://goo.gl/jvn5TN
19 | # Jenkins itself login the server
20 |
21 | private_key = node['jenkins_demo']['chef_private_key']
22 | public_key = node['jenkins_demo']['chef_public_key']
23 |
24 | # Set the private key on the executor
25 | node.run_state[:jenkins_private_key] = private_key
26 |
27 | # Create a default Chef user with the public key
28 | jenkins_user 'chef' do
29 | full_name 'Chef Client'
30 | public_keys [public_key]
31 | end
32 |
33 | # Turn on basic authentication
34 | jenkins_script 'setup authentication' do
35 | command <<-EOH.gsub(/^ {4}/, '')
36 | import jenkins.model.*
37 | def instance = Jenkins.getInstance()
38 |
39 | import hudson.security.*
40 | def realm = new HudsonPrivateSecurityRealm(false)
41 | instance.setSecurityRealm(realm)
42 |
43 | def strategy = new hudson.security.FullControlOnceLoggedInAuthorizationStrategy()
44 | instance.setAuthorizationStrategy(strategy)
45 |
46 | instance.save()
47 | EOH
48 | # TODO: add not_if
49 | end
50 |
51 | ################################################################################
52 | username = node['jenkins_demo']['default_username']
53 | password = node['jenkins_demo']['default_password']
54 | if username != ''
55 | # Create a dummy user
56 | # https://gist.github.com/hayderimran7/50cb1244cc1e856873a4
57 | jenkins_script "add_user #{username}" do
58 | command <<-EOH.gsub(/^ {4}/, '')
59 | import jenkins.model.*
60 | import hudson.security.*
61 |
62 | def instance = Jenkins.getInstance()
63 |
64 | def hudsonRealm = new HudsonPrivateSecurityRealm(false)
65 | hudsonRealm.createAccount("#{username}", "#{password}")
66 | instance.setSecurityRealm(hudsonRealm)
67 | instance.save()
68 | EOH
69 | not_if "test -d /var/lib/jenkins/users/#{username}"
70 | end
71 | end
72 |
73 | # Use matrix authorization model
74 | # Gives all authenticated users admin access
75 | # https://github.com/glenjamin/jenkins-groovy-examples/blob/master/README.md
76 | jenkins_script 'all authenticated users admin access' do
77 | command <<-EOH.gsub(/^ {4}/, '')
78 | import jenkins.model.*
79 | def instance = Jenkins.getInstance()
80 |
81 | import hudson.security.*
82 | def realm = new HudsonPrivateSecurityRealm(false)
83 | instance.setSecurityRealm(realm)
84 |
85 | def strategy = new hudson.security.GlobalMatrixAuthorizationStrategy()
86 | strategy.add(Jenkins.ADMINISTER, 'authenticated')
87 | instance.setAuthorizationStrategy(strategy)
88 |
89 | instance.save()
90 | EOH
91 | # TODO: add not_if
92 | end
93 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/recipes/test_pipeline.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: test_pipeline
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 | ################################################################################
12 | # Install Jenkins pipeline plugins
13 |
14 | package 'git' do
15 | action :install
16 | end
17 |
18 | jenkins_pipeline_plugins = {
19 | ############################################
20 | # Install git plugin
21 | 'git' => '3.6.4',
22 | # upgrade or downgrade plugins
23 | 'structs' => '1.10',
24 | 'scm-api' => '2.2.5',
25 | ############################################
26 | # Install pipeline plugin
27 | 'workflow-aggregator' => '2.5',
28 | # upgrade or downgrade plugins
29 | 'workflow-step-api' => '2.14',
30 | 'branch-api' => '2.0.15',
31 | # Need to install branch-api, then cloudbees-folder
32 | # If not, branch-api:v2.0.15 will downgrade cloudbees-folder to v6.1.0
33 | 'cloudbees-folder' => '6.2.1',
34 | 'workflow-cps' => '2.41',
35 | 'workflow-support' => '2.16',
36 | 'credentials' => '2.1.16',
37 | 'plain-credentials' => '1.4',
38 | 'git-client' => '2.6.0'
39 | }
40 |
41 | jenkins_pipeline_plugins.each do |plugin|
42 | jenkins_plugin plugin[0] do
43 | version plugin[1]
44 | notifies :execute, 'jenkins_command[safe-restart]', :delayed
45 | end
46 | end
47 |
48 | # force restart, since critical jenkins plugin installed
49 | jenkins_command 'safe-restart' do
50 | action :execute
51 | end
52 |
53 | %w[JenkinsFileExample1 JenkinsFileExample2].each do |job_name|
54 | config = File.join(Chef::Config[:file_cache_path], "#{job_name}.xml")
55 | template config do
56 | source "#{job_name}/config.xml"
57 | end
58 |
59 | jenkins_job job_name do
60 | config config
61 | end
62 | end
63 | ################################################################################
64 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/templates/default/CommonServerCheckRepo/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | false
5 |
6 |
7 |
8 | -1
9 | 50
10 | -1
11 | -1
12 |
13 |
14 |
15 | false
16 |
17 |
18 |
19 |
20 | test_spec
21 |
22 | # ping check
23 | ["www.github.com"].each do |item|
24 | describe command("ping -c3 #{item}") do
25 | its(:exit_status) { should eq 0 }
26 | end
27 | end
28 |
29 | # Check anonymous http links
30 | ["http://www.dennyzhang.com/",
31 | "https://www.dennyzhang.com/",
32 | "https://code.dennyzhang.com/",
33 | "http://slack.dennyzhang.com/",
34 | ].each do |url|
35 | describe command('curl -I --connect-timeout 10 -k %s 2>&1' %[url]) do
36 | its(:stdout) { should match /HTTP\/1.1 200 OK/ }
37 | end
38 | end
39 |
40 | describe service('jenkins') do
41 | it { should be_running }
42 | end
43 |
44 | # Check at least 2 GB free disk
45 | describe command("[ $(df -h / | tail -n1 |awk -F' ' '{print $4}' | awk -F'G' '{print $1}' | awk -F'.' '{print $1}') -gt 2 ]") do
46 | its(:exit_status) { should eq 0 }
47 | end
48 |
49 | # TODO: enable this
50 | # # Check at least 2 GB free memory
51 | # describe command("[ $(free -ml | grep 'buffers/cache' | awk -F' ' '{print $4}') -gt 2048 ]") do
52 | # its(:exit_status) { should eq 0 }
53 | # end
54 |
55 | # TODO: support for both CentOS and Ubuntu OS
56 | # # Check remote tcp port
57 | # ["vpn.dennyzhang.com:6188", # vpn
58 | # "www.dennyzhang.com:443", # ssl
59 | # ].each do |ip_port|
60 | # (ip, port) = ip_port.split(':')
61 | # describe command("nc -z -v -w5 #{ip} #{port} 2>&1") do
62 | # its(:stdout) { should match /open/ }
63 | # end
64 | # end
65 |
66 | # # check cpu loadavg in latest one min
67 | # ["172.17.0.1:2702:10"].each do |item|
68 | # (ip, port, cpu_load) = item.split(':')
69 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s cat /proc/loadavg | awk '{print int($1+0.99)}'` -lt %s ]" \
70 | # % [port, ip, cpu_load]
71 | # describe command(command_str) do
72 | # its(:exit_status) { should eq 0 }
73 | # end
74 | # end
75 |
76 | # # check docker container number
77 | # ["172.17.0.1:2702:15"].each do |item|
78 | # (ip, port, container_count) = item.split(':')
79 | # command_str = "[ `ssh -o stricthostkeychecking=no -i /var/jenkins_home/.ssh/docker_host_id_rsa -p %s root@%s docker ps | sed 1d | wc -l` -lt %s ]" \
80 | # % [port, ip, container_count]
81 | # describe command(command_str) do
82 | # its(:exit_status) { should eq 0 }
83 | # end
84 | # end
85 |
86 |
87 |
88 |
89 |
90 |
91 | true
92 | false
93 | false
94 | false
95 |
96 |
97 | H H/5 * * *
98 |
99 |
100 | false
101 |
102 |
103 | #!/bin/bash -ex
104 | export PATH=$PATH:/usr/local/bin/
105 | bash -e /var/lib/jenkins/script/serverspec_check.sh
106 |
107 |
108 |
109 |
110 |
111 | false
112 | false
113 | false
114 | TestParent
115 |
116 | 3
117 |
118 | 1
119 |
120 |
121 | <%= node['jenkins_demo']['slack_teamdomain'] %>
122 | <%= node['jenkins_demo']['slack_authtoken'] %>
123 | <%= node['jenkins_demo']['slack_buildserverurl'] %>
124 | <%= node['jenkins_demo']['slack_room'] %>
125 | false
126 | false
127 | false
128 | false
129 | false
130 | true
131 | true
132 | true
133 | false
134 | NONE
135 | false
136 |
137 |
138 |
139 |
140 |
141 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/templates/default/JenkinsFileExample1/Jenkinsfile.groovy:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env groovy
2 |
3 | node('master') {
4 | try {
5 | stage('build') {
6 | sh "echo dummy build action"
7 | }
8 |
9 | stage('test') {
10 | sh "echo dummy test action"
11 | }
12 |
13 | stage('deploy') {
14 | sh "echo dummy deploy action"
15 | }
16 | } catch(error) {
17 | throw error
18 | } finally {
19 | // Any cleanup operations needed, whether we hit an error or not
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/templates/default/JenkinsFileExample1/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | 2
14 |
15 |
16 | https://github.com/DennyZhang/challenges-jenkins-groovy.git
17 |
18 |
19 |
20 |
21 | */master
22 |
23 |
24 | false
25 |
26 |
27 |
28 | Scenario-301/cookbooks/jenkins-demo/templates/default/JenkinsFileExample1/Jenkinsfile.groovy
29 | true
30 |
31 |
32 | false
33 |
34 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/templates/default/JenkinsFileExample2/Jenkinsfile.groovy:
--------------------------------------------------------------------------------
1 | node {
2 | // // http://www.commandlinefu.com/commands/view/3584/remove-color-codes-special-characters-with-sed
3 | // // parameters: slack_channel, slack_domain, slack_token
4 | // // get who has triggered the pipeline job
5 | // def sh_command = "head -n 1 $HUDSON_HOME/jobs/$JOB_BASE_NAME/builds/$BUILD_NUMBER/log | awk -F'=' '{print \$2}' | sed -r \"s/\\x1B\\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g\""
6 | // def username = sh(script: sh_command, returnStdout: true)
7 | // username = username.trim()
8 | // def job_name = sh(script: "echo $JOB_BASE_NAME", returnStdout: true)
9 | // job_name = job_name.trim()
10 | // slackSend channel: slack_channel, message: 'Job(' + job_name + ') has been triggered by ' + username, teamDomain: slack_domain, tokenCredentialId: slack_token
11 |
12 | try {
13 | stage('Build') {
14 | echo 'Building..'
15 | }
16 | stage('Test') {
17 | build job: "CommonServerCheckRepo"
18 | }
19 | if (whether_skip_deploy == "false") {
20 | stage('Deploy') {
21 | echo 'Deploying....'
22 | }
23 | }
24 | }
25 | finally {
26 | echo "Finally Actions"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/templates/default/JenkinsFileExample2/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | false
6 |
7 |
8 |
9 |
10 | whether_skip_deploy
11 | If checked, deploy stage will be skipped
12 | false
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | 2
23 |
24 |
25 | https://github.com/DennyZhang/challenges-jenkins-groovy.git
26 |
27 |
28 |
29 |
30 | */master
31 |
32 |
33 | false
34 |
35 |
36 |
37 | Scenario-301/cookbooks/jenkins-demo/templates/default/JenkinsFileExample2/Jenkinsfile.groovy
38 | true
39 |
40 |
41 | false
42 |
43 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 |
8 | #############################################################################
9 | require 'json'
10 |
11 | describe command('java -version') do
12 | its(:stderr) { should contain '1.8' }
13 | end
14 |
15 | describe command('chef-solo --version') do
16 | its(:stdout) { should contain '13.6.4' }
17 | end
18 |
19 | if %w[redhat centos].include?(os[:family])
20 | describe command('yum info jenkins') do
21 | its(:stdout) { should contain '2.73.3' }
22 | end
23 | elsif %w[debian ubuntu].include?(os[:family])
24 | # debian related environment spec
25 | describe command('dpkg -l | grep jenkins') do
26 | its(:stdout) { should contain '2.91' }
27 | end
28 | end
29 |
30 | #############################################################################
31 | # If extra jenkins jobs have been triggered, verify the logic
32 | require_relative '../../../kitchen/data/verify_job_config'
33 |
34 | #############################################################################
35 | require 'json'
36 | chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
37 |
38 | jenkins_port = chef_data.fetch('jenkins_demo').fetch('jenkins_port')
39 | # Wait for service slow start/restart
40 | describe port(jenkins_port), wait: { timeout: 60 } do
41 | it { should be_listening }
42 | end
43 |
44 | #############################################################################
45 | username = chef_data.fetch('jenkins_demo').fetch('default_username')
46 |
47 | if username != ''
48 | describe file("/var/lib/jenkins/users/#{username}") do
49 | it { should be_directory }
50 | end
51 | end
52 |
--------------------------------------------------------------------------------
/Scenario-303/cookbooks/jenkins-demo/test/shared/verify_job_config.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 | # https://github.com/test-kitchen/test-kitchen/issues/469
8 | set :path, '/sbin:/usr/local/sbin:/usr/local/bin:$PATH'
9 |
10 | #############################################################################
11 | describe file('/var/lib/jenkins/script/serverspec_check.sh') do
12 | it { should be_file }
13 | end
14 |
15 | describe command('which nc') do
16 | its(:exit_status) { should eq 0 }
17 | end
18 |
19 | describe command('gem list | grep serverspec') do
20 | its(:stdout) { should contain '2.41.3' }
21 | end
22 |
23 | if %w[redhat centos].include?(os[:family])
24 | describe command('gem --version') do
25 | its(:stdout) { should contain '2.0.14' }
26 | end
27 |
28 | describe command('rake --version') do
29 | its(:stdout) { should contain '12.3.0' }
30 | end
31 | elsif %w[debian ubuntu].include?(os[:family])
32 | # debian related environment spec
33 | describe command('gem --version') do
34 | its(:stdout) { should contain '2.6.13' }
35 | end
36 |
37 | describe command('rake --version') do
38 | its(:stdout) { should contain '10.0.4' }
39 | end
40 | end
41 |
42 | jenkins_plugins_versions = {
43 | 'workflow-cps' => '2.41',
44 | 'git' => '3.6.4',
45 | 'workflow-job' => '2.9',
46 | 'workflow-support' => '2.16',
47 | 'cloudbees-folder' => '6.2.1',
48 | 'credentials' => '2.1.16',
49 | 'plain-credentials' => '1.4',
50 | 'git-client' => '2.6.0'
51 | }
52 | # verify plugin version
53 | jenkins_plugins_versions.each do |plugin|
54 | describe file("/var/lib/jenkins/plugins/#{plugin[0]}/META-INF/MANIFEST.MF") do
55 | its(:content) { should contain "Plugin-Version: #{plugin[1]}" }
56 | end
57 | end
58 |
--------------------------------------------------------------------------------
/Scenario-401/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.linkedin.com/in/dennyzhang001)
[](https://github.com/DennyZhang)
2 |
3 | File me [tickets](https://github.com/DennyZhang/challenges-chef/issues) or star [the repo](https://github.com/DennyZhang/challenges-chef).
4 |
5 |
6 |
7 | Table of Contents
8 | =================
9 |
10 | * [Requirement](#requirement)
11 | * [Procedure](#procedure)
12 | * [More Resources](#more-resources)
13 |
14 |
15 |
16 |
17 | # Requirement
18 |
19 | 1. Test 2 nodes jenkins cluster deployment in docker
20 | 2. Use Jenkinsfile to configure Jenkins
21 | 3. Define Jenkins pipeline
22 |
23 | # Procedure
24 | - Start docker-compose env
25 | docker-compose up -d
26 |
27 | - Login to the container, and run procedure
28 | ```
29 | docker exec -it my_chef sh
30 |
31 | mkdir -p /tmp/berks_cookbooks
32 |
33 | cd /tmp/cookbooks/jenkins-demo/
34 | berks vendor /tmp/berks_cookbooks
35 | ls -lth /tmp/berks_cookbooks
36 | ```
37 |
38 | - Apply Chef update
39 | ```
40 | cd /tmp
41 | # From config/node.json, we specify to apply example cookbook
42 | chef-solo -L chef_solo.log -c config/solo.rb -j config/node.json
43 |
44 | - After deployment, jenkins is up and running
45 | ```
46 |
47 | - Verify Jenkins
48 | curl -I http://localhost:8080
49 |
50 | - Destroy docker-compose env after testing
51 |
52 | ```
53 | docker-compose down -v
54 | ```
55 |
56 | # More Resources
57 | - jenkins cookbook: https://github.com/chef-cookbooks/jenkins
58 |
59 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/.kitchen.yml:
--------------------------------------------------------------------------------
1 | ---
2 | driver:
3 | name: docker
4 |
5 | driver_config:
6 | instance_name: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
7 | hostname: <%= ENV.fetch('INSTANCE_NAME', "jenkins-demo") %>
8 | use_sudo: false
9 | privileged: true
10 | remove_images: false
11 | image: <%= ENV.fetch('IMAGE_NAME', "chef/chefdk") %>
12 | forward:
13 | - <%= ENV.fetch('DOCKER_PORT_FORWARD_PREFIX', "80") %>80:8080
14 | # tls_verify: true
15 | # tls_cacert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/ca.pem
16 | # tls_cert: <%= ENV.fetch('TLS_FOLDER', "tls") %>/cert.pem
17 | # tls_key: <%= ENV.fetch('TLS_FOLDER', "tls") %>/key.pem
18 | # socket: tcp://172.17.0.1:4243
19 | transport:
20 | username: kitchen
21 |
22 | provisioner:
23 | name: chef_zero
24 | require_chef_omnibus: 13.6.4
25 | data_path: test/shared
26 | client_rb:
27 | file_cache_path: "/var/chef/cache"
28 |
29 | platforms:
30 | - name: ubuntu-14.04
31 |
32 | suites:
33 | - name: default
34 | run_list:
35 | - recipe[apt::default]
36 | - recipe[jenkins-demo::default]
37 | attributes:
38 | {jenkins-demo:
39 | {update_version: '1.1'
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/.rubocop.yml:
--------------------------------------------------------------------------------
1 | AllCops:
2 | Exclude:
3 | - Berksfile
4 |
5 | Style/Next:
6 | Enabled: false
7 |
8 | Metrics/LineLength:
9 | Max: 90
10 |
11 | MethodLength:
12 | Max: 20
13 |
14 | Metrics/AbcSize:
15 | Enabled: false
16 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/Berksfile:
--------------------------------------------------------------------------------
1 | # -*- ruby -*-
2 | source 'https://supermarket.getchef.com'
3 |
4 | metadata
5 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/Gemfile:
--------------------------------------------------------------------------------
1 | source 'https://rubygems.org'
2 | # source 'https://ruby.taobao.org/'
3 |
4 | gem 'kitchen-digitalocean', '= 0.9.8'
5 | gem 'kitchen-docker', '= 2.6.0'
6 | gem 'kitchen-ec2', '= 1.3.2'
7 | gem 'kitchen-vagrant', '= 1.2.1'
8 |
9 | gem 'test-kitchen', '= 1.19.1'
10 |
11 | gem 'berkshelf', '= 6.3.1'
12 |
13 | gem 'foodcritic', '~> 4.0.0'
14 | gem 'rubocop', '~> 0.48.1'
15 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/README.md:
--------------------------------------------------------------------------------
1 | jenkins-demo Cookbook
2 | ================
3 | Setup and configure jenkins for mdm project
4 |
5 | KITCHEN_YAML=.kitchen.docker.yml kitchen test
6 | KITCHEN_YAML=.kitchen.vagrant.yml kitchen test
7 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/attributes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | default['jenkins_plugins'] = {
4 | 'thinBackup' => '1.9',
5 | 'slack' => '2.3'
6 | }
7 |
8 | default['jenkins_mdm']['buildrepo_dir'] = '/var/lib/jenkins/code'
9 | default['jenkins_mdm']['avoid_external_network'] = '1'
10 | default['jenkins_mdm']['data_rentention_days'] = '7'
11 |
12 | default['jenkins_mdm']['docker_daemon_ip'] = '172.17.0.1'
13 | default['jenkins_mdm']['install_devkit'] = '0'
14 |
15 | default['jenkins_mdm']['jenkins_jobs'] = 'TailLogfile'
16 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/metadata.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | name 'jenkins-demo'
4 | maintainer 'DennyZhang'
5 | maintainer_email 'contact@dennyzhang.com'
6 | license 'All rights reserved'
7 | description 'Setup and configure jenkins'
8 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
9 | version '0.0.1'
10 | source_url 'https://www.dennyzhang.com'
11 | issues_url 'https://www.dennyzhang.com'
12 |
13 | supports 'ubuntu', '>= 14.04'
14 | depends 'apt', '=2.6.1'
15 | depends 'java'
16 | depends 'jenkins', '=5.0.4'
17 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/recipes/conf_job.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: conf_job
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | node['jenkins_mdm']['jenkins_jobs'].split(',').each do |job_name|
13 | config = File.join(Chef::Config[:file_cache_path], "#{job_name}.xml")
14 |
15 | template config do
16 | source "#{job_name}.xml.erb"
17 | end
18 |
19 | # Create a jenkins job (default action is `:create`)
20 | jenkins_job job_name do
21 | config config
22 | end
23 | end
24 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/recipes/default.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: default
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | # TODO
13 | include_recipe 'jenkins-demo::master'
14 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/recipes/master.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | #
4 | # Cookbook Name:: jenkins-demo
5 | # Recipe:: master
6 | #
7 | # Copyright 2017, DennyZhang.com
8 | #
9 | # All rights reserved - Do Not Redistribute
10 | #
11 |
12 | apt_update 'update' if platform_family?('debian')
13 |
14 | node.default['java']['install_flavor'] = 'oracle'
15 | node.default['java']['jdk_version'] = '8'
16 | node.default['java']['set_etc_environment'] = true
17 | node.default['java']['oracle']['accept_oracle_download_terms'] = true
18 |
19 | include_recipe 'java::default'
20 | include_recipe 'jenkins::master'
21 |
22 | # Install some plugins needed, but not installed on jenkins2 by default
23 | node['jenkins_plugins'].each do |plugin|
24 | jenkins_plugin plugin[0] do
25 | version plugin[1]
26 | notifies :execute, 'jenkins_command[safe-restart]', :immediately
27 | end
28 | end
29 |
30 | jenkins_command 'safe-restart' do
31 | action :nothing
32 | end
33 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/templates/default/CollectFiles.xml.erb:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | -1
7 | 50
8 | -1
9 | -1
10 |
11 | false
12 |
13 |
14 |
15 |
16 | server_list
17 |
18 | <%= node['jenkins_mdm']['docker_daemon_ip'] %>:6022
19 |
20 |
21 | file_list
22 |
23 | /etc/hosts
24 | /opt/couchbase/etc/couchbase/static_config
25 | /opt/mdm/config/mdm.yml
26 | /opt/mdm/logs/mdm-initscript.log
27 | /opt/mdm/logs/mdm-app.log
28 | /opt/mdm/logs/mdm-app-audit.log
29 | /opt/mdm/logs/mdm-app-error.log
30 | /opt/mdm/logs/mdmbackup-initscript.log
31 | /etc/elasticsearch/elasticsearch.yml
32 | /var/log/elasticsearch/mdm.log
33 | /var/log/elasticsearch/mdm_index_indexing_slowlog.log
34 | /var/log/elasticsearch/mdm_deprecation.log
35 | /var/log/elasticsearch/mdm_index_search_slowlog.log
36 |
37 |
38 | env_parameters
39 |
40 | export jenkins_baseurl="http://192.168.50.10:18080"
41 |
42 |
43 |
44 |
45 |
46 |
47 | true
48 | false
49 | false
50 | false
51 |
52 | false
53 |
54 |
55 | #!/bin/bash -e
56 | export ssh_key_file="/var/lib/jenkins/ssh_id_rsa"
57 | bash -e /var/lib/jenkins/code/scripts/collect_files.sh
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/Scenario-401/cookbooks/jenkins-demo/test/integration/default/serverspec/server_spec.rb:
--------------------------------------------------------------------------------
1 | # -*- encoding: utf-8 -*-
2 |
3 | require 'serverspec'
4 |
5 | # Required by serverspec
6 | set :backend, :exec
7 |
8 | #############################################################################
9 | # TODO: make the code more general
10 | require 'json'
11 | # chef_data = JSON.parse(IO.read('/tmp/kitchen/dna.json'))
12 | # buildrepo_dir = chef_data.fetch('jenkins_mdm').fetch('buildrepo_dir')
13 |
14 | describe command('java -version') do
15 | its(:stderr) { should contain 'java version \"1.8' }
16 | end
17 |
18 | %w[8080].each do |port|
19 | describe port(port) do
20 | it { should be_listening }
21 | end
22 | end
23 |
--------------------------------------------------------------------------------
/images/chef_icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/chef_icon.png
--------------------------------------------------------------------------------
/images/scenario-101-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-101-screenshot.jpg
--------------------------------------------------------------------------------
/images/scenario-102-screenshot.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-102-screenshot.jpg
--------------------------------------------------------------------------------
/images/scenario-103-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-103-design.png
--------------------------------------------------------------------------------
/images/scenario-201-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-201-design.png
--------------------------------------------------------------------------------
/images/scenario-202-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-202-design.png
--------------------------------------------------------------------------------
/images/scenario-401-design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dennyzhang/challenges-chef/5e58a8153e7b98a3b9b7ad574591ac25b004267c/images/scenario-401-design.png
--------------------------------------------------------------------------------