ecs_compose 0.1.0.pre7 → 0.1.0.pre8

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ae0188dc62e80cc71af5875294462deda6c5edd
4
- data.tar.gz: 8e6f777891d855a5199eb117370be12596a4fb5a
3
+ metadata.gz: b1650cd5ac69bc7a05d43dfb153cecd2a399c3d6
4
+ data.tar.gz: 2ec1eabb033e0b12c7cb7a4c16b1b945913cf2cc
5
5
  SHA512:
6
- metadata.gz: e14d979474af2e9a368b1a6973fff7b0571480c55da159fad7bdee7fc0b4cf311f8a720e8dfea12196c4a5c553ddf39804d08f503270997aaacce325c117fb59
7
- data.tar.gz: e880db7381c14d238fd36c12d86f42704c552e540fab0088b018375bfd1d5bcf745d1842fb590bd7bd08081a58bfa4ee5eb60a54603b294f855dd8bf334bbedd
6
+ metadata.gz: b7528f64aac476b999b960c3baeaa93e86f9e17422e84e4a30c2e1d0f6fe8e5395b89948cdbfa8076bc94aed51e2d8d0c15d8d12cb2e3c55cd131688061483a3
7
+ data.tar.gz: 538236cee418cd6cb01a26dfded1d813a5dab847a63e03776bb34783c23123a9c9535c58f8b2028581f42670bb4d9d8e228e82b1d661a9ee1c707115f56a13c9
data/ecs_compose.gemspec CHANGED
@@ -27,7 +27,7 @@ Gem::Specification.new do |spec|
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
29
 
30
- spec.add_dependency "thor", "~> 0.19.1"
30
+ spec.add_dependency "docopt", "~> 0.5.0"
31
31
  spec.add_dependency "colorize", "~> 0.7.7"
32
32
 
33
33
  spec.add_development_dependency "bundler", "~> 1.10"
data/exe/ecs-compose CHANGED
@@ -1,5 +1,185 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "ecs_compose/cli"
3
+ require "docopt"
4
+ require "ecs_compose"
4
5
 
5
- EcsCompose::CLI.start(ARGV)
6
+ USAGE = <<DOCOPT
7
+ ecs-compose - Like docker-compose, but for AWS EC2 Container Service
8
+
9
+ Usage:
10
+ ecs-compose --help
11
+ ecs-compose --version
12
+ ecs-compose [options] register [<task_def>...]
13
+ ecs-compose [options] up [<service>...]
14
+ ecs-compose [options] run [-e <name>=<value>]... [--entrypoint <entrypoint>] <task> [--] [<arg>...]
15
+ ecs-compose [options] json [<task_def>]
16
+
17
+ Options:
18
+ -h, --help Show this help message
19
+ --version Print the version of this program
20
+ -m, --manifest <manifest>
21
+ Path to an ecs-compose manifest (defaults to
22
+ deploy/DEPLOY-MANIFEST.yml, takes precedence over --file)
23
+ -f, --file <file> Path to docker-compose.yml file (defaults to
24
+ docker-compose.yml)
25
+ -i, --file-info (task:<name> | service:<name>)
26
+ Specify the task type and task name for a
27
+ docker-compose.yml file
28
+ -e <name>=<value> Set an environment variable
29
+ --entrypoint <entrypoint>
30
+ Override the container's regular entrypoint
31
+
32
+ Commands:
33
+ register Registers the specified ECS task definitions (defaults to all)
34
+ up Updates the specified ECS services (defaults to all)
35
+ run Runs the specified task
36
+ json Generate JSON for a specific task definition
37
+ DOCOPT
38
+
39
+ # Our command-line application. Parses our rather complicated arguments,
40
+ # then delegates all the real work to our usual internal classes.
41
+ class App
42
+ include EcsCompose
43
+
44
+ DEFAULT_FILE = "docker-compose.yml"
45
+ DEFAULT_MANIFEST = "deploy/DEPLOY-MANIFEST.yml"
46
+
47
+ attr_reader :options, :manifest
48
+
49
+ def initialize
50
+ @options = Docopt::docopt(USAGE, version: EcsCompose::VERSION)
51
+ @manifest = load_manifest()
52
+
53
+ # Uncomment to dump the docopt parser output, which can be non-obvious.
54
+ #require "pp"
55
+ #pp(options)
56
+ end
57
+
58
+ # Figure out which subcommand was chosen, and run it.
59
+ def run
60
+ for command in %w{register up run json}
61
+ if options.fetch(command)
62
+ send("command_#{command}")
63
+ return
64
+ end
65
+ end
66
+ # We shouldn't ever get here.
67
+ raise "Unknown command: #{command}"
68
+ end
69
+
70
+ protected
71
+
72
+ def command_register
73
+ available = manifest.task_definitions
74
+ chosen = all_or_specified(available, options.fetch('<task_def>'))
75
+ chosen.each {|td| td.register }
76
+ end
77
+
78
+ def command_up
79
+ available = manifest.task_definitions.select {|td| td.type == :service }
80
+ chosen = all_or_specified(available, options.fetch('<service>'))
81
+ chosen.each {|td| td.up }
82
+ end
83
+
84
+ def command_run
85
+ available = manifest.task_definitions.select {|td| td.type == :task }
86
+ task_name = options.fetch('<task>')
87
+ task = available.find {|td| td.name == task_name } or
88
+ fatal_err("Cannot find task '#{task_name}'")
89
+
90
+ env = options.fetch('-e').flatten.inject({}) do |hsh, e_opt|
91
+ e_opt =~ /\A([^=]+)=(.*)/ or
92
+ fatal_err "Can't parse '-e #{e_opt}'"
93
+ hsh[$1] = $2
94
+ hsh
95
+ end
96
+
97
+ command = options.fetch('<arg>')
98
+ command = nil if command.empty?
99
+
100
+ task.run(environment: env,
101
+ entrypoint: options.fetch('--entrypoint').flatten[0],
102
+ command: command)
103
+ end
104
+
105
+ def command_json
106
+ task_definition = options.fetch('<task_def>')[0]
107
+ if task_definition.nil?
108
+ choices = manifest.task_definitions.map {|td| td.name }
109
+ case choices.length
110
+ when 0
111
+ fatal_err("Please supply a manifest with at least one task definition")
112
+ when 1
113
+ task_definition = choices.first
114
+ else
115
+ fatal_err("Please choose one of: #{choices.join(', ')}")
116
+ end
117
+ end
118
+
119
+ found = manifest.task_definitions.find {|td| td.name } or
120
+ fatal_err("Can't find task definition: #{task_definition}")
121
+ puts found.to_json
122
+ end
123
+
124
+ # Choose either all items in `available`, or just those with the
125
+ # specified `names`.
126
+ def all_or_specified(available, names)
127
+ if names.empty?
128
+ available
129
+ else
130
+ available.select {|td| names.include?(td.name) }
131
+ end
132
+ end
133
+
134
+ # Figure out whether we have a manifest or a docker-compose.yml. We
135
+ # check supplied flags first, then defaults, and we prefer manifests
136
+ # when there's a tie.
137
+ def mode
138
+ if options.fetch('--manifest')
139
+ :manifest
140
+ elsif options.fetch('--file')
141
+ :file
142
+ elsif File.exist?(DEFAULT_MANIFEST)
143
+ :manifest
144
+ elsif File.exist?(DEFAULT_FILE)
145
+ :file
146
+ else
147
+ fatal_err("Unable to find either #{DEFAULT_FILE} or #{DEFAULT_MANIFEST}")
148
+ end
149
+ end
150
+
151
+ # Create a manifest, either by reading it in, or synthesizing it from a
152
+ # `docker-compose.yml` file and some extra arguments.
153
+ def load_manifest
154
+ case mode
155
+ when :manifest
156
+ Manifest.read_from_manifest(options.fetch('--manifest') || DEFAULT_MANIFEST)
157
+ when :file
158
+ info = options.fetch('--file-info')
159
+ if info.nil?
160
+ fatal_err("Must pass -i option when using docker-compose.yml")
161
+ end
162
+ unless info =~ /\A(service|task):([-_A-Za-z0-9\z]+)/
163
+ fatal_err("Incorrectly formatted -i option")
164
+ end
165
+ type, name = $1, $2
166
+ Manifest.read_from_file(options.fetch('--file') || DEFAULT_FILE,
167
+ type.to_sym, name)
168
+ else raise "Unknown mode: #{mode}"
169
+ end
170
+ end
171
+
172
+ # Print an error and quit.
173
+ def fatal_err(msg)
174
+ STDERR.puts(msg.red)
175
+ exit(1)
176
+ end
177
+ end
178
+
179
+ # Run our application.
180
+ begin
181
+ App.new.run
182
+ rescue Docopt::Exit => e
183
+ puts e.message
184
+ exit(1)
185
+ end
@@ -1,13 +1,52 @@
1
1
  module EcsCompose
2
2
 
3
- # Information required to create an ECS task definition.
3
+ # Information required to create an ECS task definition, and commands to
4
+ # act upon it.
4
5
  class TaskDefinition
5
6
  attr_reader :type, :name, :yaml
6
7
 
8
+ # Create a new TaskDefinition. The type should be either `:task` or
9
+ # `:service`, the name should be both the name of the ECS task
10
+ # definition and the corresponding ECS service (if any), and the YAML
11
+ # should be `docker-compose`-format YAML describing the containers
12
+ # associated with this task.
7
13
  def initialize(type, name, yaml)
8
14
  @name = name
9
15
  @type = type
10
16
  @yaml = yaml
11
17
  end
18
+
19
+ # Register this task definition with ECS. Will create the task
20
+ # definition if it doesn't exist, and add a new version of the task.
21
+ def register
22
+ EcsCompose::Ecs.register_task_definition(to_json)
23
+ end
24
+
25
+ # Register this task definition with ECS, and update the corresponding
26
+ # service.
27
+ def up
28
+ EcsCompose::Ecs.update_service_with_json(name, to_json)
29
+ end
30
+
31
+ # Run this task definition as a one-shot ECS task, with the specified
32
+ # overrides.
33
+ def run(environment: {}, entrypoint: nil, command: nil)
34
+ puts "environment: #{environment.inspect}"
35
+ puts "entrypoint: #{entrypoint.inspect}"
36
+ puts "command: #{command.inspect}"
37
+ raise "Not yet implemented"
38
+ end
39
+
40
+ # Generate ECS task definition JSON for this instance.
41
+ def to_json
42
+ json_generator.json
43
+ end
44
+
45
+ protected
46
+
47
+ # Return a JSON generator for this task.
48
+ def json_generator
49
+ @json_generator ||= EcsCompose::JsonGenerator.new(name, yaml)
50
+ end
12
51
  end
13
52
  end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ecs_compose
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre7
4
+ version: 0.1.0.pre8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric Kidd
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-08-07 00:00:00.000000000 Z
11
+ date: 2015-08-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: thor
14
+ name: docopt
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.19.1
19
+ version: 0.5.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.19.1
26
+ version: 0.5.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: colorize
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -104,7 +104,6 @@ files:
104
104
  - exe/ecs-compose
105
105
  - go-publish.sh
106
106
  - lib/ecs_compose.rb
107
- - lib/ecs_compose/cli.rb
108
107
  - lib/ecs_compose/ecs.rb
109
108
  - lib/ecs_compose/json_generator.rb
110
109
  - lib/ecs_compose/manifest.rb
