flynn-cli-tools 0.0.1
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 +7 -0
- data/bin/flynn-cluster +157 -0
- data/bin/flynn-dns +191 -0
- data/bin/flynn-migrate +22 -0
- data/bin/flynn-release +80 -0
- data/dev-bin/console +14 -0
- data/dev-bin/setup +8 -0
- data/lib/flynn/cli/tools.rb +118 -0
- data/lib/flynn/cli/tools/cloudflare.rb +58 -0
- data/lib/flynn/cli/tools/commander_setup.rb +33 -0
- data/lib/flynn/cli/tools/logger.rb +19 -0
- data/lib/flynn/cli/tools/option_parser.rb +42 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4fecf07c24f887cd5c4068ceec7f932e3c9428a7
|
4
|
+
data.tar.gz: 75569666b7f8c9b75cb1be196e353d417208dcb8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1a8944e1e43d3e5f9ec213b5a6fdcc1b0a9d12d4be324633d398689fd7d4b4de718c2e20c81ebc09512ced381faac9248111872df64abd4c619af8e75d7a5c66
|
7
|
+
data.tar.gz: 0a0646c08e87b608f4ef08d1b0c4f0e541102a831fb6a786eae2c9dfe86b32399e5b0515a7575ba45998f7dcb823a9264e210783bac2d115d01cc85b4d51040e
|
data/bin/flynn-cluster
ADDED
@@ -0,0 +1,157 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'table_print'
|
4
|
+
require 'commander'
|
5
|
+
require 'json'
|
6
|
+
require 'httparty'
|
7
|
+
|
8
|
+
# Custom libs
|
9
|
+
$:.unshift File.join(File.dirname(__FILE__), "..")
|
10
|
+
require 'lib/flynn/cli/tools'
|
11
|
+
|
12
|
+
tp.set :max_width, 100
|
13
|
+
|
14
|
+
# Returns whether the object is tagged with something
|
15
|
+
def has_tag? obj, key, value
|
16
|
+
obj["Tags"].each do |tag|
|
17
|
+
return true if tag["Key"] == key && tag["Value"] == value
|
18
|
+
end
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns the value of a tag or nil
|
23
|
+
def tag_value obj, key
|
24
|
+
obj["Tags"].each do |tag|
|
25
|
+
return tag["Value"] if tag["Key"] == key
|
26
|
+
end
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
# Returns a table row for the given auto scaling group
|
31
|
+
def asg_table_row obj
|
32
|
+
return ({
|
33
|
+
cluster: tag_value(obj, "Name"),
|
34
|
+
asg_name: obj["AutoScalingGroupName"],
|
35
|
+
launch_config: obj["LaunchConfigurationName"],
|
36
|
+
num_instances: obj["Instances"].length,
|
37
|
+
zones: obj["AvailabilityZones"].join(", "),
|
38
|
+
created: obj["CreatedTime"]
|
39
|
+
})
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a table row for the given launch configuration
|
43
|
+
def lc_table_row obj
|
44
|
+
return ({
|
45
|
+
launch_config: obj["LaunchConfigurationName"],
|
46
|
+
version: obj["LaunchConfigurationName"].sub('Flynn Platform', '').strip,
|
47
|
+
image: obj["ImageId"],
|
48
|
+
instance_type: obj["InstanceType"],
|
49
|
+
security_groups: obj["SecurityGroups"].join(", "),
|
50
|
+
ssh_key: obj["KeyName"],
|
51
|
+
created: obj["CreatedTime"]
|
52
|
+
})
|
53
|
+
end
|
54
|
+
|
55
|
+
module Flynn::CLI::Tools
|
56
|
+
|
57
|
+
Commander.configure do
|
58
|
+
include Flynn::CLI::Tools::CommanderSetup
|
59
|
+
program :description, "Administrates flynn clusters on AWS"
|
60
|
+
|
61
|
+
global_option "-y", "--yes", "Assume 'yes' to all prompts and run non-interactively." do
|
62
|
+
Flynn::CLI::Tools.options[:yes] = true
|
63
|
+
end
|
64
|
+
|
65
|
+
command :list do |c|
|
66
|
+
|
67
|
+
c.description = "Lists existing flynn clusters"
|
68
|
+
|
69
|
+
c.action do |args, opts|
|
70
|
+
|
71
|
+
# Find all auto scaling groups
|
72
|
+
res = JSON.parse(Flynn::CLI::Tools.capture "aws autoscaling describe-auto-scaling-groups")
|
73
|
+
|
74
|
+
# Find only the ones that are flynn tagged
|
75
|
+
rows = []
|
76
|
+
res["AutoScalingGroups"].each do |row|
|
77
|
+
|
78
|
+
if tag_value(row, "Platform") == "flynn"
|
79
|
+
rows.push asg_table_row(row)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
puts "\nFlynn auto scaling groups...\n\n"
|
85
|
+
tp rows
|
86
|
+
puts ""
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
command :"list-configs" do |c|
|
93
|
+
|
94
|
+
c.description = "Lists existing flynn launch configurations"
|
95
|
+
|
96
|
+
c.action do |args, opts|
|
97
|
+
|
98
|
+
# Find all launch configurations
|
99
|
+
res = JSON.parse(Flynn::CLI::Tools.capture "aws autoscaling describe-launch-configurations")
|
100
|
+
|
101
|
+
# Find only the ones that are flynn related
|
102
|
+
rows = []
|
103
|
+
res["LaunchConfigurations"].each do |row|
|
104
|
+
|
105
|
+
if row["LaunchConfigurationName"].start_with? "Flynn Platform"
|
106
|
+
|
107
|
+
rows.push lc_table_row(row)
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
puts "\nFlynn launch configurations...\n\n"
|
114
|
+
tp rows
|
115
|
+
puts ""
|
116
|
+
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
command :"list-images" do |c|
|
122
|
+
|
123
|
+
c.description = "Lists the AMIs flynn uses by version"
|
124
|
+
|
125
|
+
c.option "--for-version VERSION", "Lists the AMI used by a specific flynn version"
|
126
|
+
|
127
|
+
c.action do |args, opts|
|
128
|
+
|
129
|
+
# Pull a specific version?
|
130
|
+
if opts.for_version
|
131
|
+
puts "\nFlynn AMI for version #{opts.for_version} in region #{Flynn::CLI::Tools.aws_region}...\n\n"
|
132
|
+
tp Flynn::CLI::Tools.flynn_images opts.for_version
|
133
|
+
puts ""
|
134
|
+
else
|
135
|
+
puts "\nFlynn AMIs for region #{Flynn::CLI::Tools.aws_region}...\n\n"
|
136
|
+
tp Flynn::CLI::Tools.flynn_images
|
137
|
+
puts ""
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
|
144
|
+
command :"latest-version" do |c|
|
145
|
+
|
146
|
+
c.description = "Shows the latest version released"
|
147
|
+
|
148
|
+
c.action do |args, opts|
|
149
|
+
res = JSON.parse HTTParty.get("https://api.github.com/repos/flynn/flynn/tags").body
|
150
|
+
puts res[0]["name"].strip
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
end
|
data/bin/flynn-dns
ADDED
@@ -0,0 +1,191 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'table_print'
|
4
|
+
require 'commander'
|
5
|
+
|
6
|
+
# Custom libs
|
7
|
+
$:.unshift File.join(File.dirname(__FILE__), "..")
|
8
|
+
require 'lib/flynn/cli/tools'
|
9
|
+
require 'lib/flynn/cli/tools/cloudflare'
|
10
|
+
|
11
|
+
tp.set :max_width, 100
|
12
|
+
|
13
|
+
module Flynn::CLI::Tools
|
14
|
+
|
15
|
+
IP_REGEX = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
16
|
+
TABLE_FIELDS = [:id, :type, :name, :ttl, :content]
|
17
|
+
|
18
|
+
Commander.configure do
|
19
|
+
include CommanderSetup
|
20
|
+
program :description, "Administrates DNS for a flynn cluster"
|
21
|
+
|
22
|
+
global_option "-y", "--yes", "Assume 'yes' to all prompts and run non-interactively." do
|
23
|
+
Flynn::CLI::Tools.options[:yes] = true
|
24
|
+
end
|
25
|
+
|
26
|
+
command :list do |c|
|
27
|
+
|
28
|
+
c.description = "Outputs DNS info for a cluster"
|
29
|
+
|
30
|
+
c.action do |args, opts|
|
31
|
+
|
32
|
+
name = "#{Flynn::CLI::Tools.flynn_cluster}.#{ENV['CLOUDFLARE_ZONE']}"
|
33
|
+
|
34
|
+
puts "\nDNS records for #{name}...\n\n"
|
35
|
+
tp CloudFlare.get("/zones/#{CloudFlare.zone_identifier}/dns_records?name=#{name},*.#{name}"), *TABLE_FIELDS
|
36
|
+
puts ""
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
command :"remove-cluster" do |c|
|
43
|
+
|
44
|
+
c.description = "Removes all DNS entries for the cluster"
|
45
|
+
|
46
|
+
c.action do |args, opts|
|
47
|
+
|
48
|
+
name = "#{Flynn::CLI::Tools.flynn_cluster}.#{ENV['CLOUDFLARE_ZONE']}"
|
49
|
+
|
50
|
+
# List the entries to be removed
|
51
|
+
entries = CloudFlare.get("/zones/#{CloudFlare.zone_identifier}/dns_records?name=#{name},*.#{name}&type=CNAME,A")
|
52
|
+
puts "\nDNS records to be removed for #{name}...\n\n"
|
53
|
+
tp [entries], *TABLE_FIELDS
|
54
|
+
|
55
|
+
# Ask
|
56
|
+
agreed = agree "This will remove the DNS entries listed above. Are you sure? (y/n)" unless Flynn::CLI::Tools.options[:yes]
|
57
|
+
if agreed || Flynn::CLI::Tools.options[:yes]
|
58
|
+
|
59
|
+
# Remove the records
|
60
|
+
puts ""
|
61
|
+
entries.each do |entry|
|
62
|
+
CloudFlare.delete("/zones/#{CloudFlare.zone_identifier}/dns_records/#{entry['id']}")
|
63
|
+
puts "Removed #{entry['type']} record for #{entry['content']}"
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
puts ""
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
command :"add-ip" do |c|
|
75
|
+
|
76
|
+
c.description = "Adds an A record for the given IP to the cluster"
|
77
|
+
|
78
|
+
c.action do |args, opts|
|
79
|
+
|
80
|
+
# Verify the IP address
|
81
|
+
ip = args[0]
|
82
|
+
unless ip.match IP_REGEX
|
83
|
+
Flynn::CLI::Tools.logger.error "add-ip: Invalid IP address: #{ip}"
|
84
|
+
puts "Invalid IP address. Given: #{ip}"
|
85
|
+
exit 1
|
86
|
+
end
|
87
|
+
|
88
|
+
name = "#{Flynn::CLI::Tools.flynn_cluster}.#{ENV['CLOUDFLARE_ZONE']}"
|
89
|
+
agreed = agree "Add A record for #{ip} to #{name}? (y/n)" unless Flynn::CLI::Tools.options[:yes]
|
90
|
+
|
91
|
+
# Ensure the CNAME record exists
|
92
|
+
req = {
|
93
|
+
body: {
|
94
|
+
type: "CNAME",
|
95
|
+
name: "*.#{name}",
|
96
|
+
content: name,
|
97
|
+
ttl: 1
|
98
|
+
}.to_json
|
99
|
+
}
|
100
|
+
res = CloudFlare.raw_post("/zones/#{CloudFlare.zone_identifier}/dns_records", req)
|
101
|
+
if res["success"]
|
102
|
+
puts "\nAdded CNAME record for cluster...\n\n"
|
103
|
+
tp [res["result"]], *TABLE_FIELDS
|
104
|
+
end
|
105
|
+
|
106
|
+
# Add the record
|
107
|
+
if agreed || Flynn::CLI::Tools.options[:yes]
|
108
|
+
req = {
|
109
|
+
body: {
|
110
|
+
type: "A",
|
111
|
+
name: name,
|
112
|
+
content: ip,
|
113
|
+
ttl: 1
|
114
|
+
}.to_json
|
115
|
+
}
|
116
|
+
res = CloudFlare.post("/zones/#{CloudFlare.zone_identifier}/dns_records", req)
|
117
|
+
puts "\nAdded DNS record...\n\n"
|
118
|
+
tp [res], *TABLE_FIELDS
|
119
|
+
puts ""
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
command :"remove-ip" do |c|
|
127
|
+
|
128
|
+
c.description = "Removes the A record of the given IP from the cluster"
|
129
|
+
|
130
|
+
c.action do |args, opts|
|
131
|
+
|
132
|
+
# Verify the IP addrss
|
133
|
+
ip = args[0]
|
134
|
+
unless ip.match IP_REGEX
|
135
|
+
Flynn::CLI::Tools.logger.error "remove-ip: Invalid IP address: #{ip}"
|
136
|
+
puts "Invalid IP address. Given: #{ip}"
|
137
|
+
exit 1
|
138
|
+
end
|
139
|
+
|
140
|
+
name = "#{Flynn::CLI::Tools.flynn_cluster}.#{ENV['CLOUDFLARE_ZONE']}"
|
141
|
+
agreed = agree "Delete A record for #{ip} from #{name}? (y/n)" unless Flynn::CLI::Tools.options[:yes]
|
142
|
+
|
143
|
+
# Remove the record
|
144
|
+
if agreed || Flynn::CLI::Tools.options[:yes]
|
145
|
+
|
146
|
+
# Find the record
|
147
|
+
record = nil
|
148
|
+
entries = CloudFlare.get("/zones/#{CloudFlare.zone_identifier}/dns_records?name=#{name}&type=A")
|
149
|
+
entries.each do |entry|
|
150
|
+
record = entry if entry['content'] == ip
|
151
|
+
end
|
152
|
+
unless record
|
153
|
+
Flynn::CLI::Tools.logger.error "remove-ip: IP address not found in cluster #{Flynn::CLI::Tools.flynn_cluster}: #{ip}"
|
154
|
+
exit 1
|
155
|
+
end
|
156
|
+
|
157
|
+
# Remove it
|
158
|
+
CloudFlare.delete("/zones/#{CloudFlare.zone_identifier}/dns_records/#{record['id']}")
|
159
|
+
|
160
|
+
puts "\nRemoved DNS record...\n\n"
|
161
|
+
tp [record], *TABLE_FIELDS
|
162
|
+
|
163
|
+
# Remove the CNAME if the last record was deleted
|
164
|
+
if entries.length == 1
|
165
|
+
|
166
|
+
# Find the CNAME
|
167
|
+
entries = CloudFlare.raw_get("/zones/#{CloudFlare.zone_identifier}/dns_records?name=*.#{name}&type=CNAME")
|
168
|
+
if entries["success"] && entries["result"].length == 1
|
169
|
+
|
170
|
+
# Remove it
|
171
|
+
Flynn::CLI::Tools.logger.info "remove-ip: Removing CNAME for cluster #{Flynn::CLI::Tools.flynn_cluster}"
|
172
|
+
CloudFlare.delete("/zones/#{CloudFlare.zone_identifier}/dns_records/#{entries["result"][0]['id']}")
|
173
|
+
|
174
|
+
puts "\nRemoved CNAME record for cluster...\n\n"
|
175
|
+
tp [entries["result"]], *TABLE_FIELDS
|
176
|
+
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
puts ""
|
182
|
+
|
183
|
+
end
|
184
|
+
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
data/bin/flynn-migrate
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Rename the remote
|
4
|
+
git remote remove flynn
|
5
|
+
|
6
|
+
# Create the app
|
7
|
+
flynn create $(basename $(pwd))
|
8
|
+
|
9
|
+
# Add the environment
|
10
|
+
cat .flynn-env | xargs flynn env set
|
11
|
+
|
12
|
+
# Add the routes
|
13
|
+
bash .flynn-routes
|
14
|
+
|
15
|
+
# Create a release
|
16
|
+
flynn-release
|
17
|
+
|
18
|
+
# Run post-create
|
19
|
+
bash .flynn-post-create
|
20
|
+
|
21
|
+
# Show running processes
|
22
|
+
flynn ps
|
data/bin/flynn-release
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Custom libs
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), "..")
|
5
|
+
require 'lib/flynn/cli/tools'
|
6
|
+
|
7
|
+
module Flynn::CLI::Tools
|
8
|
+
|
9
|
+
# Default options
|
10
|
+
self.options.merge!({
|
11
|
+
release: true,
|
12
|
+
tag: true,
|
13
|
+
tag_prefix: app_env + "-release-"
|
14
|
+
})
|
15
|
+
|
16
|
+
# Build options parser
|
17
|
+
OptionParser.new do |opts|
|
18
|
+
opts.on "--no-tag", "Skips tagging the release" do |v|
|
19
|
+
options[:tag] = v
|
20
|
+
end
|
21
|
+
opts.on "--no-build", "Skips pushing to flynn repo" do |v|
|
22
|
+
options[:release] = v
|
23
|
+
end
|
24
|
+
opts.on "-r REMOTE", "--remote REMOTE", String, "Set the git remote to release to" do |v|
|
25
|
+
options[:remote] = v
|
26
|
+
end
|
27
|
+
opts.add_general_options!
|
28
|
+
end.parse!
|
29
|
+
|
30
|
+
# Attempt a release if configured
|
31
|
+
if options[:release]
|
32
|
+
|
33
|
+
system "git push #{options[:remote]}"
|
34
|
+
exit_if_failed
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
# Attempt to tag the release
|
39
|
+
if options[:tag]
|
40
|
+
|
41
|
+
# Determine the tag prefix
|
42
|
+
prefix = app_env + "-release-"
|
43
|
+
|
44
|
+
# Find the last release id
|
45
|
+
release = capture "flynn release -q | head -n 1"
|
46
|
+
logger.info "Tagging release #{release}"
|
47
|
+
|
48
|
+
# Find the last release number
|
49
|
+
num = capture "git tag | egrep '^#{prefix}[0-9]+' | wc -l"
|
50
|
+
last_release = num.to_i rescue 0
|
51
|
+
|
52
|
+
# Check the last tag
|
53
|
+
create_release_tag = true
|
54
|
+
if last_release > 0
|
55
|
+
|
56
|
+
last_commit = capture "git rev-list -n 1 #{prefix}#{num}"
|
57
|
+
head_commit = capture "git rev-list -n 1 HEAD"
|
58
|
+
|
59
|
+
if last_commit == head_commit
|
60
|
+
logger.info "Tag #{prefix}#{num} already exists"
|
61
|
+
create_release_tag = false
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
# Create a new release tag if needed
|
67
|
+
if create_release_tag
|
68
|
+
tag = prefix + (num.to_i + 1).to_s
|
69
|
+
system "git tag -a #{tag} -m 'Flynn release #{release} on cluster #{flynn_cluster}'"
|
70
|
+
system "git push origin #{tag}"
|
71
|
+
end
|
72
|
+
|
73
|
+
# Update the current environment tag
|
74
|
+
tag = "#{app_env}-current"
|
75
|
+
system "git tag -f -a #{tag} -m 'Flyyn release #{release} on cluster #{flynn_cluster}'"
|
76
|
+
system "git push origin #{tag} --force"
|
77
|
+
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
data/dev-bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "flynn/cli/tools"
|
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
|
data/dev-bin/setup
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
require_relative 'tools/commander_setup'
|
2
|
+
require_relative 'tools/logger'
|
3
|
+
require_relative 'tools/option_parser'
|
4
|
+
|
5
|
+
# Ensure tools are present
|
6
|
+
if `which aws`.empty?
|
7
|
+
raise RuntimeError, "aws executable could not be found on $PATH. Try running `brew install awscli`."
|
8
|
+
end
|
9
|
+
if `which flynn`.empty?
|
10
|
+
raise RuntimeError, "flynn executable could not be found on $PATH. See https://flynn.io/docs/cli#installation."
|
11
|
+
end
|
12
|
+
|
13
|
+
module Flynn
|
14
|
+
module CLI
|
15
|
+
module Tools
|
16
|
+
|
17
|
+
class << self
|
18
|
+
attr_accessor :options
|
19
|
+
attr_accessor :logger
|
20
|
+
end
|
21
|
+
|
22
|
+
# Intialization
|
23
|
+
self.logger = Logger.new STDERR
|
24
|
+
logger.level = Logger::WARN
|
25
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
26
|
+
date_format = datetime.strftime("%Y-%m-%d %H:%M:%S")
|
27
|
+
"[#{date_format}] #{severity}: #{msg}\n"
|
28
|
+
end
|
29
|
+
|
30
|
+
# Options initialization
|
31
|
+
self.options = {
|
32
|
+
remote: "flynn",
|
33
|
+
quiet: false,
|
34
|
+
dry_run: false
|
35
|
+
}
|
36
|
+
|
37
|
+
def self.flynn_cluster
|
38
|
+
@cluster ||= self.capture "flynn cluster default | tail -n 1 | awk '{print $1}'"
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.flynn_cluster= cluster
|
42
|
+
@cluster = cluster
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.app_env
|
46
|
+
@app_env ||= self.capture "cat .flynn-env | grep RAILS_ENV | cut -f 2 -d ="
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.app_env= app
|
50
|
+
@app_env = app
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.flynn_images version = nil
|
54
|
+
|
55
|
+
# Return the full list of images when not asking for a specific version
|
56
|
+
images = self._flynn_images
|
57
|
+
return images unless version
|
58
|
+
|
59
|
+
# Return the image that matches when a specific version is given
|
60
|
+
images.each do |img|
|
61
|
+
return [img] if img[:flynn_version] <= version
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def self._flynn_images
|
67
|
+
|
68
|
+
# Short-circuit
|
69
|
+
return @images if @images
|
70
|
+
|
71
|
+
# Load from source
|
72
|
+
require 'json'
|
73
|
+
require 'httparty'
|
74
|
+
res = JSON.parse HTTParty.get("https://dl.flynn.io/ec2/images.json").body
|
75
|
+
|
76
|
+
# Find only the ones that are for the current region
|
77
|
+
@images = []
|
78
|
+
res["versions"].each do |version|
|
79
|
+
image = version["images"].select{|img| img["region"] == self.aws_region}[0]
|
80
|
+
@images.push({
|
81
|
+
flynn_version: version["version"],
|
82
|
+
region: image["region"],
|
83
|
+
image: image["id"],
|
84
|
+
name: image["name"]
|
85
|
+
})
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return it
|
89
|
+
@images
|
90
|
+
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.aws_region
|
94
|
+
@region ||= self.capture "aws configure get region"
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.system! *args
|
98
|
+
self.system *args, allow_dry: false
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.system *args, allow_dry: true
|
102
|
+
dry = allow_dry && options[:dry_run]
|
103
|
+
logger.debug "#{dry ? 'Dry ' : ''}Running: #{args.join " "}" unless options[:quiet]
|
104
|
+
super *args unless dry
|
105
|
+
end
|
106
|
+
|
107
|
+
def self.capture command
|
108
|
+
logger.debug "Running: #{command}" unless options[:quiet]
|
109
|
+
`#{command}`.strip
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.exit_if_failed
|
113
|
+
exit $?.exitstatus unless $?.success?
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
|
4
|
+
['CLOUDFLARE_EMAIL', 'CLOUDFLARE_KEY', 'CLOUDFLARE_ZONE'].each do |v|
|
5
|
+
unless ENV[v]
|
6
|
+
puts "Please define the #{v} environment variable"
|
7
|
+
exit 1
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module Flynn
|
12
|
+
module CLI
|
13
|
+
module Tools
|
14
|
+
class CloudFlare
|
15
|
+
include HTTParty
|
16
|
+
base_uri 'https://api.cloudflare.com/client/v4'
|
17
|
+
|
18
|
+
# Default headers
|
19
|
+
headers({
|
20
|
+
"X-Auth-Email": ENV['CLOUDFLARE_EMAIL'],
|
21
|
+
"X-Auth-Key": ENV['CLOUDFLARE_KEY'],
|
22
|
+
"Content-Type": "application/json"
|
23
|
+
})
|
24
|
+
|
25
|
+
# Override common methods
|
26
|
+
class << self
|
27
|
+
[:get, :post, :delete].each do |m|
|
28
|
+
|
29
|
+
alias_method :"_#{m}", m
|
30
|
+
|
31
|
+
# Override the base method
|
32
|
+
define_method m do |*args|
|
33
|
+
resp = self.send :"raw_#{m}", *args
|
34
|
+
unless resp["success"]
|
35
|
+
Flynn::CLI::Tools.logger.error "Request failed: #{resp["errors"]}"
|
36
|
+
exit 2
|
37
|
+
end
|
38
|
+
resp["result"]
|
39
|
+
end
|
40
|
+
|
41
|
+
# Define a raw version
|
42
|
+
define_method :"raw_#{m}" do |*args|
|
43
|
+
Flynn::CLI::Tools.logger.info "#{m.upcase} #{base_uri}#{args[0]}"
|
44
|
+
JSON.parse(self.send(:"_#{m}", *args).body)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Pulls the zone identifier for our domain
|
51
|
+
def self.zone_identifier
|
52
|
+
@zone_identifier ||= self.get("/zones?name=#{ENV['CLOUDFLARE_ZONE']}")[0]["id"]
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# Provides defaults for programs that use commander
|
2
|
+
module Flynn
|
3
|
+
module CLI
|
4
|
+
module Tools
|
5
|
+
module CommanderSetup
|
6
|
+
def self.included mod
|
7
|
+
mod.class_exec do
|
8
|
+
program :version, "0.0.0"
|
9
|
+
default_command :help
|
10
|
+
|
11
|
+
global_option "--dry-run", "Prevents this command from making changes" do |v|
|
12
|
+
Flynn::CLI::Tools.options[:dry_run] = v
|
13
|
+
end
|
14
|
+
global_option "--verbose", "Sets log level to INFO" do |v|
|
15
|
+
Flynn::CLI::Tools.logger.level = Logger::INFO
|
16
|
+
end
|
17
|
+
global_option "--debug", "Sets log level to DEBUG" do |v|
|
18
|
+
Flynn::CLI::Tools.logger.level = Logger::DEBUG
|
19
|
+
end
|
20
|
+
if File.basename($0).start_with? "flynn-"
|
21
|
+
global_option "-c CLUSTER", "--cluster CLUSTER", String, "Set the flynn cluster to use" do |v|
|
22
|
+
Flynn::CLI::Tools.flynn_cluster = v
|
23
|
+
end
|
24
|
+
end
|
25
|
+
global_option "-q", "--quiet", "Disables logging" do |v|
|
26
|
+
Flynn::CLI::Tools.options[:quiet] = v
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module Flynn
|
4
|
+
module CLI
|
5
|
+
module Tools
|
6
|
+
class Logger < Logger
|
7
|
+
def debug msg
|
8
|
+
super unless Flynn::CLI::Tools.options[:quiet]
|
9
|
+
end
|
10
|
+
def info msg
|
11
|
+
super unless Flynn::CLI::Tools.options[:quiet]
|
12
|
+
end
|
13
|
+
def warn msg
|
14
|
+
super unless Flynn::CLI::Tools.options[:quiet]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module Flynn
|
4
|
+
module CLI
|
5
|
+
module Tools
|
6
|
+
class OptionParser < OptionParser
|
7
|
+
@@log_levels = [Logger::INFO, Logger::DEBUG]
|
8
|
+
def parse!
|
9
|
+
begin
|
10
|
+
super
|
11
|
+
rescue ::OptionParser::InvalidOption, ::OptionParser::MissingArgument
|
12
|
+
puts self
|
13
|
+
exit 1
|
14
|
+
end
|
15
|
+
end
|
16
|
+
def add_general_options!
|
17
|
+
on "--dry-run", "Prevents this command from making changes" do |v|
|
18
|
+
Flynn::CLI::Tools.options[:dry_run] = v
|
19
|
+
end
|
20
|
+
on "--verbose", "Sets log level to INFO" do
|
21
|
+
Flynn::CLI::Tools.logger.level = Logger::INFO
|
22
|
+
end
|
23
|
+
on "--debug", "Sets log level to DEBUG" do
|
24
|
+
Flynn::CLI::Tools.logger.level = Logger::DEBUG
|
25
|
+
end
|
26
|
+
if File.basename($0).start_with? "flynn-"
|
27
|
+
on "-c CLUSTER", "--cluster CLUSTER", String, "Set the flynn cluster to use" do |v|
|
28
|
+
Flynn::CLI::Tools.flynn_cluster = v
|
29
|
+
end
|
30
|
+
end
|
31
|
+
on "-q", "--quiet", "Disables logging" do |v|
|
32
|
+
Flynn::CLI::Tools.options[:quiet] = v
|
33
|
+
end
|
34
|
+
on "-h", "--help", "Prints this help" do
|
35
|
+
puts self
|
36
|
+
exit
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
ADDED
@@ -0,0 +1,142 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: flynn-cli-tools
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Kenaniah Cerny
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-01-31 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: table_print
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: commander
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: json
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: httparty
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: bundler
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rake
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description:
|
98
|
+
email:
|
99
|
+
- kenaniah@gmail.com
|
100
|
+
executables:
|
101
|
+
- flynn-cluster
|
102
|
+
- flynn-dns
|
103
|
+
- flynn-migrate
|
104
|
+
- flynn-release
|
105
|
+
extensions: []
|
106
|
+
extra_rdoc_files: []
|
107
|
+
files:
|
108
|
+
- bin/flynn-cluster
|
109
|
+
- bin/flynn-dns
|
110
|
+
- bin/flynn-migrate
|
111
|
+
- bin/flynn-release
|
112
|
+
- dev-bin/console
|
113
|
+
- dev-bin/setup
|
114
|
+
- lib/flynn/cli/tools.rb
|
115
|
+
- lib/flynn/cli/tools/cloudflare.rb
|
116
|
+
- lib/flynn/cli/tools/commander_setup.rb
|
117
|
+
- lib/flynn/cli/tools/logger.rb
|
118
|
+
- lib/flynn/cli/tools/option_parser.rb
|
119
|
+
homepage: https://github.com/kenaniah/flynn-cli-tools
|
120
|
+
licenses: []
|
121
|
+
metadata: {}
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
132
|
+
requirements:
|
133
|
+
- - ">="
|
134
|
+
- !ruby/object:Gem::Version
|
135
|
+
version: '0'
|
136
|
+
requirements: []
|
137
|
+
rubyforge_project:
|
138
|
+
rubygems_version: 2.6.8
|
139
|
+
signing_key:
|
140
|
+
specification_version: 4
|
141
|
+
summary: A collection of CLI tools for administrating Flynn (flynn.io)
|
142
|
+
test_files: []
|