putpaws 0.0.9 → 0.1.0

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +153 -2
  3. data/lib/Putpawsfile +4 -0
  4. data/lib/putpaws/ai/ai_task.rb +1 -0
  5. data/lib/putpaws/ai/guide.rb +119 -0
  6. data/lib/putpaws/ai/tasks/ai_task.rake +14 -0
  7. data/lib/putpaws/application_config.rb +15 -2
  8. data/lib/putpaws/ecs/run_command.rb +115 -0
  9. data/lib/putpaws/ecs/task_command.rb +63 -9
  10. data/lib/putpaws/ecs/tasks/ecs_task.rake +113 -6
  11. data/lib/putpaws/iam/grant_command.rb +205 -0
  12. data/lib/putpaws/iam/iam_task.rb +1 -0
  13. data/lib/putpaws/iam/operator_config.rb +46 -0
  14. data/lib/putpaws/iam/tasks/iam_task.rake +65 -0
  15. data/lib/putpaws/info.rb +1 -0
  16. data/lib/putpaws/provision/all.rb +29 -0
  17. data/lib/putpaws/provision/aws_clients.rb +59 -0
  18. data/lib/putpaws/provision/config_writer.rb +88 -0
  19. data/lib/putpaws/provision/policy_generator.rb +221 -0
  20. data/lib/putpaws/provision/preset.rb +91 -0
  21. data/lib/putpaws/provision/presets/rails-nginx/preset.json +32 -0
  22. data/lib/putpaws/provision/presets/rails-nginx/templates/taskdef-app.json.erb +29 -0
  23. data/lib/putpaws/provision/presets/rails-nginx/templates/taskdef-web.json.erb +48 -0
  24. data/lib/putpaws/provision/provision_config.rb +156 -0
  25. data/lib/putpaws/provision/provision_task.rb +1 -0
  26. data/lib/putpaws/provision/resources/base.rb +49 -0
  27. data/lib/putpaws/provision/resources/cluster.rb +30 -0
  28. data/lib/putpaws/provision/resources/codebuild_project.rb +85 -0
  29. data/lib/putpaws/provision/resources/iam_role.rb +89 -0
  30. data/lib/putpaws/provision/resources/log_group.rb +50 -0
  31. data/lib/putpaws/provision/resources/security_group.rb +72 -0
  32. data/lib/putpaws/provision/resources/service.rb +71 -0
  33. data/lib/putpaws/provision/resources/task_definition.rb +119 -0
  34. data/lib/putpaws/provision/runner.rb +218 -0
  35. data/lib/putpaws/provision/state.rb +45 -0
  36. data/lib/putpaws/provision/tasks/provision.rake +129 -0
  37. data/lib/putpaws/provision/util.rb +50 -0
  38. data/lib/putpaws/tasks/info.rake +35 -0
  39. data/lib/putpaws/version.rb +1 -1
  40. metadata +62 -2