@@ -1,125 +0,0 @@
1
- require "ecs_compose"
2
- require "thor"
3
-
4
- module EcsCompose
5
- # Our basic command-line interface.
6
- class CLI < Thor
7
- DEFAULT_FILE = "docker-compose.yml"
8
- DEFAULT_MANIFEST = "deploy/DEPLOY-MANIFEST.yml"
9
-
10
- # Force status 1 on exit. See: https://github.com/erikhuda/thor/issues/244
11
- def self.exit_on_failure?
12
- true
13
- end
14
-
15
- class_option(:manifest, type: :string,
16
- aliases: %w(-m),
17
- desc: "Manifest describing a set of tasks and services (takes precedence over --file) [default: #{DEFAULT_MANIFEST}]")
18
- class_option(:file, type: :string,
19
- aliases: %w(-f),
20
- desc: "File describing a single task or service [default: #{DEFAULT_FILE}]")
21
- class_option(:file_info, type: :string,
22
- aliases: %w(-i),
23
- desc: "Type and name for use with --file [ex: 'service:hello' or 'task:migrate']")
24
-
25
- desc("up [SERVICES...]", "Register ECS task definitions and update services")
26
- def up(*services)
27
- available = manifest.task_definitions.select {|td| td.type == :service }
28
- chosen = all_or_specified(available, services)
29
-
30
- chosen.each do |service|
31
- json = EcsCompose::JsonGenerator.new(service.name, service.yaml).json
32
- EcsCompose::Ecs.update_service_with_json(service.name, json)
33
- end
34
- end
35
-
36
- desc("register [TASK_DEFINITIONS...]", "Register ECS task definitions")
37
- def register(*task_definitions)
38
- available = manifest.task_definitions
39
- chosen = all_or_specified(available, task_definitions)
40
-
41
- chosen.each do |td|
42
- json = EcsCompose::JsonGenerator.new(td.name, td.yaml).json
43
- EcsCompose::Ecs.register_task_definition(json)
44
- end
45
- end
46
-
47
- desc("json [TASK_DEFINITION]",
48
- "Convert a task definition to ECS JSON format")
49
- def json(task_definition=nil)
50
- if task_definition.nil?
51
- choices = manifest.task_definitions.map {|td| td.name }
52
- case choices.length
53
- when 0
54
- fatal_err("Please supply a manifest with at least one task definition")
55
- when 1
56
- task_definition = choices.first
57
- else
58
- fatal_err("Please choose one of: #{choices.join(', ')}")
59
- end
60
- end
61
-
62
- found = manifest.task_definitions.find {|td| td.name } or
63
- fatal_err("Can't find task definition: #{task_definition}")
64
- puts EcsCompose::JsonGenerator.new(found.name, found.yaml).json
65
- end
66
-
67
- protected
68
-
69
- # Choose either all items in `available`, or just those with the
70
- # specified `names`.
71
- def all_or_specified(available, names)
72
- if names.empty?
73
- available
74
- else
75
- available.select {|td| names.include?(td.name) }
76
- end
77
- end
78
-
79
- # Figure out whether we have a manifest or a docker-compose.yml. We
80
- # check supplied flags first, then defaults, and we prefer manifests
81
- # when there's a tie.
82
- def mode
83
- @mode ||=
84
- if options.manifest
85
- :manifest
86
- elsif options.file
87
- :file
88
- elsif File.exist?(DEFAULT_MANIFEST)
89
- :manifest
90
- elsif File.exist?(DEFAULT_FILE)
91
- :file
92
- else
93
- fatal_err("Unable to find either #{DEFAULT_FILE} or #{DEFAULT_MANIFEST}")
94
- end
95
- end
96
-
97
- # Create a manifest, either by reading it in, or synthesizing it from a
98
- # `docker-compose.yml` file and some extra arguments.
99
- def manifest
100
- @manifest ||=
101
- case mode
102
- when :manifest
103
- Manifest.read_from_manifest(options.manifest || DEFAULT_MANIFEST)
104
- when :file
105
- info = options.file_info
106
- if info.nil?
107
- fatal_err("Must pass -i option when using docker-compose.yml")
108
- end
109
- unless info =~ /\A(service|task):([-_A-Za-z0-9\z]+)/
110
- fatal_err("Incorrectly formatted -i option")
111
- end
112
- type, name = $1, $2
113
- Manifest.read_from_file(options.file || DEFAULT_FILE,
114
- type.to_sym, name)
115
- else raise "Unknown mode: #{mode}"
116
- end
117
- end
118
-
119
- # Print an error and quit.
120
- def fatal_err(msg)
121
- STDERR.puts(msg.red)
122
- exit(1)
123
- end
124
- end
125
- end