putpaws 0.0.9 → 0.1.3

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 +165 -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 +121 -0
  9. data/lib/putpaws/ecs/task_command.rb +63 -9
  10. data/lib/putpaws/ecs/tasks/ecs_task.rake +117 -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 +36 -0
  22. data/lib/putpaws/provision/presets/rails-nginx/templates/taskdef-app.json.erb +33 -0
  23. data/lib/putpaws/provision/presets/rails-nginx/templates/taskdef-web.json.erb +52 -0
  24. data/lib/putpaws/provision/provision_config.rb +170 -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 +107 -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 +74 -0
  33. data/lib/putpaws/provision/resources/task_definition.rb +121 -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 +63 -6
@@ -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.3"
3
3
  end
metadata CHANGED
@@ -1,14 +1,13 @@
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.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - metheglin
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2024-06-03 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: rake
@@ -66,6 +65,34 @@ dependencies:
66
65
  - - ">="
67
66
  - !ruby/object:Gem::Version
68
67
  version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: aws-sdk-ec2
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: aws-sdk-iam
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - ">="
87
+ - !ruby/object:Gem::Version
88
+ version: '0'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
69
96
  - !ruby/object:Gem::Dependency
70
97
  name: aws-sdk-cloudwatchlogs
71
98
  requirement: !ruby/object:Gem::Requirement
@@ -119,6 +146,9 @@ files:
119
146
  - bin/putpaws
120
147
  - lib/Putpawsfile
121
148
  - lib/putpaws.rb
149
+ - lib/putpaws/ai/ai_task.rb
150
+ - lib/putpaws/ai/guide.rb
151
+ - lib/putpaws/ai/tasks/ai_task.rake
122
152
  - lib/putpaws/all.rb
123
153
  - lib/putpaws/application.rb
124
154
  - lib/putpaws/application_config.rb
@@ -131,25 +161,53 @@ files:
131
161
  - lib/putpaws/code_build/tasks/build_task.rake
132
162
  - lib/putpaws/dsl.rb
133
163
  - lib/putpaws/ecs/ecs_task.rb
164
+ - lib/putpaws/ecs/run_command.rb
134
165
  - lib/putpaws/ecs/task_command.rb
135
166
  - lib/putpaws/ecs/tasks/ecs_task.rake
136
167
  - lib/putpaws/env.rb
137
168
  - lib/putpaws/hello.rb
169
+ - lib/putpaws/iam/grant_command.rb
170
+ - lib/putpaws/iam/iam_task.rb
171
+ - lib/putpaws/iam/operator_config.rb
172
+ - lib/putpaws/iam/tasks/iam_task.rake
173
+ - lib/putpaws/info.rb
138
174
  - lib/putpaws/infra_network_config.rb
139
175
  - lib/putpaws/infra_target_config.rb
140
176
  - lib/putpaws/prompt.rb
177
+ - lib/putpaws/provision/all.rb
178
+ - lib/putpaws/provision/aws_clients.rb
179
+ - lib/putpaws/provision/config_writer.rb
180
+ - lib/putpaws/provision/policy_generator.rb
181
+ - lib/putpaws/provision/preset.rb
182
+ - lib/putpaws/provision/presets/rails-nginx/preset.json
183
+ - lib/putpaws/provision/presets/rails-nginx/templates/taskdef-app.json.erb
184
+ - lib/putpaws/provision/presets/rails-nginx/templates/taskdef-web.json.erb
185
+ - lib/putpaws/provision/provision_config.rb
186
+ - lib/putpaws/provision/provision_task.rb
187
+ - lib/putpaws/provision/resources/base.rb
188
+ - lib/putpaws/provision/resources/cluster.rb
189
+ - lib/putpaws/provision/resources/codebuild_project.rb
190
+ - lib/putpaws/provision/resources/iam_role.rb
191
+ - lib/putpaws/provision/resources/log_group.rb
192
+ - lib/putpaws/provision/resources/security_group.rb
193
+ - lib/putpaws/provision/resources/service.rb
194
+ - lib/putpaws/provision/resources/task_definition.rb
195
+ - lib/putpaws/provision/runner.rb
196
+ - lib/putpaws/provision/state.rb
197
+ - lib/putpaws/provision/tasks/provision.rake
198
+ - lib/putpaws/provision/util.rb
141
199
  - lib/putpaws/schedule_config.rb
142
200
  - lib/putpaws/scheduler/schedule_command.rb
143
201
  - lib/putpaws/scheduler/scheduler_task.rb
144
202
  - lib/putpaws/scheduler/tasks/scheduler_task.rake
145
203
  - lib/putpaws/setup.rb
146
204
  - lib/putpaws/tasks/hello.rake
205
+ - lib/putpaws/tasks/info.rake
147
206
  - lib/putpaws/version.rb
148
207
  homepage: https://rubygems.org/gems/putpaws
149
208
  licenses:
150
209
  - MIT
151
210
  metadata: {}
152
- post_install_message:
153
211
  rdoc_options: []
154
212
  require_paths:
155
213
  - lib
@@ -164,8 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
222
  - !ruby/object:Gem::Version
165
223
  version: '0'
166
224
  requirements: []
167
- rubygems_version: 3.4.10
168
- signing_key:
225
+ rubygems_version: 4.0.16
169
226
  specification_version: 4
170
227
  summary: Put your paws up!!
171
228
  test_files: []