@@ -0,0 +1,218 @@
1
+ require 'json'
2
+ require 'fileutils'
3
+ require 'putpaws/provision/util'
4
+ require 'putpaws/provision/state'
5
+ require 'putpaws/provision/aws_clients'
6
+ require 'putpaws/provision/policy_generator'
7
+ require 'putpaws/provision/config_writer'
8
+ require 'putpaws/provision/resources/base'
9
+ require 'putpaws/provision/resources/iam_role'
10
+ require 'putpaws/provision/resources/security_group'
11
+ require 'putpaws/provision/resources/cluster'
12
+ require 'putpaws/provision/resources/log_group'
13
+ require 'putpaws/provision/resources/task_definition'
14
+ require 'putpaws/provision/resources/service'
15
+ require 'putpaws/provision/resources/codebuild_project'
16
+
17
+ module Putpaws
18
+ module Provision
19
+ # Orchestrates the provisioning commands:
20
+ # ready (provision:init) ... interview + drafts
21
+ # steady (provision:roles) ... create IAM roles from the reviewed drafts
22
+ # ahead (provision:plan) ... dry-run
23
+ # up (provision:up) ... build the rest, idempotent
24
+ #
25
+ # Running `steady` IS the user's explicit confirmation of the drafts:
26
+ # `up` never touches IAM and stops until the role ARNs are filled.
27
+ class Runner
28
+ ROLE_KEYS = [:task_execution_role_arn, :task_role_arn, :codebuild_role_arn, :scheduler_role_arn]
29
+ ROLE_DRAFTS = {
30
+ task_execution_role_arn: 'role-task-execution.json',
31
+ task_role_arn: 'role-task.json',
32
+ codebuild_role_arn: 'role-codebuild.json',
33
+ scheduler_role_arn: 'role-scheduler.json',
34
+ }
35
+
36
+ attr_reader :config, :state, :clients, :prompt, :io
37
+ def initialize(config:, state: nil, clients: nil, prompt: nil, io: $stdout)
38
+ @config = config
39
+ @state = state || State.load(config)
40
+ @clients = clients || AwsClients.new(region: config.region)
41
+ @prompt = prompt
42
+ @io = io
43
+ end
44
+
45
+ def blank_role_keys
46
+ ROLE_KEYS.select{|k| Util.blank?(config.roles[k])}
47
+ end
48
+
49
+ # A role is managed by `steady` when its ARN is blank (to be created) or
50
+ # when the filled ARN points at the draft's own role name (created by a
51
+ # previous `steady`; kept updatable). An ARN with a different role name
52
+ # is treated as external (org-managed) and never touched.
53
+ def steady_role_entries
54
+ args = {config: config, state: state, clients: clients}
55
+ ROLE_KEYS.map do |key|
56
+ resource = Resources::IamRole.new(roles_key: key, draft_file: ROLE_DRAFTS[key], **args)
57
+ arn = config.roles[key]
58
+ external = !Util.blank?(arn) && arn.split('/').last != resource.name
59
+ {key: key, resource: resource, external: external}
60
+ end
61
+ end
62
+
63
+ def service_resources
64
+ args = {config: config, state: state, clients: clients}
65
+ [
66
+ Resources::SecurityGroup.new(**args),
67
+ Resources::LogGroup.new(log_group_name: config.log_group, output_key: :log_group, **args),
68
+ Resources::Cluster.new(**args),
69
+ *config.preset.task_definitions.map{|entry| Resources::TaskDefinition.new(entry: entry, **args)},
70
+ Resources::Service.new(**args),
71
+ ]
72
+ end
73
+
74
+ def devops_resources
75
+ args = {config: config, state: state, clients: clients}
76
+ [
77
+ Resources::LogGroup.new(log_group_name: config.build_log_group, output_key: :build_log_group, **args),
78
+ Resources::CodebuildProject.new(**args),
79
+ ]
80
+ end
81
+
82
+ def missing_devops_requirements
83
+ missing = []
84
+ missing << 'devops.source_repository (provision.json)' if Util.blank?(config.devops_settings[:source_repository])
85
+ missing
86
+ end
87
+
88
+ # `putpaws steady`: show each draft inline, confirm one by one, then
89
+ # apply it as-is and fill the ARN into provision.json.
90
+ # Idempotent: re-run after editing drafts to update.
91
+ def steady!
92
+ io.puts "Applying IAM roles from drafts in #{config.policies_dir}/"
93
+ filled = {}
94
+ steady_role_entries.each do |entry|
95
+ if entry[:external]
96
+ print_action('SKIP', 'IamRole', "#{config.roles[entry[:key]]} (external)")
97
+ next
98
+ end
99
+ resource = entry[:resource]
100
+ action = resource.plan[:action]
101
+
102
+ if action == :skip
103
+ print_action('SKIP', 'IamRole', resource.name)
104
+ else
105
+ io.puts ""
106
+ io.puts "=== #{resource.draft_file} -> #{action.to_s.upcase} role: #{resource.name} ==="
107
+ io.puts JSON.pretty_generate(resource.draft)
108
+ unless prompt.yes?("Apply this content as role #{resource.name}?")
109
+ io.puts "Skipped #{resource.name}"
110
+ next
111
+ end
112
+ print_action(action.to_s.upcase, 'IamRole', resource.name)
113
+ end
114
+
115
+ outputs = resource.ensure!
116
+ state.merge_resources!(outputs)
117
+ filled[entry[:key]] = outputs[entry[:key]]
118
+ end
119
+ write_roles_to_provision_json!(filled)
120
+ io.puts "Next: check with `putpaws ahead`, then build with `putpaws up`."
121
+ end
122
+
123
+ def plan
124
+ io.puts "Service: #{config.service_name} (region: #{config.region}, account: #{config.account_id})"
125
+ io.puts ""
126
+ resources = steady_role_entries.reject{|e| e[:external]}.map{|e| e[:resource]}
127
+ resources += service_resources
128
+ resources += devops_resources if missing_devops_requirements.empty?
129
+ resources.each do |r|
130
+ p = r.plan
131
+ print_action(p[:action].to_s.upcase, p[:kind], p[:name])
132
+ end
133
+ if blank_role_keys.any?
134
+ io.puts "[stop point] IAM roles are not created yet. Review the drafts, then run `putpaws steady`."
135
+ end
136
+ if missing_devops_requirements.any?
137
+ io.puts "[stop point] Devops step is blocked. Fill in: #{missing_devops_requirements.join(', ')}"
138
+ end
139
+ check_ssm_parameters
140
+ end
141
+
142
+ def up!
143
+ if blank_role_keys.any?
144
+ io.puts "[stop point] IAM roles are not ready: #{blank_role_keys.join(', ')}"
145
+ io.puts "1. Review and edit the drafts in #{config.policies_dir}/"
146
+ io.puts "2. Run `putpaws steady` to create the roles and fill their ARNs."
147
+ io.puts " (or fill in existing role ARNs in provision.json yourself)"
148
+ return
149
+ end
150
+
151
+ io.puts "Applying service step for #{config.service_name} (account: #{config.account_id}, region: #{config.region})"
152
+ apply_resources(service_resources)
153
+ state.mark_step!(:service, 'done')
154
+
155
+ ConfigWriter.new(config: config, state: state, prompt: prompt, io: io).apply!
156
+
157
+ if missing_devops_requirements.any?
158
+ io.puts "[stop point] Devops step is not ready. Fill in: #{missing_devops_requirements.join(', ')}"
159
+ io.puts "Then run `putpaws up` again."
160
+ return
161
+ end
162
+
163
+ io.puts "Applying devops step"
164
+ apply_resources(devops_resources)
165
+ state.mark_step!(:devops, 'done')
166
+ ConfigWriter.new(config: config, state: state, prompt: prompt, io: io).apply!
167
+
168
+ io.puts "All steps completed."
169
+ io.puts "Verify with: bundle exec putpaws #{config.service_name} ecs:run cmd='echo ok' wait=true"
170
+ end
171
+
172
+ private
173
+
174
+ def print_action(action, kind, name)
175
+ io.puts format("%-8s %-18s %s", action, kind, name)
176
+ end
177
+
178
+ def write_roles_to_provision_json!(filled)
179
+ return if filled.empty?
180
+ path = config.dir.join('provision.json')
181
+ data = JSON.parse(File.read(path), symbolize_names: true)
182
+ data[:roles] ||= {}
183
+ changed = filled.reject{|k, arn| data[:roles][k] == arn}
184
+ return if changed.empty?
185
+ FileUtils.cp(path, "#{path}.bak")
186
+ changed.each{|k, arn| data[:roles][k] = arn}
187
+ Util.write_json(path, data)
188
+ config.data[:roles] = data[:roles]
189
+ io.puts "Filled role ARNs into #{path}:"
190
+ changed.each{|k, arn| io.puts " #{k}: #{arn}"}
191
+ end
192
+
193
+ def apply_resources(resources)
194
+ resources.each do |r|
195
+ print_action(r.plan[:action].to_s.upcase, r.kind, r.name)
196
+ outputs = r.ensure!
197
+ state.merge_resources!(outputs)
198
+ end
199
+ end
200
+
201
+ def check_ssm_parameters
202
+ paths = config.resolved_secrets.values
203
+ return if paths.empty?
204
+ res = clients.ssm.describe_parameters(
205
+ parameter_filters: [{key: 'Name', option: 'Equals', values: paths}]
206
+ )
207
+ existing = res.parameters.map(&:name)
208
+ missing = paths - existing
209
+ if missing.any?
210
+ io.puts "[warning] Missing SSM parameters (register them yourself, putpaws never touches values):"
211
+ missing.each{|p| io.puts " aws ssm put-parameter --type SecureString --name #{p} --value '...'"}
212
+ end
213
+ rescue StandardError => e
214
+ io.puts "(ssm parameter check skipped: #{e.class})"
215
+ end
216
+ end
217
+ end
218
+ end
@@ -0,0 +1,45 @@
1
+ require 'json'
2
+ require 'putpaws/provision/util'
3
+
4
+ module Putpaws
5
+ module Provision
6
+ class State
7
+ def self.load(config)
8
+ path = config.dir.join('state.json')
9
+ data = path.exist? ? JSON.parse(File.read(path), symbolize_names: true) : {}
10
+ new(path: path.to_s, data: data)
11
+ end
12
+
13
+ attr_reader :path, :data
14
+ def initialize(path:, data:)
15
+ @path = path
16
+ @data = data
17
+ @data[:resources] ||= {}
18
+ @data[:steps] ||= {}
19
+ end
20
+
21
+ def resources
22
+ data[:resources]
23
+ end
24
+
25
+ def steps
26
+ data[:steps]
27
+ end
28
+
29
+ def merge_resources!(outputs)
30
+ resources.merge!(outputs.map{|k, v| [k.to_sym, v]}.to_h)
31
+ save!
32
+ end
33
+
34
+ def mark_step!(name, status)
35
+ steps[name.to_sym] = status
36
+ save!
37
+ end
38
+
39
+ def save!
40
+ data[:updated_at] = Time.now.to_s
41
+ Util.write_json(path, data)
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,129 @@
1
+ require "fileutils"
2
+ require "putpaws/prompt"
3
+ require "putpaws/provision/all"
4
+
5
+ namespace :provision do
6
+ desc "Interview basic infra inputs and generate provision.json + IAM policy drafts. (alias: ready)"
7
+ task :init do
8
+ prompt = Putpaws::Prompt.safe
9
+ util = Putpaws::Provision::Util
10
+
11
+ service_name = ENV['service'] || prompt.ask("Application name (Ex: awesome-api-staging):") do |q|
12
+ q.required(true)
13
+ q.validate(/\A[a-z0-9][a-z0-9\-]*\z/, "lowercase letters, numbers and hyphens only")
14
+ end
15
+
16
+ dir = Putpaws::Provision::ProvisionConfig.dir_for(service_name)
17
+ if dir.join('provision.json').exist?
18
+ unless prompt.yes?("#{dir}/provision.json already exists. Overwrite?", default: false)
19
+ puts "Aborted."
20
+ next
21
+ end
22
+ end
23
+
24
+ region = prompt.ask("Region:", default: 'ap-northeast-1')
25
+ preset_choices = Putpaws::Provision::Preset.catalog.map{|e| ["#{e[:name]} (#{e[:source]})", e[:name]]}.to_h
26
+ preset_name = prompt.select("Preset:", preset_choices)
27
+
28
+ puts "--- Basic infra (existing resources; used to generate IAM policies) ---"
29
+ vpc_id = prompt.ask("VPC ID:"){|q| q.required(true)}
30
+ subnets = prompt.ask("Subnet IDs (comma separated):"){|q| q.required(true)}.split(',').map(&:strip)
31
+ sg_ids = prompt.ask("Security group IDs (existing, comma separated, empty to create a new one):")
32
+ .to_s.split(',').map(&:strip).reject(&:empty?)
33
+ ecr_arn = prompt.ask("ECR repository ARN:"){|q| q.required(true)}
34
+ ses_arn = prompt.ask("SES identity ARN (empty to skip):")
35
+ s3_arn = prompt.ask("S3 bucket ARN (empty to skip):")
36
+ ssm_prefix = prompt.ask("SSM parameter path prefix (existing; putpaws never writes values):", default: "/#{service_name}")
37
+ repo = prompt.ask("CodeBuild source repository URL (GitHub, empty to fill later):")
38
+
39
+ data = {
40
+ service_name: service_name,
41
+ region: region,
42
+ preset: preset_name,
43
+ base: {
44
+ vpc_id: vpc_id,
45
+ subnets: subnets,
46
+ security_group_ids: sg_ids,
47
+ ecr_repository_arn: ecr_arn,
48
+ ses_identity_arn: util.blank?(ses_arn) ? nil : ses_arn,
49
+ s3_bucket_arn: util.blank?(s3_arn) ? nil : s3_arn,
50
+ ssm_parameter_prefix: ssm_prefix,
51
+ },
52
+ roles: {
53
+ task_execution_role_arn: nil,
54
+ task_role_arn: nil,
55
+ codebuild_role_arn: nil,
56
+ scheduler_role_arn: nil,
57
+ },
58
+ overrides: {
59
+ cluster_name: nil,
60
+ cpu: nil,
61
+ memory: nil,
62
+ desired_count: nil,
63
+ env: {},
64
+ secrets: {},
65
+ },
66
+ devops: {
67
+ source_repository: util.blank?(repo) ? nil : repo,
68
+ buildspec: "buildspec.yml",
69
+ },
70
+ }
71
+
72
+ Putpaws::Provision::Preset.install(preset_name)
73
+ FileUtils.mkdir_p(dir)
74
+ util.write_json(dir.join('provision.json'), data)
75
+
76
+ config = Putpaws::Provision::ProvisionConfig.new(data)
77
+ files = Putpaws::Provision::PolicyGenerator.new(config).write_step1_drafts!
78
+
79
+ puts ""
80
+ puts "Generated:"
81
+ puts " #{dir}/provision.json"
82
+ files.each{|f| puts " #{f}"}
83
+ puts ""
84
+ puts "Next steps:"
85
+ puts " 1. Review and edit the role drafts in policies/."
86
+ puts " When confirmed, run `putpaws steady` to create the IAM roles from the drafts as-is."
87
+ puts " (or fill in existing role ARNs in provision.json instead)"
88
+ puts " 2. Register SSM parameters (Ex: #{ssm_prefix}/RAILS_MASTER_KEY) yourself."
89
+ puts " 3. Check with `putpaws ahead`, then build with `putpaws up`."
90
+ end
91
+
92
+ desc "Create IAM roles from the reviewed drafts and fill their ARNs into provision.json. Each role is shown and confirmed one by one. Idempotent. (alias: steady)"
93
+ task :roles do
94
+ config = Putpaws::Provision.resolve_config
95
+ prompt = Putpaws::Prompt.safe
96
+ puts "Service: #{config.service_name} / Account: #{config.account_id} / Region: #{config.region}"
97
+ Putpaws::Provision::Runner.new(config: config, prompt: prompt).steady!
98
+ end
99
+
100
+ desc "Show what `putpaws up` would do (dry-run). (alias: ahead)"
101
+ task :plan do
102
+ config = Putpaws::Provision.resolve_config
103
+ Putpaws::Provision::Runner.new(config: config, prompt: Putpaws::Prompt.safe).plan
104
+ end
105
+
106
+ desc "Build infra as far as possible, stopping where manual steps are required. Re-runnable. (alias: up)"
107
+ task :up do
108
+ config = Putpaws::Provision.resolve_config
109
+ prompt = Putpaws::Prompt.safe
110
+ puts "Service: #{config.service_name} / Account: #{config.account_id} / Region: #{config.region}"
111
+ unless prompt.yes?("Proceed?")
112
+ puts "Aborted."
113
+ next
114
+ end
115
+ Putpaws::Provision::Runner.new(config: config, prompt: prompt).up!
116
+ end
117
+ end
118
+
119
+ desc "Alias of provision:init"
120
+ task ready: 'provision:init'
121
+
122
+ desc "Alias of provision:roles"
123
+ task steady: 'provision:roles'
124
+
125
+ desc "Alias of provision:up"
126
+ task up: 'provision:up'
127
+
128
+ desc "Alias of provision:plan"
129
+ task ahead: 'provision:plan'
@@ -0,0 +1,50 @@
1
+ require 'json'
2
+
3
+ module Putpaws
4
+ module Provision
5
+ module Util
6
+ module_function
7
+
8
+ def underscore(str)
9
+ str.to_s.gsub(/([a-z0-9])([A-Z])/, '\1_\2').downcase
10
+ end
11
+
12
+ # Task definition JSON is written in camelCase convention.
13
+ # Convert it into snake_case symbol keys for aws-sdk params.
14
+ def deep_underscore_keys(obj)
15
+ case obj
16
+ when Hash
17
+ obj.map{|k, v| [underscore(k).to_sym, deep_underscore_keys(v)]}.to_h
18
+ when Array
19
+ obj.map{|x| deep_underscore_keys(x)}
20
+ else
21
+ obj
22
+ end
23
+ end
24
+
25
+ def arn_account_id(arn)
26
+ arn.to_s.split(':')[4]
27
+ end
28
+
29
+ def arn_region(arn)
30
+ arn.to_s.split(':')[3]
31
+ end
32
+
33
+ def ecr_repository_name(arn)
34
+ arn.to_s.split(':', 6).last.to_s.sub(/\Arepository\//, '')
35
+ end
36
+
37
+ def ecr_repository_uri(arn)
38
+ "#{arn_account_id(arn)}.dkr.ecr.#{arn_region(arn)}.amazonaws.com/#{ecr_repository_name(arn)}"
39
+ end
40
+
41
+ def blank?(value)
42
+ value.nil? || value.to_s.strip.empty?
43
+ end
44
+
45
+ def write_json(path, data)
46
+ File.write(path, JSON.pretty_generate(data) + "\n")
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,35 @@
1
+ desc "Show resolved settings for the service. No AWS access."
2
+ task :info do
3
+ app = fetch(:app)
4
+ row = ->(key, value){ puts format("%-26s %s", "#{key}:", value) unless value.nil? }
5
+
6
+ row.call('name', app.name)
7
+ row.call('region', app.region)
8
+ row.call('cluster', app.cluster)
9
+ row.call('service', app.service)
10
+ row.call('task_name_prefix', app.task_name_prefix)
11
+ row.call('ecs_region', app.ecs_region)
12
+ row.call('log_group_prefix', app.log_group_prefix)
13
+ row.call('log_region', app.log_region)
14
+ row.call('build_project_name_prefix', app.build_project_name_prefix)
15
+ row.call('build_log_group_prefix', app.build_log_group_prefix)
16
+ row.call('build_region', app.build_region)
17
+
18
+ if (network = app.network)
19
+ row.call('network', network.name)
20
+ row.call(' subnets', network.subnets && network.subnets.join(', '))
21
+ row.call(' security_groups', network.security_groups && network.security_groups.join(', '))
22
+ row.call(' assign_public_ip', network.assign_public_ip)
23
+ end
24
+
25
+ if (target = app.target)
26
+ row.call('target', target.name)
27
+ row.call(' cluster', target.cluster)
28
+ row.call(' task_definition', target.task_definition)
29
+ row.call(' container_name', target.container_name)
30
+ row.call(' scheduler_role', target.scheduler_role)
31
+ end
32
+
33
+ schedules = app.schedules
34
+ row.call('schedules', schedules.map(&:name).join(', ')) unless schedules.empty?
35
+ end
@@ -1,3 +1,3 @@
1
1
  module Putpaws
2
- VERSION = "0.0.9"
2
+ VERSION = "0.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: putpaws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.9
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - metheglin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
11
+ date: 2026-09-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -66,6 +66,34 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: aws-sdk-ec2
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
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: aws-sdk-iam
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
69
97
  - !ruby/object:Gem::Dependency
70
98
  name: aws-sdk-cloudwatchlogs
71
99
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +147,9 @@ files:
119
147
  - bin/putpaws
120
148
  - lib/Putpawsfile
121
149
  - lib/putpaws.rb
150
+ - lib/putpaws/ai/ai_task.rb
151
+ - lib/putpaws/ai/guide.rb
152
+ - lib/putpaws/ai/tasks/ai_task.rake
122
153
  - lib/putpaws/all.rb
123
154
  - lib/putpaws/application.rb
124
155
  - lib/putpaws/application_config.rb
@@ -131,19 +162,48 @@ files:
131
162
  - lib/putpaws/code_build/tasks/build_task.rake
132
163
  - lib/putpaws/dsl.rb
133
164
  - lib/putpaws/ecs/ecs_task.rb
165
+ - lib/putpaws/ecs/run_command.rb
134
166
  - lib/putpaws/ecs/task_command.rb
135
167
  - lib/putpaws/ecs/tasks/ecs_task.rake
136
168
  - lib/putpaws/env.rb
137
169
  - lib/putpaws/hello.rb
170
+ - lib/putpaws/iam/grant_command.rb
171
+ - lib/putpaws/iam/iam_task.rb
172
+ - lib/putpaws/iam/operator_config.rb
173
+ - lib/putpaws/iam/tasks/iam_task.rake
174
+ - lib/putpaws/info.rb
138
175
  - lib/putpaws/infra_network_config.rb
139
176
  - lib/putpaws/infra_target_config.rb
140
177
  - lib/putpaws/prompt.rb
178
+ - lib/putpaws/provision/all.rb
179
+ - lib/putpaws/provision/aws_clients.rb
180
+ - lib/putpaws/provision/config_writer.rb
181
+ - lib/putpaws/provision/policy_generator.rb
182
+ - lib/putpaws/provision/preset.rb
183
+ - lib/putpaws/provision/presets/rails-nginx/preset.json
184
+ - lib/putpaws/provision/presets/rails-nginx/templates/taskdef-app.json.erb
185
+ - lib/putpaws/provision/presets/rails-nginx/templates/taskdef-web.json.erb
186
+ - lib/putpaws/provision/provision_config.rb
187
+ - lib/putpaws/provision/provision_task.rb
188
+ - lib/putpaws/provision/resources/base.rb
189
+ - lib/putpaws/provision/resources/cluster.rb
190
+ - lib/putpaws/provision/resources/codebuild_project.rb
191
+ - lib/putpaws/provision/resources/iam_role.rb
192
+ - lib/putpaws/provision/resources/log_group.rb
193
+ - lib/putpaws/provision/resources/security_group.rb
194
+ - lib/putpaws/provision/resources/service.rb
195
+ - lib/putpaws/provision/resources/task_definition.rb
196
+ - lib/putpaws/provision/runner.rb
197
+ - lib/putpaws/provision/state.rb
198
+ - lib/putpaws/provision/tasks/provision.rake
199
+ - lib/putpaws/provision/util.rb
141
200
  - lib/putpaws/schedule_config.rb
142
201
  - lib/putpaws/scheduler/schedule_command.rb
143
202
  - lib/putpaws/scheduler/scheduler_task.rb
144
203
  - lib/putpaws/scheduler/tasks/scheduler_task.rake
145
204
  - lib/putpaws/setup.rb
146
205
  - lib/putpaws/tasks/hello.rake
206
+ - lib/putpaws/tasks/info.rake
147
207
  - lib/putpaws/version.rb
148
208
  homepage: https://rubygems.org/gems/putpaws
149
209
  licenses: