putpaws 0.1.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: cbb1de2cdc7c119427ca5dfa073f5e8d07f504ff73f93a464f2912a8ef5168ed
4
- data.tar.gz: 042f6202ae3cb0396b0ab7210b2d299504f7e099e8a0cf43d9c6314f0b6384ba
3
+ metadata.gz: f0adf3a9b8987d214af5c9a2c8348554ef7a34a47bc4ff55a1ea677c628d3fa2
4
+ data.tar.gz: 15edd0ace3e1eeded5bc3687fc0f7b02e3189f50bf78255d708308818e861fa1
5
5
  SHA512:
6
- metadata.gz: 12b7e736fe78e9a49569627fd296e9f5540cbea849f8b78a7edbb56c8652de73b82d1b2ac92fef279a682f64e4e83e061ba20e2c3afe1b3c99dce7fd35526fe1
7
- data.tar.gz: efad6347afdc46833694e48070afd0330fe42f8bb0bc16638b6b88a7d5b6d1a091ce50f5ce1ddec4f92cc07e54796f42cc9802c2b5aa07ed4af1d96ba5ebd171
6
+ metadata.gz: 124c94a1b9b20738b48a2de2fe124847930d7ac4fdc921ae7519fa3b8bbe678a5743514258bbffabb3815aa933377f21ea388ee31600a8e211be49ad76af147c
7
+ data.tar.gz: afabd0af48a055ddd0ee8a7e4604700d0fc9b810978a181e6513569d53d9f410ee62cf83e05d34f5ffdb1fdb3c2d42e8c03ded2815316e529df4f568b48d9744
data/README.md CHANGED
@@ -61,6 +61,14 @@ SSM parameters (Ex: `/{service_name}/RAILS_MASTER_KEY`) and putpaws never touche
61
61
  A scheduler role is always created too, and the `target` entry of infra.json carries it,
62
62
  so `scheduler:deploy` works any time by just writing `.putpaws/schedule.json`.
63
63
 
64
+ The CPU architecture is declared once as `cpu_architecture` (`ARM64` / `X86_64`) in the preset
65
+ defaults (overridable per service via `overrides`), and applied consistently to both
66
+ task definitions (`runtimePlatform`) and CodeBuild (environment type and image).
67
+ The bundled preset defaults to `ARM64`; projects whose copied preset predates this setting
68
+ fall back to `X86_64` so nothing changes silently. When switching an existing service to ARM,
69
+ run the CI build right after `up` so an ARM image exists before tasks roll
70
+ (`devops.environment_type` / `environment_image` can override the derivation for staged migration).
71
+
64
72
  CodeBuild is created as CI: builds run inside the VPC with the same subnets and
65
73
  security group as the service, so `db:migrate` against RDS works from the build.
66
74
  Note that the private subnets need a NAT gateway (or VPC endpoints) so that
@@ -147,6 +155,10 @@ bundle exec putpaws awesome-api-staging ecs:run cmd='bundle exec rake db:migrate
147
155
 
148
156
  # Pass wait=true to wait until the task stops and check the exit code
149
157
  bundle exec putpaws awesome-api-staging ecs:run cmd='bundle exec rake db:migrate' wait=true
158
+
159
+ # Override the task size for this launch only (must be a valid Fargate combination).
160
+ # Also available on ecs:shell.
161
+ bundle exec putpaws awesome-api-staging ecs:run cmd='bundle exec rake heavy:job' cpu=1024 memory=2048 wait=true
150
162
  ```
151
163
 
152
164
  Launch a temporary task for operation and attach to it (like SSH-ing into the environment).
@@ -50,7 +50,20 @@ module Putpaws::Ecs
50
50
  # Launch a temporary task whose main process is overridden with the given
51
51
  # command, so that the task terminates itself when the command finishes.
52
52
  # started_by and group are set so that temporary tasks are identifiable.
53
- def run_ecs_task(command:, started_by:, group:, container: nil)
53
+ # cpu/memory override the task-level size for this launch only
54
+ # (must be a valid Fargate combination).
55
+ def run_ecs_task(command:, started_by:, group:, container: nil, cpu: nil, memory: nil)
56
+ overrides = {
57
+ container_overrides: [
58
+ {
59
+ name: container || container_name,
60
+ command: ['/bin/sh', '-c', command],
61
+ }
62
+ ]
63
+ }
64
+ overrides[:cpu] = cpu.to_s unless cpu.to_s.strip.empty?
65
+ overrides[:memory] = memory.to_s unless memory.to_s.strip.empty?
66
+
54
67
  res = ecs_client.run_task({
55
68
  cluster: target.cluster,
56
69
  task_definition: target.task_definition,
@@ -66,14 +79,7 @@ module Putpaws::Ecs
66
79
  assign_public_ip: network.assign_public_ip,
67
80
  }
68
81
  },
69
- overrides: {
70
- container_overrides: [
71
- {
72
- name: container || container_name,
73
- command: ['/bin/sh', '-c', command],
74
- }
75
- ]
76
- },
82
+ overrides: overrides,
77
83
  })
78
84
  failure = res.failures.first
79
85
  raise "Failed to run task: #{failure.reason} #{failure.detail}" if failure
@@ -56,7 +56,7 @@ namespace :ecs do
56
56
  system(*cmd)
57
57
  end
58
58
 
59
- desc "Run a command on a temporary ECS task. The task terminates itself when the command finishes. (Ex) cmd='bundle exec rake db:migrate' wait=true"
59
+ desc "Run a command on a temporary ECS task. The task terminates itself when the command finishes. (Ex) cmd='bundle exec rake db:migrate' wait=true cpu=1024 memory=2048"
60
60
  task :run do
61
61
  runner = Putpaws::Ecs::RunCommand.config(fetch(:app))
62
62
  command = ENV['cmd']
@@ -68,7 +68,9 @@ namespace :ecs do
68
68
  command: command,
69
69
  started_by: 'putpaws-run',
70
70
  group: 'putpaws-run',
71
- container: ENV['container']
71
+ container: ENV['container'],
72
+ cpu: ENV['cpu'],
73
+ memory: ENV['memory']
72
74
  )
73
75
  task_id = ecs_task.task_arn.split('/').last
74
76
  puts "Task started: #{task_id} [putpaws-run]"
@@ -119,7 +121,7 @@ namespace :ecs do
119
121
  end
120
122
  end
121
123
 
122
- desc "Launch a temporary ECS task for operation and attach to it. The task terminates itself when ttl passes (default 30m). (Ex) ttl=45m keep=true"
124
+ desc "Launch a temporary ECS task for operation and attach to it. The task terminates itself when ttl passes (default 30m). (Ex) ttl=45m keep=true cpu=256 memory=512"
123
125
  task :shell do
124
126
  runner = Putpaws::Ecs::RunCommand.config(fetch(:app))
125
127
  ttl = Putpaws::Ecs::RunCommand.parse_ttl(ENV['ttl'])
@@ -128,7 +130,9 @@ namespace :ecs do
128
130
  ecs_task = runner.run_ecs_task(
129
131
  command: "sleep #{ttl}",
130
132
  started_by: 'putpaws-shell',
131
- group: 'putpaws-shell'
133
+ group: 'putpaws-shell',
134
+ cpu: ENV['cpu'],
135
+ memory: ENV['memory']
132
136
  )
133
137
  task_id = ecs_task.task_arn.split('/').last
134
138
  puts "Task started: #{task_id} [putpaws-shell]"
@@ -65,7 +65,7 @@ module Putpaws
65
65
  version_id: policy.default_version_id
66
66
  )
67
67
  JSON.parse(URI.decode_www_form_component(ver.policy_version.document))
68
- rescue Aws::IAM::Errors::NoSuchEntityException
68
+ rescue Aws::IAM::Errors::NoSuchEntity, Aws::IAM::Errors::NoSuchEntityException
69
69
  nil
70
70
  end
71
71
 
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "defaults": {
3
+ "cpu_architecture": "ARM64",
3
4
  "cpu": "256",
4
5
  "memory": "512",
5
6
  "desired_count": 1,
@@ -24,7 +25,10 @@
24
25
  "service_task_definition": "app",
25
26
  "devops_defaults": {
26
27
  "source_type": "GITHUB",
27
- "environment_image": "aws/codebuild/standard:7.0",
28
+ "environment_images": {
29
+ "ARM64": "aws/codebuild/amazonlinux-aarch64-standard:3.0",
30
+ "X86_64": "aws/codebuild/standard:7.0"
31
+ },
28
32
  "compute_type": "BUILD_GENERAL1_SMALL",
29
33
  "privileged_mode": true,
30
34
  "buildspec": "buildspec.yml"
@@ -2,6 +2,10 @@
2
2
  "family": "<%= service_name %>-app",
3
3
  "requiresCompatibilities": ["FARGATE"],
4
4
  "networkMode": "awsvpc",
5
+ "runtimePlatform": {
6
+ "cpuArchitecture": "<%= cpu_architecture %>",
7
+ "operatingSystemFamily": "LINUX"
8
+ },
5
9
  "cpu": "<%= cpu %>",
6
10
  "memory": "<%= memory %>",
7
11
  "executionRoleArn": "<%= execution_role_arn %>",
@@ -2,6 +2,10 @@
2
2
  "family": "<%= service_name %>-web",
3
3
  "requiresCompatibilities": ["FARGATE"],
4
4
  "networkMode": "awsvpc",
5
+ "runtimePlatform": {
6
+ "cpuArchitecture": "<%= cpu_architecture %>",
7
+ "operatingSystemFamily": "LINUX"
8
+ },
5
9
  "cpu": "<%= cpu %>",
6
10
  "memory": "<%= memory %>",
7
11
  "executionRoleArn": "<%= execution_role_arn %>",
@@ -92,6 +92,20 @@ module Putpaws
92
92
  preset.devops_defaults.merge(devops.reject{|_, v| v.nil?})
93
93
  end
94
94
 
95
+ CPU_ARCHITECTURES = %w[X86_64 ARM64]
96
+
97
+ # Single source of truth for the CPU architecture, applied to both
98
+ # task definitions (runtimePlatform) and CodeBuild (environment type/image).
99
+ # Falls back to X86_64 when unspecified so that existing projects
100
+ # (whose copied presets/templates predate this setting) keep working.
101
+ def cpu_architecture
102
+ arch = (settings[:cpu_architecture] || 'X86_64').to_s
103
+ unless CPU_ARCHITECTURES.include?(arch)
104
+ raise "Invalid cpu_architecture: #{arch} (available: #{CPU_ARCHITECTURES.join(', ')})"
105
+ end
106
+ arch
107
+ end
108
+
95
109
  def account_id
96
110
  Util.arn_account_id(base[:ecr_repository_arn])
97
111
  end
@@ -5,6 +5,17 @@ module Putpaws
5
5
  module Provision
6
6
  module Resources
7
7
  class CodebuildProject < Base
8
+ # Derived from cpu_architecture; devops.environment_type / environment_image
9
+ # override the derivation (useful for staged arch migration).
10
+ ENVIRONMENT_TYPES = {
11
+ 'ARM64' => 'ARM_CONTAINER',
12
+ 'X86_64' => 'LINUX_CONTAINER',
13
+ }
14
+ DEFAULT_IMAGES = {
15
+ 'ARM64' => 'aws/codebuild/amazonlinux-aarch64-standard:3.0',
16
+ 'X86_64' => 'aws/codebuild/standard:7.0',
17
+ }
18
+
8
19
  def name
9
20
  config.build_project_name
10
21
  end
@@ -13,6 +24,16 @@ module Putpaws
13
24
  config.devops_settings
14
25
  end
15
26
 
27
+ def environment_type
28
+ devops[:environment_type] || ENVIRONMENT_TYPES.fetch(config.cpu_architecture)
29
+ end
30
+
31
+ def environment_image
32
+ devops[:environment_image] ||
33
+ (devops[:environment_images] || {})[config.cpu_architecture.to_sym] ||
34
+ DEFAULT_IMAGES.fetch(config.cpu_architecture)
35
+ end
36
+
16
37
  def security_group_ids
17
38
  ids = state.resources[:security_group_ids]
18
39
  raise "security_group_ids not found in state. Run the service step first." if ids.nil? || ids.empty?
@@ -30,8 +51,8 @@ module Putpaws
30
51
  },
31
52
  artifacts: {type: 'NO_ARTIFACTS'},
32
53
  environment: {
33
- type: 'LINUX_CONTAINER',
34
- image: devops[:environment_image] || 'aws/codebuild/standard:7.0',
54
+ type: environment_type,
55
+ image: environment_image,
35
56
  compute_type: devops[:compute_type] || 'BUILD_GENERAL1_SMALL',
36
57
  privileged_mode: devops.fetch(:privileged_mode, true),
37
58
  },
@@ -60,6 +81,7 @@ module Putpaws
60
81
  current.source&.location != desired_params[:source][:location] ||
61
82
  current.source&.buildspec != desired_params[:source][:buildspec] ||
62
83
  current.service_role != desired_params[:service_role] ||
84
+ current.environment&.type != desired_params[:environment][:type] ||
63
85
  current.environment&.image != desired_params[:environment][:image] ||
64
86
  current.environment&.compute_type != desired_params[:environment][:compute_type] ||
65
87
  current.vpc_config&.subnets.to_a.sort != desired_params[:vpc_config][:subnets].sort ||
@@ -43,7 +43,7 @@ module Putpaws
43
43
 
44
44
  def current
45
45
  clients.iam.get_role(role_name: name).role
46
- rescue Aws::IAM::Errors::NoSuchEntityException
46
+ rescue Aws::IAM::Errors::NoSuchEntity, Aws::IAM::Errors::NoSuchEntityException
47
47
  nil
48
48
  end
49
49
 
@@ -25,6 +25,9 @@ module Putpaws
25
25
  def current
26
26
  res = clients.ecs.describe_services(cluster: config.cluster_name, services: [name])
27
27
  res.services.detect{|s| s.status == 'ACTIVE'}
28
+ rescue Aws::ECS::Errors::ClusterNotFoundException
29
+ # cluster not created yet (Ex: `ahead` on a fresh setup) -> no service either
30
+ nil
28
31
  end
29
32
 
30
33
  def changed?(current)
@@ -11,7 +11,8 @@ module Putpaws
11
11
  # Variables exposed to taskdef ERB templates.
12
12
  class TemplateContext
13
13
  attr_reader :service_name, :region, :account_id,
14
- :cpu, :memory, :container_port, :image, :nginx_image,
14
+ :cpu, :memory, :container_port, :cpu_architecture,
15
+ :image, :nginx_image,
15
16
  :log_group, :execution_role_arn, :task_role_arn,
16
17
  :env_json, :secrets_json
17
18
 
@@ -23,6 +24,7 @@ module Putpaws
23
24
  @cpu = settings[:cpu].to_s
24
25
  @memory = settings[:memory].to_s
25
26
  @container_port = (settings[:container_port] || 3000).to_i
27
+ @cpu_architecture = config.cpu_architecture
26
28
  @image = config.ecr_image_uri
27
29
  @nginx_image = settings[:nginx_image] || 'public.ecr.aws/nginx/nginx:stable'
28
30
  @log_group = config.log_group
@@ -1,3 +1,3 @@
1
1
  module Putpaws
2
- VERSION = "0.1.0"
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.1.0
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: 2026-09-01 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
@@ -209,7 +208,6 @@ homepage: https://rubygems.org/gems/putpaws
209
208
  licenses:
210
209
  - MIT
211
210
  metadata: {}
212
- post_install_message:
213
211
  rdoc_options: []
214
212
  require_paths:
215
213
  - lib
@@ -224,8 +222,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
224
222
  - !ruby/object:Gem::Version
225
223
  version: '0'
226
224
  requirements: []
227
- rubygems_version: 3.4.10
228
- signing_key:
225
+ rubygems_version: 4.0.16
229
226
  specification_version: 4
230
227
  summary: Put your paws up!!
231
228
  test_files: []