sambot 0.1.99 → 0.1.100

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +10 -1
  4. data/bin/sambot +3 -0
  5. data/lib/sambot.rb +12 -2
  6. data/lib/sambot/chef/cookbook.rb +8 -13
  7. data/lib/sambot/chef/kitchen.rb +6 -5
  8. data/lib/sambot/chef/metadata.rb +2 -0
  9. data/lib/sambot/chef/server.rb +21 -23
  10. data/lib/sambot/cli.rb +4 -1
  11. data/lib/sambot/commands/base_command.rb +65 -1
  12. data/lib/sambot/commands/cookbook.rb +18 -60
  13. data/lib/sambot/commands/dns.rb +45 -0
  14. data/lib/sambot/commands/instance.rb +17 -0
  15. data/lib/sambot/commands/rdp.rb +18 -0
  16. data/lib/sambot/commands/report.rb +5 -6
  17. data/lib/sambot/commands/session.rb +16 -15
  18. data/lib/sambot/commands/team.rb +16 -0
  19. data/lib/sambot/commands/workstation.rb +8 -8
  20. data/lib/sambot/config.rb +2 -0
  21. data/lib/sambot/developer_workflow/brew.rb +31 -0
  22. data/lib/sambot/developer_workflow/dns.rb +22 -11
  23. data/lib/sambot/developer_workflow/networking.rb +30 -0
  24. data/lib/sambot/developer_workflow/session.rb +90 -11
  25. data/lib/sambot/developer_workflow/tunnel.rb +15 -0
  26. data/lib/sambot/developer_workflow/vault.rb +2 -0
  27. data/lib/sambot/developer_workflow/workstation.rb +33 -15
  28. data/lib/sambot/dns/records.rb +98 -0
  29. data/lib/sambot/dns/repository.rb +51 -0
  30. data/lib/sambot/docs/cookbook/build.txt +12 -0
  31. data/lib/sambot/docs/cookbook/clean.txt +2 -0
  32. data/lib/sambot/docs/cookbook/generate.txt +5 -0
  33. data/lib/sambot/{commands/rundeck.rb → docs/cookbook/version.txt} +0 -0
  34. data/lib/sambot/docs/dns/add.txt +0 -0
  35. data/lib/sambot/docs/dns/list.txt +0 -0
  36. data/lib/sambot/docs/dns/remove.txt +0 -0
  37. data/lib/sambot/docs/dns/show.txt +0 -0
  38. data/lib/sambot/docs/instance/generate.txt +0 -0
  39. data/lib/sambot/docs/report/consistency.txt +18 -0
  40. data/lib/sambot/docs/session/start.txt +0 -0
  41. data/lib/sambot/docs/session/stop.txt +0 -0
  42. data/lib/sambot/docs/team/list.txt +0 -0
  43. data/lib/sambot/docs/workstation/configure.txt +0 -0
  44. data/lib/sambot/file_management/file_checker.rb +30 -28
  45. data/lib/sambot/file_management/template_provider.rb +8 -6
  46. data/lib/sambot/rackspace/client.rb +9 -7
  47. data/lib/sambot/rackspace/flavors.rb +3 -3
  48. data/lib/sambot/rackspace/images.rb +7 -5
  49. data/lib/sambot/rackspace/instances.rb +20 -18
  50. data/lib/sambot/runtime.rb +2 -0
  51. data/lib/sambot/ssh/config_file.rb +53 -57
  52. data/lib/sambot/ssh/config_section.rb +60 -58
  53. data/lib/sambot/ssh/parser.rb +33 -32
  54. data/lib/sambot/templates/.kitchen.yml.erb +1 -1
  55. data/lib/sambot/ui.rb +2 -0
  56. data/lib/sambot/version.rb +3 -1
  57. data/sambot.gemspec +5 -1
  58. metadata +81 -13
  59. data/bin/cookbook +0 -4
  60. data/bin/report +0 -4
  61. data/bin/rundeck +0 -4
  62. data/bin/session +0 -4
  63. data/bin/workstation +0 -4
  64. data/lib/sambot/developer_workflow/bastion_host.rb +0 -58
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6e779e1412fd356ebd1c2d95a1e2bba17f95f271
4
- data.tar.gz: 34d07a2b89b11d01d7b38d8965df70a06fae25ef
3
+ metadata.gz: b5ec6ff097c32a95918f9ea05cdd036324ea8f54
4
+ data.tar.gz: 7d0a575a9b98dc0ae5db63e767e6256c793bf81a
5
5
  SHA512:
6
- metadata.gz: 43e34ed4faad4c51a78006949492230236899c6461b8ac56813f099663bb41acc8fdfda5c37c4bd2c2d4783ac4849b6542a603dc26b4a7d8a2056d2dabf14b56
7
- data.tar.gz: 1cf8f3347ab0464e23040bda5757e367f2e50440cc9c75fde66cf79688d45aabe8e8d9f2d22c5a6baf313fad0d209a598cd8f7c754b4f00b8563eaa1e8909147
6
+ metadata.gz: d6e81a25dd723813f9124bd882ebffa040fe7599b68ebc7d25b1ad0e2892713b9b25ba0095faaec0688ea9350e971219f07a11e23b62fd315414a4b7313980a7
7
+ data.tar.gz: 050c201c54cb984af3472048f05962a75e5b14753cf307d9f88bc8c2f97d4ea40687fd959f96174d34790266e74b77cc7fe9b92b4931a220152571556244574d
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
 
11
11
  # rspec failure tracking
12
12
  .rspec_status
13
+ sambot-session.log
data/.rubocop.yml CHANGED
@@ -7,5 +7,14 @@ Documentation:
7
7
  Metrics/AbcSize:
8
8
  Enabled: false
9
9
 
10
- Style/EmptyLinesAroundBody:
10
+ Style/EmptyLinesAroundClassBody:
11
+ Enabled: false
12
+
13
+ Style/EmptyLinesAroundBlockBody:
14
+ Enabled: false
15
+
16
+ Metrics/ModuleLength:
17
+ Enabled: false
18
+
19
+ Metrics/MethodLength:
11
20
  Enabled: false
data/bin/sambot CHANGED
@@ -1,3 +1,6 @@
1
1
  #!/usr/bin/env ruby
2
+ require 'hashie'
3
+ $VERBOSE = nil
4
+ Hashie.logger = Logger.new(nil)
2
5
  require_relative '../lib/sambot'
3
6
  Sambot::CLI.start
data/lib/sambot.rb CHANGED
@@ -1,3 +1,5 @@
1
+ require 'thor'
2
+
1
3
  require_relative 'sambot/application_error'
2
4
  require_relative 'sambot/config'
3
5
  require_relative 'sambot/ui'
@@ -17,11 +19,16 @@ require_relative 'sambot/rackspace/flavors'
17
19
  require_relative 'sambot/rackspace/images'
18
20
  require_relative 'sambot/rackspace/instances'
19
21
 
22
+ require_relative 'sambot/dns/records'
23
+ require_relative 'sambot/dns/repository'
24
+
20
25
  require_relative 'sambot/ssh/config_file'
21
26
  require_relative 'sambot/ssh/config_section'
22
27
  require_relative 'sambot/ssh/parser'
23
28
 
24
- require_relative 'sambot/developer_workflow/bastion_host'
29
+ require_relative 'sambot/developer_workflow/tunnel'
30
+ require_relative 'sambot/developer_workflow/brew'
31
+ require_relative 'sambot/developer_workflow/networking'
25
32
  require_relative 'sambot/developer_workflow/dns'
26
33
  require_relative 'sambot/developer_workflow/session'
27
34
  require_relative 'sambot/developer_workflow/vault'
@@ -29,9 +36,12 @@ require_relative 'sambot/developer_workflow/workstation'
29
36
 
30
37
  require_relative 'sambot/commands/base_command'
31
38
  require_relative 'sambot/commands/cookbook'
39
+ require_relative 'sambot/commands/rdp'
32
40
  require_relative 'sambot/commands/session'
33
41
  require_relative 'sambot/commands/workstation'
34
- require_relative 'sambot/commands/rundeck'
42
+ require_relative 'sambot/commands/instance'
43
+ require_relative 'sambot/commands/dns'
44
+ require_relative 'sambot/commands/team'
35
45
  require_relative 'sambot/commands/report'
36
46
 
37
47
  require_relative 'sambot/cli'
@@ -1,3 +1,5 @@
1
+ #frozen_string_literal: true
2
+
1
3
  require 'yaml'
2
4
  require 'git'
3
5
 
@@ -5,8 +7,7 @@ module Sambot
5
7
  module Chef
6
8
  class Cookbook
7
9
 
8
- def self.build(essential_files, generated_files)
9
- config = Config.new.read
10
+ def self.build(config, essential_files, generated_files)
10
11
  validate_cookbook_structure(config['platforms'], essential_files, generated_files)
11
12
  setup_test_kitchen(config)
12
13
  build_metadata(config)
@@ -16,26 +17,20 @@ module Sambot
16
17
 
17
18
  def self.clean(generated_files)
18
19
  UI.info('Removing all generated files from this cookbook.')
19
- delete_file('metadata.rb')
20
- delete_file('winrm_config')
21
- delete_file('Berksfile.lock')
22
- delete_file('packer.json')
23
- generated_files.each { |file| delete_file(file) }
24
- Dir.glob('\.kitchen*\.yml').each do |file|
20
+ targets = ['metadata.rb', 'winrm_config', 'Berksfile.lock'] + generated_files + Dir.glob('\.kitchen*\.yml')
21
+ targets.each do |file|
25
22
  delete_file(file)
26
23
  end
27
24
  UI.info('The cookbook has been successfully cleaned.')
28
25
  end
29
26
 
30
- def self.generate(name, platforms, type, description, essential_files, generated_files)
27
+ def self.generate(config, name, platforms, type, description, essential_files, generated_files)
31
28
  Git.init(name)
32
29
  Dir.chdir(name) do
33
- FileUtils.mkdir('test')
34
- FileUtils.mkdir('spec')
35
- FileUtils.mkdir('recipes')
30
+ ['test', 'spec', 'recipes'].each {|target| FileUtils.mkdir(target) }
36
31
  FileUtils.touch('README.md')
37
32
  write_config(name, description, platforms, type)
38
- build(essential_files, generated_files)
33
+ build(config, essential_files, generated_files)
39
34
  end
40
35
  UI.info('The cookbook has been successfully generated.')
41
36
  end
@@ -1,11 +1,12 @@
1
+ #frozen_string_literal: true
2
+
1
3
  module Sambot
2
4
  module Chef
3
5
  class Kitchen
4
6
 
5
- KITCHEN_LOCAL_YML = ".kitchen.yml"
6
- KITCHEN_GCP_YML = ".kitchen.gcp.yml"
7
- KITCHEN_RACKSPACE_YML = ".kitchen.rackspace.yml"
8
-
7
+ KITCHEN_LOCAL_YML = '.kitchen.yml'
8
+ KITCHEN_GCP_YML = '.kitchen.gcp.yml'
9
+ KITCHEN_RACKSPACE_YML = '.kitchen.rackspace.yml'
9
10
 
10
11
  def self.generate_yml(cookbook_name, platforms, suites = nil)
11
12
  raise ApplicationError, 'Missing platforms when trying to generate Test-Kitchen YAML.' unless platforms
@@ -28,7 +29,7 @@ module Sambot
28
29
  filename = File.join(FileManagement::TemplateProvider.get_path("#{template}.erb"))
29
30
  contents = File.read(filename).gsub(/@@cookbook_name@@/, cookbook_name)
30
31
  eruby = Erubis::Eruby.new(contents)
31
- yaml = eruby.evaluate({platforms: platforms}).gsub(/\_@/, "<%=").gsub(/@\_/, "%>")
32
+ yaml = eruby.evaluate({platforms: platforms}).gsub(/\_@/, '<%=').gsub(/@\_/, '%>')
32
33
  YAML.load(yaml)
33
34
  end
34
35
 
@@ -1,3 +1,5 @@
1
+ #frozen_string_literal: true
2
+
1
3
  require 'erubis'
2
4
 
3
5
  module Sambot
@@ -1,3 +1,5 @@
1
+ #frozen_string_literal: true
2
+
1
3
  require 'ridley'
2
4
  require 'json'
3
5
 
@@ -6,23 +8,23 @@ module Sambot
6
8
  class Server
7
9
 
8
10
  SHORT_NAMES = {
9
- "wsus" => "WSUS",
10
- "nginx-proxy" => "PRXY",
11
- "jetstream" => "JTS",
12
- "task-scheduler" => "TASKS",
13
- "queue-service" => "QUE",
14
- "skylight" => "SKY",
15
- "prometheus" => "PRT",
16
- "octopus" => "OCTO",
17
- "vault" => "VAULT",
18
- "consul" => "CONSUL",
19
- "rabbitmq" => "RMQ",
20
- "etcd" => "ETCD",
21
- "teamcity-agent" => "TCA",
22
- "teamcity-server" => "TCS",
23
- "bastion" => "BST",
24
- "base" => "BASE",
25
- "grafana" => "MON"
11
+ 'wsus' => 'WSUS',
12
+ 'nginx-proxy' => 'PRXY',
13
+ 'jetstream' => 'JTS',
14
+ 'task-scheduler' => 'TASKS',
15
+ 'queue-service' => 'QUE',
16
+ 'skylight' => 'SKY',
17
+ 'prometheus' => 'PRT',
18
+ 'octopus' => 'OCTO',
19
+ 'vault' => 'VAULT',
20
+ 'consul' => 'CONSUL',
21
+ 'rabbitmq' => 'RMQ',
22
+ 'etcd' => 'ETCD',
23
+ 'teamcity-agent' => 'TCA',
24
+ 'teamcity-server' => 'TCS',
25
+ 'bastion' => 'BST',
26
+ 'base' => 'BASE',
27
+ 'grafana' => 'MON'
26
28
  }
27
29
 
28
30
  def initialize(ridley = nil)
@@ -43,18 +45,14 @@ module Sambot
43
45
  end
44
46
 
45
47
  def find_role_name(cookbook)
46
- naive_name = cookbook.gsub(/as-role-/, "").gsub(/as-app-role-/, "")
48
+ naive_name = cookbook.gsub(/as-role-/, '').gsub(/as-app-role-/, '')
47
49
  if SHORT_NAMES.key?(naive_name)
48
50
  SHORT_NAMES[naive_name]
49
51
  else
50
- raise "Could not generate an instance name"
52
+ raise 'Could not generate an instance name'
51
53
  end
52
54
  end
53
55
 
54
56
  end
55
57
  end
56
58
  end
57
-
58
-
59
- #Find out what's happening on the security front
60
- #Summarize conversation with Daven & take
data/lib/sambot/cli.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'thor'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Sambot
4
4
  class CLI < Thor
@@ -12,5 +12,8 @@ module Sambot
12
12
  desc 'workstation', 'Manage engineer workstations'
13
13
  subcommand 'workstation', Sambot::Commands::Workstation
14
14
 
15
+ desc 'dns', 'Manage DEV/QE DNS'
16
+ subcommand 'dns', Sambot::Commands::DNS
17
+
15
18
  end
16
19
  end
@@ -1,5 +1,56 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'thor/hollaback'
2
4
 
