sambot 0.1.69 → 0.1.83
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sambot/cli.rb +16 -18
- data/lib/sambot/commands/cookbook.rb +56 -38
- data/lib/sambot/commands/packer.rb +21 -0
- data/lib/sambot/commands/session.rb +15 -5
- data/lib/sambot/commands/workstation.rb +8 -10
- data/lib/sambot/domain/bastion_host.rb +59 -0
- data/lib/sambot/domain/chef/kitchen.rb +39 -0
- data/lib/sambot/domain/{cookbooks → chef}/metadata.rb +6 -5
- data/lib/sambot/domain/common/{application_exception.rb → application_error.rb} +1 -1
- data/lib/sambot/domain/common/config.rb +13 -6
- data/lib/sambot/domain/common/file_checker.rb +3 -2
- data/lib/sambot/domain/common/runtime.rb +5 -5
- data/lib/sambot/domain/common/template_provider.rb +1 -1
- data/lib/sambot/domain/cookbook.rb +103 -0
- data/lib/sambot/domain/dns.rb +24 -0
- data/lib/sambot/domain/packer.rb +26 -0
- data/lib/sambot/domain/session.rb +25 -0
- data/lib/sambot/domain/{workstations/ssh_config_file.rb → ssh/config_file.rb} +7 -7
- data/lib/sambot/domain/{workstations/ssh_config_section.rb → ssh/config_section.rb} +2 -2
- data/lib/sambot/domain/{workstations/ssh_parser.rb → ssh/parser.rb} +8 -7
- data/lib/sambot/domain/ui.rb +19 -0
- data/lib/sambot/domain/vault.rb +32 -0
- data/lib/sambot/domain/workstation.rb +25 -0
- data/lib/sambot/templates/{.kitchen.gcp.windows.yml → .kitchen.gcp.yml.erb} +33 -5
- data/lib/sambot/templates/.kitchen.rackspace.yml.erb +49 -0
- data/lib/sambot/templates/{.kitchen.centos.yml → .kitchen.yml.erb} +6 -1
- data/lib/sambot/templates/metadata.rb.erb +9 -2
- data/lib/sambot/templates/packer.linux.json +22 -0
- data/lib/sambot/templates/packer.windows.json.erb +18 -0
- data/lib/sambot/templates/teamcity.sh.erb +7 -7
- data/lib/sambot/version.rb +1 -1
- data/sambot.gemspec +7 -1
- metadata +120 -36
- data/lib/sambot/commands/secret.rb +0 -32
- data/lib/sambot/commands/teamcity.rb +0 -15
- data/lib/sambot/domain/common/ui.rb +0 -21
- data/lib/sambot/domain/cookbooks/assistant_chef.rb +0 -103
- data/lib/sambot/domain/cookbooks/kitchen.rb +0 -30
- data/lib/sambot/domain/secrets/vault.rb +0 -28
- data/lib/sambot/domain/workstations/env.rb +0 -0
- data/lib/sambot/domain/workstations/hosts.rb +0 -0
- data/lib/sambot/domain/workstations/install.sh +0 -1
- data/lib/sambot/templates/.kitchen.gcp.centos.yml +0 -39
- data/lib/sambot/templates/.kitchen.rackspace.centos.yml +0 -27
- data/lib/sambot/templates/.kitchen.rackspace.windows.yml +0 -34
- data/lib/sambot/templates/.kitchen.windows.yml +0 -16
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a37d00724675ee46fdcf68b9ee7cdb2d1382d954
|
4
|
+
data.tar.gz: f5109307d67e54161b76ae51ee00e8ad4efe767c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 76dcfeb1c4f34cd18c03483011b78eb23dd015d18529227f6f24e0a50dfc23bfb7bc488cb0c03a02024470f4c209c0a1ef3d33341f13a62e00d15ea130202328
|
7
|
+
data.tar.gz: '08bfa75fda01edd760e02431c29fd960df0e0fc0de7b8645fe0c69949f08e5fa0db11ea39e958ec6af92751b8ed4651beef67319cf0235022ed4dc68f9997e67'
|
data/lib/sambot/cli.rb
CHANGED
@@ -1,35 +1,33 @@
|
|
1
1
|
require 'thor'
|
2
|
-
require_relative 'domain/common/
|
2
|
+
require_relative 'domain/common/application_error'
|
3
3
|
require_relative 'domain/common/file_checker'
|
4
|
-
require_relative 'domain/secrets/vault'
|
5
|
-
require_relative 'domain/workstations/hosts'
|
6
|
-
require_relative 'domain/workstations/env'
|
7
|
-
require_relative 'domain/workstations/ssh_config_file'
|
8
|
-
require_relative 'domain/workstations/ssh_config_section'
|
9
|
-
require_relative 'domain/workstations/ssh_parser'
|
10
|
-
require_relative 'domain/common/ui'
|
11
4
|
require_relative 'domain/common/config'
|
12
5
|
require_relative 'domain/common/runtime'
|
13
6
|
require_relative 'domain/common/template_provider'
|
14
|
-
require_relative 'domain/
|
15
|
-
require_relative 'domain/
|
16
|
-
require_relative 'domain/
|
7
|
+
require_relative 'domain/chef/kitchen'
|
8
|
+
require_relative 'domain/chef/metadata'
|
9
|
+
require_relative 'domain/ssh/config_file'
|
10
|
+
require_relative 'domain/ssh/config_section'
|
11
|
+
require_relative 'domain/ssh/parser'
|
12
|
+
require_relative 'domain/bastion_host'
|
13
|
+
require_relative 'domain/dns'
|
14
|
+
require_relative 'domain/session'
|
15
|
+
require_relative 'domain/vault'
|
16
|
+
require_relative 'domain/ui'
|
17
|
+
require_relative 'domain/cookbook'
|
18
|
+
require_relative 'domain/workstation'
|
17
19
|
require_relative 'commands/cookbook'
|
18
|
-
require_relative 'commands/
|
19
|
-
require_relative 'commands/teamcity'
|
20
|
+
require_relative 'commands/session'
|
20
21
|
require_relative 'commands/workstation'
|
21
22
|
|
22
23
|
module Sambot
|
23
24
|
class CLI < Thor
|
24
25
|
|
25
|
-
desc 'teamcity', 'Manage TeamCity'
|
26
|
-
subcommand 'teamcity', Sambot::Commands::TeamCity
|
27
|
-
|
28
26
|
desc 'cookbook', 'Manage Chef cookbooks'
|
29
27
|
subcommand 'cookbook', Sambot::Commands::Cookbook
|
30
28
|
|
31
|
-
desc '
|
32
|
-
subcommand '
|
29
|
+
desc 'session', 'Manage sessions'
|
30
|
+
subcommand 'session', Sambot::Commands::Session
|
33
31
|
|
34
32
|
desc 'workstation', 'Manage engineer workstations'
|
35
33
|
subcommand 'workstation', Sambot::Commands::Workstation
|
@@ -6,64 +6,82 @@ module Sambot
|
|
6
6
|
|
7
7
|
class Cookbook < Thor
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
Runtime = Sambot::Domain::Common::Runtime
|
10
|
+
ApplicationError = Sambot::Domain::Common::ApplicationError
|
11
|
+
|
12
|
+
GUIDE =
|
13
|
+
{
|
14
|
+
clean: {
|
15
|
+
SHORT_DESC: 'Remove all generated build files from a cookbook',
|
16
|
+
LONG_DESC: <<-LONGDESC
|
17
|
+
`sambot cookbook clean` will remove all files generated by `sambot cookbook build`.
|
18
|
+
This is required to ensure the generated files are not stored in source control.
|
19
|
+
LONGDESC
|
20
|
+
},
|
21
|
+
build: {
|
22
|
+
SHORT_DESC: 'Builds a cookbook from its configuration file',
|
23
|
+
LONG_DESC: <<-LONGDESC
|
24
|
+
`sambot cookbook build` will generate all the files required for the functioning
|
25
|
+
of a Chef cookbook from a configuration file. The motivation behind this setup is to
|
26
|
+
standardize and simplify the Chef cookbook creation workflow. The configuration file should be
|
27
|
+
called .config.yml and stored in the root of the Chef cookbook.
|
28
|
+
LONGDESC
|
29
|
+
},
|
30
|
+
generate: {
|
31
|
+
SHORT_DESC: 'Creates a new cookbook',
|
32
|
+
LONG_DESC: <<-LONGDESC
|
33
|
+
`sambot cookbook generate` will create a new cookbook. This can be either a
|
34
|
+
wrapper cookbook or an instance role cookbook.
|
35
|
+
LONGDESC
|
36
|
+
},
|
37
|
+
version: {
|
38
|
+
SHORT_DESC: 'Gives the cookbook version as a TeamCity service message',
|
39
|
+
LONG_DESC: ''
|
40
|
+
}
|
41
|
+
}
|
11
42
|
|
12
43
|
namespace 'cookbook'
|
13
44
|
|
14
|
-
desc 'clean',
|
15
|
-
long_desc
|
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
|
45
|
+
desc 'clean', GUIDE[:clean][:SHORT_DESC]
|
46
|
+
long_desc GUIDE[:clean][:LONG_DESC]
|
19
47
|
def clean
|
20
|
-
ensure_latest
|
21
|
-
|
22
|
-
|
23
|
-
modified_files.each {|file| debug("./#{file} has been removed.")}
|
24
|
-
info('The cookbook has been successfully cleaned.')
|
25
|
-
rescue Domain::Common::ApplicationException => e
|
48
|
+
Runtime.ensure_latest
|
49
|
+
Domain::Cookbook.clean(GENERATED_FILES - ['.gitignore'])
|
50
|
+
rescue ApplicationError => e
|
26
51
|
error(e.message)
|
27
52
|
end
|
28
53
|
|
29
|
-
desc 'build',
|
30
|
-
long_desc
|
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
|
54
|
+
desc 'build', GUIDE[:clean][:SHORT_DESC]
|
55
|
+
long_desc GUIDE[:clean][:LONG_DESC]
|
36
56
|
def build
|
37
|
-
ensure_latest
|
38
|
-
|
39
|
-
|
40
|
-
info('The cookbook has been successfully built.')
|
41
|
-
rescue Domain::Common::ApplicationException => e
|
57
|
+
Runtime.ensure_latest
|
58
|
+
Domain::Cookbook.build(ESSENTIAL_FILES, GENERATED_FILES)
|
59
|
+
rescue ApplicationError => e
|
42
60
|
error(e.message)
|
43
61
|
end
|
44
62
|
|
45
|
-
desc 'generate',
|
46
|
-
long_desc
|
47
|
-
`sambot cookbook generate` will create a new cookbook. This can be either a
|
48
|
-
wrapper cookbook or an instance role cookbook.
|
49
|
-
LONGDESC
|
63
|
+
desc 'generate', GUIDE[:generate][:SHORT_DESC]
|
64
|
+
long_desc GUIDE[:generate][:LONG_DESC]
|
50
65
|
def generate()
|
51
|
-
ensure_latest
|
66
|
+
Runtime.ensure_latest
|
52
67
|
name = ask(' What is the name of this cookbook?')
|
53
68
|
description = ask(' What does this cookbook do?')
|
54
|
-
|
69
|
+
platforms = ask(' What operating system will this cookbook run on?', :limited_to => ['windows', 'centos', 'both'])
|
55
70
|
type = ask(' What type of cookbook will this be?', :limited_to => ['wrapper', 'role'])
|
56
|
-
|
57
|
-
|
58
|
-
rescue
|
71
|
+
platforms = platforms == 'both' ? ['centos', 'windows'] : [platforms]
|
72
|
+
Domain::Cookbook.generate(name, platforms, type, description, ESSENTIAL_FILES, GENERATED_FILES)
|
73
|
+
rescue ApplicationError => e
|
59
74
|
error(e.message)
|
60
75
|
end
|
61
76
|
|
62
|
-
desc 'version',
|
77
|
+
desc 'version', GUIDE[:version][:SHORT_DESC]
|
78
|
+
long_desc GUIDE[:version][:LONG_DESC]
|
63
79
|
def version()
|
64
|
-
|
65
|
-
|
80
|
+
Runtime.ensure_latest
|
81
|
+
result = Domain::Common::Config.read
|
66
82
|
puts "##teamcity[buildNumber '#{result['version'].to_s}']"
|
83
|
+
rescue ApplicationError => e
|
84
|
+
error(e.message)
|
67
85
|
end
|
68
86
|
|
69
87
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Commands
|
3
|
+
|
4
|
+
class Packer < Thor
|
5
|
+
|
6
|
+
ApplicationError = Sambot::Domain::Common::ApplicationError
|
7
|
+
Runtime = Sambot::Domain::Common::Runtime
|
8
|
+
|
9
|
+
namespace 'packer'
|
10
|
+
|
11
|
+
desc "prepare", "Sets up a Packer configuration"
|
12
|
+
def prepare
|
13
|
+
Runtime.ensure_latest
|
14
|
+
Domain::Packer.prepare
|
15
|
+
rescue ApplicationError => e
|
16
|
+
error(e.message)
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -3,18 +3,28 @@ module Sambot
|
|
3
3
|
|
4
4
|
class Session < Thor
|
5
5
|
|
6
|
+
ApplicationError = Sambot::Domain::Common::ApplicationError
|
7
|
+
Runtime = Sambot::Domain::Common::Runtime
|
8
|
+
|
6
9
|
namespace 'session'
|
7
10
|
|
8
11
|
desc "start", "Start a new DEV/QE session"
|
9
12
|
def start
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
Runtime.ensure_latest
|
14
|
+
username = ask(' What is your DEV/QE username i.e. jsmith? ')
|
15
|
+
password = ask(' What is your DEV/QE password? ', :echo => false)
|
16
|
+
say('')
|
17
|
+
Domain::Session.start(username, password)
|
18
|
+
rescue ApplicationError => e
|
19
|
+
error(e.message)
|
13
20
|
end
|
14
21
|
|
15
22
|
desc "stop", "Stop the DEV/QE session"
|
16
|
-
def
|
17
|
-
|
23
|
+
def stop
|
24
|
+
Runtime.ensure_latest
|
25
|
+
Domain::Session.stop()
|
26
|
+
rescue ApplicationError => e
|
27
|
+
error(e.message)
|
18
28
|
end
|
19
29
|
|
20
30
|
end
|
@@ -3,19 +3,17 @@ module Sambot
|
|
3
3
|
|
4
4
|
class Workstation < Thor
|
5
5
|
|
6
|
+
Runtime = Sambot::Domain::Common::Runtime
|
7
|
+
|
6
8
|
namespace 'workstation'
|
7
9
|
|
8
|
-
desc "
|
10
|
+
desc "configure", "Sets up an engineering workstation"
|
9
11
|
def configure
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
Domain::Workstations::Env.new.update
|
16
|
-
debug("Generating the datasource for Free Remote Desktop Manager, your RDP client.")
|
17
|
-
filename = Domain::Workstations::Hosts.new.generate
|
18
|
-
info("Your workstation is now ready for use. The RDM datasource is available here: #{filename}")
|
12
|
+
Runtime.ensure_latest
|
13
|
+
username = ask(" What is your DEV/QE Active Directory username i.e. john.smith? ")
|
14
|
+
Domain::Workstation.configure(username)
|
15
|
+
rescue ApplicationError => e
|
16
|
+
error(e.message)
|
19
17
|
end
|
20
18
|
|
21
19
|
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'awesome_print'
|
2
|
+
require 'process_exists'
|
3
|
+
|
4
|
+
module Sambot
|
5
|
+
module Domain
|
6
|
+
class BastionHost
|
7
|
+
|
8
|
+
ApplicationError = Sambot::Domain::Common::ApplicationError
|
9
|
+
Parser = Sambot::Domain::Ssh::Parser
|
10
|
+
|
11
|
+
def self.connect(username, password)
|
12
|
+
disconnect
|
13
|
+
cmd = "sshpass -p #{password} ssh -N -f -l DEV\\\\#{username} bastion "
|
14
|
+
success = system(cmd)
|
15
|
+
sleep(3)
|
16
|
+
unless success
|
17
|
+
raise ApplicationError.new('Unable to open SSH tunnels to the bastion host')
|
18
|
+
end
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.forwards(config_file = nil)
|
23
|
+
config = ConfigFile.new(config_file)
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.disconnect()
|
28
|
+
close_tunnels(list_tunnels)
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.close_tunnels(tunnels)
|
32
|
+
if tunnels
|
33
|
+
tunnels.each do |tunnel|
|
34
|
+
components = tunnel.split(' ')
|
35
|
+
pid = components[1].to_i
|
36
|
+
parse_forwards.each do |forward|
|
37
|
+
if components[8] == forward && components[9] == '(LISTEN)' && Process.exists?(pid)
|
38
|
+
Process.kill('INT', pid)
|
39
|
+
UI.debug("The process #{pid}, parent of the tunnel #{forward}, has been killed.")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.parse_forwards
|
47
|
+
Parser::ENTRIES[:bastion][:LocalForward].map do |entry|
|
48
|
+
"127.0.0.1:#{entry.split(' ')[0]}"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.list_tunnels
|
53
|
+
result = `lsof -i -n -P | grep -E '^ssh'`
|
54
|
+
result.split(/\n/)
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Sambot
|
2
|
+
module Domain
|
3
|
+
module Chef
|
4
|
+
class Kitchen
|
5
|
+
|
6
|
+
KITCHEN_LOCAL_YML = ".kitchen.yml"
|
7
|
+
KITCHEN_GCP_YML = ".kitchen.gcp.yml"
|
8
|
+
KITCHEN_RACKSPACE_YML = ".kitchen.rackspace.yml"
|
9
|
+
|
10
|
+
|
11
|
+
def self.generate_yml(cookbook_name, platforms, suites = nil)
|
12
|
+
raise ApplicationError, 'Missing platforms when trying to generate Test-Kitchen YAML.' unless platforms
|
13
|
+
raise ApplicationError, 'Missing cookbook name when trying to generate Test-Kitchen YAML.' unless cookbook_name
|
14
|
+
test_kitchen_configs = {
|
15
|
+
"#{KITCHEN_LOCAL_YML}": read_template(KITCHEN_LOCAL_YML, cookbook_name, platforms),
|
16
|
+
"#{KITCHEN_GCP_YML}": read_template(KITCHEN_GCP_YML, cookbook_name, platforms),
|
17
|
+
"#{KITCHEN_RACKSPACE_YML}": read_template(KITCHEN_RACKSPACE_YML, cookbook_name, platforms)
|
18
|
+
}
|
19
|
+
test_kitchen_configs.each do |key, value|
|
20
|
+
value['suites'] = suites if suites
|
21
|
+
test_kitchen_configs[key] = value.to_yaml
|
22
|
+
end
|
23
|
+
test_kitchen_configs
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def self.read_template(template, cookbook_name, platforms)
|
29
|
+
filename = File.join(TemplateProvider.get_path("#{template}.erb"))
|
30
|
+
contents = File.read(filename).gsub(/@@cookbook_name@@/, cookbook_name)
|
31
|
+
eruby = Erubis::Eruby.new(contents)
|
32
|
+
yaml = eruby.evaluate({platforms: platforms}).gsub(/\_@/, "<%=").gsub(/@\_/, "%>")
|
33
|
+
YAML.load(yaml)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -2,23 +2,24 @@ require 'erubis'
|
|
2
2
|
|
3
3
|
module Sambot
|
4
4
|
module Domain
|
5
|
-
module
|
5
|
+
module Chef
|
6
6
|
class Metadata
|
7
7
|
|
8
|
-
def generate(name,
|
8
|
+
def self.generate(name, platforms, version, description, dependencies = nil, gems = nil)
|
9
9
|
context = {
|
10
10
|
'cookbook_name' => name,
|
11
|
-
'
|
11
|
+
'cookbook_platforms' => platforms,
|
12
12
|
'cookbook_version' => version,
|
13
13
|
'cookbook_description' => description,
|
14
|
-
'cookbook_dependencies' => dependencies
|
14
|
+
'cookbook_dependencies' => dependencies,
|
15
|
+
'cookbook_gems' => gems,
|
15
16
|
}
|
16
17
|
generate_metadata(context)
|
17
18
|
end
|
18
19
|
|
19
20
|
private
|
20
21
|
|
21
|
-
def generate_metadata(context)
|
22
|
+
def self.generate_metadata(context)
|
22
23
|
filename = File.join(File.dirname(__FILE__), '../../templates', 'metadata.rb.erb')
|
23
24
|
input = File.read(filename)
|
24
25
|
eruby = Erubis::Eruby.new(input)
|
@@ -9,13 +9,20 @@ module Sambot
|
|
9
9
|
|
10
10
|
def read(path = nil)
|
11
11
|
path ||= File.join(Dir.getwd, CONFIGURATION_FILENAME)
|
12
|
-
raise
|
12
|
+
raise ApplicationError, "The configuration file was not found at #{path}." unless File.exist?(path)
|
13
13
|
config = YAML.load_file(path)
|
14
|
-
raise
|
15
|
-
raise
|
16
|
-
raise
|
17
|
-
raise
|
18
|
-
raise
|
14
|
+
raise ApplicationError, 'Missing cookbook name in the .config.yml configuration file' unless config['name']
|
15
|
+
raise ApplicationError, 'Missing platforms in the .config.yml configuration file' unless config['platform'] || config['platforms']
|
16
|
+
raise ApplicationError, 'Missing version in the .config.yml configuration file' unless config['version']
|
17
|
+
raise ApplicationError, 'Missing list of suites in the .config.yml configuration file' unless config['suites']
|
18
|
+
raise ApplicationError, 'Missing description in the .config.yml configuration file' unless config['description']
|
19
|
+
# Dealing with legacy tech debt of allowing multiple platforms rather than a single platform
|
20
|
+
unless config['platforms']
|
21
|
+
unless config['platform'].kind_of?(Array)
|
22
|
+
config['platform'] = [config['platform']]
|
23
|
+
end
|
24
|
+
config['platforms'] = config['platform']
|
25
|
+
end
|
19
26
|
config
|
20
27
|
end
|
21
28
|
|
@@ -5,7 +5,7 @@ module Sambot
|
|
5
5
|
|
6
6
|
def verify(path)
|
7
7
|
return if File.exist?(path) || Dir.exist?(path)
|
8
|
-
raise
|
8
|
+
raise ApplicationError, "The file or directory #{path} was not found in the current directory."
|
9
9
|
end
|
10
10
|
|
11
11
|
def update(files)
|
@@ -19,7 +19,7 @@ module Sambot
|
|
19
19
|
|
20
20
|
def update_template(filename)
|
21
21
|
working_path = filename.end_with?(".erb") ? filename.gsub(/\.erb/, '') : filename
|
22
|
-
template_path = TemplateProvider.
|
22
|
+
template_path = TemplateProvider.get_path(filename)
|
23
23
|
File.delete(working_path) if File.exist?(working_path)
|
24
24
|
if template_path.end_with?(".erb")
|
25
25
|
input = File.read(template_path)
|
@@ -34,6 +34,7 @@ module Sambot
|
|
34
34
|
else
|
35
35
|
FileUtils.cp(template_path, working_path)
|
36
36
|
end
|
37
|
+
UI.debug("#{working_path} has been added to the cookbook.")
|
37
38
|
end
|
38
39
|
|
39
40
|
end
|