sambot 0.1.175 → 0.1.176
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sambot/chef/cookbook.rb +7 -10
- data/lib/sambot/chef/kitchen.rb +6 -6
- data/lib/sambot/templates/Vagrantfile.erb +1 -1
- data/lib/sambot/templates/bootstrap_scripts/local/sidecar_vault/bootstrap.sh.erb +23 -27
- data/lib/sambot/templates/test_kitchen/local.yml.erb +4 -1
- data/lib/sambot/version.rb +1 -1
- data/lib/sambot.rb +0 -9
- metadata +1 -15
- data/lib/sambot/rackspace/client.rb +0 -41
- data/lib/sambot/rackspace/flavors.rb +0 -19
- data/lib/sambot/rackspace/images.rb +0 -27
- data/lib/sambot/rackspace/instances.rb +0 -86
- data/lib/sambot/slack/api.rb +0 -13
- data/lib/sambot/slack/dispatcher.rb +0 -16
- data/lib/sambot/slack/formatter.rb +0 -30
- data/lib/sambot/slack/gus_bot.rb +0 -14
- data/lib/sambot/slack/product_tag.rb +0 -19
- data/lib/sambot/slack/work_item.rb +0 -105
- data/lib/sambot/templates/consul_helper.rb +0 -0
- data/lib/sambot/workflow/brew.rb +0 -46
- data/lib/sambot/workflow/vault.rb +0 -60
- data/lib/sambot/workflow/workstation.rb +0 -75
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: eab59e5f0e0b8c2ad376fce691f5a5648a86d661
|
4
|
+
data.tar.gz: 034017c58ab37062840f06fcea9fcbaad5162630
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2ef1cdc040babdc5e217561b7fc4e559526f354f6cfc73243c5efadfad09834b8a4efcfc77ece4c2cdc0d55810f06e1733be546f6328c82ec19de2df3347ef1c
|
7
|
+
data.tar.gz: f8fd14fd310eb21a9b47e0a6026c29709c09bd14d92ff92690bdf673258a922f8b6eeec259daa81d5262a375dde459454b1302956ca8e34911ef7918f0dc55d2
|
data/lib/sambot/chef/cookbook.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
#frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'yaml'
|
4
|
-
require 'git'
|
5
4
|
|
6
5
|
module Sambot
|
7
6
|
module Chef
|
@@ -20,9 +19,9 @@ module Sambot
|
|
20
19
|
class << self
|
21
20
|
|
22
21
|
def build(config, cloud, vault_setup = nil)
|
23
|
-
create_files(config)
|
22
|
+
create_files(config, true)
|
24
23
|
Generator.from_templates(config, cloud, vault_setup, GENERATED_FILES)
|
25
|
-
Kitchen.setup(cloud, config)
|
24
|
+
Kitchen.setup(cloud, config, vault_setup)
|
26
25
|
Metadata.generate(config)
|
27
26
|
Hooks.copy()
|
28
27
|
UI.info('The cookbook has been successfully built.')
|
@@ -45,6 +44,7 @@ module Sambot
|
|
45
44
|
end
|
46
45
|
|
47
46
|
def create(config)
|
47
|
+
require 'git'
|
48
48
|
Git.init(config.name)
|
49
49
|
Dir.chdir(config.name) do
|
50
50
|
create_files(config)
|
@@ -54,17 +54,14 @@ module Sambot
|
|
54
54
|
|
55
55
|
private
|
56
56
|
|
57
|
-
def create_files(config)
|
57
|
+
def create_files(config, build_phase = false)
|
58
58
|
['.vault.yml', '.consul.yml', 'README.md'].each { |resource| FS.copy(resource) unless FS.exist?(resource) }
|
59
59
|
['spec', 'test', 'attributes', 'vault'].each { |resource| FS.mkdir(resource) unless FS.exist?(resource) }
|
60
|
-
Dir.chdir('attributes') { FileUtils.touch('default.rb') }
|
61
|
-
Dir.chdir('spec') { FS.copy('spec_helper.rb') unless FS.exist?('spec_helper.rb') }
|
60
|
+
Dir.chdir('attributes') { FileUtils.touch('default.rb') unless build_phase }
|
61
|
+
Dir.chdir('spec') { FS.copy('spec_helper.rb') unless FS.exist?('spec_helper.rb') unless build_phase }
|
62
62
|
['recipes', 'libraries', 'resources', 'files', 'templates'].each { |target| FS.mkdir(target) unless FS.exist?(target) }
|
63
63
|
Dir.chdir('recipes') do
|
64
|
-
|
65
|
-
FileUtils.touch('install.rb') unless FS.exist?('install.rb')
|
66
|
-
FileUtils.touch('configure.rb') unless FS.exist?('configure.rb')
|
67
|
-
FileUtils.touch('default.rb') unless FS.exist?('default.rb')
|
64
|
+
FileUtils.touch('default.rb') unless FS.exist?('default.rb') && !build_phase
|
68
65
|
end
|
69
66
|
unless FS.exist?('.config.yml')
|
70
67
|
Template.new('.config.yml.erb').write({config: config}, '.config.yml')
|
data/lib/sambot/chef/kitchen.rb
CHANGED
@@ -8,8 +8,8 @@ module Sambot
|
|
8
8
|
|
9
9
|
GENERATED_FILE = '.kitchen.yml'
|
10
10
|
|
11
|
-
def setup(cloud, config)
|
12
|
-
contents = generate_yml(cloud, config.name, config.available_platforms, config.suites)
|
11
|
+
def setup(cloud, config, vault_setup)
|
12
|
+
contents = generate_yml(cloud, config.name, config.available_platforms, config.suites, vault_setup)
|
13
13
|
File.write(GENERATED_FILE, contents)
|
14
14
|
UI.debug("#{GENERATED_FILE} has been added to the cookbook.")
|
15
15
|
end
|
@@ -18,10 +18,10 @@ module Sambot
|
|
18
18
|
FS.delete(GENERATED_FILE)
|
19
19
|
end
|
20
20
|
|
21
|
-
def generate_yml(cloud, cookbook_name, platforms, suites = nil)
|
21
|
+
def generate_yml(cloud, cookbook_name, platforms, suites = nil, vault_setup = nil)
|
22
22
|
raise ApplicationError, 'Missing platforms when trying to generate Test-Kitchen YAML.' unless platforms
|
23
23
|
raise ApplicationError, 'Missing cookbook name when trying to generate Test-Kitchen YAML.' unless cookbook_name
|
24
|
-
template = read_template(cloud, cookbook_name, platforms)
|
24
|
+
template = read_template(cloud, cookbook_name, platforms, vault_setup)
|
25
25
|
if suites
|
26
26
|
template['suites'] = Marshal.load(Marshal.dump(suites))
|
27
27
|
add_platform_identifier(template, cloud)
|
@@ -57,8 +57,8 @@ module Sambot
|
|
57
57
|
platform == 'local' ? runlist['local'] : runlist['dev']
|
58
58
|
end
|
59
59
|
|
60
|
-
def read_template(cloud, cookbook_name, platforms)
|
61
|
-
ctx = {platforms: platforms, name: cookbook_name}
|
60
|
+
def read_template(cloud, cookbook_name, platforms, vault_setup)
|
61
|
+
ctx = {platforms: platforms, name: cookbook_name, vault_setup: vault_setup}
|
62
62
|
result = Template.new("test_kitchen/#{cloud}.yml.erb").evaluate(ctx, {:pattern => '<!--% %-->'})
|
63
63
|
YAML.load(result)
|
64
64
|
end
|
@@ -1,30 +1,35 @@
|
|
1
1
|
#!/bin/bash -e
|
2
2
|
|
3
|
-
|
3
|
+
echo "Install required tools"
|
4
|
+
sudo yum install -y unzip wget epel-release zlib-devel bzip2 openssl-devel libyaml-devel libffi-devel readline-devel gdbm-devel ncurses-devel gcc gcc-c++ make
|
4
5
|
|
5
|
-
|
6
|
-
|
6
|
+
echo "Download and install Hashicorp Vault"
|
7
|
+
if [ ! -f /usr/bin/vault ]; then
|
8
|
+
curl --fail -sSO "https://releases.hashicorp.com/vault/0.6.5/vault_0.6.5_linux_amd64.zip" > /dev/null 2>&1
|
9
|
+
unzip vault_0.6.5_linux_amd64.zip -d /usr/bin;
|
10
|
+
fi
|
11
|
+
if [ ! -d "/etc/vault" ]; then sudo mkdir /etc/vault; fi
|
7
12
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
13
|
+
echo "Download and install Hashicorp Consul"
|
14
|
+
if [ ! -f /usr/bin/consul ]; then
|
15
|
+
curl --fail -sSO "https://releases.hashicorp.com/consul/0.8.5/consul_0.8.5_linux_amd64.zip" > /dev/null 2>&1
|
16
|
+
unzip consul_0.8.5_linux_amd64.zip -d /usr/bin;
|
17
|
+
fi
|
18
|
+
if [ ! -d "/etc/consul" ]; then sudo mkdir /etc/consul; fi
|
12
19
|
|
13
|
-
|
14
|
-
wget "https://releases.hashicorp.com/consul/0.8.5/consul_0.8.5_linux_amd64.zip"
|
15
|
-
unzip consul_0.8.5_linux_amd64.zip -d /usr/bin
|
16
|
-
sudo mkdir /etc/consul
|
20
|
+
########## Everything above this line is pre-installed on the 'adstudio-centos-provisioned-v*' box ############
|
17
21
|
|
18
|
-
|
19
|
-
consul -dev -server -bootstrap
|
22
|
+
echo "Launch the Consul Agent in Development mode"
|
23
|
+
consul agent -dev -server -bootstrap < /dev/null &> /dev/null &
|
20
24
|
|
21
|
-
|
25
|
+
echo "Launch the Vault Server in Development mode"
|
22
26
|
export VAULT_ADDR="http://127.0.0.1:8200"
|
23
27
|
export VAULT_TOKEN="root"
|
24
28
|
vault server -dev -dev-root-token-id=${VAULT_TOKEN} -dev-listen-address=0.0.0.0:8200 < /dev/null &> /dev/null &
|
29
|
+
sleep 5
|
25
30
|
vault mount -path=dev generic
|
26
31
|
|
27
|
-
|
32
|
+
echo "Create the addressing file so that Chef and other applications can access the Vault server"
|
28
33
|
cat << EOF > /etc/vault/tokens.json
|
29
34
|
{
|
30
35
|
"vault-addr": "${VAULT_ADDR}",
|
@@ -34,16 +39,7 @@ cat << EOF > /etc/vault/tokens.json
|
|
34
39
|
}
|
35
40
|
EOF
|
36
41
|
|
37
|
-
|
38
|
-
|
39
|
-
sudo yum install rh-ruby22
|
40
|
-
scl enable rh-ruby22 bash
|
41
|
-
sudo yum groupinstall Development tools -y
|
42
|
-
sudo yum install rh-ruby22-ruby-devel zlib-devel -y
|
43
|
-
|
44
|
-
## Install Sambot
|
45
|
-
gem install sambot
|
46
|
-
|
47
|
-
## Populate Vault
|
42
|
+
echo "Populate Vault with test secrets using the Chef embedded Ruby"
|
43
|
+
/opt/chef/embedded/bin/gem install sambot --no-ri --no-doc
|
48
44
|
cd /vagrant
|
49
|
-
sambot populate --vault
|
45
|
+
/opt/chef/embedded/bin/sambot populate --vault
|
@@ -17,7 +17,10 @@ platforms:
|
|
17
17
|
<!--% if @platforms.include?('centos') %-->
|
18
18
|
- name: centos-7.2
|
19
19
|
driver:
|
20
|
-
|
20
|
+
<!--% if @vault_setup == 'sidecar' %-->
|
21
|
+
box: adstudio/centos-provisioned-v5
|
22
|
+
<!--% end %-->
|
23
|
+
network:
|
21
24
|
- ["private_network", {ip: "192.168.255.10"}]
|
22
25
|
<!--% end %-->
|
23
26
|
<!--% if @platforms.include?('windows') %-->
|
data/lib/sambot/version.rb
CHANGED
data/lib/sambot.rb
CHANGED
@@ -18,15 +18,6 @@ require_relative 'sambot/chef/cookbook'
|
|
18
18
|
require_relative 'sambot/chef/server'
|
19
19
|
require_relative 'sambot/chef/generator'
|
20
20
|
|
21
|
-
require_relative 'sambot/rackspace/client'
|
22
|
-
require_relative 'sambot/rackspace/flavors'
|
23
|
-
require_relative 'sambot/rackspace/images'
|
24
|
-
require_relative 'sambot/rackspace/instances'
|
25
|
-
|
26
|
-
require_relative 'sambot/workflow/brew'
|
27
|
-
require_relative 'sambot/workflow/vault'
|
28
|
-
require_relative 'sambot/workflow/workstation'
|
29
|
-
|
30
21
|
require_relative 'sambot/cli'
|
31
22
|
|
32
23
|
module Sambot
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sambot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.176
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Olivier Kouame
|
@@ -444,17 +444,7 @@ files:
|
|
444
444
|
- lib/sambot/docs/create.txt
|
445
445
|
- lib/sambot/docs/version.txt
|
446
446
|
- lib/sambot/fs.rb
|
447
|
-
- lib/sambot/rackspace/client.rb
|
448
|
-
- lib/sambot/rackspace/flavors.rb
|
449
|
-
- lib/sambot/rackspace/images.rb
|
450
|
-
- lib/sambot/rackspace/instances.rb
|
451
447
|
- lib/sambot/runtime.rb
|
452
|
-
- lib/sambot/slack/api.rb
|
453
|
-
- lib/sambot/slack/dispatcher.rb
|
454
|
-
- lib/sambot/slack/formatter.rb
|
455
|
-
- lib/sambot/slack/gus_bot.rb
|
456
|
-
- lib/sambot/slack/product_tag.rb
|
457
|
-
- lib/sambot/slack/work_item.rb
|
458
448
|
- lib/sambot/template.rb
|
459
449
|
- lib/sambot/templates/.config.yml.erb
|
460
450
|
- lib/sambot/templates/.consul.yml
|
@@ -471,7 +461,6 @@ files:
|
|
471
461
|
- lib/sambot/templates/bootstrap_scripts/local/standalone_vault/bootstrap.ps1.erb
|
472
462
|
- lib/sambot/templates/bootstrap_scripts/local/standalone_vault/bootstrap.sh.erb
|
473
463
|
- lib/sambot/templates/chefignore
|
474
|
-
- lib/sambot/templates/consul_helper.rb
|
475
464
|
- lib/sambot/templates/git_hooks/pre-commit
|
476
465
|
- lib/sambot/templates/git_hooks/pre-push
|
477
466
|
- lib/sambot/templates/metadata.rb.erb
|
@@ -486,9 +475,6 @@ files:
|
|
486
475
|
- lib/sambot/testing/vault_helper.rb
|
487
476
|
- lib/sambot/ui.rb
|
488
477
|
- lib/sambot/version.rb
|
489
|
-
- lib/sambot/workflow/brew.rb
|
490
|
-
- lib/sambot/workflow/vault.rb
|
491
|
-
- lib/sambot/workflow/workstation.rb
|
492
478
|
- sambot.gemspec
|
493
479
|
homepage: http://github.com/okouam/sambot
|
494
480
|
licenses:
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'flavors'
|
4
|
-
require_relative 'instances'
|
5
|
-
require_relative 'images'
|
6
|
-
|
7
|
-
module Sambot
|
8
|
-
module Rackspace
|
9
|
-
class Client
|
10
|
-
|
11
|
-
RACKSPACE_ACCOUNTS = [
|
12
|
-
{ api_key: -> { ENV['ADVERTISING1_API_KEY'] }, id: 'advertising1' },
|
13
|
-
{ api_key: -> { ENV['SAMTAYLOR_API_KEY'] }, id: 'samtaylor' }
|
14
|
-
]
|
15
|
-
|
16
|
-
def initialize(api_key = RACKSPACE_ACCOUNTS[0][:api_key], account_id = RACKSPACE_ACCOUNTS[0][:id])
|
17
|
-
options = {
|
18
|
-
provider: 'Rackspace',
|
19
|
-
rackspace_api_key: api_key.call,
|
20
|
-
rackspace_username: account_id,
|
21
|
-
rackspace_region: 'LON'
|
22
|
-
}
|
23
|
-
options[:connection_options] = { proxy: ENV['FIXIE_URL'] } if ENV['FIXIE_URL']
|
24
|
-
Fog::Compute.new(options)
|
25
|
-
end
|
26
|
-
|
27
|
-
def instances
|
28
|
-
@instances ||= Instances.new(self)
|
29
|
-
end
|
30
|
-
|
31
|
-
def flavors
|
32
|
-
@flavors ||= Flavors.new(self)
|
33
|
-
end
|
34
|
-
|
35
|
-
def images
|
36
|
-
@images ||= Images.new(self)
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Sambot
|
2
|
-
module Rackspace
|
3
|
-
class Flavors
|
4
|
-
|
5
|
-
def initialize(client)
|
6
|
-
@client = client
|
7
|
-
end
|
8
|
-
|
9
|
-
def all
|
10
|
-
@client.flavors.all.map { |flavor| { name: flavor.name, value: flavor.id } }.compact
|
11
|
-
end
|
12
|
-
|
13
|
-
def available
|
14
|
-
all.find_all { |x| x[:name] =~ /Standard/ }
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Sambot
|
4
|
-
module Rackspace
|
5
|
-
class Images
|
6
|
-
|
7
|
-
def initialize(client)
|
8
|
-
@client = client
|
9
|
-
end
|
10
|
-
|
11
|
-
def all
|
12
|
-
@client.images.all.map { |image| { name: image.name, value: image.id } }.compact
|
13
|
-
end
|
14
|
-
|
15
|
-
def available
|
16
|
-
all.find_all { |x| x[:name] =~ /AS/ }
|
17
|
-
end
|
18
|
-
|
19
|
-
def find_platform_by_image_id(id)
|
20
|
-
available_images = all
|
21
|
-
image = available_images.find { |x| x[:value] == id }
|
22
|
-
image[:name].match(/Linux/) ? 'L' : 'W'
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,86 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Sambot
|
4
|
-
module Rackspace
|
5
|
-
class Instances
|
6
|
-
|
7
|
-
def all(extended = false)
|
8
|
-
result = []
|
9
|
-
RACKSPACE_ACCOUNTS.each do |account|
|
10
|
-
api = Client.new(account[:api_key], account[:id])
|
11
|
-
api.servers.all.map do |server|
|
12
|
-
name = server.name
|
13
|
-
ip = server.addresses['private'].last['addr']
|
14
|
-
if extended
|
15
|
-
result << { name: name, value: ip, id: server.id }
|
16
|
-
else
|
17
|
-
result << { name: name, value: ip }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
result.flatten
|
22
|
-
end
|
23
|
-
|
24
|
-
def belonging_to(team)
|
25
|
-
results = self.all
|
26
|
-
team_initials = team.downcase
|
27
|
-
results.select do |instance|
|
28
|
-
instance_name = instance[:name].downcase
|
29
|
-
if team_initials == 'nw'
|
30
|
-
instance_name.start_with?(team_initials) || instance_name.start_with?('dev')
|
31
|
-
else
|
32
|
-
instance_name.start_with?(team_initials)
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def find_next_index(team, role)
|
38
|
-
raise 'No team name was provided. It should be the short form of the team i.e. NW or AVG.' unless team
|
39
|
-
raise 'No cookbook name was provided. It needs to be a role cookbook.' unless role
|
40
|
-
team_instances = self.all.find_all { |x| x[:name] =~ /#{team}-#{role}/i }
|
41
|
-
return '01' if team_instances.size < 1
|
42
|
-
similar_instances = team_instances.map { |x| x[:name].upcase.gsub("#{team}-#{role}".upcase, '').gsub(/^\-/, '') }
|
43
|
-
current_index = similar_instances.map { |x| x.match(/(.+)-(.+)/)[1].to_i }.sort[-1] + 1
|
44
|
-
current_index.to_s.rjust(2, '0')
|
45
|
-
end
|
46
|
-
|
47
|
-
def as_rundeck_nodes
|
48
|
-
result = []
|
49
|
-
images = Images.all
|
50
|
-
flavors = Flavors.all
|
51
|
-
RACKSPACE_ACCOUNTS.each do |account|
|
52
|
-
api = Rackspace.connect(account[:api_key], account[:id])
|
53
|
-
api.servers.all.map do |server|
|
54
|
-
flavor = flavors.detect { |x| x[:value] == server.flavor_id }
|
55
|
-
image = images.detect { |x| x[:value] == server.image_id }
|
56
|
-
image_name = image ? image[:name] : 'unknown'
|
57
|
-
team = Teams.find_from_instance_name(server.name)
|
58
|
-
result << {
|
59
|
-
name: server.name,
|
60
|
-
team: team ? Teams.all.find { |x| x[:value] == team }[:name] : 'Night Watch',
|
61
|
-
os: find_os(server.name),
|
62
|
-
hostname: server.addresses['private'].last['addr'],
|
63
|
-
created: server.created,
|
64
|
-
state: server.state,
|
65
|
-
role: 'none',
|
66
|
-
flavor: flavor ? flavor[:name] : 'unknown',
|
67
|
-
image: image_name
|
68
|
-
}
|
69
|
-
end
|
70
|
-
end
|
71
|
-
result.flatten
|
72
|
-
end
|
73
|
-
|
74
|
-
def by_name(name)
|
75
|
-
instances = all(true)
|
76
|
-
x = instances.select { |y| y[:name].upcase == name.upcase }
|
77
|
-
x.size == 1 ? x[0][:id] : nil
|
78
|
-
end
|
79
|
-
|
80
|
-
def find_os(name)
|
81
|
-
name =~ /\-L\d+$/ ? 'Linux' : 'Windows'
|
82
|
-
end
|
83
|
-
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
data/lib/sambot/slack/api.rb
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
module Sambot
|
2
|
-
module Slack
|
3
|
-
class API
|
4
|
-
|
5
|
-
def self.connect
|
6
|
-
client_id = '3MVG99qusVZJwhsmVNpi.WqbGRUWtQC6srXMiq4QA.HjbH.jC.HsY24FyEzrtiGgfWTn7glS1Ni7P_xaUfyG3'
|
7
|
-
client_secret = '4690317352869892602'
|
8
|
-
Restforce.new(:client_id => client_id, :client_secret => client_secret, :username => 'olivier.kouame@gus.com', :password => 'Xamarin[2023]com99123')
|
9
|
-
end
|
10
|
-
|
11
|
-
end
|
12
|
-
end
|
13
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
require 'slack-ruby-bot'
|
2
|
-
require 'restforce'
|
3
|
-
|
4
|
-
module Sambot
|
5
|
-
module Slack
|
6
|
-
class Dispatcher
|
7
|
-
|
8
|
-
def self.backlog
|
9
|
-
api = Sambot::Slack::API.connect
|
10
|
-
work_items = Sambot::Slack::WorkItem.find_by_product_tag(api, 'AS-PE').map { |x| Formatter.format(x) }
|
11
|
-
Formatter.index + work_items
|
12
|
-
end
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,30 +0,0 @@
|
|
1
|
-
module Sambot
|
2
|
-
module Slack
|
3
|
-
class Formatter
|
4
|
-
|
5
|
-
COLUMNS = {
|
6
|
-
'Blocked': {color: '#e85151', order: 1},
|
7
|
-
'In Progress': {color: '#49d14b', order: 2},
|
8
|
-
'Ready': {color: '#336334', order: 3},
|
9
|
-
'Pending Prioritization': {color: '#5b7aa3', order: 4},
|
10
|
-
'Icebox': {color: '#d1d1d1', order: 5}
|
11
|
-
}
|
12
|
-
|
13
|
-
def self.format(work_item)
|
14
|
-
{
|
15
|
-
fallback: "#{work_item.id_and_subject}",
|
16
|
-
title: "#{work_item.id_and_subject}",
|
17
|
-
text: "#{work_item.column} - #{work_item.assignee}",
|
18
|
-
color: "#{COLUMNS[work_item.column.to_sym] ? COLUMNS[work_item.column.to_sym][:color] : ''}"
|
19
|
-
}
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.index
|
23
|
-
COLUMNS.keys.map do |key|
|
24
|
-
{fallback: key, title: key, color: COLUMNS[key][:color]}
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
data/lib/sambot/slack/gus_bot.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
require 'slack-ruby-bot'
|
2
|
-
require 'restforce'
|
3
|
-
|
4
|
-
module Sambot
|
5
|
-
module Slack
|
6
|
-
class GusBot < SlackRubyBot::Bot
|
7
|
-
|
8
|
-
command 'backlog' do |client, data, match|
|
9
|
-
client.web_client.chat_postMessage(channel: data.channel, attachments: Dispatcher.backlog)
|
10
|
-
end
|
11
|
-
|
12
|
-
end
|
13
|
-
end
|
14
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Sambot
|
2
|
-
module Slack
|
3
|
-
|
4
|
-
class ProductTag
|
5
|
-
attr_reader :id, :name
|
6
|
-
|
7
|
-
def initialize(id, name)
|
8
|
-
@id = id
|
9
|
-
@name = name
|
10
|
-
end
|
11
|
-
|
12
|
-
def self.find(client, name)
|
13
|
-
query = "SELECT Id, Name FROM ADM_Product_Tag__c WHERE Active__c = true AND Name = '#{name}'"
|
14
|
-
client.query(query).map {|x| ProductTag.new(x[:Id], x[:Name]) }[0]
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
end
|
19
|
-
end
|
@@ -1,105 +0,0 @@
|
|
1
|
-
module Sambot
|
2
|
-
module Slack
|
3
|
-
class WorkItem
|
4
|
-
|
5
|
-
attr_reader :id, :name, :subject, :status, :product_tag
|
6
|
-
|
7
|
-
def initialize(s_object)
|
8
|
-
@s_object = s_object
|
9
|
-
end
|
10
|
-
|
11
|
-
def id; @s_object.Id; end
|
12
|
-
|
13
|
-
def name; @s_object.Name; end
|
14
|
-
|
15
|
-
def status; @s_object.Status__c; end
|
16
|
-
|
17
|
-
def product_tag; @s_object.Product_Tag__c; end
|
18
|
-
|
19
|
-
def subject; @s_object.Subject__c; end
|
20
|
-
|
21
|
-
def priority; @s_object.Priority__c; end
|
22
|
-
|
23
|
-
def product_owner; @s_object.Product_Owner__c; end
|
24
|
-
|
25
|
-
def qa_engineer; @s_object.QA_Engineer__c; end
|
26
|
-
|
27
|
-
def help_status; @s_object.Help_Status__c; end
|
28
|
-
|
29
|
-
def assignee; @s_object.Assignee__r.Name; end
|
30
|
-
|
31
|
-
def assigned_on; @s_object.Assigned_On__c; end
|
32
|
-
|
33
|
-
def last_activity_date; @s_object.LastActivityDate; end
|
34
|
-
|
35
|
-
def created_by_id; @s_object.CreatedById; end
|
36
|
-
|
37
|
-
def created_date; @s_object.CreatedDate; end
|
38
|
-
|
39
|
-
def record_type_id; @s_object.RecordTypeId; end
|
40
|
-
|
41
|
-
def owner_id; @s_object.OwnerId; end
|
42
|
-
|
43
|
-
def deleted?; @s_object.IsDeleted; end
|
44
|
-
|
45
|
-
def description; @s_object.Product_Owner__c; end
|
46
|
-
|
47
|
-
def story_points; @s_object.QA_Engineer__c; end
|
48
|
-
|
49
|
-
def closed_by; @s_object.Closed_By__c; end
|
50
|
-
|
51
|
-
def product_tag_name; @s_object.Product_Tag_Name__c; end
|
52
|
-
|
53
|
-
def epic; @s_object.Epic__c; end
|
54
|
-
|
55
|
-
def resolution; @s_object.Resolution__c; end
|
56
|
-
|
57
|
-
def column_rank; @s_object.Column_Rank__c || 0; end
|
58
|
-
|
59
|
-
def column; @s_object.Column__r ? @s_object.Column__r.Name : ''; end
|
60
|
-
|
61
|
-
def column_order
|
62
|
-
puts Formatter::COLUMNS[column.to_sym] ? Formatter::COLUMNS[column.to_sym][:order] : 100
|
63
|
-
column && Formatter::COLUMNS[column.to_sym] ? Formatter::COLUMNS[column.to_sym][:order] : 100
|
64
|
-
end
|
65
|
-
|
66
|
-
def id_and_subject; @s_object.WorkId_and_Subject__c; end
|
67
|
-
|
68
|
-
def self.find_by_product_tag(client, val)
|
69
|
-
product_tag = ProductTag.find(client, val)
|
70
|
-
query = "SELECT
|
71
|
-
Id,
|
72
|
-
Name,
|
73
|
-
Status__c,
|
74
|
-
Product_Tag__c,
|
75
|
-
Subject__c,
|
76
|
-
Priority__c,
|
77
|
-
Product_Owner__c,
|
78
|
-
QA_Engineer__c,
|
79
|
-
Help_Status__c,
|
80
|
-
Assignee__r.Name,
|
81
|
-
Assigned_On__c,
|
82
|
-
LastActivityDate,
|
83
|
-
CreatedById,
|
84
|
-
CreatedDate,
|
85
|
-
RecordTypeId,
|
86
|
-
OwnerId,
|
87
|
-
IsDeleted,
|
88
|
-
Description__c,
|
89
|
-
Story_Points__c,
|
90
|
-
Closed_By__c,
|
91
|
-
Product_Tag_Name__c,
|
92
|
-
Epic__c,
|
93
|
-
Resolution__c,
|
94
|
-
Column_Rank__c,
|
95
|
-
Column__r.Name,
|
96
|
-
WorkId_and_Subject__c
|
97
|
-
FROM ADM_Work__c \
|
98
|
-
WHERE Product_Tag__c = '#{product_tag.id}' AND (Status__c = 'New' OR Status__c = 'In Progress')"
|
99
|
-
results = client.query(query)
|
100
|
-
results.map {|x| WorkItem.new(x) }.sort_by {|x| [x.column_order, x.column_rank]}
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
File without changes
|
data/lib/sambot/workflow/brew.rb
DELETED
@@ -1,46 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Sambot
|
4
|
-
module Workflow
|
5
|
-
class Brew
|
6
|
-
|
7
|
-
def configure
|
8
|
-
UI.debug("Updating Homebrew formulas and casks")
|
9
|
-
update
|
10
|
-
tap('caskroom/cask')
|
11
|
-
update
|
12
|
-
end
|
13
|
-
|
14
|
-
def update
|
15
|
-
Bundler.with_clean_env do
|
16
|
-
`brew update`
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
def tap(name)
|
21
|
-
Bundler.with_clean_env do
|
22
|
-
`brew tap #{name}`
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
def install_cask(cask, binary)
|
27
|
-
result = `which #{binary}`
|
28
|
-
if result
|
29
|
-
UI.info("Not installing the Homebrew cask #{cask} as the corresponding binary is already available")
|
30
|
-
else
|
31
|
-
`brew cask install #{cask}`
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
def install_formula(formula, binary)
|
36
|
-
result = `which #{binary}`
|
37
|
-
if result
|
38
|
-
UI.info("Not installing the Homebrew formula #{formula} as the corresponding binary is already available")
|
39
|
-
else
|
40
|
-
`brew install #{formula}`
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,60 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'vault'
|
4
|
-
require 'open4'
|
5
|
-
|
6
|
-
module Sambot
|
7
|
-
module Workflow
|
8
|
-
class Vault
|
9
|
-
|
10
|
-
def self.authenticate(username, password, forwards)
|
11
|
-
secret = get_user_token(username, password, forwards)
|
12
|
-
secret.auth.client_token
|
13
|
-
end
|
14
|
-
|
15
|
-
def self.get_user_token(username, password, forwards)
|
16
|
-
::Vault.configure do |config|
|
17
|
-
sleep(3)
|
18
|
-
config.address = build_vault_address(forwards)
|
19
|
-
config.ssl_verify = false
|
20
|
-
return ::Vault.auth.ldap(username, password)
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def self.setup_environment(forwards, target = File.expand_path('~/.zshrc'))
|
25
|
-
save_environment_variable('VAULT_SKIP_VERIFY', true, target)
|
26
|
-
save_environment_variable('VAULT_ADDR', build_vault_address(forwards), target)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.build_vault_address(forwards)
|
30
|
-
"https://vault.brighter.io:#{forwards[:'vault.brighter.io'][:proxy_port]}"
|
31
|
-
end
|
32
|
-
|
33
|
-
def self.save_environment_variable(key, value, target = File.expand_path('~/.zshrc'))
|
34
|
-
contents = File.read(target)
|
35
|
-
contents = contents.gsub(/export #{key}=#{value}/, '') if has_environment_variable?(key, value, target)
|
36
|
-
new_line = "export #{key}=#{value.to_s}\n"
|
37
|
-
UI.debug("Adding `#{new_line}` to your ~/.zshrc")
|
38
|
-
contents << new_line
|
39
|
-
File.write(target, contents)
|
40
|
-
ENV[key] = value.to_s
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.has_environment_variables?(forwards, target = File.expand_path('~/.zshrc'))
|
44
|
-
has_vault_skip_verify = has_environment_variable?('VAULT_SKIP_VERIFY', true, target)
|
45
|
-
has_vault_addr = has_environment_variable?('VAULT_ADDR', build_vault_address(forwards), target)
|
46
|
-
(has_vault_addr != nil) && (has_vault_skip_verify != nil)
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.has_environment_variable?(key, value, target = File.expand_path('~/.zshrc'))
|
50
|
-
contents = File.read(target)
|
51
|
-
contents.match(/export #{key}=#{value}/)
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.save_token(token, home_directory = File.expand_path('~'))
|
55
|
-
File.write(File.expand_path(File.join(home_directory, '.vault-token')), token)
|
56
|
-
end
|
57
|
-
|
58
|
-
end
|
59
|
-
end
|
60
|
-
end
|
@@ -1,75 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'bundler'
|
4
|
-
|
5
|
-
module Sambot
|
6
|
-
module Workflow
|
7
|
-
class Workstation
|
8
|
-
|
9
|
-
FORMULAS = {
|
10
|
-
'git': 'git',
|
11
|
-
'vault': 'vault',
|
12
|
-
'ruby-build': 'ruby-build',
|
13
|
-
'rbenv': 'rbenv'
|
14
|
-
}
|
15
|
-
|
16
|
-
CASKS = {
|
17
|
-
'virtualbox': 'virtualbox',
|
18
|
-
'vagrant': 'vagrant',
|
19
|
-
'chefdk': 'chef'
|
20
|
-
}
|
21
|
-
|
22
|
-
XCODE_INSTALLATION_SCRIPT = 'xcode-select --install'
|
23
|
-
|
24
|
-
def self.configure(username)
|
25
|
-
update_environment_variables
|
26
|
-
install_native_binaries
|
27
|
-
UI.info('Your workstation is now ready for use - please close this shell and open up a new one to start making use of your new environment')
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.install_native_binaries
|
31
|
-
if `xcode-select version`
|
32
|
-
UI.info("Not installing XCode Developer Tools as they are already present")
|
33
|
-
else
|
34
|
-
system(XCODE_INSTALLATION_SCRIPT)
|
35
|
-
end
|
36
|
-
brew = Brew.new
|
37
|
-
brew.configure
|
38
|
-
install_formulas(brew)
|
39
|
-
install_casks(brew)
|
40
|
-
update_ruby
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.install_casks(brew)
|
44
|
-
CASKS.each do |formula, binary|
|
45
|
-
brew.install_cask(formula, binary)
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.install_formulas(brew)
|
50
|
-
FORMULAS.each do |formula, binary|
|
51
|
-
brew.install_formula(formula, binary)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
def self.update_environment_variables
|
56
|
-
UI.debug('Updating your Vault environment variables')
|
57
|
-
Vault.setup_environment(Session::FORWARDS)
|
58
|
-
end
|
59
|
-
|
60
|
-
def self.update_ruby
|
61
|
-
profile = File.read(File.expand_path("~/.bash_profile"))
|
62
|
-
`echo 'if which rbenv > /dev/null; then eval "$(rbenv init -)"; fi' >> ~/.bash_profile` unless /rbenv init/.match(profile)
|
63
|
-
current_ruby = `ruby -v`
|
64
|
-
if /ruby 2\.4/.match(current_ruby)
|
65
|
-
UI.info("Ruby 2.4.0 is already installed")
|
66
|
-
else
|
67
|
-
UI.info("Installing Ruby 2.4.0")
|
68
|
-
`rbenv install 2.4.0`
|
69
|
-
`rbenv global 2.4.0`
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|