├── recipes ├── create_enterprise.rb ├── delivery_license.rb ├── install_push_jobs.rb ├── create_delivered_env.rb ├── default.rb ├── install_build_nodes.rb ├── supermarket.rb ├── compliance_patch.rb ├── delivery.rb ├── compliance.rb ├── chef-server.rb └── save_secrets.rb ├── test ├── fixtures │ ├── secrets │ │ └── fakey-mcfakerton │ ├── cookbooks │ │ └── test │ │ │ ├── README.md │ │ │ ├── recipes │ │ │ ├── yum_update.rb │ │ │ ├── delivery_keys.rb │ │ │ ├── suse_connect.rb │ │ │ ├── replicate_opscode_analytics.rb │ │ │ ├── replicate_etc_opscode.rb │ │ │ ├── save_secrets_kitchen.rb │ │ │ ├── setup_ssh_keys.rb │ │ │ ├── hostsfile.rb │ │ │ ├── cookbook_upload.rb │ │ │ ├── example_org_and_user.rb │ │ │ ├── chef_server.rb │ │ │ ├── delivery_setup.rb │ │ │ ├── delivery_build_node.rb │ │ │ ├── delivery_node.rb │ │ │ ├── compliance_node.rb │ │ │ └── supermarket_node.rb │ │ │ ├── files │ │ │ └── default │ │ │ │ ├── delivery.license │ │ │ │ ├── insecure_public_key │ │ │ │ └── insecure_private_key │ │ │ ├── metadata.rb │ │ │ ├── Berksfile │ │ │ ├── templates │ │ │ └── default │ │ │ │ └── supermarket.json.erb │ │ │ ├── libraries │ │ │ └── _helper.rb │ │ │ ├── attributes │ │ │ └── default.rb │ │ │ └── Berksfile.lock │ └── data_bags │ │ ├── keys │ │ └── delivery_builder_keys.json │ │ └── automate │ │ └── automate.json └── integration │ ├── helpers │ └── serverspec │ │ └── spec_helper.rb │ └── default │ └── serverspec │ └── default_spec.rb ├── spec ├── spec_helper.rb └── unit │ └── recipes │ └── default_spec.rb ├── .rubocop.yml ├── files └── default │ ├── delivery.license │ ├── config.rb │ ├── git-ssh-wrapper │ ├── installer.sh │ └── delivery-cmd ├── .gitattributes ├── .gitignore ├── templates └── default │ ├── push-jobs-client-system-d │ ├── push-jobs-client-upstart │ ├── push-jobs-client.rb.erb │ └── push-jobs-client-rhel-6 ├── metadata.rb ├── Berksfile ├── libraries └── helper.rb ├── resources └── wait_for_server_startup.rb ├── Berksfile.lock ├── chefignore ├── attributes └── default.rb ├── .kitchen.yml └── README.md /recipes/create_enterprise.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /recipes/delivery_license.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /recipes/install_push_jobs.rb: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/secrets/fakey-mcfakerton: -------------------------------------------------------------------------------- 1 | hello -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/README.md: -------------------------------------------------------------------------------- 1 | This is a README 2 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'chefspec' 2 | require 'chefspec/berkshelf' 3 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/yum_update.rb: -------------------------------------------------------------------------------- 1 | execute 'yum update -y' 2 | -------------------------------------------------------------------------------- /test/fixtures/data_bags/keys/delivery_builder_keys.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "delivery_builder_keys" 3 | } -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/delivery_keys.rb: -------------------------------------------------------------------------------- 1 | 2 | include_recipe 'test::setup_ssh_keys' 3 | -------------------------------------------------------------------------------- /test/integration/helpers/serverspec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | require 'serverspec' 2 | 3 | set :backend, :exec 4 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | AllCops: 2 | Exclude: 3 | - 'test/**/*' 4 | - 'spec/**/*' 5 | Metrics/LineLength: 6 | Max: 120 7 | -------------------------------------------------------------------------------- /files/default/delivery.license: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephenlauck/chef-services/HEAD/files/default/delivery.license -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/suse_connect.rb: -------------------------------------------------------------------------------- 1 | execute 'SUSEConnect -r DE98C0808F7DD8 -e andy.k.dufour@gmail.com' 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Set the default behavior, in case people don't have core.autocrlf set. 2 | * text=auto 3 | 4 | *.sh text eol=lf 5 | *.license binary -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/files/default/delivery.license: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/stephenlauck/chef-services/HEAD/test/fixtures/cookbooks/test/files/default/delivery.license -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'test' 2 | version '0.0.1' 3 | 4 | depends 'hostsfile' 5 | depends 'chef-server-ctl' 6 | depends 'supermarket-omnibus-cookbook' 7 | depends 'ntp' 8 | depends 'fancy_execute' 9 | -------------------------------------------------------------------------------- /files/default/config.rb: -------------------------------------------------------------------------------- 1 | current_dir = File.dirname(__FILE__) 2 | eval(IO.read('/etc/chef/client.rb')) 3 | log_location STDOUT 4 | node_name "delivery" 5 | client_key "#{current_dir}/delivery.pem" 6 | trusted_certs_dir "/etc/chef/trusted_certs" 7 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/Berksfile: -------------------------------------------------------------------------------- 1 | source "https://supermarket.chef.io" 2 | 3 | metadata 4 | 5 | cookbook 'chef-services', path: '../../../../' 6 | cookbook 'chef-server-ctl', git: 'https://github.com/stephenlauck/chef-server-ctl.git' 7 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/replicate_opscode_analytics.rb: -------------------------------------------------------------------------------- 1 | 2 | include_recipe 'test::setup_ssh_keys' 3 | 4 | execute "scp -i /root/.ssh/insecure_private_key -o StrictHostKeyChecking=no -r root@chef.services.com:/etc/opscode-analytics /etc/" 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | *~ 3 | *# 4 | .#* 5 | \#*# 6 | .*.sw[a-z] 7 | *.un~ 8 | 9 | # Bundler 10 | Gemfile.lock 11 | bin/* 12 | .bundle/* 13 | 14 | .kitchen/ 15 | .kitchen.local.yml 16 | .kitchen.local* 17 | 18 | # Berks 19 | Berksfile.lock 20 | 21 | #Mac 22 | .DS_Store 23 | -------------------------------------------------------------------------------- /recipes/create_delivered_env.rb: -------------------------------------------------------------------------------- 1 | 2 | execute 'create delivered environment' do 3 | command 'knife environment create delivered -d "Delivered"' 4 | cwd "#{node['chef_server']['install_dir']}/chef_installer" 5 | environment 'PATH' => "/opt/chefdk/gitbin:#{ENV['PATH']}" 6 | end 7 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/replicate_etc_opscode.rb: -------------------------------------------------------------------------------- 1 | # replicate /etc/opscode from bootstrap backend to frontend server 2 | 3 | include_recipe 'test::setup_ssh_keys' 4 | 5 | execute "scp -i /root/.ssh/insecure_private_key -o StrictHostKeyChecking=no -r root@33.33.33.12:/etc/opscode /etc/" -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/templates/default/supermarket.json.erb: -------------------------------------------------------------------------------- 1 | { 2 | "chef_server_url": "<%= @chef_server_url %>", 3 | "chef_oauth2_app_id": "<%= @chef_oauth2_app_id %>", 4 | "chef_oauth2_secret": "<%= @chef_oauth2_secret %>", 5 | "chef_oauth2_verify_ssl": <%= @chef_oauth2_verify_ssl %> 6 | } -------------------------------------------------------------------------------- /templates/default/push-jobs-client-system-d: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Push Jobs Client 3 | After=network.target 4 | 5 | [Service] 6 | Type=simple 7 | ExecStart=/opt/chefdk/bin/pushy-client -l info -c /etc/chef/push-jobs-client.rb 8 | Restart=on-failure 9 | 10 | [Install] 11 | WantedBy=multi-user.target 12 | -------------------------------------------------------------------------------- /test/integration/default/serverspec/default_spec.rb: -------------------------------------------------------------------------------- 1 | require 'spec_helper' 2 | 3 | describe 'chef-services::default' do 4 | 5 | # Serverspec examples can be found at 6 | # http://serverspec.org/resource_types.html 7 | 8 | it 'does something' do 9 | skip 'Replace this with meaningful tests' 10 | end 11 | 12 | end -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | name 'chef-services' 2 | maintainer 'The Authors' 3 | maintainer_email 'you@example.com' 4 | license 'all_rights' 5 | description 'Installs/Configures chef-services' 6 | long_description 'Installs/Configures chef-services' 7 | version '5.2.0' 8 | 9 | depends 'fancy_execute' 10 | depends 'chef_stack' 11 | -------------------------------------------------------------------------------- /templates/default/push-jobs-client-upstart: -------------------------------------------------------------------------------- 1 | # push-jobs-client - the Chef Push Jobs client 2 | # 3 | # push-jobs-client is here! 4 | 5 | description "Chef Push Jobs Client" 6 | 7 | start on runlevel [2345] 8 | stop on runlevel [!2345] 9 | 10 | respawn 11 | 12 | exec env PATH=/opt/chefdk/bin:/opt/chefdk/embedded/bin:$PATH /opt/chefdk/bin/pushy-client -l info -c /etc/chef/push-jobs-client.rb > /var/log/push-jobs-client/current 2>&1 13 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/libraries/_helper.rb: -------------------------------------------------------------------------------- 1 | module Test 2 | module Helper 3 | 4 | def get_supermarket_attribute(attr) 5 | @supermarket ||= begin 6 | supermarket_file = File.read("/tmp/supermarket.json") 7 | JSON.parse(supermarket_file) 8 | end 9 | @supermarket[attr] 10 | end 11 | 12 | end 13 | end 14 | 15 | Chef::Recipe.send(:include, Test::Helper) 16 | Chef::Resource.send(:include, Test::Helper) -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: chef-services 3 | # Recipe:: default 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | directory '/tmp/chef_installer' 8 | 9 | cookbook_file '/tmp/chef_installer/installer.rb' do 10 | source 'installer.rb' 11 | end 12 | 13 | cookbook_file '/tmp/chef_installer/installer.sh' do 14 | source 'installer.sh' 15 | mode 0755 16 | end 17 | 18 | execute '/tmp/chef_installer/installer.sh' 19 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/files/default/insecure_public_key: -------------------------------------------------------------------------------- 1 | ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/save_secrets_kitchen.rb: -------------------------------------------------------------------------------- 1 | 2 | ruby_block 'save databag' do 3 | block do 4 | require 'json' 5 | databag_json = ::File.read("#{node['chef_server']['install_dir']}/chef_installer/data_bags/automate.json") 6 | 7 | databag_hash = JSON.parse(databag_json) 8 | 9 | automate_item = Chef::DataBagItem.new 10 | automate_item.data_bag('automate') 11 | automate_item.raw_data = databag_hash 12 | automate_item.save 13 | end 14 | end 15 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | source "https://supermarket.chef.io" 2 | 3 | metadata 4 | 5 | cookbook 'chef-server-ctl', git: 'https://github.com/stephenlauck/chef-server-ctl.git' 6 | cookbook 'supermarket-omnibus-cookbook', git: 'https://github.com/chef-cookbooks/supermarket-omnibus-cookbook.git' 7 | 8 | group :integration do 9 | cookbook 'test', path: './test/fixtures/cookbooks/test' 10 | end 11 | 12 | cookbook 'chef_stack', git: 'https://github.com/ncerny/chef_stack.git', branch: 'nc/modify-frozen-string' 13 | -------------------------------------------------------------------------------- /files/default/git-ssh-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Martin Emde 3 | # https://github.com/martinemde/git-ssh-wrapper 4 | 5 | unset SSH_AUTH_SOCK 6 | ssh -o CheckHostIP=no \ 7 | -o IdentitiesOnly=yes \ 8 | -o LogLevel=INFO \ 9 | -o StrictHostKeyChecking=no \ 10 | -o PasswordAuthentication=no \ 11 | -o UserKnownHostsFile=/var/opt/delivery/workspace/etc/delivery-git-ssh-known-hosts \ 12 | -o IdentityFile=/var/opt/delivery/workspace/etc/builder_key \ 13 | -l builder \ 14 | $* 15 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/attributes/default.rb: -------------------------------------------------------------------------------- 1 | default['delivery']['version'] = 'latest' 2 | default['delivery']['chef_server'] = 'https://chef.services.com/organizations/delivery' 3 | default['chef_server']['fqdn'] = nil 4 | default['compliance']['version'] = 'latest' 5 | default['compliance']['package_source'] = nil 6 | default['compliance']['channel'] = :stable 7 | default['compliance']['accept_license'] = false 8 | default['chef_automate']['fqdn'] = 'automate.services.com' 9 | default['chefdk']['bashrc'] = '/etc/bashrc' 10 | -------------------------------------------------------------------------------- /recipes/install_build_nodes.rb: -------------------------------------------------------------------------------- 1 | delivery_databag = data_bag_item('automate', 'automate') 2 | 3 | workflow_builder node['fqdn'] do 4 | accept_license true 5 | chef_user 'delivery' 6 | chef_user_pem delivery_databag['user_pem'] 7 | builder_pem delivery_databag['builder_pem'] 8 | chef_fqdn node['chef_server']['fqdn'] 9 | automate_fqdn node['chef_automate']['fqdn'] 10 | supermarket_fqdn 'supermarket.services.com' 11 | job_dispatch_version 'v2' 12 | automate_user 'admin' 13 | automate_password delivery_databag['automate_password'] 14 | automate_enterprise 'test' 15 | end 16 | -------------------------------------------------------------------------------- /spec/unit/recipes/default_spec.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: chef-services 3 | # Spec:: default 4 | # 5 | # Copyright (c) 2015 The Authors, All Rights Reserved. 6 | 7 | require 'spec_helper' 8 | 9 | describe 'chef-services::default' do 10 | 11 | context 'When all attributes are default, on an unspecified platform' do 12 | 13 | let(:chef_run) do 14 | runner = ChefSpec::ServerRunner.new 15 | runner.converge(described_recipe) 16 | end 17 | 18 | it 'converges successfully' do 19 | chef_run # This should not raise an error 20 | end 21 | 22 | end 23 | end 24 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/setup_ssh_keys.rb: -------------------------------------------------------------------------------- 1 | # set up shared vagrant keys in order to copy files across chef services 2 | 3 | directory '/root/.ssh' do 4 | action :create 5 | owner 'root' 6 | group 'root' 7 | mode '0700' 8 | end 9 | 10 | cookbook_file '/root/.ssh/insecure_private_key' do 11 | action :create 12 | owner 'root' 13 | group 'root' 14 | mode '0600' 15 | source 'insecure_private_key' 16 | end 17 | 18 | cookbook_file '/root/.ssh/authorized_keys' do 19 | action :create 20 | owner 'root' 21 | group 'root' 22 | mode '0600' 23 | source 'insecure_public_key' 24 | end 25 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/hostsfile.rb: -------------------------------------------------------------------------------- 1 | include_recipe 'ntp' 2 | 3 | hostsfile_entry '33.33.33.10' do 4 | hostname 'chef.services.com' 5 | unique true 6 | end 7 | 8 | hostsfile_entry '33.33.33.11' do 9 | hostname 'automate.services.com' 10 | unique true 11 | end 12 | 13 | hostsfile_entry '33.33.33.12' do 14 | hostname 'build.services.com' 15 | unique true 16 | end 17 | 18 | hostsfile_entry '33.33.33.13' do 19 | hostname 'supermarket.services.com' 20 | unique true 21 | end 22 | 23 | hostsfile_entry '33.33.33.14' do 24 | hostname 'compliance.services.com' 25 | unique true 26 | end 27 | -------------------------------------------------------------------------------- /recipes/supermarket.rb: -------------------------------------------------------------------------------- 1 | delivery_databag = data_bag_item('automate', 'automate') 2 | 3 | user 'supermarket' do 4 | group 'supermarket' 5 | only_if { node['platform'].eql?('suse') } 6 | end 7 | 8 | chef_supermarket 'supermarket.services.com' do 9 | chef_server_url "https://#{node['chef_server']['fqdn']}" 10 | chef_oauth2_app_id delivery_databag['supermarket_oauth2_app_id'] 11 | chef_oauth2_secret delivery_databag['supermarket_oauth2_secret'] 12 | chef_oauth2_verify_ssl node['chef-supermarket']['supermarket']['verify_ssl'] 13 | config node['chef-services']['supermarket']['config'] 14 | accept_license node['chef-services']['accept_license'] 15 | end 16 | -------------------------------------------------------------------------------- /templates/default/push-jobs-client.rb.erb: -------------------------------------------------------------------------------- 1 | # File managed by Chef. Do not modify. 2 | 3 | chef_server_url "https://<%= node['chef_server']['fqdn'] %>/organizations/delivery" 4 | 5 | allow_unencrypted true 6 | 7 | # Chef server connect options 8 | 9 | node_name "<%= @node_name %>" 10 | trusted_certs_dir "/etc/chef/trusted_certs" 11 | verify_api_cert true 12 | ssl_verify_mode :verify_peer 13 | whitelist({"chef-client"=>"chef-client", 14 | /^delivery-cmd (.+)$/=>"/var/opt/delivery/workspace/bin/delivery-cmd '\\1'"}) 15 | 16 | # NOTE - if we settle on a daemon provider that captures and timestamps logs, 17 | # set this to 'false' to avoid duplicated timestamps in the logs. 18 | Mixlib::Log::Formatter.show_time = true 19 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/cookbook_upload.rb: -------------------------------------------------------------------------------- 1 | 2 | file '/tmp/config.rb' do 3 | content <<-EOF 4 | log_level :info 5 | log_location STDOUT 6 | node_name "delivery" 7 | client_key "/tmp/delivery.pem" 8 | validation_client_name "delivery-validator" 9 | validation_key "/tmp/delivery-validator.pem" 10 | chef_server_url "https://chef.services.com/organizations/delivery" 11 | cookbook_path ["/tmp/kitchen/cookbooks"] 12 | EOF 13 | end 14 | 15 | execute 'knife ssl fetch -c /tmp/config.rb' 16 | 17 | # execute 'knife upload cookbooks data_bags --chef-repo-path . -c ../config.rb' do 18 | execute 'knife cookbook upload -a cookbooks -c ../config.rb && knife upload data_bags --chef-repo-path . -c ../config.rb' do 19 | cwd '/tmp/kitchen' 20 | end 21 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/example_org_and_user.rb: -------------------------------------------------------------------------------- 1 | execute 'chef-server-ctl restart' do 2 | action :nothing 3 | end 4 | 5 | cache_path = Chef::Config[:file_cache_path] 6 | 7 | file "#{cache_path}/chef-server-core.restart" do 8 | action :create 9 | notifies :run, 'execute[chef-server-ctl restart]', :immediately 10 | not_if do ::File.exists?("#{cache_path}/chef-server-core.restart") end 11 | end 12 | 13 | chef_server_user 'testuser' do 14 | firstname 'Test' 15 | lastname 'User' 16 | email 'testuser@services.com' 17 | password 'testuser' 18 | private_key_path '/tmp/testuser.pem' 19 | action :create 20 | end 21 | 22 | chef_server_org 'example' do 23 | org_long_name 'Example Organization' 24 | org_private_key_path '/tmp/example-validator.pem' 25 | action :create 26 | end 27 | 28 | chef_server_org 'example' do 29 | admins %w{ testuser } 30 | action :add_admin 31 | end 32 | -------------------------------------------------------------------------------- /libraries/helper.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | 3 | def get_node_name_from_config 4 | node_line = File.foreach('/etc/chef/client.rb').grep(/^node_name/).last 5 | node_line.split(" ").last.gsub!(/\"|\\/, '') 6 | end 7 | 8 | def get_product_info(project, version, platform = node['platform'], platform_version = node['platform_version'], omnitruck_url = 'omnitruck.chef.io', channel = 'stable', arch="x86_64") 9 | pv = (node['platform'].eql?('ubuntu') ? node['platform_version'].delete('.') : node['platform_version'].to_i) 10 | url = URI.parse("http://#{omnitruck_url}/#{channel}/#{project}/metadata?p=#{platform}&pv=#{pv}&m=#{arch}&v=#{version}") 11 | request = Net::HTTP.new(url.host, url.port) 12 | res = request.get(url) 13 | dl_info = res.body.split("\n").map do |resource| 14 | resource = resource.split("\t") 15 | end 16 | dl_info = dl_info.to_h 17 | dl_info['name'] = File.basename(dl_info['url']) 18 | dl_info 19 | end 20 | -------------------------------------------------------------------------------- /resources/wait_for_server_startup.rb: -------------------------------------------------------------------------------- 1 | resource_name :wait_for_server_startup 2 | provides :wait_for_server_startup 3 | 4 | action :create do 5 | wait_for_server_startup 6 | end 7 | 8 | action_class do 9 | def wait_for_server_startup 10 | Chef::Log.info('Waiting for the Chef server to be ready') 11 | attempts = 90 12 | STDOUT.sync = true 13 | (0..attempts).each do |attempt| 14 | break if erchef_ready? 15 | sleep 1 16 | print '.' 17 | if attempt == attempts 18 | raise "Gave up waiting for the Chef server to be ready after #{attempt} attempts" 19 | end 20 | end 21 | end 22 | 23 | def erchef_ready? 24 | require 'open-uri' 25 | require 'openssl' 26 | require 'json' 27 | 28 | begin 29 | server_status = JSON.parse(open('https://localhost/_status', ssl_verify_mode: OpenSSL::SSL::VERIFY_NONE).read) 30 | rescue Exception 31 | return false 32 | end 33 | 34 | return true if server_status['status'] == 'pong' 35 | false 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/Berksfile.lock: -------------------------------------------------------------------------------- 1 | DEPENDENCIES 2 | chef-server-ctl 3 | git: https://github.com/stephenlauck/chef-server-ctl.git 4 | revision: 55bfa054f9d5cda86f1a96b28b5ccaddbec7a69d 5 | chef-services 6 | path: ../../../.. 7 | test 8 | path: . 9 | metadata: true 10 | 11 | GRAPH 12 | chef-ingredient (0.21.0) 13 | compat_resource (>= 12.10) 14 | chef-server (5.1.0) 15 | chef-ingredient (>= 0.18.0) 16 | chef-server-ctl (0.1.0) 17 | chef-server (>= 0.0.0) 18 | chef-services (2.0.5) 19 | chef-ingredient (>= 0.0.0) 20 | chef-server-ctl (>= 0.0.0) 21 | fancy_execute (>= 0.0.0) 22 | ntp (>= 0.0.0) 23 | compat_resource (12.14.7) 24 | fancy_execute (1.0.2) 25 | hostsfile (2.4.5) 26 | ntp (3.2.0) 27 | supermarket-omnibus-cookbook (2.0.0) 28 | chef-ingredient (>= 0.19.0) 29 | compat_resource (>= 12.14) 30 | fancy_execute (>= 0.0.0) 31 | hostsfile (>= 0.0.0) 32 | test (0.0.1) 33 | chef-ingredient (>= 0.0.0) 34 | chef-server-ctl (>= 0.0.0) 35 | hostsfile (>= 0.0.0) 36 | supermarket-omnibus-cookbook (>= 0.0.0) 37 | -------------------------------------------------------------------------------- /recipes/compliance_patch.rb: -------------------------------------------------------------------------------- 1 | # create a basic patch level scan compliance profile role and upload to chef-server 2 | directory "#{node['chef_server']['install_dir']}/chef_installer/roles/" do 3 | action :create 4 | recursive true 5 | end 6 | 7 | file "#{node['chef_server']['install_dir']}/chef_installer/roles/patch.json" do 8 | content <<-EOD 9 | { 10 | "name": "patch", 11 | "description": "", 12 | "json_class": "Chef::Role", 13 | "default_attributes": { 14 | "audit": { 15 | "collector": "chef-server-visibility", 16 | "profiles": [ 17 | { 18 | "name": "dev-sec/linux-patch-benchmark", 19 | "url": "https://github.com/dev-sec/linux-patch-benchmark" 20 | } 21 | ] 22 | }, 23 | "chef-client": { 24 | "interval": "300" 25 | } 26 | }, 27 | "chef_type": "role", 28 | "run_list": [ 29 | "recipe[chef-client]", 30 | "recipe[audit]" 31 | ] 32 | } 33 | EOD 34 | end 35 | 36 | execute 'upload roles' do 37 | command 'knife upload roles' 38 | cwd "#{node['chef_server']['install_dir']}/chef_installer" 39 | environment 'PATH' => "/opt/chefdk/gitbin:#{ENV['PATH']}" 40 | end 41 | -------------------------------------------------------------------------------- /recipes/delivery.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: test 3 | # Recipe:: delivery 4 | # 5 | # Copyright (c) 2016 The Authors, All Rights Reserved. 6 | 7 | delivery_databag = data_bag_item('automate', 'automate') 8 | 9 | chef_automate node['chef_automate']['fqdn'] do 10 | chef_user 'delivery' 11 | chef_user_pem delivery_databag['user_pem'] 12 | validation_pem delivery_databag['validator_pem'] 13 | builder_pem delivery_databag['builder_pem'] 14 | config node['delivery']['config'] 15 | enterprise 'test' 16 | license 'cookbook_file://chef-services::delivery.license' 17 | accept_license node['chef-services']['accept_license'] 18 | notifies :run, 'ruby_block[add automate password to databag]', :immediately 19 | end 20 | 21 | ruby_block 'add automate password to databag' do 22 | block do 23 | delivery_databag['automate_password'] = ::File.read('/etc/delivery/test.creds')[/Admin password: (?.*)$/, 'pw'] 24 | 25 | @chef_rest = Chef::ServerAPI.new( 26 | Chef::Config[:chef_server_url], 27 | { 28 | client_name: 'delivery', 29 | signing_key_filename: '/etc/delivery/delivery.pem' 30 | } 31 | ) 32 | 33 | @chef_rest.put('data/automate/automate', delivery_databag) 34 | end 35 | action :nothing 36 | end 37 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/chef_server.rb: -------------------------------------------------------------------------------- 1 | remote_file '/tmp/installer.sh' do 2 | source 'file:///tmp/kitchen/cookbooks/chef-services/files/default/installer.sh' 3 | mode 0755 4 | end 5 | 6 | execute 'install Chef server' do 7 | command "./installer.sh -c chef.services.com -cs-source \"path: '/tmp/kitchen/cookbooks/chef-services'\"" 8 | cwd '/tmp' 9 | action :run 10 | end 11 | 12 | file '/tmp/pre-delivery-validator.pub' do 13 | content <<-eos 14 | -----BEGIN PUBLIC KEY----- 15 | MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuK094FPDVk8YgRxNyCsz 16 | fpMwuoLinQGbDtHUtiqodVrJk5Q8PYN7f8K5tM61tPMv0VduCDahm7LXOLk/SWgI 17 | lBFdBurrwMeIsRhoqohtsUW2qhaKSX6dhPjWjFAwP1C8WqjL9xuyWTMjS6hF2w6+ 18 | za43OLvV+srnoBPIcRDWqr/76IbO1RO+fgw1cX4FBPHp+rdJI/BjkufSQNGEQuWa 19 | QDYv7ZGgCBgb0xtOEARlHZUWBCjcW6apMo6jKnOCEqvheN6PboSYXAITwueLdGB7 20 | COOJxa9h3vZYI9jFqUKMMV/kTCls5KlnxI0ATDTeZ4Y9KASNISQQA0Sv0i1R28Oy 21 | +wIDAQAB 22 | -----END PUBLIC KEY----- 23 | eos 24 | end 25 | 26 | execute 'add delivery validator' do 27 | command 'chef-server-ctl add-client-key delivery delivery-validator --public-key-path /tmp/pre-delivery-validator.pub --key-name delivery-pub' 28 | action :run 29 | not_if 'chef-server-ctl list-client-keys delivery delivery-validator | grep delivery-pub' 30 | end 31 | -------------------------------------------------------------------------------- /Berksfile.lock: -------------------------------------------------------------------------------- 1 | DEPENDENCIES 2 | chef-server-ctl 3 | git: https://github.com/stephenlauck/chef-server-ctl.git 4 | revision: 55bfa054f9d5cda86f1a96b28b5ccaddbec7a69d 5 | chef-services 6 | path: . 7 | metadata: true 8 | chef_stack 9 | git: https://github.com/ncerny/chef_stack.git 10 | revision: 8e96c1d6adea13f8e580608d3a18c2fe6fca61f0 11 | branch: nc/modify-frozen-string 12 | supermarket-omnibus-cookbook 13 | git: https://github.com/chef-cookbooks/supermarket-omnibus-cookbook.git 14 | revision: f03dd57d0a054cb5960d03873ef03bbd1c648705 15 | test 16 | path: test/fixtures/cookbooks/test 17 | 18 | GRAPH 19 | chef-ingredient (1.1.0) 20 | chef-server (5.4.0) 21 | chef-ingredient (~> 1.1) 22 | chef-server-ctl (0.1.0) 23 | chef-server (>= 0.0.0) 24 | chef-services (5.1.1) 25 | chef_stack (>= 0.0.0) 26 | fancy_execute (>= 0.0.0) 27 | chef_stack (0.8.6) 28 | chef-ingredient (>= 0.0.0) 29 | fancy_execute (2.0.0) 30 | hostsfile (2.4.5) 31 | ntp (3.3.1) 32 | supermarket-omnibus-cookbook (3.0.0) 33 | chef-ingredient (>= 1.1.0) 34 | hostsfile (>= 0.0.0) 35 | test (0.0.1) 36 | chef-server-ctl (>= 0.0.0) 37 | fancy_execute (>= 0.0.0) 38 | hostsfile (>= 0.0.0) 39 | ntp (>= 0.0.0) 40 | supermarket-omnibus-cookbook (>= 0.0.0) 41 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/delivery_setup.rb: -------------------------------------------------------------------------------- 1 | 2 | chef_server_user 'delivery' do 3 | firstname 'Delivery' 4 | lastname 'User' 5 | email 'delivery@services.com' 6 | password 'delivery' 7 | private_key_path '/tmp/delivery.pem' 8 | action :create 9 | end 10 | 11 | chef_server_org 'delivery' do 12 | org_long_name 'Chef Delivery Organization' 13 | org_private_key_path '/tmp/delivery-validator.pem' 14 | action :create 15 | end 16 | 17 | chef_server_org 'delivery' do 18 | admins %w{ delivery } 19 | action :add_admin 20 | end 21 | 22 | file '/tmp/config.rb' do 23 | content <<-EOF 24 | log_level :info 25 | log_location STDOUT 26 | node_name "delivery" 27 | client_key "/tmp/delivery.pem" 28 | validation_client_name "delivery-validator" 29 | validation_key "/tmp/delivery-validator.pem" 30 | chef_server_url "https://chef.services.com/organizations/delivery" 31 | cookbook_path ["/tmp/kitchen/cookbooks"] 32 | EOF 33 | end 34 | 35 | execute 'knife ssl fetch -c /tmp/config.rb' 36 | 37 | # execute 'knife upload cookbooks data_bags --chef-repo-path . -c ../config.rb' do 38 | execute 'knife cookbook upload -a cookbooks -c ../config.rb && knife upload data_bags --chef-repo-path . -c ../config.rb' do 39 | cwd '/tmp/kitchen' 40 | end 41 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # or sharing to the community site. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | Icon? 9 | nohup.out 10 | ehthumbs.db 11 | Thumbs.db 12 | 13 | # SASS # 14 | ######## 15 | .sass-cache 16 | 17 | # EDITORS # 18 | ########### 19 | \#* 20 | .#* 21 | *~ 22 | *.sw[a-z] 23 | *.bak 24 | REVISION 25 | TAGS* 26 | tmtags 27 | *_flymake.* 28 | *_flymake 29 | *.tmproj 30 | .project 31 | .settings 32 | mkmf.log 33 | 34 | ## COMPILED ## 35 | ############## 36 | a.out 37 | *.o 38 | *.pyc 39 | *.so 40 | *.com 41 | *.class 42 | *.dll 43 | *.exe 44 | */rdoc/ 45 | 46 | # Testing # 47 | ########### 48 | .watchr 49 | .rspec 50 | spec/* 51 | spec/fixtures/* 52 | test/* 53 | features/* 54 | Guardfile 55 | Procfile 56 | 57 | # SCM # 58 | ####### 59 | .git 60 | */.git 61 | .gitignore 62 | .gitmodules 63 | .gitconfig 64 | .gitattributes 65 | .svn 66 | */.bzr/* 67 | */.hg/* 68 | */.svn/* 69 | 70 | # Berkshelf # 71 | ############# 72 | Berksfile 73 | Berksfile.lock 74 | cookbooks/* 75 | tmp 76 | 77 | # Cookbooks # 78 | ############# 79 | CONTRIBUTING 80 | 81 | # Strainer # 82 | ############ 83 | Colanderfile 84 | Strainerfile 85 | .colander 86 | .strainer 87 | 88 | # Vagrant # 89 | ########### 90 | .vagrant 91 | Vagrantfile 92 | 93 | # Travis # 94 | ########## 95 | .travis.yml 96 | -------------------------------------------------------------------------------- /recipes/compliance.rb: -------------------------------------------------------------------------------- 1 | 2 | remote_file "compliance package" do 3 | path "#{node['chef_server']['install_dir']}/#{::File.basename(node['compliance']['package_url'])}" 4 | source node['compliance']['package_url'] 5 | only_if { node['compliance']['package_url'] } 6 | end 7 | 8 | chef_ingredient "compliance" do 9 | config node['compliance']['config'] if node['compliance']['config'] 10 | package_source "#{node['chef_server']['install_dir']}/#{::File.basename(node['compliance']['package_url'])}" if node['compliance']['package_url'] 11 | accept_license node['chef-services']['accept_license'] 12 | action [:upgrade,:reconfigure] 13 | end 14 | 15 | ingredient_config "compliance" do 16 | notifies :reconfigure, "chef_ingredient[compliance]", :immediately 17 | end 18 | 19 | # Extra steps needed for SuSE 20 | 21 | if node['platform'] == 'suse' 22 | 23 | user 'chef-compliance' do 24 | group 'chef-compliance' 25 | action :manage 26 | end 27 | 28 | user 'chef-pgsql' do 29 | group 'chef-compliance' 30 | action :manage 31 | end 32 | 33 | user 'dex-worker' do 34 | group 'dex-worker' 35 | action :manage 36 | end 37 | 38 | user 'dex-overlord' do 39 | group 'dex-overlord' 40 | action :manage 41 | end 42 | 43 | file '/etc/chef-compliance/server-config.json' do 44 | owner 'chef-compliance' 45 | end 46 | 47 | execute 'chown core' do 48 | command 'chown -R chef-compliance.chef-compliance /var/opt/chef-compliance/core' 49 | action :run 50 | end 51 | 52 | execute 'restart chef-compliance' do 53 | command 'chef-compliance-ctl restart' 54 | end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /recipes/chef-server.rb: -------------------------------------------------------------------------------- 1 | chef_server node['chef_server']['fqdn'] do 2 | version :latest 3 | config <<-EOS 4 | api_fqdn '#{node['chef_server']['fqdn']}' 5 | 6 | oc_id['applications'] = { 7 | "supermarket"=>{"redirect_uri"=>"https://supermarket.services.com/auth/chef_oauth2/callback"} 8 | } 9 | 10 | profiles['root_url'] = 'https://automate.services.com' 11 | EOS 12 | addons manage: { version: '2.4.3', config: '' }, 13 | :"push-jobs-server" => { version: '2.1.0', config: '' } 14 | accept_license true 15 | data_collector_url 'https://automate.services.com/data-collector/v0/' 16 | end 17 | 18 | chef_user 'delivery' do 19 | first_name 'Delivery' 20 | last_name 'User' 21 | email 'delivery@services.com' 22 | password 'delivery' 23 | key_path "#{node['chef_server']['install_dir']}/delivery.pem" 24 | end 25 | 26 | chef_org 'delivery' do 27 | org_full_name 'Delivery Organization' 28 | key_path "#{node['chef_server']['install_dir']}/delivery-validator.pem" 29 | admins %w( delivery ) 30 | end 31 | 32 | directory "#{node['chef_server']['install_dir']}/chef_installer/.chef/cache" do 33 | recursive true 34 | end 35 | 36 | chef_client node['chef_server']['fqdn'] do 37 | chef_server_url "https://#{node['chef_server']['fqdn']}/organizations/delivery" 38 | validation_client_name 'delivery-validator' 39 | validation_pem "file://#{node['chef_server']['install_dir']}/delivery-validator.pem" 40 | config "file_cache_path '#{node['chef_server']['install_dir']}/chef_installer/.chef/cache'" 41 | ssl_verify false 42 | run_list [ 43 | "role[patch]", 44 | "recipe[chef-services::chef-server]" 45 | ] 46 | end 47 | 48 | include_recipe 'chef-services::save_secrets' 49 | include_recipe 'chef-services::compliance_patch' 50 | include_recipe 'chef-services::create_delivered_env' 51 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/files/default/insecure_private_key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIEogIBAAKCAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzI 3 | w+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoP 4 | kcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2 5 | hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NO 6 | Td0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcW 7 | yLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQIBIwKCAQEA4iqWPJXtzZA68mKd 8 | ELs4jJsdyky+ewdZeNds5tjcnHU5zUYE25K+ffJED9qUWICcLZDc81TGWjHyAqD1 9 | Bw7XpgUwFgeUJwUlzQurAv+/ySnxiwuaGJfhFM1CaQHzfXphgVml+fZUvnJUTvzf 10 | TK2Lg6EdbUE9TarUlBf/xPfuEhMSlIE5keb/Zz3/LUlRg8yDqz5w+QWVJ4utnKnK 11 | iqwZN0mwpwU7YSyJhlT4YV1F3n4YjLswM5wJs2oqm0jssQu/BT0tyEXNDYBLEF4A 12 | sClaWuSJ2kjq7KhrrYXzagqhnSei9ODYFShJu8UWVec3Ihb5ZXlzO6vdNQ1J9Xsf 13 | 4m+2ywKBgQD6qFxx/Rv9CNN96l/4rb14HKirC2o/orApiHmHDsURs5rUKDx0f9iP 14 | cXN7S1uePXuJRK/5hsubaOCx3Owd2u9gD6Oq0CsMkE4CUSiJcYrMANtx54cGH7Rk 15 | EjFZxK8xAv1ldELEyxrFqkbE4BKd8QOt414qjvTGyAK+OLD3M2QdCQKBgQDtx8pN 16 | CAxR7yhHbIWT1AH66+XWN8bXq7l3RO/ukeaci98JfkbkxURZhtxV/HHuvUhnPLdX 17 | 3TwygPBYZFNo4pzVEhzWoTtnEtrFueKxyc3+LjZpuo+mBlQ6ORtfgkr9gBVphXZG 18 | YEzkCD3lVdl8L4cw9BVpKrJCs1c5taGjDgdInQKBgHm/fVvv96bJxc9x1tffXAcj 19 | 3OVdUN0UgXNCSaf/3A/phbeBQe9xS+3mpc4r6qvx+iy69mNBeNZ0xOitIjpjBo2+ 20 | dBEjSBwLk5q5tJqHmy/jKMJL4n9ROlx93XS+njxgibTvU6Fp9w+NOFD/HvxB3Tcz 21 | 6+jJF85D5BNAG3DBMKBjAoGBAOAxZvgsKN+JuENXsST7F89Tck2iTcQIT8g5rwWC 22 | P9Vt74yboe2kDT531w8+egz7nAmRBKNM751U/95P9t88EDacDI/Z2OwnuFQHCPDF 23 | llYOUI+SpLJ6/vURRbHSnnn8a/XG+nzedGH5JGqEJNQsz+xT2axM0/W/CRknmGaJ 24 | kda/AoGANWrLCz708y7VYgAtW2Uf1DPOIYMdvo6fxIB5i9ZfISgcJ/bbCUkFrhoH 25 | +vq/5CIWxCPp0f85R4qxxQ5ihxJ0YDQT9Jpx4TMss4PSavPaBH3RXow5Ohe+bYoQ 26 | NE5OgEXk2wVfZczCZpigBKbKZHNYcelXtTt/nP3rsCuGcM4h53s= 27 | -----END RSA PRIVATE KEY----- 28 | -------------------------------------------------------------------------------- /templates/default/push-jobs-client-rhel-6: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # push-jobs-client 4 | # 5 | # chkconfig: 345 70 30 6 | # description: The Chef Push Jobs client 7 | # processname: push-jobs-client 8 | 9 | 10 | # source common function library 11 | . /etc/init.d/functions 12 | 13 | # Source networking configuration. 14 | . /etc/sysconfig/network 15 | 16 | # Check that networking is up. 17 | [ "$NETWORKING" = "no" ] && exit 0 18 | 19 | PATH=/opt/chefdk/bin:/opt/chefdk/embedded/bin:$PATH 20 | lockfile=/var/lock/subsys/push-jobs-client 21 | pushclient=/opt/chefdk/bin/pushy-client 22 | prog=$(basename $pushclient) 23 | 24 | start() { 25 | echo -n "Starting Push Jobs Client" 26 | # daemon lives in 'functions' 27 | daemon $pushclient -l info -c /etc/chef/push-jobs-client.rb > /var/log/push-jobs-client/current 2>&1 & 28 | retval=$? 29 | echo 30 | [ $retval -eq 0 ] && touch $lockfile 31 | return $retval 32 | } 33 | 34 | stop() { 35 | echo -n "Terminating Push Jobs Client" 36 | # killproc lives in 'functions' 37 | killproc $prog -QUIT 38 | retval=$? 39 | echo 40 | [ $retval -eq 0 ] && rm -f $lockfile 41 | return $retval 42 | } 43 | 44 | restart() { 45 | stop 46 | start 47 | } 48 | 49 | reload() { 50 | echo "Reloading Push Jobs Client Configuration" 51 | echo -n "Reload not supported, use restart" 52 | killproc $prog -USR1 53 | } 54 | 55 | force_reload() { 56 | restart 57 | } 58 | 59 | rh_status() { 60 | status $prog 61 | } 62 | 63 | rh_status_q() { 64 | rh_status >/dev/null 2>&1 65 | } 66 | 67 | case "$1" in 68 | start) 69 | # only start if not running 70 | rh_status_q && exit 0 71 | $1 72 | ;; 73 | stop) 74 | # only stop if running 75 | rh_status_q || exit 0 76 | $1 77 | ;; 78 | restart|configtest) 79 | $1 80 | ;; 81 | reload) 82 | rh_status_q || exit 7 83 | $1 84 | ;; 85 | force-reload) 86 | force_reload 87 | ;; 88 | status) 89 | rh_status 90 | ;; 91 | condrestart|try-restart) 92 | rh_status_q || exit 0 93 | ;; 94 | *) 95 | echo $"Usage: $0 {start|stop|status|restartcondrestart|try-restart|reload|force-reload}" 96 | exit 2 97 | esac 98 | -------------------------------------------------------------------------------- /recipes/save_secrets.rb: -------------------------------------------------------------------------------- 1 | #TODO: Replace with chef vault or similar. Non-encrypted databags == bad. 2 | require 'json' 3 | require 'net/ssh' 4 | require 'base64' 5 | 6 | directory "#{node['chef_server']['install_dir']}/chef_installer/.chef/" do 7 | action :create 8 | recursive true 9 | end 10 | 11 | file "#{node['chef_server']['install_dir']}/chef_installer/.chef/knife.rb" do 12 | content " 13 | node_name \"delivery\" 14 | client_key \"#{node['chef_server']['install_dir']}/delivery.pem\" 15 | chef_server_url \"https://#{node['chef_server']['fqdn']}/organizations/delivery\" 16 | cookbook_path [\"#{node['chef_server']['install_dir']}/chef_installer/cookbooks\"] 17 | ssl_verify_mode :verify_none 18 | validation_key \"/nonexist\" 19 | " 20 | end 21 | automate_db = begin 22 | data_bag('automate') 23 | rescue Net::HTTPServerException, Chef::Exceptions::InvalidDataBagPath 24 | nil # empty array for length comparison 25 | end 26 | 27 | unless automate_db 28 | builder_key = OpenSSL::PKey::RSA.new(2048) 29 | 30 | directory "#{node['chef_server']['install_dir']}/chef_installer/data_bags" 31 | 32 | ruby_block 'write_automate_databag' do 33 | block do 34 | supermarket_ocid = JSON.parse(::File.read('/etc/opscode/oc-id-applications/supermarket.json')) 35 | 36 | automate_db_item = { 37 | 'id' => 'automate', 38 | 'validator_pem' => ::File.read("#{node['chef_server']['install_dir']}/delivery-validator.pem"), 39 | 'user_pem' => ::File.read("#{node['chef_server']['install_dir']}/delivery.pem"), 40 | 'builder_pem' => builder_key.to_pem, 41 | 'builder_pub' => "ssh-rsa #{[builder_key.to_blob].pack('m0')}", 42 | 'supermarket_oauth2_app_id' => supermarket_ocid['uid'], 43 | 'supermarket_oauth2_secret' => supermarket_ocid['secret'] 44 | } 45 | ::File.write("#{node['chef_server']['install_dir']}/chef_installer/data_bags/automate.json", automate_db_item.to_json) 46 | chef_server_install_dir = '/tmp/chef_installer' 47 | end 48 | not_if { ::File.exist?("#{node['chef_server']['install_dir']}/chef_installer/data_bags/automate.json") } 49 | end 50 | 51 | execute 'upload databag' do 52 | command 'knife data bag create automate;knife data bag from file automate data_bags/automate.json' 53 | cwd "#{node['chef_server']['install_dir']}/chef_installer" 54 | environment 'PATH' => "/opt/chefdk/gitbin:#{ENV['PATH']}" 55 | end 56 | 57 | end 58 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/delivery_build_node.rb: -------------------------------------------------------------------------------- 1 | directory '/etc/chef' 2 | 3 | file '/etc/chef/client.rb' do 4 | content <<-EOF 5 | node_name "build.services.com" 6 | log_level :info 7 | log_location STDOUT 8 | validation_client_name "delivery-validator" 9 | validation_key "/etc/chef/delivery-validator.pem" 10 | chef_server_url "https://chef.services.com/organizations/delivery" 11 | encrypted_data_bag_secret "/tmp/kitchen/encrypted_data_bag_secret" 12 | trusted_certs_dir "/etc/chef/trusted_certs" 13 | EOF 14 | end 15 | 16 | file '/etc/chef/delivery-validator.pem' do 17 | content <<-eos 18 | -----BEGIN RSA PRIVATE KEY----- 19 | MIIEowIBAAKCAQEAuK094FPDVk8YgRxNyCszfpMwuoLinQGbDtHUtiqodVrJk5Q8 20 | PYN7f8K5tM61tPMv0VduCDahm7LXOLk/SWgIlBFdBurrwMeIsRhoqohtsUW2qhaK 21 | SX6dhPjWjFAwP1C8WqjL9xuyWTMjS6hF2w6+za43OLvV+srnoBPIcRDWqr/76IbO 22 | 1RO+fgw1cX4FBPHp+rdJI/BjkufSQNGEQuWaQDYv7ZGgCBgb0xtOEARlHZUWBCjc 23 | W6apMo6jKnOCEqvheN6PboSYXAITwueLdGB7COOJxa9h3vZYI9jFqUKMMV/kTCls 24 | 5KlnxI0ATDTeZ4Y9KASNISQQA0Sv0i1R28Oy+wIDAQABAoIBAGSRaxXDZ6eTsSt2 25 | J2FvLT6rlyiqaA/KNQ9v8x80wcIOq6EjY164QEPF3e15d/hPSmX8752naoBods2c 26 | C7vE3I8NmZRP0AyOXIDcYvsjCmE0LpIXbj0xp0QnYmbMsEl6hOf17gTmX0w2De2A 27 | eHIfaIaHbekGWTOW1WYV/9yap9wZfYS4zDtES5LX+wTakxHV3Dl1XTTVzkhebrBg 28 | t7v7bpM37CuCAXNM6SWQkfZ1Rt8sDdvteKmIJhlkNfSaH9ofS8RnJqCdHqSm8frN 29 | EkqfIJ9yRXsRgXlINSsGH/zoBuCxt6pkdFPpOU5K4pJ4HxJAOzqkLnaO87PqABmA 30 | 1MIhdTECgYEA33G2N/M1P5IUnYsq91eWqH8W1voTrhaLHAWOiiqz7EGL5efXxmuR 31 | YbEOJbLw86uNbLNmxuG1R89NDOP7YlzNWpCHFJKgENdBi7PoCIEHW7I37V+55jJg 32 | qrotCj5CU+dFYsOO34iZtaJNO6A3GGI8z/mX8vQf1pwKHonIu0X2/rMCgYEA05WI 33 | 6pPLJrEfVyKaTAehUm480HWaQ4wfmp3S8JejD35oL7rd0O/eILnkpcNcwb6sv+On 34 | OxeJap2XtjCMODY+qU/UDCE8lZCpjwoxF1eeGqouGqYxpaGKWQ5DHq3GYoiiWOA1 35 | KaiLPHhWyaIQ4soI9zw+af8DN9co3T/Op5fBnpkCgYEAraK/51qn1m6+dm7fRLZb 36 | 7TRVm1laUb5S+8OVsOjeSInnHRG9LAQLRc9BHyqe87wsenwvMf3T0anWRl4jy5wy 37 | OF53mhUXLf8YgGeduH4MKcWkkGIDJE+hrwpeVcdr46ek08sEC9ErIWqueddW+Svd 38 | 9gAPhE0RMMSxWGnaAy2rcuECgYBTIGjOYIpsBSKfBUVBoa3LyOuzqsCU0TSJdoAt 39 | biXuLGeaePw03kiS6vXd+kczB0qviS1mlfSzIn88YQ519znfIzHYIia/TDqRrBtl 40 | ZFMFft7mMW1H+ZN1MZlFMFjE1ZGTAWNhnoo1k8HlLfscXuvu1ohe9IW7Jpkzc6Ip 41 | TgIP4QKBgAfH73z9nQ1GObORMDxw6LatGmC0xyYGDDQPdkEfNXa+EcdWbiB4rElS 42 | U+AfElCk1SMK7vru/ZD/iRE0SBdtrTi7ZTpvB1sJYlk0LjrDTGG0n6OCsT6XOQSd 43 | 1hTdaZ9y3hUzjL/NSulIELEmzF2Rm6QnKD1rOsTfl2aPCrpf1OWB 44 | -----END RSA PRIVATE KEY----- 45 | eos 46 | end 47 | 48 | file '/etc/chef/dna.json' do 49 | content <<-EOF 50 | { 51 | "chef_server": { 52 | "fqdn": "chef.services.com" 53 | }, 54 | "chef_automate": { 55 | "fqdn": "automate.services.com" 56 | }, 57 | "run_list": [ 58 | "role[patch]", 59 | "recipe[chef-services::install_build_nodes]" 60 | ], 61 | "chef_environment": "delivered" 62 | } 63 | EOF 64 | end 65 | 66 | execute 'knife ssl fetch -c /etc/chef/client.rb' 67 | 68 | execute 'chef-client -j /etc/chef/dna.json' 69 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/delivery_node.rb: -------------------------------------------------------------------------------- 1 | directory '/etc/chef' do 2 | mode 0755 3 | recursive true 4 | end 5 | 6 | file '/etc/chef/delivery-validator.pem' do 7 | content <<-eos 8 | -----BEGIN RSA PRIVATE KEY----- 9 | MIIEowIBAAKCAQEAuK094FPDVk8YgRxNyCszfpMwuoLinQGbDtHUtiqodVrJk5Q8 10 | PYN7f8K5tM61tPMv0VduCDahm7LXOLk/SWgIlBFdBurrwMeIsRhoqohtsUW2qhaK 11 | SX6dhPjWjFAwP1C8WqjL9xuyWTMjS6hF2w6+za43OLvV+srnoBPIcRDWqr/76IbO 12 | 1RO+fgw1cX4FBPHp+rdJI/BjkufSQNGEQuWaQDYv7ZGgCBgb0xtOEARlHZUWBCjc 13 | W6apMo6jKnOCEqvheN6PboSYXAITwueLdGB7COOJxa9h3vZYI9jFqUKMMV/kTCls 14 | 5KlnxI0ATDTeZ4Y9KASNISQQA0Sv0i1R28Oy+wIDAQABAoIBAGSRaxXDZ6eTsSt2 15 | J2FvLT6rlyiqaA/KNQ9v8x80wcIOq6EjY164QEPF3e15d/hPSmX8752naoBods2c 16 | C7vE3I8NmZRP0AyOXIDcYvsjCmE0LpIXbj0xp0QnYmbMsEl6hOf17gTmX0w2De2A 17 | eHIfaIaHbekGWTOW1WYV/9yap9wZfYS4zDtES5LX+wTakxHV3Dl1XTTVzkhebrBg 18 | t7v7bpM37CuCAXNM6SWQkfZ1Rt8sDdvteKmIJhlkNfSaH9ofS8RnJqCdHqSm8frN 19 | EkqfIJ9yRXsRgXlINSsGH/zoBuCxt6pkdFPpOU5K4pJ4HxJAOzqkLnaO87PqABmA 20 | 1MIhdTECgYEA33G2N/M1P5IUnYsq91eWqH8W1voTrhaLHAWOiiqz7EGL5efXxmuR 21 | YbEOJbLw86uNbLNmxuG1R89NDOP7YlzNWpCHFJKgENdBi7PoCIEHW7I37V+55jJg 22 | qrotCj5CU+dFYsOO34iZtaJNO6A3GGI8z/mX8vQf1pwKHonIu0X2/rMCgYEA05WI 23 | 6pPLJrEfVyKaTAehUm480HWaQ4wfmp3S8JejD35oL7rd0O/eILnkpcNcwb6sv+On 24 | OxeJap2XtjCMODY+qU/UDCE8lZCpjwoxF1eeGqouGqYxpaGKWQ5DHq3GYoiiWOA1 25 | KaiLPHhWyaIQ4soI9zw+af8DN9co3T/Op5fBnpkCgYEAraK/51qn1m6+dm7fRLZb 26 | 7TRVm1laUb5S+8OVsOjeSInnHRG9LAQLRc9BHyqe87wsenwvMf3T0anWRl4jy5wy 27 | OF53mhUXLf8YgGeduH4MKcWkkGIDJE+hrwpeVcdr46ek08sEC9ErIWqueddW+Svd 28 | 9gAPhE0RMMSxWGnaAy2rcuECgYBTIGjOYIpsBSKfBUVBoa3LyOuzqsCU0TSJdoAt 29 | biXuLGeaePw03kiS6vXd+kczB0qviS1mlfSzIn88YQ519znfIzHYIia/TDqRrBtl 30 | ZFMFft7mMW1H+ZN1MZlFMFjE1ZGTAWNhnoo1k8HlLfscXuvu1ohe9IW7Jpkzc6Ip 31 | TgIP4QKBgAfH73z9nQ1GObORMDxw6LatGmC0xyYGDDQPdkEfNXa+EcdWbiB4rElS 32 | U+AfElCk1SMK7vru/ZD/iRE0SBdtrTi7ZTpvB1sJYlk0LjrDTGG0n6OCsT6XOQSd 33 | 1hTdaZ9y3hUzjL/NSulIELEmzF2Rm6QnKD1rOsTfl2aPCrpf1OWB 34 | -----END RSA PRIVATE KEY----- 35 | eos 36 | end 37 | 38 | file '/etc/chef/client.rb' do 39 | content <<-EOF 40 | log_level :info 41 | log_location STDOUT 42 | validation_client_name "delivery-validator" 43 | validation_key "/etc/chef/delivery-validator.pem" 44 | chef_server_url "https://chef.services.com/organizations/delivery" 45 | encrypted_data_bag_secret "/tmp/kitchen/encrypted_data_bag_secret" 46 | EOF 47 | end 48 | 49 | file '/etc/chef/dna.json' do 50 | content <<-EOF 51 | { 52 | "delivery": { 53 | "fqdn": "automate.services.com", 54 | "chef_server": "https://chef.services.com/organizations/delivery" 55 | }, 56 | "chef_automate": { 57 | "fqdn": "automate.services.com" 58 | }, 59 | "chef_server": { 60 | "fqdn": "chef.services.com" 61 | }, 62 | "run_list": [ 63 | "role[patch]", 64 | "recipe[chef-services::delivery]" 65 | ], 66 | "chef_environment": "delivered" 67 | } 68 | EOF 69 | end 70 | 71 | execute 'knife ssl fetch -c /etc/chef/client.rb' 72 | 73 | execute 'chef-client -j /etc/chef/dna.json' 74 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/compliance_node.rb: -------------------------------------------------------------------------------- 1 | directory '/etc/chef' do 2 | mode 0755 3 | recursive true 4 | end 5 | 6 | file '/etc/chef/delivery-validator.pem' do 7 | content <<-eos 8 | -----BEGIN RSA PRIVATE KEY----- 9 | MIIEowIBAAKCAQEAuK094FPDVk8YgRxNyCszfpMwuoLinQGbDtHUtiqodVrJk5Q8 10 | PYN7f8K5tM61tPMv0VduCDahm7LXOLk/SWgIlBFdBurrwMeIsRhoqohtsUW2qhaK 11 | SX6dhPjWjFAwP1C8WqjL9xuyWTMjS6hF2w6+za43OLvV+srnoBPIcRDWqr/76IbO 12 | 1RO+fgw1cX4FBPHp+rdJI/BjkufSQNGEQuWaQDYv7ZGgCBgb0xtOEARlHZUWBCjc 13 | W6apMo6jKnOCEqvheN6PboSYXAITwueLdGB7COOJxa9h3vZYI9jFqUKMMV/kTCls 14 | 5KlnxI0ATDTeZ4Y9KASNISQQA0Sv0i1R28Oy+wIDAQABAoIBAGSRaxXDZ6eTsSt2 15 | J2FvLT6rlyiqaA/KNQ9v8x80wcIOq6EjY164QEPF3e15d/hPSmX8752naoBods2c 16 | C7vE3I8NmZRP0AyOXIDcYvsjCmE0LpIXbj0xp0QnYmbMsEl6hOf17gTmX0w2De2A 17 | eHIfaIaHbekGWTOW1WYV/9yap9wZfYS4zDtES5LX+wTakxHV3Dl1XTTVzkhebrBg 18 | t7v7bpM37CuCAXNM6SWQkfZ1Rt8sDdvteKmIJhlkNfSaH9ofS8RnJqCdHqSm8frN 19 | EkqfIJ9yRXsRgXlINSsGH/zoBuCxt6pkdFPpOU5K4pJ4HxJAOzqkLnaO87PqABmA 20 | 1MIhdTECgYEA33G2N/M1P5IUnYsq91eWqH8W1voTrhaLHAWOiiqz7EGL5efXxmuR 21 | YbEOJbLw86uNbLNmxuG1R89NDOP7YlzNWpCHFJKgENdBi7PoCIEHW7I37V+55jJg 22 | qrotCj5CU+dFYsOO34iZtaJNO6A3GGI8z/mX8vQf1pwKHonIu0X2/rMCgYEA05WI 23 | 6pPLJrEfVyKaTAehUm480HWaQ4wfmp3S8JejD35oL7rd0O/eILnkpcNcwb6sv+On 24 | OxeJap2XtjCMODY+qU/UDCE8lZCpjwoxF1eeGqouGqYxpaGKWQ5DHq3GYoiiWOA1 25 | KaiLPHhWyaIQ4soI9zw+af8DN9co3T/Op5fBnpkCgYEAraK/51qn1m6+dm7fRLZb 26 | 7TRVm1laUb5S+8OVsOjeSInnHRG9LAQLRc9BHyqe87wsenwvMf3T0anWRl4jy5wy 27 | OF53mhUXLf8YgGeduH4MKcWkkGIDJE+hrwpeVcdr46ek08sEC9ErIWqueddW+Svd 28 | 9gAPhE0RMMSxWGnaAy2rcuECgYBTIGjOYIpsBSKfBUVBoa3LyOuzqsCU0TSJdoAt 29 | biXuLGeaePw03kiS6vXd+kczB0qviS1mlfSzIn88YQ519znfIzHYIia/TDqRrBtl 30 | ZFMFft7mMW1H+ZN1MZlFMFjE1ZGTAWNhnoo1k8HlLfscXuvu1ohe9IW7Jpkzc6Ip 31 | TgIP4QKBgAfH73z9nQ1GObORMDxw6LatGmC0xyYGDDQPdkEfNXa+EcdWbiB4rElS 32 | U+AfElCk1SMK7vru/ZD/iRE0SBdtrTi7ZTpvB1sJYlk0LjrDTGG0n6OCsT6XOQSd 33 | 1hTdaZ9y3hUzjL/NSulIELEmzF2Rm6QnKD1rOsTfl2aPCrpf1OWB 34 | -----END RSA PRIVATE KEY----- 35 | eos 36 | end 37 | 38 | file '/etc/chef/client.rb' do 39 | content <<-EOF 40 | log_level :info 41 | log_location STDOUT 42 | validation_client_name "delivery-validator" 43 | validation_key "/etc/chef/delivery-validator.pem" 44 | chef_server_url "https://chef.services.com/organizations/delivery" 45 | encrypted_data_bag_secret "/tmp/kitchen/encrypted_data_bag_secret" 46 | EOF 47 | end 48 | 49 | file '/etc/chef/dna.json' do 50 | content <<-EOF 51 | { 52 | "delivery": { 53 | "fqdn": "automate.services.com", 54 | "chef_server": "https://chef.services.com/organizations/delivery" 55 | }, 56 | "chef_automate": { 57 | "fqdn": "automate.services.com" 58 | }, 59 | "chef_server": { 60 | "fqdn": "chef.services.com" 61 | }, 62 | "supermarket_omnibus": { 63 | "chef_oauth2_verify_ssl": false 64 | }, 65 | "run_list": [ 66 | "role[patch]", 67 | "recipe[chef-services::compliance]" 68 | ], 69 | "chef_environment": "delivered" 70 | } 71 | EOF 72 | end 73 | 74 | execute 'knife ssl fetch -c /etc/chef/client.rb' 75 | 76 | execute 'chef-client -j /etc/chef/dna.json' 77 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/supermarket_node.rb: -------------------------------------------------------------------------------- 1 | directory '/etc/chef' do 2 | mode 0755 3 | recursive true 4 | end 5 | 6 | file '/etc/chef/delivery-validator.pem' do 7 | content <<-eos 8 | -----BEGIN RSA PRIVATE KEY----- 9 | MIIEowIBAAKCAQEAuK094FPDVk8YgRxNyCszfpMwuoLinQGbDtHUtiqodVrJk5Q8 10 | PYN7f8K5tM61tPMv0VduCDahm7LXOLk/SWgIlBFdBurrwMeIsRhoqohtsUW2qhaK 11 | SX6dhPjWjFAwP1C8WqjL9xuyWTMjS6hF2w6+za43OLvV+srnoBPIcRDWqr/76IbO 12 | 1RO+fgw1cX4FBPHp+rdJI/BjkufSQNGEQuWaQDYv7ZGgCBgb0xtOEARlHZUWBCjc 13 | W6apMo6jKnOCEqvheN6PboSYXAITwueLdGB7COOJxa9h3vZYI9jFqUKMMV/kTCls 14 | 5KlnxI0ATDTeZ4Y9KASNISQQA0Sv0i1R28Oy+wIDAQABAoIBAGSRaxXDZ6eTsSt2 15 | J2FvLT6rlyiqaA/KNQ9v8x80wcIOq6EjY164QEPF3e15d/hPSmX8752naoBods2c 16 | C7vE3I8NmZRP0AyOXIDcYvsjCmE0LpIXbj0xp0QnYmbMsEl6hOf17gTmX0w2De2A 17 | eHIfaIaHbekGWTOW1WYV/9yap9wZfYS4zDtES5LX+wTakxHV3Dl1XTTVzkhebrBg 18 | t7v7bpM37CuCAXNM6SWQkfZ1Rt8sDdvteKmIJhlkNfSaH9ofS8RnJqCdHqSm8frN 19 | EkqfIJ9yRXsRgXlINSsGH/zoBuCxt6pkdFPpOU5K4pJ4HxJAOzqkLnaO87PqABmA 20 | 1MIhdTECgYEA33G2N/M1P5IUnYsq91eWqH8W1voTrhaLHAWOiiqz7EGL5efXxmuR 21 | YbEOJbLw86uNbLNmxuG1R89NDOP7YlzNWpCHFJKgENdBi7PoCIEHW7I37V+55jJg 22 | qrotCj5CU+dFYsOO34iZtaJNO6A3GGI8z/mX8vQf1pwKHonIu0X2/rMCgYEA05WI 23 | 6pPLJrEfVyKaTAehUm480HWaQ4wfmp3S8JejD35oL7rd0O/eILnkpcNcwb6sv+On 24 | OxeJap2XtjCMODY+qU/UDCE8lZCpjwoxF1eeGqouGqYxpaGKWQ5DHq3GYoiiWOA1 25 | KaiLPHhWyaIQ4soI9zw+af8DN9co3T/Op5fBnpkCgYEAraK/51qn1m6+dm7fRLZb 26 | 7TRVm1laUb5S+8OVsOjeSInnHRG9LAQLRc9BHyqe87wsenwvMf3T0anWRl4jy5wy 27 | OF53mhUXLf8YgGeduH4MKcWkkGIDJE+hrwpeVcdr46ek08sEC9ErIWqueddW+Svd 28 | 9gAPhE0RMMSxWGnaAy2rcuECgYBTIGjOYIpsBSKfBUVBoa3LyOuzqsCU0TSJdoAt 29 | biXuLGeaePw03kiS6vXd+kczB0qviS1mlfSzIn88YQ519znfIzHYIia/TDqRrBtl 30 | ZFMFft7mMW1H+ZN1MZlFMFjE1ZGTAWNhnoo1k8HlLfscXuvu1ohe9IW7Jpkzc6Ip 31 | TgIP4QKBgAfH73z9nQ1GObORMDxw6LatGmC0xyYGDDQPdkEfNXa+EcdWbiB4rElS 32 | U+AfElCk1SMK7vru/ZD/iRE0SBdtrTi7ZTpvB1sJYlk0LjrDTGG0n6OCsT6XOQSd 33 | 1hTdaZ9y3hUzjL/NSulIELEmzF2Rm6QnKD1rOsTfl2aPCrpf1OWB 34 | -----END RSA PRIVATE KEY----- 35 | eos 36 | end 37 | 38 | file '/etc/chef/client.rb' do 39 | content <<-EOF 40 | log_level :info 41 | log_location STDOUT 42 | validation_client_name "delivery-validator" 43 | validation_key "/etc/chef/delivery-validator.pem" 44 | chef_server_url "https://chef.services.com/organizations/delivery" 45 | encrypted_data_bag_secret "/tmp/kitchen/encrypted_data_bag_secret" 46 | EOF 47 | end 48 | 49 | file '/etc/chef/dna.json' do 50 | content <<-EOF 51 | { 52 | "delivery": { 53 | "fqdn": "automate.services.com", 54 | "chef_server": "https://chef.services.com/organizations/delivery" 55 | }, 56 | "chef_automate": { 57 | "fqdn": "automate.services.com" 58 | }, 59 | "chef_server": { 60 | "fqdn": "chef.services.com" 61 | }, 62 | "supermarket_omnibus": { 63 | "chef_oauth2_verify_ssl": false 64 | }, 65 | "run_list": [ 66 | "role[patch]", 67 | "recipe[chef-services::supermarket]" 68 | ], 69 | "chef_environment": "delivered" 70 | } 71 | EOF 72 | end 73 | 74 | execute 'knife ssl fetch -c /etc/chef/client.rb' 75 | 76 | execute 'chef-client -j /etc/chef/dna.json' 77 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | # Package logic 2 | # Since we're trying to keep this cookbook simple, and not use external API's 3 | # to simplify the proxy story, we're setting package URL's in attributes. 4 | # To make this work on more than one platform we're using some logic here. 5 | # 6 | # If you're overriding the package values you don't need to worry about this. 7 | # 8 | # pv = platform version 9 | # pl = platform 10 | # pf = package format 11 | # s = seperator, we apparently use - for el and _ for ubuntu between the package 12 | # name and version. 13 | 14 | case node['platform_family'] 15 | when 'rhel' 16 | pl = 'el' 17 | pv = node['platform_version'].to_i 18 | pf = ".#{pl}#{pv}.x86_64.rpm" 19 | s = '-' 20 | when 'suse' 21 | pl = 'el' 22 | if node['platform_version'].to_i == 12 23 | pv = '7' 24 | else 25 | pv = '6' 26 | end 27 | pf = ".#{pl}#{pv}.x86_64.rpm" 28 | s = '-' 29 | when 'debian' 30 | pl = 'ubuntu' 31 | pv = node['platform_version'] 32 | pf = "_amd64.deb" 33 | s = "_" 34 | else 35 | raise "You seem to be running on an unrecognized platform." 36 | end 37 | 38 | default['delivery']['version'] = "0.6.7-1" 39 | default['chef-server']['version'] = "12.11.1-1" 40 | default['manage']['version'] = "2.4.4-1" 41 | default['push-jobs-server']['version'] = "2.1.0-1" 42 | default['chefdk']['version'] = "1.0.3-1" 43 | default['supermarket']['version'] = "2.8.34-1" 44 | default['compliance']['version'] = "1.7.7-1" 45 | 46 | %w(delivery chefdk chef-server manage push-jobs-server supermarket compliance).each do |pkg| 47 | case pkg 48 | when 'chef-server' 49 | pn = 'chef-server-core' 50 | when 'manage' 51 | pn = 'chef-manage' 52 | when 'push-jobs-server' 53 | pn = 'opscode-push-jobs-server' 54 | when 'compliance' 55 | pn = 'chef-compliance' 56 | else 57 | pn = pkg 58 | end 59 | v = node[pkg]['version'] 60 | # Derive the package URL from platform (pl), platform version (pv), the 61 | # package name (pn), the package version (v), and package format (pf) 62 | default[pkg]['package_url'] = "https://packages.chef.io/files/stable/#{pn}/#{v.split('-').first}/#{pl}/#{pv}/#{pn}#{s}#{v}#{pf}" 63 | end 64 | 65 | # License attributes 66 | 67 | default['chef-services']['accept_license'] = true 68 | 69 | # Workflow attributes 70 | 71 | default['chef_automate']['fqdn'] = nil 72 | default['delivery']['config'] = <<-EOS 73 | delivery_fqdn "#{node['chef_automate']['fqdn']}" 74 | delivery['chef_username'] = "delivery" 75 | delivery['chef_private_key'] = "/etc/delivery/delivery.pem" 76 | delivery['chef_server'] = "https://#{node['chef_server']['fqdn']}/organizations/delivery" 77 | delivery['default_search'] = "tags:delivery-build-node" 78 | insights['enable'] = true 79 | compliance_profiles["enable"] = true 80 | EOS 81 | 82 | # Chef server attributes 83 | 84 | default['chef_server']['fqdn'] = nil 85 | default['chef-server']['config'] = <<-EOS 86 | api_fqdn "#{node['chef_server']['fqdn']}" 87 | 88 | oc_id['applications'] = { 89 | "supermarket"=>{"redirect_uri"=>"https://supermarket.services.com/auth/chef_oauth2/callback"} 90 | } 91 | profiles["root_url"] = "https://automate.services.com/" 92 | EOS 93 | 94 | # ChefDK Attributes 95 | 96 | # Supermarket Attributes 97 | 98 | default['chef-supermarket']['supermarket']['verify_ssl'] = false 99 | default['chef-services']['supermarket']['config'] = {} 100 | 101 | # Compliance attributes 102 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | ssh: 5 | insert_key: false 6 | # http_proxy: http://10.0.0.53:8888 7 | # https_proxy: http://10.0.0.53:8888 8 | # no_proxy: localhost,*.localdomain,127.0.0.1,*.services.com 9 | 10 | provisioner: 11 | name: chef_zero 12 | chef_zero_port: 9010 13 | encrypted_data_bag_secret_key_path: 'test/fixtures/secrets/fakey-mcfakerton' 14 | data_bags_path: 'test/fixtures/data_bags' 15 | # client_rb: 16 | # http_proxy: http://10.0.0.53:8888 17 | # https_proxy: http://10.0.0.53:8888 18 | # no_proxy: localhost,*.localdomain,127.0.0.1,*.services.com 19 | # http_proxy: http://10.0.0.53:8888 20 | # https_proxy: http://10.0.0.53:8888 21 | # no_proxy: localhost,*.localdomain,127.0.0.1,*.services.com 22 | 23 | verifier: 24 | name: inspec 25 | 26 | platforms: 27 | - name: centos-6.8 28 | - name: centos-7.3 29 | verifier: 30 | inspec_tests: 31 | - https://github.com/dev-sec/linux-patch-baseline 32 | - name: ubuntu-14.04 33 | - name: ubuntu-16.04 34 | 35 | suites: 36 | - name: chef-server 37 | run_list: 38 | - recipe[test::hostsfile] 39 | - recipe[test::chef_server] 40 | driver: 41 | vm_hostname: chef.services.com 42 | network: 43 | - ['private_network', {ip: '33.33.33.10'}] 44 | customize: 45 | memory: 2048 46 | cpus: 2 47 | attributes: 48 | chef_server: 49 | fqdn: chef.services.com 50 | install_dir: /tmp/ 51 | 52 | - name: automate 53 | run_list: 54 | - recipe[test::hostsfile] 55 | - recipe[test::delivery_node] 56 | attributes: 57 | delivery: 58 | fqdn: 'automate.services.com' 59 | chef_server: https://chef.services.com/organizations/delivery 60 | insights: 61 | enable: true 62 | chef_automate: 63 | fqdn: automate.services.com 64 | chef_services: 65 | fqdn: chef.services.com 66 | driver: 67 | vm_hostname: automate.services.com 68 | network: 69 | - ['private_network', {ip: '33.33.33.11'}] 70 | customize: 71 | memory: 2560 72 | cpus: 1 73 | 74 | - name: build 75 | run_list: 76 | - recipe[test::hostsfile] 77 | - recipe[test::delivery_build_node] 78 | attributes: 79 | driver: 80 | vm_hostname: build.services.com 81 | network: 82 | - ['private_network', {ip: '33.33.33.12'}] 83 | customize: 84 | memory: 1024 85 | cpus: 1 86 | 87 | # - name: supermarket 88 | # run_list: 89 | # - recipe[test::hostsfile] 90 | # - recipe[test::supermarket_node] 91 | # attributes: 92 | # supermarket_omnibus: 93 | # chef_server_url: 'https://chef.services.com' 94 | # chef_oauth2_verify_ssl: false 95 | # driver: 96 | # vm_hostname: supermarket.services.com 97 | # network: 98 | # - ['private_network', {ip: '33.33.33.13'}] 99 | # customize: 100 | # memory: 1024 101 | # cpus: 1 102 | # 103 | # - name: compliance 104 | # run_list: 105 | # - recipe[test::hostsfile] 106 | # - recipe[test::compliance_node] 107 | # attributes: 108 | # compliance: 109 | # accept_license: true 110 | # fqdn: compliance.services.com 111 | # driver: 112 | # vm_hostname: compliance.services.com 113 | # network: 114 | # - ['private_network', {ip: '33.33.33.14'}] 115 | # customize: 116 | # memory: 1024 117 | # cpus: 1 118 | -------------------------------------------------------------------------------- /files/default/installer.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Please provide an IP/FQDN for your chef server: domain.com 5 | # 6 | # Hab package? 7 | # 8 | 9 | usage=" 10 | This is an installer for Chef. It will install Chef Server, Chef Automate, and a build node for Automate.\n 11 | It will install the Chef server on the system you run this script from.\n 12 | 13 | You must specify the following options:\n 14 | 15 | -c|--chef-server-fqdn REQUIRED: The FQDN you want the Chef Server configured to use.\n 16 | -a|--chef-automate-fqdn The FQDN of the Chef Automate server.\n 17 | -b|--build-node-fqdn The FQDN of the build node.\n 18 | -u|--user The ssh username we'll use to connect to other systems.\n 19 | -p|--password The ssh password we'll use to connect to other systems.\n 20 | -i|--install-dir The directory to use for the installer. 21 | -cs-source|--chef-services-source The source for the chef-services cookbook 22 | 23 | If only -c is specified the local system will be configured with a Chef Server install. \n 24 | " 25 | 26 | if [ $# -eq 0 ]; then 27 | echo -e $usage 28 | exit 1 29 | fi 30 | 31 | while [[ $# -gt 0 ]] 32 | do 33 | key="$1" 34 | case $key in 35 | -c|--chef-server-fqdn) 36 | CHEF_SERVER_FQDN="$2" 37 | shift # past argument 38 | ;; 39 | -a|--chef-automate-fqdn) 40 | CHEF_AUTOMATE_FQDN="$2" 41 | shift # past argument 42 | ;; 43 | -b|--build-node-fqdn) 44 | CHEF_BUILD_FQDN="$2" 45 | shift # past argument 46 | ;; 47 | -u|--user) 48 | CHEF_USER="$2" 49 | shift 50 | ;; 51 | -p|--password) 52 | CHEF_PW="$2" 53 | shift 54 | ;; 55 | -i|--install-dir) 56 | INSTALL_DIR="$2" 57 | shift 58 | ;; 59 | -cs-source|--chef-services-source) 60 | CHEF_SERVICES_SOURCE="$2" 61 | shift 62 | ;; 63 | -h|--help) 64 | echo -e $usage 65 | exit 0 66 | ;; 67 | *) 68 | echo "Unknown option $1" 69 | echo -e $usage 70 | exit 1 71 | ;; 72 | esac 73 | shift # past argument or value 74 | done 75 | 76 | # ---------- Chef Server ---------- 77 | # ->install Chef 78 | if [ -z "$INSTALL_DIR" ]; then 79 | INSTALL_DIR=/tmp 80 | fi 81 | if [ -z "$CHEF_SERVICES_SOURCE" ]; then 82 | CHEF_SERVICES_SOURCE="git: 'https://github.com/stephenlauck/chef-services.git'" 83 | fi 84 | 85 | mkdir -p $INSTALL_DIR/chef_installer/.chef/cache/ 86 | cd $INSTALL_DIR/chef_installer 87 | if [ ! -d "/opt/chefdk" ]; then 88 | curl -LO https://omnitruck.chef.io/install.sh && sudo bash ./install.sh -P chefdk -d $INSTALL_DIR/chef_installer && rm install.sh 89 | fi 90 | 91 | # write out Berksfile of install cookbooks 92 | cat << EOF > $INSTALL_DIR/chef_installer/Berksfile 93 | source 'https://supermarket.chef.io' 94 | 95 | cookbook 'chef-services', $CHEF_SERVICES_SOURCE 96 | cookbook 'chef_stack', git: 'https://github.com/ncerny/chef_stack.git', branch: 'nc/modify-frozen-string' 97 | cookbook 'audit' 98 | cookbook 'chef-client' 99 | EOF 100 | 101 | export PATH=/opt/chefdk/gitbin:$PATH 102 | 103 | # download cookbooks for install 104 | berks install 105 | berks update 106 | berks vendor cookbooks/ 107 | 108 | # write config and build chef-server 109 | echo -e "{\"chef_server\": {\"fqdn\":\"$CHEF_SERVER_FQDN\",\"install_dir\":\"$INSTALL_DIR\"}}" > attributes.json 110 | chef-client -z -j attributes.json --config-option file_cache_path=$INSTALL_DIR -r 'recipe[chef-services::chef-server]' 111 | 112 | # upload cookbooks from chef-server to itself 113 | berks upload --no-ssl-verify 114 | 115 | # ---------- All others ----------- 116 | # -> automate,chef-builder1,chef-builder2,chef-builder3,supermarket,compliance.domain.com 117 | # --> bootstrap with correct runlist 118 | 119 | if [ ! -z $CHEF_AUTOMATE_FQDN ]; then 120 | knife bootstrap $CHEF_AUTOMATE_FQDN -N $CHEF_AUTOMATE_FQDN -x $CHEF_USER -P $CHEF_PW --sudo -r "role[patch],recipe[chef-services::delivery]" -j "{\"chef_server\":{\"fqdn\":\"$CHEF_SERVER_FQDN\"},\"chef_automate\":{\"fqdn\":\"$CHEF_AUTOMATE_FQDN\"}}" -E delivered -y --node-ssl-verify-mode none 121 | fi 122 | 123 | if [ ! -z $CHEF_BUILD_FQDN ]; then 124 | knife bootstrap $CHEF_BUILD_FQDN -N $CHEF_BUILD_FQDN -x $CHEF_USER -P $CHEF_PW --sudo -r "role[patch],recipe[chef-services::install_build_nodes]" -j "{\"chef_server\":{\"fqdn\":\"$CHEF_SERVER_FQDN\"},\"chef_automate\":{\"fqdn\":\"$CHEF_AUTOMATE_FQDN\"},\"tags\":\"delivery-build-node\"}" -E delivered -y --node-ssl-verify-mode none 125 | fi 126 | 127 | # add correct compliance role, environment and scan 128 | echo -e "{\"chef_server\": {\"fqdn\":\"$CHEF_SERVER_FQDN\",\"install_dir\":\"$INSTALL_DIR\"}, \"chef_environment\": \"delivered\"}" > attributes.json 129 | chef-client -j attributes.json -r 'role[patch],recipe[chef-services::chef-server]' 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chef-services 2 | 3 | ## Background 4 | 5 | This cookbook serves as a platform to install Chef Automate in a couple of ways: 6 | 7 | * As a number of virtual machines spun up via Test Kitchen and vagrant, 8 | * Using a number of existing hosts onto which the Chef Automate services can be deployed. 9 | 10 | ## Installation via Test Kitchen 11 | 12 | ### 1. Select a platform for installation 13 | 14 | Look at the available platforms in `.kitchen.yml`: 15 | 16 | ``` 17 | platforms: 18 | - name: centos-6.8 19 | - name: centos-7.3 20 | - name: ubuntu-14.04 21 | - name: ubuntu-16.04 22 | ``` 23 | 24 | Select **ONE** of the platforms to install Chef Automate. 25 | 26 | >NOTE: For this example, we'll use __centos-7.3__. 27 | 28 | ### 2. Create the instances 29 | 30 | 1. Run `kitchen list centos-73` to see the list of instances that will get created: 31 | 32 | $ kitchen list centos-73 33 | Instance Driver Provisioner Verifier Transport Last Action Last Error 34 | chef-server-centos-73 Vagrant ChefZero Inspec Ssh 35 | automate-centos-73 Vagrant ChefZero Inspec Ssh 36 | build-centos-73 Vagrant ChefZero Inspec Ssh 37 | supermarket-centos-73 Vagrant ChefZero Inspec Ssh 38 | compliance-centos-73 Vagrant ChefZero Inspec Ssh 39 | 40 | 2. Create the instances: 41 | 42 | $ kitchen converge centos-73 43 | 44 | While the instances are getting created and converged, execute Step 3 below. 45 | 46 | ### 3. Modify local `/etc/hosts` 47 | 48 | 1. Add the following lines to your local workstation `/etc/hosts`: 49 | 50 | ``` 51 | 33.33.33.10 chef.services.com 52 | 33.33.33.11 automate.services.com 53 | 33.33.33.12 build.services.com 54 | 33.33.33.13 supermarket.services.com 55 | 33.33.33.14 compliance.services.com 56 | ``` 57 | 58 | ### 4. Verify logins 59 | 60 | Once the `kitchen converge ...` has completed, the various logins can be tested as follows. 61 | 62 | #### Chef Server 63 | 64 | 1. Browse to [http://chef.services.com]() 65 | 2. Sign in with: 66 | Username: __delivery__ 67 | Password: __delivery__ 68 | 69 | #### Automate Server 70 | 71 | 1. Obtain the credentials for the Automate login using this command: 72 | 73 | kitchen exec automate-centos-73 -c 'cat /etc/delivery/test.creds' 74 | 75 | 2. Browse to [http://automate.services.com/e/test]() 76 | 3. Sign in with the credentials from Step 1. 77 | 78 | __Recommend creating a new admin user with a sane password:__ 79 | 80 | 1. Browse to [https://automate.services.com/e/test/#/users]() and select __Users → + NEW USER__. 81 | 2. Fill in the __FIRST NAME, LAST NAME, EMAIL, USERNAME, and PASSWORD__ fields. All check the __admin__ role under __Roles Within the Enterprise__. 82 | 3. Paste your public key into the __SSH KEY__ field. Without this, subsequent `delivery` commands won't authenticate properly. 83 | 4. Click __SAVE & CLOSE__. 84 | 85 | Future admin logins can use this account rather than the __admin__ account with its cryptic password. 86 | 87 | #### Supermarket 88 | 89 | 1. Browse to [http://supermarket.services.com]() 90 | 91 | #### Compliance Server 92 | 93 | 1. Browse to [http://compliance.services.com]() 94 | 2. Sign in with: 95 | Username: __admin__ 96 | Password: __password__ 97 | 98 | ### 5. Deploy a sample pipeline (Optional) 99 | 100 | The sample pipeline we'll be using is from the [National Parks Cookbook](https://github.com/billmeyer/national_parks_cookbook). 101 | 102 | #### 5.1 Create a new Workflow Organization 103 | 104 | 1. Create a new __Workflow Organization__ by browsing to [https://automate.services.com/e/test/#/organizations](). 105 | 2. Fill in the __ORGANIZATION NAME__ field with `travel-usa`. 106 | 3. Click __SAVE & CLOSE__. 107 | 108 | #### 5.2 Create a new __Project__ in the __Workflow Organization__. 109 | 110 | 1. Browse to [https://automate.services.com/e/test/#/organizations](). 111 | 2. Click on the __travel-usa__ Workflow Org. 112 | 3. Fill in the __PROJECT NAME__ with `national_parks_cookbook`. 113 | 4. Select __Chef Automate__ for the __Source Code Provider__. 114 | 5. Click __SAVE & CLOSE__. 115 | 116 | #### 5.3 Download the sample cookbook 117 | 118 | For this step, we only want to pull the cookbook source from github and _not_ use github as our repo (We'll be using Chef Automate's git repo). So, we'll pull the source and then blow away the `national_parks_cookbook/.git` directory. 119 | 120 | 1. Clone the source to the cookbook to the local workstation: 121 | 122 | $ git clone https://github.com/billmeyer/national_parks_cookbook 123 | $ cd national_parks_cookbook 124 | 125 | 2. Change git repo from GitHub to Chef Automate: 126 | 127 | $ git remote remove origin 128 | $ git remote add origin ssh://bmeyer@test@automate.services.com:8989/test/travel-usa/national_parks_cookbook 129 | $ git remote add delivery ssh://bmeyer@test@automate.services.com:8989/test/travel-usa/national_parks_cookbook 130 | 131 | 3. Create the project config file: 132 | 133 | $ delivery setup --ent=test --org=travel-usa --user=bmeyer --server=automate.services.com 134 | $ delivery init 135 | 136 | ## Install Chef Automate to existing infrastructure 137 | 138 | This use case can be used for on-premise installations of Chef Automate using supplied hosts. 139 | 140 | `kitchen create chef-server-centos-73` 141 | 142 | `kitchen login chef-server-centos-73` 143 | 144 | `sudo su -` 145 | 146 | >NOTE: __-u <username>__ should be a user account on the remote host that has __sudo__ privileges on the remote host. 147 | 148 | curl -O https://raw.githubusercontent.com/stephenlauck/chef-services/master/files/default/installer.sh && \ 149 | sudo bash ./installer.sh \ 150 | -u vagrant -p vagrant \ 151 | -c \ 152 | -a \ 153 | -b 154 | -------------------------------------------------------------------------------- /files/default/delivery-cmd: -------------------------------------------------------------------------------- 1 | #!/opt/chefdk/embedded/bin/ruby 2 | 3 | require 'chef' 4 | require 'chef/config' 5 | require 'chef/rest' 6 | require 'chef/client' 7 | require 'base64' 8 | require 'uri' 9 | require 'date' 10 | 11 | module Delivery 12 | # Helper methods for our build node job runner workflow. 13 | module JobHelpers 14 | 15 | # All build nodes currently leverage a built-in internal user that 16 | # all enterprises have; its name is "builder". 17 | # 18 | # This is my builder. There are many like it, but this is mine. 19 | BUILDER_USER = "builder" 20 | 21 | # Create appropriate authentication headers for a builder, given a 22 | # job data hash. If no token is present in `job_data` (because the 23 | # build nodes were updated before the server began handing tokens 24 | # out), an empty set of headers is returned. 25 | # 26 | # @param job_data [Hash] Describes the job being run; we're 27 | # looking for a `token` key. 28 | # 29 | # @return [Hash] authentication headers, suitable for passing into 30 | # a `Chef::REST` call. 31 | def self.builder_auth_headers(job_data) 32 | if job_token = job_data["token"] 33 | {"chef-delivery-token" => job_token, 34 | "chef-delivery-user" => BUILDER_USER} 35 | else 36 | {} 37 | end 38 | end 39 | 40 | end # JobHelpers 41 | end # Delivery 42 | 43 | class Streamy 44 | attr_accessor :output, :rest, :path, :builder_auth_headers 45 | 46 | def initialize(rest, path, headers) 47 | @rest = rest 48 | @path = path 49 | @builder_auth_headers = headers 50 | @output = "" 51 | end 52 | 53 | def <<(arg) 54 | begin 55 | # Force the chef-client output into UTF-8 to prevent issues 56 | # sending it to our REST API. 57 | @output << arg.force_encoding('utf-8') 58 | rest.post(path, 59 | { 60 | "run_success" => false, 61 | "run_log" => @output, 62 | "run_status" => "running", 63 | "run_complete" => false 64 | }, 65 | builder_auth_headers 66 | ) 67 | rescue 68 | # If we hit this block it means 1 of 2 things went wrong: 69 | # 1) There was an error encoding the String 70 | # 2) There was an error talking to the Delivery Server 71 | # 72 | # The first case, while unlikely, shouldn't cause the entire phase 73 | # run to fail. We would rather have a successful phase runs without 74 | # logs than a failed phase runs due to logging errors. 75 | # 76 | # The second case, if it happens with the request, the logs will continue 77 | # to aggregate and be sent on the next attempt. If we continue to get 78 | # request errors than eventually the job will time out and we will know 79 | # there is something wrong with the build node or the delivery server. 80 | end 81 | end 82 | 83 | def to_str 84 | @output 85 | end 86 | end 87 | 88 | def write_profile(workspace_root) 89 | cli_env = { 90 | 'LC_ALL' => 'en_US.UTF-8', 91 | 'HOME' => workspace_root 92 | } 93 | cmd = Mixlib::ShellOut.new("/opt/chefdk/bin/chef shell-init sh > #{workspace_root}/.chef-profile", environment: cli_env) 94 | cmd.run_command 95 | end 96 | 97 | workspace_root = "/var/opt/delivery/workspace" 98 | workspace_bin = "/var/opt/delivery/workspace/bin" 99 | 100 | Chef::Config.from_file(Chef::Config.platform_specific_path("/etc/chef/client.rb")) 101 | client = Chef::Client.new 102 | client.run_ohai 103 | client.node_name 104 | 105 | write_profile(workspace_root) 106 | 107 | change_file = File.join(workspace_root, 'change.json') 108 | raw_json = Base64.decode64(ARGV[0]) 109 | File.open(change_file, 'w') do |file| 110 | file.puts(raw_json) 111 | end 112 | 113 | job_data = Chef::JSONCompat.from_json(raw_json) 114 | 115 | builder_auth_headers = Delivery::JobHelpers.builder_auth_headers(job_data) 116 | 117 | rest = Chef::REST.new(job_data["delivery_api_url"]) 118 | path = File.join(job_data['enterprise'], 119 | 'orgs', job_data['organization'], 120 | 'projects', job_data['project'], 121 | 'pipelines', job_data['pipeline'], 122 | 'phase_runs', job_data['phase_run_id'].to_s) 123 | 124 | streamy = Streamy.new(rest, path, builder_auth_headers) 125 | server = URI(job_data['delivery_api_url']) 126 | 127 | command_line = if job_data['stage'] == "verify" 128 | "delivery job #{job_data['stage']} #{job_data['phase']} --server #{server.host} --user builder --ent #{job_data['enterprise']} --org #{job_data['organization']} --project #{job_data['project']} --for #{job_data['pipeline']} --change-id #{job_data['change_id']} --branch #{job_data['patchset_branch']} --git-url #{job_data['git_url']}" 129 | else 130 | "delivery job #{job_data['stage']} #{job_data['phase']} --server #{server.host} --user builder --ent #{job_data['enterprise']} --org #{job_data['organization']} --project #{job_data['project']} --for #{job_data['pipeline']} --change-id #{job_data['change_id']} --shasum #{job_data['sha']} --git-url #{job_data['git_url']}" 131 | end 132 | 133 | https_proxy = Chef::Config[:https_proxy] || ENV['HTTPS_PROXY'] || ENV['https_proxy'] 134 | http_proxy = Chef::Config[:http_proxy] || ENV['HTTP_PROXY'] || ENV['http_proxy'] 135 | no_proxy = Chef::Config[:no_proxy] || ENV['NO_PROXY'] || ENV['no_proxy'] 136 | 137 | cli_env = { 138 | 'PATH' => ['/opt/chefdk/bin:/opt/chefdk/embedded/bin', ENV['PATH']].join(File::PATH_SEPARATOR), 139 | 'LC_ALL' => 'en_US.UTF-8', 140 | 'GIT_SSH' => File.join(workspace_bin, 'git_ssh'), 141 | 'HOME' => workspace_root, 142 | 'TERM' => 'screen-256color' 143 | } 144 | cli_env['https_proxy'] = https_proxy if https_proxy && !https_proxy.strip.empty? 145 | cli_env['http_proxy'] = http_proxy if http_proxy && !http_proxy.strip.empty? 146 | cli_env['no_proxy'] = no_proxy if no_proxy && !no_proxy.strip.empty? 147 | 148 | cmd = Mixlib::ShellOut.new(". #{workspace_root}/.chef-profile && #{command_line} --no-spinner", environment: cli_env) 149 | 150 | start_datetime = DateTime.now 151 | 152 | streamy << "Starting job on builder #{client.node_name} at #{start_datetime.iso8601}.\nCommand: #{command_line}\n" 153 | ## This we will want to be configurable. but for now make it big and 154 | ## and rely on pushy to timeout. 155 | cmd.timeout = 6600 156 | cmd.log_level = :error 157 | cmd.live_stream = streamy 158 | cmd.cwd = workspace_root 159 | cmd.run_command 160 | 161 | end_datetime = DateTime.now 162 | # difference between 2 DateTimes is expressed in days 163 | elapsed_time = ((end_datetime - start_datetime) * 24 * 60 * 60).to_i 164 | streamy << "\nJob ended at #{end_datetime.iso8601} (ran in #{elapsed_time} seconds)" 165 | 166 | # Borrowed from chef-cookbooks/jenkins; used to create a cleanly normalized URL 167 | def uri_join(*parts) 168 | parts = parts.compact.map(&URI.method(:escape)) 169 | URI.parse(parts.join('/')).normalize.to_s 170 | end 171 | 172 | # Borrowed from chef-cookbooks/omnibus; used to create a windows-safe file.join 173 | def windows_safe_path_join(*args) 174 | ::File.join(args).gsub(::File::SEPARATOR, ::File::ALT_SEPARATOR || File::SEPARATOR) 175 | end 176 | 177 | compliance_json = windows_safe_path_join( 178 | workspace_root, server.host, job_data['enterprise'], 179 | job_data['organization'], job_data['project'], job_data['pipeline'], 180 | job_data['stage'], job_data['phase'], "repo", ".delivery-compliance.json" 181 | ) 182 | 183 | path_compliance = uri_join(job_data['enterprise'], 184 | 'orgs', job_data['organization'], 185 | 'projects', job_data['project'], 186 | 'pipelines', job_data['pipeline'], 187 | 'phase_runs', job_data['phase_run_id'].to_s, 'log_objects') 188 | 189 | if File.exist?(compliance_json) 190 | rest.post(path_compliance,File.read(compliance_json),builder_auth_headers) 191 | streamy << "\nCompliance data has posted.\n" 192 | end 193 | 194 | if cmd.error? 195 | # Chef Stacktrace File Path 196 | chef_stacktrace_file = File.join( 197 | workspace_root, server.host, job_data['enterprise'], 198 | job_data['organization'], job_data['project'], job_data['pipeline'], 199 | job_data['stage'], job_data['phase'], "cache", "chef-stacktrace.out" 200 | ) 201 | if File.exist?(chef_stacktrace_file) 202 | streamy << "\nChef Stacktrace\n" 203 | streamy << File.read(chef_stacktrace_file) 204 | end 205 | 206 | rest.post(path, 207 | { 208 | "run_success" => false, 209 | "run_log" => streamy.output, 210 | "run_status" => "failed", 211 | "run_complete" => true 212 | }, 213 | builder_auth_headers 214 | ) 215 | else 216 | rest.post(path, 217 | { 218 | "run_success" => true, 219 | "run_log" => streamy.output, 220 | "run_status" => "finished", 221 | "run_complete" => true 222 | }, 223 | builder_auth_headers 224 | ) 225 | end 226 | -------------------------------------------------------------------------------- /test/fixtures/data_bags/automate/automate.json: -------------------------------------------------------------------------------- 1 | {"id":"automate","validator_pem":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEAted1v29d0avAljmXx2uYJuY+Ss29ebBZ6fxjQFr9Adc84hMs\nTvak3iFEGt9c8w+svidmCAWGLAK/WToiAtZtnH/LE/ubs5MDdqXPi4zDdpA/UsV4\nzoZAoEqiGmrvBIUD6VSjPVm7n1H9tRbKdhSCQOjvstPvYIgLmH0w29y05/Igw82r\nP/wlZUGwX6YLN4Xn3y2w7w1+mFhfdfGDcipSji/JUv1H/L+xc+3yuttAgYHg2tqe\n0kBfsEF84Ry9K14j2VqPseHi17ESwopM/d7uIkn1zmn9TXOadq6A/jNpvX8uq/kc\nBnbvLZkkhxD/qoQEuJ5U3yOfyBhGToA7F99dPQIDAQABAoIBAB18MjLgm2WEIIh5\nN2gEwbn0cj5v0PmrozdxSKlC1mX4/I5sqy71fc3fuIlekVN4w/hirIA6XQA/RcLx\n0FeDaGsIr+NCUn+uIc6Wm+iz3W8XfJwvFCDt1AXncxUzJiEmanbk2Dz2kZoGkUhM\nNG8lbeOVnlzvS4rrIm4KROQuh0hdScAxq4pPanTQfX4c4m1afStf/nnmn+qrTXxz\nxlx34Uw26IytL7mAbzNjEt8xSy74sHuFgh6DhXY1PIoObsqSy+gTQ5CNMLSG3obe\nPrCDodBg7KExudWPHwP4WZAQVA5XkztSCnqJfiEtS7/Mzn3aFAeopOWp0TY7Pnei\npNF8ZUUCgYEA7HHi+GbURjPm5RUwOUrX6uxNghM1Iwmge6mtvdZOsnOoIqJkf4Bh\nEVhHAjIHDdBXNSqxrhXX7hC+yYVXumWWFotYMXiD4m6KpX0qGfeqCiHdjkqz5u3Y\nZiL/MrgRbJaG9EWA9AtT4ilkKYj/Ud+vo1yj7xnmlnBVOttPNMypftMCgYEAxPLQ\nOHnMZiPDqf7/jg6WpeIyDLzT517s5zOkRHVRf2AZBRghiIkXAuqzfR6fRK/2/gEJ\nBLBqX1CL6ZLJl97tINPlswgdjjz2o053ar8C7RxWBDmlxZysX3YWv5mWystCUVIT\nSLeWzgGkahW+oL0zPEcd1VDTIDxBHK70F54aya8CgYBwJSQuBTexhHSDOyWARwta\nFXI9u7Z8Q9imTrhlTfxNj6Wzp6pa/x0LCP/E/s1xs9tpEDLuCtY7yB11n5UYh45E\naxsNe8ex4hRIobESV/GClMVs8+mYIj99UiQQflVlV4/y0/Rxy92ha1hiiuPuhVXc\n+deXVIWV3PnPzK0osdnCmQKBgQDC3OgN6NzG9n3i1e1uVZrSeFJC7hXPp8lIHH1c\nSqOfHqrCspSDLfi5pxR+KG03Hc+Ik+ejXxVwRxaXvOd/P09pmp57m/z6PfFdtQZM\ndL9lcRLeTVdqhVC7hvCNFF7xOVjdcxKncRZhr5hIaklZarml20t2QukRzOwzgBr8\nvy8L+wKBgG9QnuD5qHCaMrNIVSCt/6K/1F7MmcN/PMgViR+eopn6GXJKUixGL+GH\nc9VjhgRSJVYPxSQcFYIvm5/sqQSlJSZtusHptJZHUTtsGiwJVDTug7TAcT25xcYc\nLbSJrNCXg6ZMDCuyjlJFwinXlHcGx1PpwHqcZSk5Kt1wVFxpY3ph\n-----END RSA PRIVATE KEY-----","user_pem":"-----BEGIN RSA PRIVATE KEY-----\nMIIEowIBAAKCAQEArTIZnkbzpWMpBQ4BI+iV2r4fC42RhsKALO2tYNeXalYu558S\nInM44JoPkIsQf4GDP0YlEYTaqGl3cj622UvPI6lIk0+sbygHdAwfaOt7FgQFhopa\nPii4hVzodKFsa5k3unIURhpShOdDoh7ymq2R4tZ/oHq2D8nXTGwS6bZXFmJFlFrR\nSEa6ZdZWjZ2ysFwu79cOQ45TbhoZA9TduOf6pUHGIaKN6Hc/dCNT7F7U74pi+yaY\nAHzxlNoFsoXzBKMQCZXvsnqv86C2L31yPC+6/qiicntDbqjdEb4zMm7zqlCVXVMk\n2bl0jC2h9rqpjxm8liz5r+CN9izU/gAtrEATJwIDAQABAoIBADIK38wTxCJtXFTR\njxLJCUOC24WDCiFd4ZsZsZbhtCZNcJAMLjk2AaEj4otpIwM0cK+/nMZLFMLEdnbU\nGBEBDoDHUOj/hFs5va2SMyElqRLbZp1RLHH5YhdmmOPaIHGWe7uraqA2ytEL4Ube\nmkqHDDf2sjm0Oxakw0iZkX1l6hPVJ2q1KleZzvQRn+rgmBKGrTebyw3xbLjGKOZS\nuQFkDOeVZtuUmCytLXOE93Vv0hOGPttONaoD5qBoiCfz3fE5ILZAmK7UPYb/wRKl\nieiLdRglyhqJXjns/IhvTvNPYXMncIvMZW1p1JHY6te4smc+TrJo+5+Uv3a2ZUyK\nB8BpLsECgYEA27jA+IbwFv/Y7eTgNnWrM9LEnMCrsHExHbV6PGlZQ0dtZKc5Dtq7\nunuwUEta3odVNCoqTtIV1eVv0rDjGBQfeQqaC0XngbzusmuGPlg50C4tqvbqBhqZ\nxJhZcVb2sqrdYargxscibrNL67HifazeJRId9j8pAox5DZguJdsyZGUCgYEAycrG\ncik31YCWgC0BXbAOGtNn2VC/4h65J7JY6KL73dH0obVPKgcQESDduMEJ6uXFGnZk\nbMLEwrl8CXgCmYu6Lmtxy1cYCulm9Hu82KJ0fTSzLR9fli+tBV2nfxdNJPOmM1Qt\nkKoD6CnQj27eTrXFn7nQvlKJe+ZuuPk+PAWagpsCgYA1a8APLM+m5+GYRXN2Cjnr\nyazf58BWj86/SGZF1d9MCkvAkx++StQlzPjbLNcVD5ZZrn7G1zFT5grAER3Ftu7I\nARne78oPsx3d52KmOdEkmnWkAZB4l3MXZ2snsVsdqYlVu7QW4Eew3orw7TkCEUuZ\ne8QpIMYZxomQEpX1wkuIOQKBgDbOpGeNWmTasAXQM3bGwo32rVYQ4I0B2zg08ID/\nA3mT9OWW4RGBKZP9YTs08wShs48kaNJBdD+PMWlA9zPNB5xkAlxAI3+TNStiEECm\nnw0Cq0euJcAc4tl6Pmv+YC2RH6sBSf7ornb4JHVQn4CxTiO7zD5lHIJSa/BBge27\nd+PRAoGBALh0MrO4X7+9WDC1IFeiTrKvj5JC4C8w4AIyUaCfvJ4nn1LpV2WUVJBD\nsFnKEAuvrusPUT3Lsikn/QmnytlJHaYAMLAdvnjb/Yq41Ot+9PJmgp3CJUznLxH3\nTK7oAjGzziwjeLJLzI/ArBGXpBkaN8QjgzjXZt5vedV2WcGmocly\n-----END RSA PRIVATE KEY-----","builder_pem":"-----BEGIN RSA PRIVATE KEY-----\nMIIEpQIBAAKCAQEAsJnadG2ReDHEYNOx3jcuwQD0JN2P7AuSeg19F3n4DPkG9lpj\n5YZDgG+mWLwBF2SFhM66KlhwaPLEVWYOehuVuUV+hk2W60gX4LuL9KIgsfyL09xD\nHbYJ0bq434s2sgTzqmjbHY+nxnvemu85muos6LaWtLM5+sL8k5SQeTn+OlXlmazL\n6Sd0dFEHAxp5NXXKSGn9XluiFjeIRAatwITB0twYbrTSujYXeFnIUowOHdTCd49R\n99ar3h5HraUTWw9KPnW4vhLXYqi2UspGyckHXsAfvhsnE/Ge9sWNcllTLYxtdRjq\nCNwaXrGwQKRw3+9iW/6M16xRna85SF7DJX+S6QIDAQABAoIBAQCS2r3gh6SqUKg+\n5ItKgJTuhj5/0Yb3AQCDYmgdd52gHA2AGtZrbWUAjtfDfkNiEoM9VzNUN0ry2r4N\nTdrIC9xLvtBiGm9fpAnHJe5SNef+WkZknQtqz5AGycEmk3ueOaPul1duk6Eu2p7Y\nNAqxGf7SXdOg3FFgh3jFuIsTY/hWxOloreCN4K4ovXsi/k1y2NJ4wU+foIftJcDV\nUmubQ+ru2Zj3uWzSFNJ7OOJesKBxOaLPUTXZxeM2QEFbmeN3vb2ZMMUtE6+QsL5V\ndkJLpJXuuq8pMbRHVulRNMokTYOWznKOmp2WBoTzjattCVGECv/fotG2LKx4VeaG\nM6by3b8pAoGBANspTPJmoxXKO/SLYufZd47rfPovRJcOFKIG+83gTgUbXvWAmsxn\nXF3mEcP6+miZnuCz5gvu0/FUNb5By2enpg8v51+caVQ5L7nvHhO09gk/HkD4Sn3Y\nBZz8S+qGfCpAfJMHkjC7JEMwCJKAfQxOFY9vOXKK9Mt+vcaeM3wIq/yfAoGBAM5J\nJRkRLALZ8PpNSH/7nprh34xAENXPv//+efICZPyuv8ZgE/jMIVIAota7bAifkWDJ\nltqs/Us39awxOHp5Pe7Xb05PMeTsRe31OWB/GDAKpC6N5JcKbwZr76XnXYp2NSdb\ndFi9i17ErKwZECqM2bPCW74fSoDO3BuyOp+g27t3AoGBALKcZzSKh1ED33b+fh3c\nMr8Mlm9DRJAjDpe6P09bBdrNosdMB1ycxD9WeJYTHi9PO5d/pfWFr79XVPF4p7AT\nhpeL//IBBCp67LWI9iczbOy+PwbOE8+Z1YFKcQhykBDTO3OMUQ1cB0Kmi+Xxx3fW\nz2V1TQlXzAdohHuxhN4KJzibAoGBAKaYHdS7sH5xAhMy3M03KSTOK5p5lt8F03pr\nSpJu6p3ChvAvYZG5UWOHTfr7C8l/DIpM436g3EKl48r3STRnu+OqqqJkhNfrFKKT\nO445tg/+WA+c2jI84+McwkKKslmDE3RAgJq2INsdHJIz/4FNlPd+jFbjsGiMJuhb\nLMsDvtELAoGAR+y7tp5KWel1yHxlqRcrWuBLTctYy0KJnGrq8L44w2Ba+iCyofQn\niH4A+Q2uy9Mvly1kWKS/HuV/2hZ7cYw7I9xQlHWbrNiG2bq3Pu/kRN15PtShJFBo\nw4lowiVlDe0PR6eGemcQbUpowWULboeJDNhHd6J9ovTfIp5GMTypy/s=\n-----END RSA PRIVATE KEY-----\n","builder_pub":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwmdp0bZF4McRg07HeNy7BAPQk3Y/sC5J6DX0XefgM+Qb2WmPlhkOAb6ZYvAEXZIWEzroqWHBo8sRVZg56G5W5RX6GTZbrSBfgu4v0oiCx/IvT3EMdtgnRurjfizayBPOqaNsdj6fGe96a7zma6izotpa0szn6wvyTlJB5Of46VeWZrMvpJ3R0UQcDGnk1dcpIaf1eW6IWN4hEBq3AhMHS3BhutNK6Nhd4WchSjA4d1MJ3j1H31qveHketpRNbD0o+dbi+EtdiqLZSykbJyQdewB++GycT8Z72xY1yWVMtjG11GOoI3BpesbBApHDf72Jb/ozXrFGdrzlIXsMlf5Lp","license_file":"ZGVsaXZlcnktbGljZW5zZQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAADAwMDY0NCAAMDAwNzY1IAAwMDAwMjQgADAwMDAwMDAwMjQx\nIDEyNjEzMjQ3NTcxIDAxNDM1NwAgMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB1c3RhcgAwMHNldGgA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc3RhZmYAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAwMDAwMDAgADAwMDAwMCAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAB7Imd1aWQiOiI0YTA2NTA0OC1jZjg1LTRjMmUt\nOGJkYS05YTgyYzljOGU1ZTgiLCJkYXRlIjoiMjAxNS0xMC0yNVQyMTo1MToz\nM1oiLCJsaWNlbnNlX3ZlcnNpb24iOjEsImNvbXBhbnkiOiJMZWFybiBDaGVm\nIFR1dG9yaWFsIEV2YWx1YXRpb24gT25seSIsInR5cGUiOiJPVUVwQXgifQAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGRlbGl2ZXJ5LWxp\nY2Vuc2Uuc2lnAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw\nMDA2NDQgADAwMDc2NSAAMDAwMDI0IAAwMDAwMDAwMDQwMCAxMjYxMzI0NzU3\nMSAwMTUxMzUAIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAdXN0YXIAMDBzZXRoAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAHN0YWZmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAMDAwMDAwIAAwMDAwMDAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAARgdtYPAP3wKfLeo9S9r5CaGex//aD7oYFyXD9m3oGQoSsmboyMsv\nFrD6ADFH0gSKa8bdC/7AqLDcppni65eCh3+TmLp+r8uUDffgMvf+CIyTcR3I\nw+S1nkd7BvYto/kF5+jSyOO002wNDU+45zSqwE/ReuBkDtoXV0GAahzVdWOq\n9OTRWe07EdNyKzq0CmLjBb/gziS999MkihSeQpT8fmWcqXFVkQNdhbHDq7Gl\n78Uy1fbDI/vzYcsA4A08LqQD1cEQYc8ZBJfA11Vczacbbnvw32y7dZZc9t1Q\nUsCMcEmpwWrQ9YVfyW3ZSQ8wNVIdUwi4eZi8/SOjl3IasZcQngAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\nAAAAAAAAAAAAAAAA\n"} 2 | --------------------------------------------------------------------------------