5
+ class Thor
6
+ module Shell
7
+ class Basic
8
+ def print_wrapped(message, options = {})
9
+ indent = options[:indent] || 0
10
+ width = 100 - indent
11
+ paras = message.split("\n\n")
12
+
13
+ paras.map! do |unwrapped|
14
+ unwrapped.strip.tr("\n", " ").squeeze(" ").gsub(/.{1,#{width}}(?:\s|\Z)/) { ($& + 5.chr).gsub(/\n\005/, "\n").gsub(/\005/, "\n") }
15
+ end
16
+
17
+ paras.each do |para|
18
+ para.split("\n").each do |line|
19
+ stdout.puts line.insert(0, " " * indent)
20
+ end
21
+ stdout.puts unless para == paras.last
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+
28
+
29
+ class Thor
30
+ class << self
31
+ def command_help(shell, command_name)
32
+ meth = normalize_command_name(command_name)
33
+ command = all_commands[meth]
34
+ handle_no_command_error(meth) unless command
35
+ shell.say
36
+ shell.say("Usage:", :green)
37
+ shell.say
38
+ shell.say " sambot #{namespace} #{command_name} "
39
+ shell.say
40
+ shell.say
41
+ class_options_help(shell, nil => command.options.values)
42
+ if command.long_description
43
+ shell.say "Description:", :green
44
+ shell.say
45
+ shell.print_wrapped(docs("#{namespace}/#{command_name}"), :indent => 2)
46
+ else
47
+ shell.say command.description
48
+ end
49
+ shell.say
50
+ end
51
+ end
52
+ end
53
+
3
54
  module Sambot
4
55
  module Commands
5
56
 
@@ -8,9 +59,22 @@ module Sambot
8
59
  before :check_version
9
60
 
10
61
  no_commands do
11
- def check_version
62
+
63
+ def execute
12
64
  Runtime.ensure_latest
65
+ yield
66
+ rescue ApplicationError => e
67
+ UI.error(e.message)
13
68
  end
69
+
70
+ def config
71
+ Config.new.read
72
+ end
73
+
74
+ def self.docs(path)
75
+ File.read(File.join(File.dirname(__FILE__), '../docs', path + '.txt'))
76
+ end
77
+
14
78
  end
15
79
 
16
80
  end
@@ -1,4 +1,4 @@
1
- require 'thor'
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Sambot
4
4
  module Commands
@@ -8,75 +8,33 @@ module Sambot
8
8
 
9
9
  class Cookbook < BaseCommand
10
10
 
11
- GUIDE =
12
- {
13
- clean: {
14
- SHORT_DESC: '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
- },
20
- build: {
21
- SHORT_DESC: 'Builds a cookbook from its configuration file',
22
- LONG_DESC: <<-LONGDESC
23
- `sambot cookbook build` will generate all the files required for the functioning
24
- of a Chef cookbook from a configuration file. The motivation behind this setup is to
25
- standardize and simplify the Chef cookbook creation workflow. The configuration file should be
26
- called .config.yml and stored in the root of the Chef cookbook.
27
- LONGDESC
28
- },
29
- generate: {
30
- SHORT_DESC: 'Creates a new cookbook',
31
- LONG_DESC: <<-LONGDESC
32
- `sambot cookbook generate` will create a new cookbook. This can be either a
33
- wrapper cookbook or an instance role cookbook.
34
- LONGDESC
35
- },
36
- version: {
37
- SHORT_DESC: 'Gives the cookbook version as a TeamCity service message',
38
- LONG_DESC: ''
39
- }
40
- }
41
-
42
11
  namespace 'cookbook'
43
12
 
44
- desc 'clean', GUIDE[:clean][:SHORT_DESC]
45
- long_desc GUIDE[:clean][:LONG_DESC]
13
+ desc 'clean', 'Remove all generated build files from a cookbook'
46
14
  def clean
47
- Chef::Cookbook.clean(GENERATED_FILES - ['.gitignore'])
48
- rescue ApplicationError => e
49
- error(e.message)
15
+ execute { Chef::Cookbook.clean(GENERATED_FILES - ['.gitignore']) }
50
16
  end
51
17
 
52
- desc 'build', GUIDE[:clean][:SHORT_DESC]
53
- long_desc GUIDE[:clean][:LONG_DESC]
18
+ desc 'build', 'Builds a cookbook from its configuration file'
54
19
  def build
55
- Chef::Cookbook.build(ESSENTIAL_FILES, GENERATED_FILES)
56
- rescue ApplicationError => e
57
- error(e.message)
20
+ execute { Chef::Cookbook.build(config, ESSENTIAL_FILES, GENERATED_FILES) }
58
21
  end
59
22
 
60
- desc 'generate', GUIDE[:generate][:SHORT_DESC]
61
- long_desc GUIDE[:generate][:LONG_DESC]
62
- def generate()
63
- name = ask(' What is the name of this cookbook?')
64
- description = ask(' What does this cookbook do?')
65
- platforms = ask(' What operating system will this cookbook run on?', :limited_to => ['windows', 'centos', 'both'])
66
- type = ask(' What type of cookbook will this be?', :limited_to => ['wrapper', 'role'])
67
- platforms = platforms == 'both' ? ['centos', 'windows'] : [platforms]
68
- Chef::Cookbook.generate(name, platforms, type, description, ESSENTIAL_FILES, GENERATED_FILES)
69
- rescue ApplicationError => e
70
- error(e.message)
23
+ desc 'generate', 'Creates a new cookbook'
24
+ def generate
25
+ execute do
26
+ name = ask(' What is the name of this cookbook?')
27
+ description = ask(' What does this cookbook do?')
28
+ platforms = ask(' What operating system will this cookbook run on?', :limited_to => ['windows', 'centos', 'both'])
29
+ type = ask(' What type of cookbook will this be?', :limited_to => ['wrapper', 'role'])
30
+ platforms = platforms == 'both' ? ['centos', 'windows'] : [platforms]
31
+ Chef::Cookbook.generate(config, name, platforms, type, description, ESSENTIAL_FILES, GENERATED_FILES)
32
+ end
71
33
  end
72
34
 
73
- desc 'version', GUIDE[:version][:SHORT_DESC]
74
- long_desc GUIDE[:version][:LONG_DESC]
75
- def version()
76
- result = Config.new.read
77
- puts "##teamcity[buildNumber '#{result['version'].to_s}']"
78
- rescue ApplicationError => e
79
- error(e.message)
35
+ desc 'version', 'Gives the cookbook version as a TeamCity service message'
36
+ def version
37
+ execute { puts "##teamcity[buildNumber '#{config['version'].to_s}']" }
80
38
  end
81
39
 
82
40
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'git'
4
+
5
+ module Sambot
6
+ module Commands
7
+ class DNS < BaseCommand
8
+
9
+ namespace 'dns'
10
+
11
+ desc 'remove', 'Removes the given DNS entry'
12
+ option :hostname, :required => true, :desc => 'The DNS name for the A record'
13
+ def remove
14
+ execute do
15
+ Sambot::DNS::Repository.new.records.remove(options[:hostname])
16
+ end
17
+ end
18
+
19
+ desc 'list', 'Shows all DNS entries'
20
+ def list
21
+ execute do
22
+ records = Sambot::DNS::Repository.new.list_records
23
+ say
24
+ print_table(records)
25
+ end
26
+ end
27
+
28
+ desc 'show', 'Shows a given DNS entry'
29
+ def show
30
+ rescue ApplicationError => e
31
+ UI.error(e.message)
32
+ end
33
+
34
+ desc 'add', 'Adds or modify a DNS entry'
35
+ option :address, :required => true, :desc => 'The internal IP address for the A record'
36
+ option :hostname, :required => true, :desc => 'The DNS name for the A record'
37
+ option :team, :desc => 'The team owning the instance pointed to. Leave blank if the hostname contains stable, patch or unstable i.e. stable-api'
38
+ long_desc docs('cookbook/clean')
39
+ def add
40
+ execute { Sambot::DNS::Repository.new.records.add(options[:hostname], options[:address], options[:team]) }
41
+ end
42
+
43
+ end
44
+ end
45
+ end