sambot 0.1.19
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.rubocop.yml +8 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/README.md +20 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/sambot +3 -0
- data/bin/setup +8 -0
- data/lib/sambot.rb +5 -0
- data/lib/sambot/cli.rb +33 -0
- data/lib/sambot/commands/cookbook.rb +68 -0
- data/lib/sambot/commands/inventory.rb +13 -0
- data/lib/sambot/commands/secret.rb +27 -0
- data/lib/sambot/commands/teamcity.rb +13 -0
- data/lib/sambot/domain/common/application_exception.rb +9 -0
- data/lib/sambot/domain/common/config.rb +25 -0
- data/lib/sambot/domain/common/file_checker.rb +30 -0
- data/lib/sambot/domain/common/runtime.rb +25 -0
- data/lib/sambot/domain/common/template_provider.rb +13 -0
- data/lib/sambot/domain/common/ui.rb +17 -0
- data/lib/sambot/domain/cookbooks/assistant_chef.rb +87 -0
- data/lib/sambot/domain/cookbooks/kitchen.rb +30 -0
- data/lib/sambot/domain/cookbooks/metadata.rb +30 -0
- data/lib/sambot/domain/secrets/vault.rb +28 -0
- data/lib/sambot/templates/.gitignore +31 -0
- data/lib/sambot/templates/.kitchen.gcp.linux.yml +39 -0
- data/lib/sambot/templates/.kitchen.gcp.windows.yml +39 -0
- data/lib/sambot/templates/.kitchen.linux.yml +16 -0
- data/lib/sambot/templates/.kitchen.rackspace.linux.yml +27 -0
- data/lib/sambot/templates/.kitchen.rackspace.windows.yml +29 -0
- data/lib/sambot/templates/.kitchen.windows.yml +16 -0
- data/lib/sambot/templates/metadata.rb.erb +9 -0
- data/lib/sambot/templates/pre_push +4 -0
- data/lib/sambot/version.rb +3 -0
- data/sambot.gemspec +30 -0
- metadata +209 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 13646525edfdebe22db06eb03641637b8e13fb24
|
4
|
+
data.tar.gz: b5d51109ac21f78d913009a0681e184b4626e2cd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 99fcf7c187b4cec866c6bb54056c0aca9cfb247dce41efb6751d23fc7b987088c9032bc45af03049b0ce9dac414ebdceec8815bfbc4733a08d31381d33cfbd3d
|
7
|
+
data.tar.gz: 7a51961cb15d54e62eac4631dbd9fb8ad7fca6b330efe59338aba8e85dd98f6277e264a9759e3090829aec6fc80fa1c2296318c168197f7647ec0bdde9d9aad6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.6
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Sambot
|
2
|
+
|
3
|
+
Sambot is our internal Platform Engineering gem to help standardize and simplify our DevOps workflow.
|
4
|
+
|
5
|
+
It can be used both as a library - to read secrets from Hashicorp Vault in a Chef cookbook for example - or as an
|
6
|
+
executable to guide tasks such as managing Chef cookbooks.
|
7
|
+
|
8
|
+
## Usage
|
9
|
+
|
10
|
+
To install the gem, simply run `gem install sambot`.
|
11
|
+
|
12
|
+
Run `sambot` to be shown the help menu.
|
13
|
+
|
14
|
+
## Available Commands
|
15
|
+
|
16
|
+
To view the list of available commands and their descriptions, refer to the files in lib/sambot/commands.
|
17
|
+
|
18
|
+
## Contributing
|
19
|
+
|
20
|
+
Bug reports and pull requests are welcome on GitHub at https://github.exacttarget.com/ads-devops/sambot.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'sambot'
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require 'pry'
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require 'irb'
|
14
|
+
IRB.start(__FILE__)
|
data/bin/sambot
ADDED
data/bin/setup
ADDED
data/lib/sambot.rb
ADDED
data/lib/sambot/cli.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require_relative 'domain/common/application_exception'
|
3
|
+
require_relative 'domain/common/file_checker'
|
4
|
+
require_relative 'domain/secrets/vault'
|
5
|
+
require_relative 'domain/common/ui'
|
6
|
+
require_relative 'domain/common/config'
|
7
|
+
require_relative 'domain/common/runtime'
|
8
|
+
require_relative 'domain/common/template_provider'
|
9
|
+
require_relative 'domain/cookbooks/kitchen'
|
10
|
+
require_relative 'domain/cookbooks/assistant_chef'
|
11
|
+
require_relative 'domain/cookbooks/metadata'
|
12
|
+
require_relative 'commands/cookbook'
|
13
|
+
require_relative 'commands/secret'
|
14
|
+
require_relative 'commands/teamcity'
|
15
|
+
require_relative 'commands/inventory'
|
16
|
+
|
17
|
+
module Sambot
|
18
|
+
class CLI < Thor
|
19
|
+
|
20
|
+
desc 'teamcity', 'Manage TeamCity'
|
21
|
+
subcommand 'teamcity', Sambot::Commands::TeamCity
|
22
|
+
|
23
|
+
desc 'cookbook', 'Manage Chef cookbooks'
|
24
|
+
subcommand 'cookbook', Sambot::Commands::Cookbook
|
25
|
+
|
26
|
+
desc 'secret', 'Manage secrets inside Chef cookbooks'
|
27
|
+
subcommand 'secret', Sambot::Commands::Secret
|
28
|
+
|
29
|
+
desc 'inventory', 'Manage instance inventories'
|
30
|
+
subcommand 'inventory', Sambot::Commands::Inventory
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
ESSENTIAL_FILES = ['.config.yml', 'spec', 'recipes', 'README.md'].freeze
|
5
|
+
GENERATED_FILES = ['teamcity.sh', 'chefignore', 'Berksfile', '.rubocop.yml', '.gitignore'].freeze
|
6
|
+
|
7
|
+
class Cookbook < Thor
|
8
|
+
|
9
|
+
include Domain::Common::UI
|
10
|
+
include Domain::Common::Runtime
|
11
|
+
|
12
|
+
namespace 'cookbook'
|
13
|
+
|
14
|
+
desc 'clean', 'Remove all generated build files from a cookbook'
|
15
|
+
long_desc <<-LONGDESC
|
16
|
+
`sambot cookbook clean` will remove all files generated by `sambot cookbook build`.
|
17
|
+
This is required to ensure the generated files are not stored in source control.
|
18
|
+
LONGDESC
|
19
|
+
def clean
|
20
|
+
ensure_latest
|
21
|
+
info('Removing all generated files from this cookbook.')
|
22
|
+
modified_files = Sambot::Domain::Cookbooks::AssistantChef.new.clean_cookbook(GENERATED_FILES)
|
23
|
+
modified_files.each {|file| debug("./#{file} has been removed.")}
|
24
|
+
info('The cookbook has been successfully cleaned.')
|
25
|
+
rescue Domain::Common::ApplicationException => e
|
26
|
+
say(e.message, :red)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc 'build', 'Builds a cookbook from its configuration file'
|
30
|
+
long_desc <<-LONGDESC
|
31
|
+
`sambot cookbook build` will generate all the files required for the functioning
|
32
|
+
of a Chef cookbook from a configuration file. The motivation behind this setup is to
|
33
|
+
standardize and simplify the Chef cookbook creation workflow. The configuration file should be
|
34
|
+
called .config.yml and stored in the root of the Chef cookbook.
|
35
|
+
LONGDESC
|
36
|
+
def build
|
37
|
+
ensure_latest
|
38
|
+
modified_files = Sambot::Domain::Cookbooks::AssistantChef.new.build_cookbook(ESSENTIAL_FILES, GENERATED_FILES)
|
39
|
+
modified_files.each {|file| debug("./#{file} has been added to the cookbook.")}
|
40
|
+
info('The cookbook has been successfully built.')
|
41
|
+
rescue Domain::Common::ApplicationException => e
|
42
|
+
say(e.message, :red)
|
43
|
+
end
|
44
|
+
|
45
|
+
desc 'generate', 'Creates a new cookbook'
|
46
|
+
long_desc <<-LONGDESC
|
47
|
+
`sambot cookbook generate` will create a new cookbook. This can be either a
|
48
|
+
wrapper cookbook or an instance role cookbook.
|
49
|
+
LONGDESC
|
50
|
+
option :name
|
51
|
+
option :platform, :desc => 'Can be either "windows" or "linux"'
|
52
|
+
option :type, :desc => 'Can be either "wrapper" or "role"'
|
53
|
+
def generate()
|
54
|
+
ensure_latest
|
55
|
+
name = ask(' What is the name of this cookbook?')
|
56
|
+
platform = ask(' What operating system will this cookbook run on?', :limited_to => ['windows', 'linux'])
|
57
|
+
type = ask(' What type of cookbook will this be?', :limited_to => ['wrapper', 'role'])
|
58
|
+
Sambot::Domain::Cookbooks::AssistantChef.new.generate_cookbook(name, options[:platform], options[:type], ESSENTIAL_FILES, GENERATED_FILES)
|
59
|
+
info('The cookbook has been successfully generated.')
|
60
|
+
rescue Domain::Common::ApplicationException => e
|
61
|
+
say(e.message, :red)
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
module Sambot
|
3
|
+
module Commands
|
4
|
+
|
5
|
+
class Secret < Thor
|
6
|
+
|
7
|
+
namespace 'secret'
|
8
|
+
|
9
|
+
desc 'read PATH', 'Reads a secret from the vault'
|
10
|
+
long_desc <<-LONGDESC
|
11
|
+
`sambot secret read /path/to/my/secret` will read the secret located in the
|
12
|
+
path provided out of Hashicorp Vault. It relies on a proprietary tool written
|
13
|
+
by the Advertising Studio Platform Engineering team called as-vault. Make sure
|
14
|
+
you have this tool installed before using this command.
|
15
|
+
LONGDESC
|
16
|
+
def read(path)
|
17
|
+
Sambot::Vault.new.read(path)
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'write', 'Write a secret to the vault'
|
21
|
+
def write
|
22
|
+
Sambot::Vault.new.write(path)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Sambot
|
4
|
+
module Domain
|
5
|
+
module Common
|
6
|
+
class Config
|
7
|
+
|
8
|
+
CONFIGURATION_FILENAME = '.config.yml'.freeze
|
9
|
+
|
10
|
+
def read(path = nil)
|
11
|
+
path ||= File.join(Dir.getwd, CONFIGURATION_FILENAME)
|
12
|
+
raise ApplicationException, "The configuration file was not found at #{path}." unless File.exist?(path)
|
13
|
+
config = YAML.load_file(path)
|
14
|
+
raise ApplicationException, 'Missing platform in the .config.yml configuration file' unless config['platform']
|
15
|
+
raise ApplicationException, 'Missing version in the .config.yml configuration file' unless config['version']
|
16
|
+
raise ApplicationException, 'Missing list of suites in the .config.yml configuration file' unless config['suites']
|
17
|
+
raise ApplicationException, 'Missing description in the .config.yml configuration file' unless config['description']
|
18
|
+
config['name'] = File.basename(Dir.getwd)
|
19
|
+
config
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Domain
|
3
|
+
module Common
|
4
|
+
class FileChecker
|
5
|
+
|
6
|
+
def verify(path)
|
7
|
+
return if File.exist?(path) || Dir.exist?(path)
|
8
|
+
raise ApplicationException, "The file or directory #{path} was not found in the current directory."
|
9
|
+
end
|
10
|
+
|
11
|
+
def update(files)
|
12
|
+
return unless files
|
13
|
+
files.each do |filename|
|
14
|
+
update_template(filename)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def update_template(filename)
|
21
|
+
working_path = filename
|
22
|
+
template_path = TemplateProvider.new.get_path(filename)
|
23
|
+
File.delete(working_path) if File.exist?(working_path)
|
24
|
+
FileUtils.cp(template_path, working_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'gems'
|
2
|
+
|
3
|
+
module Sambot
|
4
|
+
module Domain
|
5
|
+
module Common
|
6
|
+
module Runtime
|
7
|
+
|
8
|
+
def is_obsolete
|
9
|
+
latest_version = Gems.new.versions('sambot')[0]["number"]
|
10
|
+
Gem::Version.new(Sambot::VERSION) < Gem::Version.new(latest_version)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ensure_latest
|
14
|
+
latest_version = Gems.new.versions('sambot')[0]["number"]
|
15
|
+
debug("Current Sambot version is #{Sambot::VERSION}.")
|
16
|
+
debug("Latest Sambot version is #{latest_version}.")
|
17
|
+
if is_obsolete
|
18
|
+
say('A newer version of the sambot gem exists. Please update the gem before continuing.', :red)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
module Sambot
|
4
|
+
module Domain
|
5
|
+
module Cookbooks
|
6
|
+
class AssistantChef
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@modified_files = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_cookbook(essential_files, generated_files)
|
13
|
+
validate_cookbook_structure(essential_files, generated_files)
|
14
|
+
config = Common::Config.new.read
|
15
|
+
setup_test_kitchen(config)
|
16
|
+
build_metadata(config)
|
17
|
+
copy_git_hooks()
|
18
|
+
@modified_files
|
19
|
+
end
|
20
|
+
|
21
|
+
def clean_cookbook(generated_files)
|
22
|
+
delete_file('metadata.rb')
|
23
|
+
generated_files.each { |file| delete_file(file) }
|
24
|
+
Dir.glob('\.kitchen*\.yml').each { |file| delete_file(file)}
|
25
|
+
@modified_files
|
26
|
+
end
|
27
|
+
|
28
|
+
def generate_cookbook(name, platform, type, description, essential_files, generated_files)
|
29
|
+
FileUtils.mkdir(name)
|
30
|
+
FileUtils.mkdir(File.join(name, 'test'))
|
31
|
+
FileUtils.mkdir(File.join(name, 'spec'))
|
32
|
+
FileUtils.mkdir(File.join(name, 'recipes'))
|
33
|
+
Dir.chdir(name) do
|
34
|
+
write_config(description, platform, type)
|
35
|
+
build_cookbook(essential_files, generated_files)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def write_config(description, platform, type)
|
42
|
+
contents = {
|
43
|
+
:version => '0.0.1',
|
44
|
+
:platform => platform,
|
45
|
+
:suites => nil,
|
46
|
+
:description => nil
|
47
|
+
}.to_yaml
|
48
|
+
File.write('.config.yml', contents)
|
49
|
+
end
|
50
|
+
|
51
|
+
def copy_git_hooks
|
52
|
+
working_path = '.git/hooks/pre_push'
|
53
|
+
template_path = Common::TemplateProvider.new.get_path('pre_push')
|
54
|
+
File.delete(working_path) if File.exist?(working_path)
|
55
|
+
FileUtils.cp(template_path, working_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def delete_file(filename)
|
59
|
+
return unless File.exist?(filename)
|
60
|
+
File.delete(filename)
|
61
|
+
@modified_files << filename
|
62
|
+
end
|
63
|
+
|
64
|
+
def validate_cookbook_structure(essential_files, generated_files)
|
65
|
+
essential_files.each { |path| Common::FileChecker.new.verify(path) }
|
66
|
+
Common::FileChecker.new.update(generated_files)
|
67
|
+
@modified_files = @modified_files + generated_files
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup_test_kitchen(config)
|
71
|
+
files = Kitchen.new.generate_yml(config['name'], config['platform'], config['suites'])
|
72
|
+
files.each do |filename, contents|
|
73
|
+
File.write(filename, contents)
|
74
|
+
@modified_files << filename
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def build_metadata(config)
|
79
|
+
result = Metadata.new.generate(config['name'], config['platform'], config['version'], config['description'])
|
80
|
+
File.write('metadata.rb', result)
|
81
|
+
@modified_files << 'metadata.rb'
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Domain
|
3
|
+
module Cookbooks
|
4
|
+
class Kitchen
|
5
|
+
|
6
|
+
def generate_yml(name, platform, suites = nil)
|
7
|
+
raise ApplicationException, 'Missing platform when trying to generate Test-Kitchen YAML.' unless platform
|
8
|
+
raise ApplicationException, 'Missing cookbook name when trying to generate Test-Kitchen YAML.' unless name
|
9
|
+
result = {}
|
10
|
+
['', '.gcp', '.rackspace'].map do |type|
|
11
|
+
yaml = load_yaml(type, platform, name)
|
12
|
+
yaml['suites'] = suites if suites
|
13
|
+
result[".kitchen#{type}.yml"] = yaml.to_yaml
|
14
|
+
end
|
15
|
+
result
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def load_yaml(type, platform, name)
|
21
|
+
filename = File.join(File.dirname(__FILE__), '../../templates', ".kitchen#{type}.#{platform}.yml")
|
22
|
+
contents = File.read(filename)
|
23
|
+
contents = contents.gsub(/@@cookbook_name@@/, name)
|
24
|
+
YAML.load(contents)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'erubis'
|
2
|
+
|
3
|
+
module Sambot
|
4
|
+
module Domain
|
5
|
+
module Cookbooks
|
6
|
+
class Metadata
|
7
|
+
|
8
|
+
def generate(name, platform, version, description)
|
9
|
+
context = {
|
10
|
+
'cookbook_name' => name,
|
11
|
+
'cookbook_platfrom' => platform,
|
12
|
+
'cookbook_version' => version,
|
13
|
+
'cookbook_description' => description
|
14
|
+
}
|
15
|
+
generate_metadata(context)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def generate_metadata(context)
|
21
|
+
filename = File.join(File.dirname(__FILE__), '../../templates', 'metadata.rb.erb')
|
22
|
+
input = File.read(filename)
|
23
|
+
eruby = Erubis::Eruby.new(input)
|
24
|
+
eruby.evaluate(context)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Domain
|
3
|
+
module Chef
|
4
|
+
class Vault
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
if Gem.win_platform?
|
8
|
+
@tool_dir = 'C:/Program Files/vault'
|
9
|
+
@tool_exe = 'as-vault-tool.exe'
|
10
|
+
else
|
11
|
+
@tool_dir = '/opt/vault-tool'
|
12
|
+
@tool_exe = 'as-vault-tool'
|
13
|
+
end
|
14
|
+
@tool_version = '1.0.2'
|
15
|
+
end
|
16
|
+
|
17
|
+
def read(path)
|
18
|
+
`#{@tool_dir}/#{@tool_version}/#{@tool_exe} read -p #{path}`
|
19
|
+
end
|
20
|
+
|
21
|
+
def write(path)
|
22
|
+
raise 'Not yet implemented'
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
.vagrant
|
2
|
+
nodes
|
3
|
+
env
|
4
|
+
syntaxcache
|
5
|
+
*.pem
|
6
|
+
.kitchen/
|
7
|
+
.kitchen.local.yml
|
8
|
+
.vagrant
|
9
|
+
Berksfile.lock
|
10
|
+
*~
|
11
|
+
*#
|
12
|
+
*.lock
|
13
|
+
.#*
|
14
|
+
\#*#
|
15
|
+
.*.sw[a-z]
|
16
|
+
*.un~
|
17
|
+
# Bundler
|
18
|
+
Gemfile.lock
|
19
|
+
bin/*
|
20
|
+
.bundle/*
|
21
|
+
.kitchen/
|
22
|
+
.kitchen.local.yml
|
23
|
+
berks-cookbooks
|
24
|
+
Berksfile
|
25
|
+
teamcity.sh
|
26
|
+
metadata.rb
|
27
|
+
.kitchen.rackspace.yml
|
28
|
+
.kitchen.gcp.yml
|
29
|
+
.rubocop.yml
|
30
|
+
chefignore
|
31
|
+
teamcity.sh
|
@@ -0,0 +1,39 @@
|
|
1
|
+
---
|
2
|
+
provisioner:
|
3
|
+
name: chef_zero
|
4
|
+
log_level: info
|
5
|
+
deprecations_as_errors: true
|
6
|
+
cookbooks_path:
|
7
|
+
- .
|
8
|
+
|
9
|
+
platforms:
|
10
|
+
- name: linux
|
11
|
+
driver:
|
12
|
+
name: "gce"
|
13
|
+
region: <%= ENV['GCP_REGION'] %>
|
14
|
+
project: <%= ENV['GCP_PROJECT'] %>
|
15
|
+
image_project: <%= ENV['GCP_IMAGE_PROJECT'] %>
|
16
|
+
image_family: <%= ENV['GCP_IMAGE_FAMILY'] %>
|
17
|
+
network: <%= ENV['GCP_NETWORK'] %>
|
18
|
+
subnet: <%= ENV['GCP_SUBNETWORK'] %>
|
19
|
+
use_private_ip: false
|
20
|
+
preemptible: true
|
21
|
+
service_account_name: <%= ENV['GCP_SERVICE_ACCOUNT_NAME'] %>
|
22
|
+
service_account_scopes:
|
23
|
+
- userinfo-email
|
24
|
+
- logging-write
|
25
|
+
- monitoring-write
|
26
|
+
tags:
|
27
|
+
- "test-kitchen"
|
28
|
+
- "consul-agent"
|
29
|
+
- "vault-client"
|
30
|
+
|
31
|
+
transport:
|
32
|
+
username: chefuser
|
33
|
+
ssh_key:
|
34
|
+
- <%= ENV['GCP_SSH_KEY'] || "" %>
|
35
|
+
|
36
|
+
verifier:
|
37
|
+
name: inspec
|
38
|
+
format: junit
|
39
|
+
output: inspec_results.xml
|
@@ -0,0 +1,39 @@
|
|
1
|
+
---
|
2
|
+
provisioner:
|
3
|
+
name: chef_zero
|
4
|
+
log_level: info
|
5
|
+
deprecations_as_errors: true
|
6
|
+
cookbooks_path:
|
7
|
+
- .
|
8
|
+
|
9
|
+
platforms:
|
10
|
+
- name: windows
|
11
|
+
driver:
|
12
|
+
name: "gce"
|
13
|
+
region: <%= ENV['GCP_REGION'] %>
|
14
|
+
project: <%= ENV['GCP_PROJECT'] %>
|
15
|
+
image_project: <%= ENV['GCP_IMAGE_PROJECT'] %>
|
16
|
+
image_family: <%= ENV['GCP_IMAGE_FAMILY'] %>
|
17
|
+
network: <%= ENV['GCP_NETWORK'] %>
|
18
|
+
subnet: <%= ENV['GCP_SUBNETWORK'] %>
|
19
|
+
use_private_ip: false
|
20
|
+
preemptible: true
|
21
|
+
service_account_name: <%= ENV['GCP_SERVICE_ACCOUNT_NAME'] %>
|
22
|
+
service_account_scopes:
|
23
|
+
- userinfo-email
|
24
|
+
- logging-write
|
25
|
+
- monitoring-write
|
26
|
+
tags:
|
27
|
+
- "test-kitchen"
|
28
|
+
- "consul-agent"
|
29
|
+
- "vault-client"
|
30
|
+
|
31
|
+
transport:
|
32
|
+
username: chefuser
|
33
|
+
ssh_key:
|
34
|
+
- <%= ENV['GCP_SSH_KEY'] || "" %>
|
35
|
+
|
36
|
+
verifier:
|
37
|
+
name: inspec
|
38
|
+
format: junit
|
39
|
+
output: inspec_results.xml
|
@@ -0,0 +1,27 @@
|
|
1
|
+
---
|
2
|
+
provisioner:
|
3
|
+
name: chef_zero
|
4
|
+
log_level: info
|
5
|
+
deprecations_as_errors: true
|
6
|
+
cookbooks_path:
|
7
|
+
- .
|
8
|
+
|
9
|
+
platforms:
|
10
|
+
- name: linux
|
11
|
+
transport:
|
12
|
+
ssh_key: ./id_rsa
|
13
|
+
driver:
|
14
|
+
name: rackspace
|
15
|
+
rackconnect_wait: true
|
16
|
+
servicenet: true
|
17
|
+
require_chef_omnibus: true
|
18
|
+
no_ssh_tcp_check: true
|
19
|
+
no_ssh_tcp_check_sleep: 240
|
20
|
+
image_id: 398c5f65-23e2-44da-97d8-d28ff5ec583b
|
21
|
+
flavor_id: 6
|
22
|
+
public_key_path: ./id_rsa.pub
|
23
|
+
rackspace_region: 'lon'
|
24
|
+
server_name: @@cookbook_name@@-<%= Time.now.to_i %>
|
25
|
+
|
26
|
+
verifier:
|
27
|
+
name: inspec
|
@@ -0,0 +1,29 @@
|
|
1
|
+
---
|
2
|
+
provisioner:
|
3
|
+
name: chef_zero
|
4
|
+
log_level: info
|
5
|
+
deprecations_as_errors: true
|
6
|
+
cookbooks_path:
|
7
|
+
- .
|
8
|
+
|
9
|
+
platforms:
|
10
|
+
- name: "windows"
|
11
|
+
transport:
|
12
|
+
ssh_key: ./id_rsa
|
13
|
+
driver:
|
14
|
+
name: rackspace
|
15
|
+
rackconnect_wait: true
|
16
|
+
servicenet: true
|
17
|
+
require_chef_omnibus: true
|
18
|
+
no_ssh_tcp_check: true
|
19
|
+
no_ssh_tcp_check_sleep: 240
|
20
|
+
image_id: 398c5f65-23e2-44da-97d8-d28ff5ec583b
|
21
|
+
flavor_id: 6
|
22
|
+
public_key_path: ./id_rsa.pub
|
23
|
+
rackspace_region: 'lon'
|
24
|
+
server_name: @@cookbook_name@@-<%= Time.now.to_i %>
|
25
|
+
|
26
|
+
verifier:
|
27
|
+
name: inspec
|
28
|
+
format: junit
|
29
|
+
output: inspec_results.xml
|
@@ -0,0 +1,9 @@
|
|
1
|
+
name '<%= @cookbook_name %>'
|
2
|
+
maintainer 'Salesforce Marketing Cloud - Advertising Studio'
|
3
|
+
maintainer_email 'as-nightswatch@salesforce.com'
|
4
|
+
license 'All rights reserved'
|
5
|
+
description '<%= @cookbook_description %>'
|
6
|
+
long_description IO.read(File.join(File.dirname(__FILE__), 'README.md'))
|
7
|
+
version '<%= @cookbook_version %>'
|
8
|
+
issues_url 'https://github.exacttarget.com/ads-cookbooks/<%= @cookbook_name %>/issues'
|
9
|
+
source_url 'https://github.exacttarget.com/ads-cookbooks/<%= @cookbook_name %>'
|
data/sambot.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sambot/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'sambot'
|
8
|
+
spec.version = Sambot::VERSION
|
9
|
+
spec.authors = ['Olivier Kouame']
|
10
|
+
spec.email = ['olivier.kouame@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Tooling for a DevOps workflow'
|
13
|
+
spec.homepage = 'http://github.com/okouam/sambot'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'bin'
|
19
|
+
spec.executables = 'sambot'
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_dependency 'thor', '~> 0.19'
|
23
|
+
spec.add_dependency 'erubis', '~> 2.7', '>= 2.7.0'
|
24
|
+
spec.add_dependency 'gems', '~> 1.0', '>= 1.0.0'
|
25
|
+
spec.add_development_dependency 'rubocop', '~> 0.49'
|
26
|
+
spec.add_development_dependency 'gem-release', '~> 1.0.0'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
+
end
|
metadata
ADDED
@@ -0,0 +1,209 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sambot
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.19
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Olivier Kouame
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-05-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: thor
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.19'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.19'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: erubis
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.7'
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 2.7.0
|
37
|
+
type: :runtime
|
38
|
+
prerelease: false
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "~>"
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.7'
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 2.7.0
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: gems
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '1.0'
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 1.0.0
|
57
|
+
type: :runtime
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - "~>"
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.0'
|
64
|
+
- - ">="
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: 1.0.0
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: rubocop
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: '0.49'
|
74
|
+
type: :development
|
75
|
+
prerelease: false
|
76
|
+
version_requirements: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - "~>"
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0.49'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: gem-release
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
requirements:
|
85
|
+
- - "~>"
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.0.0
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
requirements:
|
92
|
+
- - "~>"
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: 1.0.0
|
95
|
+
- !ruby/object:Gem::Dependency
|
96
|
+
name: bundler
|
97
|
+
requirement: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - "~>"
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '1.14'
|
102
|
+
type: :development
|
103
|
+
prerelease: false
|
104
|
+
version_requirements: !ruby/object:Gem::Requirement
|
105
|
+
requirements:
|
106
|
+
- - "~>"
|
107
|
+
- !ruby/object:Gem::Version
|
108
|
+
version: '1.14'
|
109
|
+
- !ruby/object:Gem::Dependency
|
110
|
+
name: rake
|
111
|
+
requirement: !ruby/object:Gem::Requirement
|
112
|
+
requirements:
|
113
|
+
- - "~>"
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
version: '10.0'
|
116
|
+
type: :development
|
117
|
+
prerelease: false
|
118
|
+
version_requirements: !ruby/object:Gem::Requirement
|
119
|
+
requirements:
|
120
|
+
- - "~>"
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
version: '10.0'
|
123
|
+
- !ruby/object:Gem::Dependency
|
124
|
+
name: rspec
|
125
|
+
requirement: !ruby/object:Gem::Requirement
|
126
|
+
requirements:
|
127
|
+
- - "~>"
|
128
|
+
- !ruby/object:Gem::Version
|
129
|
+
version: '3.0'
|
130
|
+
type: :development
|
131
|
+
prerelease: false
|
132
|
+
version_requirements: !ruby/object:Gem::Requirement
|
133
|
+
requirements:
|
134
|
+
- - "~>"
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: '3.0'
|
137
|
+
description:
|
138
|
+
email:
|
139
|
+
- olivier.kouame@gmail.com
|
140
|
+
executables:
|
141
|
+
- sambot
|
142
|
+
extensions: []
|
143
|
+
extra_rdoc_files: []
|
144
|
+
files:
|
145
|
+
- ".gitignore"
|
146
|
+
- ".rspec"
|
147
|
+
- ".rubocop.yml"
|
148
|
+
- ".ruby-version"
|
149
|
+
- Gemfile
|
150
|
+
- README.md
|
151
|
+
- Rakefile
|
152
|
+
- bin/console
|
153
|
+
- bin/sambot
|
154
|
+
- bin/setup
|
155
|
+
- lib/sambot.rb
|
156
|
+
- lib/sambot/cli.rb
|
157
|
+
- lib/sambot/commands/cookbook.rb
|
158
|
+
- lib/sambot/commands/inventory.rb
|
159
|
+
- lib/sambot/commands/secret.rb
|
160
|
+
- lib/sambot/commands/teamcity.rb
|
161
|
+
- lib/sambot/domain/common/application_exception.rb
|
162
|
+
- lib/sambot/domain/common/config.rb
|
163
|
+
- lib/sambot/domain/common/file_checker.rb
|
164
|
+
- lib/sambot/domain/common/runtime.rb
|
165
|
+
- lib/sambot/domain/common/template_provider.rb
|
166
|
+
- lib/sambot/domain/common/ui.rb
|
167
|
+
- lib/sambot/domain/cookbooks/assistant_chef.rb
|
168
|
+
- lib/sambot/domain/cookbooks/kitchen.rb
|
169
|
+
- lib/sambot/domain/cookbooks/metadata.rb
|
170
|
+
- lib/sambot/domain/secrets/vault.rb
|
171
|
+
- lib/sambot/templates/.gitignore
|
172
|
+
- lib/sambot/templates/.kitchen.gcp.linux.yml
|
173
|
+
- lib/sambot/templates/.kitchen.gcp.windows.yml
|
174
|
+
- lib/sambot/templates/.kitchen.linux.yml
|
175
|
+
- lib/sambot/templates/.kitchen.rackspace.linux.yml
|
176
|
+
- lib/sambot/templates/.kitchen.rackspace.windows.yml
|
177
|
+
- lib/sambot/templates/.kitchen.windows.yml
|
178
|
+
- lib/sambot/templates/.rubocop.yml
|
179
|
+
- lib/sambot/templates/Berksfile
|
180
|
+
- lib/sambot/templates/chefignore
|
181
|
+
- lib/sambot/templates/metadata.rb.erb
|
182
|
+
- lib/sambot/templates/pre_push
|
183
|
+
- lib/sambot/templates/teamcity.sh
|
184
|
+
- lib/sambot/version.rb
|
185
|
+
- sambot.gemspec
|
186
|
+
homepage: http://github.com/okouam/sambot
|
187
|
+
licenses: []
|
188
|
+
metadata: {}
|
189
|
+
post_install_message:
|
190
|
+
rdoc_options: []
|
191
|
+
require_paths:
|
192
|
+
- lib
|
193
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
199
|
+
requirements:
|
200
|
+
- - ">="
|
201
|
+
- !ruby/object:Gem::Version
|
202
|
+
version: '0'
|
203
|
+
requirements: []
|
204
|
+
rubyforge_project:
|
205
|
+
rubygems_version: 2.4.5.2
|
206
|
+
signing_key:
|
207
|
+
specification_version: 4
|
208
|
+
summary: Tooling for a DevOps workflow
|
209
|
+
test_files: []
|