moonshot 0.7.5 → 0.7.6
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/moonshot/build_mechanism/github_release.rb +45 -0
- data/lib/moonshot/build_mechanism/travis_deploy.rb +38 -3
- data/lib/moonshot/cli.rb +36 -0
- data/lib/moonshot/controller.rb +11 -0
- data/lib/moonshot/controller_config.rb +5 -0
- data/lib/moonshot/stack.rb +43 -0
- data/lib/moonshot/stack_config.rb +5 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d67cb66c5dd32a605e63ad9c2878ba6148786aeb
|
4
|
+
data.tar.gz: ca5974cfe33c7a40d1040984017d5180e67a1da7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 970d41d6ae16a11f8285381efe2f22a8b9c47fae952e9a860c713bb3aabf57af6e4fc241ccbe72e1640b5a06edea0fc6acdc88db1148a24d03c685eabaecb92f
|
7
|
+
data.tar.gz: dde9fcf2087fdd0aa7918079aa51944b9409567866ab174a0e0c8ab5320b2dbc9ec6adb6257d6edc807b7351063e1c61e640d50c6dee9f0a7d545c0746425370
|
@@ -76,10 +76,40 @@ module Moonshot::BuildMechanism
|
|
76
76
|
end
|
77
77
|
|
78
78
|
def git_tag(tag, sha, annotation)
|
79
|
+
return if git_tag_exists(tag, sha)
|
80
|
+
|
79
81
|
cmd = "git tag -a #{tag} #{sha} --file=-"
|
80
82
|
sh_step(cmd, stdin: annotation)
|
81
83
|
end
|
82
84
|
|
85
|
+
# Determines if a valid git tag already exists.
|
86
|
+
#
|
87
|
+
# @param tag [String] Tag to check existence for.
|
88
|
+
# @param sha [String] SHA to verify the tag against.
|
89
|
+
#
|
90
|
+
# @return [Boolean] Whether or not the tag exists.
|
91
|
+
#
|
92
|
+
# @raise [RuntimeError] if the SHAs do not match.
|
93
|
+
def git_tag_exists(tag, sha)
|
94
|
+
exists = false
|
95
|
+
sh_step("git tag -l #{tag}") do |_, output|
|
96
|
+
exists = (output.strip == tag)
|
97
|
+
end
|
98
|
+
|
99
|
+
# If the tag does exist, make sure the existing SHA matches the SHA we're
|
100
|
+
# trying to build from.
|
101
|
+
if exists
|
102
|
+
sh_step("git rev-list -n 1 #{tag}") do |_, output|
|
103
|
+
raise "#{tag} already exists at a different SHA" \
|
104
|
+
if output.strip != sha
|
105
|
+
end
|
106
|
+
|
107
|
+
log.info("tag #{tag} already exists")
|
108
|
+
end
|
109
|
+
|
110
|
+
exists
|
111
|
+
end
|
112
|
+
|
83
113
|
def git_push_tag(remote, tag)
|
84
114
|
cmd = "git push #{remote} refs/tags/#{tag}:refs/tags/#{tag}"
|
85
115
|
sh_step(cmd) do
|
@@ -88,6 +118,8 @@ module Moonshot::BuildMechanism
|
|
88
118
|
end
|
89
119
|
|
90
120
|
def hub_create_release(semver, commitish, changelog_entry)
|
121
|
+
return if hub_release_exists(semver, commitish)
|
122
|
+
|
91
123
|
message = "#{semver}\n\n#{changelog_entry}"
|
92
124
|
cmd = "hub release create #{semver} --commitish=#{commitish}"
|
93
125
|
cmd << ' --prerelease' if semver.pre || semver.build
|
@@ -95,6 +127,19 @@ module Moonshot::BuildMechanism
|
|
95
127
|
sh_step(cmd)
|
96
128
|
end
|
97
129
|
|
130
|
+
# Determines if a github release already exists.
|
131
|
+
#
|
132
|
+
# @param semver [String] Semantic version string for the release.
|
133
|
+
#
|
134
|
+
# @return [Boolean]
|
135
|
+
def hub_release_exists(semver)
|
136
|
+
sh_step("hub release show #{semver}")
|
137
|
+
log.info("release #{semver} already exists")
|
138
|
+
true
|
139
|
+
rescue RuntimeError
|
140
|
+
false
|
141
|
+
end
|
142
|
+
|
98
143
|
def validate_commit
|
99
144
|
cmd = "git show --stat #{@sha}"
|
100
145
|
sh_step(cmd, msg: "Validate commit #{@sha}.") do |_, out|
|
@@ -8,6 +8,8 @@ module Moonshot::BuildMechanism
|
|
8
8
|
include Moonshot::DoctorHelper
|
9
9
|
include Moonshot::Shell
|
10
10
|
|
11
|
+
MAX_BUILD_FIND_ATTEMPTS = 10
|
12
|
+
|
11
13
|
attr_reader :output_file
|
12
14
|
|
13
15
|
def initialize(slug, pro: false)
|
@@ -33,13 +35,46 @@ module Moonshot::BuildMechanism
|
|
33
35
|
def find_build_and_job(version)
|
34
36
|
job_number = nil
|
35
37
|
ilog.start_threaded('Find Travis CI build') do |step|
|
36
|
-
|
37
|
-
|
38
|
+
job_number = wait_for_build(version)
|
39
|
+
|
40
|
+
step.success("Travis CI ##{job_number.gsub(/\..*/, '')} running.")
|
41
|
+
end
|
42
|
+
job_number
|
43
|
+
end
|
44
|
+
|
45
|
+
# Looks for the travis build and attempts to retry if the build does not
|
46
|
+
# exist yet.
|
47
|
+
#
|
48
|
+
# @param verison [String] Build version to look for.
|
49
|
+
#
|
50
|
+
# @return [String] Job number for the travis build.
|
51
|
+
def wait_for_build(version)
|
52
|
+
job_number = nil
|
53
|
+
attempts = 0
|
54
|
+
loop do
|
55
|
+
# Give travis some time to start the build.
|
56
|
+
attempts += 1
|
57
|
+
sleep 10
|
58
|
+
|
59
|
+
# Attempt to find the build. Rescue and re-attempt if the build can not
|
60
|
+
# be found on travis yet.
|
61
|
+
begin
|
62
|
+
build_out = sh_out("bundle exec travis show #{@cli_args} #{version}")
|
63
|
+
rescue RuntimeError => e
|
64
|
+
next unless attempts >= MAX_BUILD_FIND_ATTEMPTS
|
65
|
+
raise e
|
66
|
+
end
|
67
|
+
|
38
68
|
unless (job_number = build_out.match(/^#(\d+\.\d+) .+BUILD=1.+/)[1])
|
69
|
+
next unless attempts >= MAX_BUILD_FIND_ATTEMPTS
|
39
70
|
raise "Build for #{version} not found.\n#{build_out}"
|
40
71
|
end
|
41
|
-
|
72
|
+
|
73
|
+
# If we've reached this point then everything went smoothly and we can
|
74
|
+
# exit the loop.
|
75
|
+
break
|
42
76
|
end
|
77
|
+
|
43
78
|
job_number
|
44
79
|
end
|
45
80
|
|
data/lib/moonshot/cli.rb
CHANGED
@@ -47,6 +47,24 @@ module Moonshot
|
|
47
47
|
base.include(Moonshot::BuildMechanism)
|
48
48
|
base.include(Moonshot::DeploymentMechanism)
|
49
49
|
end
|
50
|
+
|
51
|
+
def ssh_options!
|
52
|
+
option :user, default: ENV['MOONSHOT_SSH_USER'] || ENV['USER'], type: :string,
|
53
|
+
aliases: '-l',
|
54
|
+
desc: 'Specifies the user to log in as on the remote machine.'
|
55
|
+
option :identity_file, default: ENV['MOONSHOT_SSH_KEY_FILE'], type: :string,
|
56
|
+
aliases: '-i',
|
57
|
+
desc: 'Selects a file from which the identity (private key) for '\
|
58
|
+
'public key authentication is read.'
|
59
|
+
option :instance, default: nil, type: :string, aliases: '-s',
|
60
|
+
desc: 'Connect to specified instance ID instead of the first one.'
|
61
|
+
option :command, default: nil, type: :string, aliases: '-c',
|
62
|
+
desc: 'Execute the specified command instead of opening a shell.'
|
63
|
+
option :auto_scaling_group, default: nil, type: :string, aliases: '-g',
|
64
|
+
desc: 'The logical ID of the auto scaling group to SSH into. '\
|
65
|
+
'Mandatory if the stack has multiple ASGs, '\
|
66
|
+
'ignored if you have only one.'
|
67
|
+
end
|
50
68
|
end
|
51
69
|
|
52
70
|
def initialize(*args)
|
@@ -91,6 +109,12 @@ module Moonshot
|
|
91
109
|
parameter_strategy = options[:parameter_strategy] || self.class.default_parameter_strategy
|
92
110
|
config.parameter_strategy = parameter_strategy_factory(parameter_strategy) \
|
93
111
|
unless parameter_strategy.nil?
|
112
|
+
|
113
|
+
config.ssh_user = options[:user]
|
114
|
+
config.ssh_identity_file = options[:identity_file]
|
115
|
+
config.ssh_instance = options[:instance]
|
116
|
+
config.ssh_command = options[:command]
|
117
|
+
config.ssh_auto_scaling_group_name = options[:auto_scaling_group]
|
94
118
|
end
|
95
119
|
rescue => e
|
96
120
|
raise Thor::Error, e.message
|
@@ -106,6 +130,12 @@ module Moonshot
|
|
106
130
|
raise Thor::Error, "Unknown parameter strategy: #{value}"
|
107
131
|
end
|
108
132
|
end
|
133
|
+
|
134
|
+
def ssh_command(command)
|
135
|
+
arguments = ARGV.drop(1)
|
136
|
+
arguments += ['--command', command]
|
137
|
+
invoke :ssh, [], arguments
|
138
|
+
end
|
109
139
|
end
|
110
140
|
|
111
141
|
desc :list, 'List stacks for this application.'
|
@@ -180,5 +210,11 @@ module Moonshot
|
|
180
210
|
success = controller.doctor
|
181
211
|
raise Thor::Error, 'One or more checks failed.' unless success
|
182
212
|
end
|
213
|
+
|
214
|
+
desc :ssh, 'SSH into the first or specified instance on the stack.'
|
215
|
+
ssh_options!
|
216
|
+
def ssh
|
217
|
+
controller.ssh
|
218
|
+
end
|
183
219
|
end
|
184
220
|
end
|
data/lib/moonshot/controller.rb
CHANGED
@@ -80,6 +80,12 @@ module Moonshot
|
|
80
80
|
success
|
81
81
|
end
|
82
82
|
|
83
|
+
def ssh
|
84
|
+
run_plugins(:pre_ssh)
|
85
|
+
stack.ssh
|
86
|
+
run_plugins(:post_ssh)
|
87
|
+
end
|
88
|
+
|
83
89
|
def stack
|
84
90
|
@stack ||= Stack.new(stack_name,
|
85
91
|
app_name: @config.app_name,
|
@@ -88,6 +94,11 @@ module Moonshot
|
|
88
94
|
config.parent_stacks = @config.parent_stacks
|
89
95
|
config.show_all_events = @config.show_all_stack_events
|
90
96
|
config.parameter_strategy = @config.parameter_strategy
|
97
|
+
config.ssh_user = @config.ssh_user
|
98
|
+
config.ssh_identity_file = @config.ssh_identity_file
|
99
|
+
config.ssh_instance = @config.ssh_instance
|
100
|
+
config.ssh_command = @config.ssh_command
|
101
|
+
config.ssh_auto_scaling_group_name = @config.ssh_auto_scaling_group_name
|
91
102
|
end
|
92
103
|
end
|
93
104
|
|
@@ -15,6 +15,11 @@ module Moonshot
|
|
15
15
|
attr_accessor :plugins
|
16
16
|
attr_accessor :show_all_stack_events
|
17
17
|
attr_accessor :parameter_strategy
|
18
|
+
attr_accessor :ssh_instance
|
19
|
+
attr_accessor :ssh_identity_file
|
20
|
+
attr_accessor :ssh_user
|
21
|
+
attr_accessor :ssh_command
|
22
|
+
attr_accessor :ssh_auto_scaling_group_name
|
18
23
|
|
19
24
|
def initialize
|
20
25
|
@auto_prefix_stack = true
|
data/lib/moonshot/stack.rb
CHANGED
@@ -93,6 +93,18 @@ module Moonshot
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
+
def ssh
|
97
|
+
box_id = @config.ssh_instance || instances.sort.first
|
98
|
+
box_ip = instance_ip(box_id)
|
99
|
+
cmd = ['ssh', '-t']
|
100
|
+
cmd << "-i #{@config.ssh_identity_file}" if @config.ssh_identity_file
|
101
|
+
cmd << "-l #{@config.ssh_user}" if @config.ssh_user
|
102
|
+
cmd << box_ip
|
103
|
+
cmd << @config.ssh_command if @config.ssh_command
|
104
|
+
puts "Opening SSH connection to #{box_id} (#{box_ip})..."
|
105
|
+
exec(cmd.join(' '))
|
106
|
+
end
|
107
|
+
|
96
108
|
def parameters
|
97
109
|
get_stack(@name)
|
98
110
|
.parameters
|
@@ -176,6 +188,37 @@ module Moonshot
|
|
176
188
|
|
177
189
|
private
|
178
190
|
|
191
|
+
def asgs
|
192
|
+
resources_of_type('AWS::AutoScaling::AutoScalingGroup')
|
193
|
+
end
|
194
|
+
|
195
|
+
def instance_ip(instance_id)
|
196
|
+
Aws::EC2::Client.new.describe_instances(instance_ids: [instance_id])
|
197
|
+
.reservations.first.instances.first.public_ip_address
|
198
|
+
rescue
|
199
|
+
raise "Failed to determine public IP address for instance #{instance_id}."
|
200
|
+
end
|
201
|
+
|
202
|
+
def instances # rubocop:disable Metrics/AbcSize
|
203
|
+
groups = asgs
|
204
|
+
asg = if groups.count == 1
|
205
|
+
groups.first
|
206
|
+
elsif asgs.count > 1
|
207
|
+
unless @config.ssh_auto_scaling_group_name
|
208
|
+
raise 'Multiple Auto Scaling Groups found in the stack. Please specify which '\
|
209
|
+
'one to SSH into using the --auto-scaling-group (-g) option.'
|
210
|
+
end
|
211
|
+
groups.detect { |x| x.logical_resource_id == @config.ssh_auto_scaling_group_name }
|
212
|
+
end
|
213
|
+
raise 'Failed to find the Auto Scaling Group.' unless asg
|
214
|
+
|
215
|
+
Aws::AutoScaling::Client.new.describe_auto_scaling_groups(
|
216
|
+
auto_scaling_group_names: [asg.physical_resource_id]
|
217
|
+
).auto_scaling_groups.first.instances.map(&:instance_id)
|
218
|
+
rescue
|
219
|
+
raise 'Failed to find instances in the Auto Scaling Group.'
|
220
|
+
end
|
221
|
+
|
179
222
|
def stack_name
|
180
223
|
"CloudFormation Stack #{@name.blue}"
|
181
224
|
end
|
@@ -4,6 +4,11 @@ module Moonshot
|
|
4
4
|
attr_accessor :parent_stacks
|
5
5
|
attr_accessor :show_all_events
|
6
6
|
attr_accessor :parameter_strategy
|
7
|
+
attr_accessor :ssh_instance
|
8
|
+
attr_accessor :ssh_identity_file
|
9
|
+
attr_accessor :ssh_user
|
10
|
+
attr_accessor :ssh_command
|
11
|
+
attr_accessor :ssh_auto_scaling_group_name
|
7
12
|
|
8
13
|
def initialize
|
9
14
|
@parent_stacks = []
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: moonshot
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Cloud Engineering <engineering@acquia.com>
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-07-
|
11
|
+
date: 2016-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|