cpl 1.1.2 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cpl.rb CHANGED
@@ -141,11 +141,12 @@ module Cpl
141
141
  usage = command_class::USAGE.empty? ? name : command_class::USAGE
142
142
  requires_args = command_class::REQUIRES_ARGS
143
143
  default_args = command_class::DEFAULT_ARGS
144
- command_options = command_class::OPTIONS + [::Command::Base.verbose_option]
144
+ command_options = command_class::OPTIONS + ::Command::Base.common_options
145
145
  description = command_class::DESCRIPTION
146
146
  long_description = command_class::LONG_DESCRIPTION
147
147
  examples = command_class::EXAMPLES
148
148
  hide = command_class::HIDE || deprecated
149
+ with_info_header = command_class::WITH_INFO_HEADER
149
150
 
150
151
  long_description += "\n#{examples}" if examples.length.positive?
151
152
 
@@ -160,6 +161,10 @@ module Cpl
160
161
  method_option(option[:name], **option[:params])
161
162
  end
162
163
 
164
+ # We'll handle required options manually in `Config`
165
+ required_options = command_options.select { |option| option[:params][:required] }.map { |option| option[:name] }
166
+ disable_required_check! name_for_method.to_sym if required_options.any?
167
+
163
168
  define_method(name_for_method) do |*provided_args| # rubocop:disable Metrics/MethodLength
164
169
  if deprecated
165
170
  ::Shell.warn_deprecated("Command '#{command_key}' is deprecated, " \
@@ -176,7 +181,9 @@ module Cpl
176
181
  raise_args_error.call(args, nil) if (args.empty? && requires_args) || (!args.empty? && !requires_args)
177
182
 
178
183
  begin
179
- config = Config.new(args, options)
184
+ config = Config.new(args, options, required_options)
185
+
186
+ Cpl::Cli.show_info_header(config) if with_info_header
180
187
 
181
188
  command_class.new(config).call
182
189
  rescue RuntimeError => e
@@ -186,6 +193,25 @@ module Cpl
186
193
  rescue StandardError => e
187
194
  ::Shell.abort("Unable to load command: #{e.message}")
188
195
  end
196
+
197
+ def self.show_info_header(config) # rubocop:disable Metrics/MethodLength
198
+ return if @showed_info_header
199
+
200
+ rows = {}
201
+ rows["ORG"] = config.org || "NOT PROVIDED!"
202
+ rows["ORG"] += " (comes from CPLN_ORG env var)" if config.org_comes_from_env
203
+ rows["APP"] = config.app || "NOT PROVIDED!"
204
+ rows["APP"] += " (comes from CPLN_APP env var)" if config.app_comes_from_env
205
+
206
+ rows.each do |key, value|
207
+ puts "#{key}: #{value}"
208
+ end
209
+
210
+ @showed_info_header = true
211
+
212
+ # Add a newline after the info header
213
+ puts
214
+ end
189
215
  end
190
216
  end
191
217
 
@@ -0,0 +1,27 @@
1
+ FROM ruby:3.1.2
2
+
3
+ RUN apt-get update
4
+
5
+ WORKDIR /app
6
+
7
+ # install ruby gems
8
+ COPY Gemfile* ./
9
+
10
+ RUN bundle config set without 'development test' && \
11
+ bundle config set with 'staging production' && \
12
+ bundle install --jobs=3 --retry=3
13
+
14
+ COPY . ./
15
+
16
+ ENV RAILS_ENV=production
17
+
18
+ # compiling assets requires any value for ENV of SECRET_KEY_BASE
19
+ ENV SECRET_KEY_BASE=NOT_USED_NON_BLANK
20
+
21
+ RUN rails assets:precompile
22
+
23
+ # add entrypoint
24
+ COPY .controlplane/entrypoint.sh ./
25
+ ENTRYPOINT ["/app/entrypoint.sh"]
26
+
27
+ CMD ["rails", "s"]
@@ -0,0 +1,57 @@
1
+ # Keys beginning with "cpln_" correspond to your settings in Control Plane.
2
+
3
+ # You can opt out of allowing the use of CPLN_ORG and CPLN_APP env vars
4
+ # to avoid any accidents with the wrong org / app.
5
+ allow_org_override_by_env: true
6
+ allow_app_override_by_env: true
7
+
8
+ aliases:
9
+ common: &common
10
+ # Organization name for staging (customize to your needs).
11
+ # Production apps will use a different organization, specified below, for security.
12
+ cpln_org: my-org-staging
13
+
14
+ # Example apps use only one location. Control Plane offers the ability to use multiple locations.
15
+ # TODO: Allow specification of multiple locations.
16
+ default_location: aws-us-east-2
17
+
18
+ # Configure the workload name used as a template for one-off scripts, like a Heroku one-off dyno.
19
+ one_off_workload: rails
20
+
21
+ # Workloads that are for the application itself and are using application Docker images.
22
+ app_workloads:
23
+ - rails
24
+
25
+ # Additional "service type" workloads, using non-application Docker images.
26
+ additional_workloads:
27
+ - postgres
28
+
29
+ # Configure the workload name used when maintenance mode is on (defaults to "maintenance")
30
+ maintenance_workload: maintenance
31
+
32
+ apps:
33
+ my-app-staging:
34
+ # Use the values from the common section above.
35
+ <<: *common
36
+ my-app-review:
37
+ <<: *common
38
+ # If `match_if_app_name_starts_with` is `true`, then use this config for app names starting with this name,
39
+ # e.g., "my-app-review-pr123", "my-app-review-anything-goes", etc.
40
+ match_if_app_name_starts_with: true
41
+ my-app-production:
42
+ <<: *common
43
+
44
+ # You can also opt out of allowing the use of CPLN_ORG and CPLN_APP env vars per app.
45
+ # It's recommended to leave this off for production, to avoid any accidents.
46
+ allow_org_override_by_env: false
47
+ allow_app_override_by_env: false
48
+
49
+ # Use a different organization for production.
50
+ cpln_org: my-org-production
51
+ # Allows running the command `cpl promote-app-from-upstream -a my-app-production`
52
+ # to promote the staging app to production.
53
+ upstream: my-app-staging
54
+ my-app-other:
55
+ <<: *common
56
+ # You can specify a different `Dockerfile` relative to the `.controlplane/` directory (defaults to "Dockerfile").
57
+ dockerfile: ../some_other/Dockerfile
@@ -0,0 +1,8 @@
1
+ #!/bin/sh
2
+ # Runs before the main command
3
+
4
+ echo " -- Preparing database"
5
+ rails db:prepare
6
+
7
+ echo " -- Finishing entrypoint.sh, executing '$@'"
8
+ exec "$@"
@@ -0,0 +1,21 @@
1
+ # Template setup of the GVC, roughly corresponding to a Heroku app
2
+ kind: gvc
3
+ name: APP_GVC
4
+ spec:
5
+ # For using templates for test apps, put ENV values here, stored in git repo.
6
+ # Production apps will have values configured manually after app creation.
7
+ env:
8
+ - name: DATABASE_URL
9
+ # Password does not matter because host postgres.APP_GVC.cpln.local can only be accessed
10
+ # locally within CPLN GVC, and postgres running on a CPLN workload is something only for a
11
+ # test app that lacks persistence.
12
+ value: 'postgres://the_user:the_password@postgres.APP_GVC.cpln.local:5432/APP_GVC'
13
+ - name: RAILS_ENV
14
+ value: production
15
+ - name: RAILS_SERVE_STATIC_FILES
16
+ value: 'true'
17
+
18
+ # Part of standard configuration
19
+ staticPlacement:
20
+ locationLinks:
21
+ - /org/APP_ORG/location/APP_LOCATION
@@ -0,0 +1,176 @@
1
+ # Comes from example at
2
+ # https://github.com/controlplane-com/examples/blob/main/examples/postgres/manifest.yaml
3
+
4
+ kind: volumeset
5
+ name: postgres-poc-vs
6
+ description: postgres-poc-vs
7
+ spec:
8
+ autoscaling:
9
+ maxCapacity: 1000
10
+ minFreePercentage: 1
11
+ scalingFactor: 1.1
12
+ fileSystemType: ext4
13
+ initialCapacity: 10
14
+ performanceClass: general-purpose-ssd
15
+ snapshots:
16
+ createFinalSnapshot: true
17
+ retentionDuration: 7d
18
+
19
+ ---
20
+ kind: secret
21
+ name: postgres-poc-credentials
22
+ description: ''
23
+ type: dictionary
24
+ data:
25
+ password: the_password #Replace this with a real password
26
+ username: the_user #Replace this with a real username
27
+
28
+ ---
29
+ kind: secret
30
+ name: postgres-poc-entrypoint-script
31
+ type: opaque
32
+ data:
33
+ encoding: base64
34
+ payload: >-
35
+ IyEvdXNyL2Jpbi9lbnYgYmFzaAoKc291cmNlIC91c3IvbG9jYWwvYmluL2RvY2tlci1lbnRyeXBvaW50LnNoCgppbnN0YWxsX2RlcHMoKSB7CiAgYXB0LWdldCB1cGRhdGUgLXkgPiAvZGV2L251bGwKICBhcHQtZ2V0IGluc3RhbGwgY3VybCAteSA+IC9kZXYvbnVsbAogIGFwdC1nZXQgaW5zdGFsbCB1bnppcCAteSA+IC9kZXYvbnVsbAogIGN1cmwgImh0dHBzOi8vYXdzY2xpLmFtYXpvbmF3cy5jb20vYXdzY2xpLWV4ZS1saW51eC14ODZfNjQuemlwIiAtbyAiYXdzY2xpdjIuemlwIiA+IC9kZXYvbnVsbAogIHVuemlwIGF3c2NsaXYyLnppcCA+IC9kZXYvbnVsbAogIC4vYXdzL2luc3RhbGwgPiAvZGV2L251bGwKfQoKZGJfaGFzX2JlZW5fcmVzdG9yZWQoKSB7CiAgaWYgWyAhIC1mICIkUEdEQVRBL0NQTE5fUkVTVE9SRUQiIF07IHRoZW4KICAgIHJldHVybiAxCiAgZmkKCiAgaWYgISBncmVwIC1xICJcLT4gJDEkIiAiJFBHREFUQS9DUExOX1JFU1RPUkVEIjsgdGhlbgogICAgcmV0dXJuIDEKICBlbHNlCiAgICByZXR1cm4gMAogIGZpCn0KCnJlc3RvcmVfZGIoKSB7Cgl3aGlsZSBbICEgLVMgL3Zhci9ydW4vcG9zdGdyZXNxbC8ucy5QR1NRTC41NDMyIF0KCWRvCiAgICBlY2hvICJXYWl0aW5nIDVzIGZvciBkYiBzb2NrZXQgdG8gYmUgYXZhaWxhYmxlIgogICAgc2xlZXAgNXMKICBkb25lCgoKCWlmICEgZGJfaGFzX2JlZW5fcmVzdG9yZWQgIiQxIjsgdGhlbgoJICBlY2hvICJJdCBhcHBlYXJzIGRiICckMScgaGFzIG5vdCB5ZXQgYmVlbiByZXN0b3JlZCBmcm9tIFMzLiBBdHRlbXB0aW5nIHRvIHJlc3RvcmUgJDEgZnJvbSAkMiIKCSAgaW5zdGFsbF9kZXBzCgkgIGRvY2tlcl9zZXR1cF9kYiAjRW5zdXJlcyAkUE9TVEdSRVNfREIgZXhpc3RzIChkZWZpbmVkIGluIHRoZSBlbnRyeXBvaW50IHNjcmlwdCBmcm9tIHRoZSBwb3N0Z3JlcyBkb2NrZXIgaW1hZ2UpCgkgIGF3cyBzMyBjcCAiJDIiIC0gfCBwZ19yZXN0b3JlIC0tY2xlYW4gLS1uby1hY2wgLS1uby1vd25lciAtZCAiJDEiIC1VICIkUE9TVEdSRVNfVVNFUiIKCSAgZWNobyAiJChkYXRlKTogJDIgLT4gJDEiIHwgY2F0ID4+ICIkUEdEQVRBL0NQTE5fUkVTVE9SRUQiCgllbHNlCgkgIGVjaG8gIkRiICckMScgYWxyZWFkeSBleGlzdHMuIFJlYWR5ISIKICBmaQp9CgpfbWFpbiAiJEAiICYKYmFja2dyb3VuZFByb2Nlc3M9JCEKCmlmIFsgLW4gIiRQT1NUR1JFU19BUkNISVZFX1VSSSIgXTsgdGhlbgogIHJlc3RvcmVfZGIgIiRQT1NUR1JFU19EQiIgIiRQT1NUR1JFU19BUkNISVZFX1VSSSIKZWxzZQogIGVjaG8gIkRlY2xpbmluZyB0byByZXN0b3JlIHRoZSBkYiBiZWNhdXNlIG5vIGFyY2hpdmUgdXJpIHdhcyBwcm92aWRlZCIKZmkKCndhaXQgJGJhY2tncm91bmRQcm9jZXNzCgoK
36
+
37
+ #Here is the ASCII-encoded version of the script in the secret above
38
+ #!/usr/bin/env bash
39
+ #
40
+ #source /usr/local/bin/docker-entrypoint.sh
41
+ #
42
+ #install_deps() {
43
+ # apt-get update -y > /dev/null
44
+ # apt-get install curl -y > /dev/null
45
+ # apt-get install unzip -y > /dev/null
46
+ # curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" > /dev/null
47
+ # unzip awscliv2.zip > /dev/null
48
+ # ./aws/install > /dev/null
49
+ #}
50
+ #
51
+ #db_has_been_restored() {
52
+ # if [ ! -f "$PGDATA/CPLN_RESTORED" ]; then
53
+ # return 1
54
+ # fi
55
+ #
56
+ # if ! grep -q "\-> $1$" "$PGDATA/CPLN_RESTORED"; then
57
+ # return 1
58
+ # else
59
+ # return 0
60
+ # fi
61
+ #}
62
+ #
63
+ #restore_db() {
64
+ # while [ ! -S /var/run/postgresql/.s.PGSQL.5432 ]
65
+ # do
66
+ # echo "Waiting 5s for db socket to be available"
67
+ # sleep 5s
68
+ # done
69
+ #
70
+ #
71
+ # if ! db_has_been_restored "$1"; then
72
+ # echo "It appears db '$1' has not yet been restored from S3. Attempting to restore $1 from $2"
73
+ # install_deps
74
+ # docker_setup_db #Ensures $POSTGRES_DB exists (defined in the entrypoint script from the postgres docker image)
75
+ # aws s3 cp "$2" - | pg_restore --clean --no-acl --no-owner -d "$1" -U "$POSTGRES_USER"
76
+ # echo "$(date): $2 -> $1" | cat >> "$PGDATA/CPLN_RESTORED"
77
+ # else
78
+ # echo "Db '$1' already exists. Ready!"
79
+ # fi
80
+ #}
81
+ #
82
+ #_main "$@" &
83
+ #backgroundProcess=$!
84
+ #
85
+ #if [ -n "$POSTGRES_ARCHIVE_URI" ]; then
86
+ # restore_db "$POSTGRES_DB" "$POSTGRES_ARCHIVE_URI"
87
+ #else
88
+ # echo "Declining to restore the db because no archive uri was provided"
89
+ #fi
90
+ #
91
+ #wait $backgroundProcess
92
+
93
+ ---
94
+ kind: identity
95
+ name: postgres-poc-identity
96
+ description: postgres-poc-identity
97
+
98
+ ---
99
+ kind: policy
100
+ name: postgres-poc-access
101
+ description: postgres-poc-access
102
+ bindings:
103
+ - permissions:
104
+ - reveal
105
+ # Uncomment these two
106
+ # - use
107
+ # - view
108
+ principalLinks:
109
+ - //gvc/APP_GVC/identity/postgres-poc-identity
110
+ targetKind: secret
111
+ targetLinks:
112
+ - //secret/postgres-poc-credentials
113
+ - //secret/postgres-poc-entrypoint-script
114
+
115
+ ---
116
+ kind: workload
117
+ name: postgres
118
+ description: postgres
119
+ spec:
120
+ type: stateful
121
+ containers:
122
+ - cpu: 1000m
123
+ memory: 512Mi
124
+ env:
125
+ # Uncomment next two envs will cause the db to be restored from the archive uri
126
+ # - name: POSTGRES_ARCHIVE_URI #Use this var to control the automatic restore behavior. If you leave it out, the db will start empty.
127
+ # value: s3://YOUR_BUCKET/PATH_TO_ARCHIVE_FILE
128
+ # - name: POSTGRES_DB #The name of the initial db in case of doing a restore
129
+ # value: test
130
+ - name: PGDATA #The location postgres stores the db. This can be anything other than /var/lib/postgresql/data, but it must be inside the mount point for the volume set
131
+ value: "/var/lib/postgresql/data/pg_data"
132
+ - name: POSTGRES_PASSWORD #The password for the default user
133
+ value: cpln://secret/postgres-poc-credentials.password
134
+ - name: POSTGRES_USER #The name of the default user
135
+ value: cpln://secret/postgres-poc-credentials.username
136
+ name: stateful
137
+ image: postgres:15
138
+ command: /bin/bash
139
+ args:
140
+ - "-c"
141
+ - "cat /usr/local/bin/cpln-entrypoint.sh >> ./cpln-entrypoint.sh && chmod u+x ./cpln-entrypoint.sh && ./cpln-entrypoint.sh postgres"
142
+ #command: "cpln-entrypoint.sh"
143
+ #args:
144
+ # - "postgres"
145
+ ports:
146
+ - number: 5432
147
+ protocol: tcp
148
+ volumes:
149
+ - uri: cpln://volumeset/postgres-poc-vs
150
+ path: "/var/lib/postgresql/data"
151
+ # Make the ENV value for the entry script a file
152
+ - uri: cpln://secret/postgres-poc-entrypoint-script
153
+ path: "/usr/local/bin/cpln-entrypoint.sh"
154
+ inheritEnv: false
155
+ livenessProbe:
156
+ tcpSocket:
157
+ port: 5432
158
+ failureThreshold: 1
159
+ readinessProbe:
160
+ tcpSocket:
161
+ port: 5432
162
+ failureThreshold: 1
163
+ identityLink: //identity/postgres-poc-identity
164
+ defaultOptions:
165
+ capacityAI: false
166
+ autoscaling:
167
+ metric: cpu
168
+ target: 95
169
+ maxScale: 1
170
+ firewallConfig:
171
+ external:
172
+ inboundAllowCIDR: []
173
+ outboundAllowCIDR:
174
+ - 0.0.0.0/0
175
+ internal:
176
+ inboundAllowType: same-gvc
@@ -0,0 +1,36 @@
1
+ # Template setup of Rails server workload, roughly corresponding to Heroku dyno
2
+ # type within Procfile.
3
+ kind: workload
4
+ name: rails
5
+ spec:
6
+ type: standard
7
+ containers:
8
+ - name: rails
9
+ # 300m is a good starting place for a test app. You can experiment with CPU configuration
10
+ # once your app is running.
11
+ cpu: 300m
12
+ env:
13
+ - name: LOG_LEVEL
14
+ value: debug
15
+ # Inherit other ENV values from GVC
16
+ inheritEnv: true
17
+ image: '/org/APP_ORG/image/APP_IMAGE'
18
+ # 512 corresponds to a standard 1x dyno type
19
+ memory: 512Mi
20
+ ports:
21
+ - number: 3000
22
+ protocol: http
23
+ defaultOptions:
24
+ # Start out like this for "test apps"
25
+ autoscaling:
26
+ # Max of 1 effectively disables autoscaling, so a like a Heroku dyno count of 1
27
+ maxScale: 1
28
+ capacityAI: false
29
+ firewallConfig:
30
+ external:
31
+ # Default to allow public access to Rails server
32
+ inboundAllowCIDR:
33
+ - 0.0.0.0/0
34
+ # Could configure outbound for more security
35
+ outboundAllowCIDR:
36
+ - 0.0.0.0/0
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cpl
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.2
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Gordon
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-10-25 00:00:00.000000000 Z
12
+ date: 2024-01-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: debug
@@ -242,6 +242,7 @@ files:
242
242
  - lib/command/deploy_image.rb
243
243
  - lib/command/env.rb
244
244
  - lib/command/exists.rb
245
+ - lib/command/generate.rb
245
246
  - lib/command/info.rb
246
247
  - lib/command/latest_image.rb
247
248
  - lib/command/logs.rb
@@ -269,11 +270,18 @@ files:
269
270
  - lib/core/controlplane_api.rb
270
271
  - lib/core/controlplane_api_cli.rb
271
272
  - lib/core/controlplane_api_direct.rb
273
+ - lib/core/helpers.rb
272
274
  - lib/core/scripts.rb
273
275
  - lib/core/shell.rb
274
276
  - lib/cpl.rb
275
277
  - lib/cpl/version.rb
276
278
  - lib/deprecated_commands.json
279
+ - lib/generator_templates/Dockerfile
280
+ - lib/generator_templates/controlplane.yml
281
+ - lib/generator_templates/entrypoint.sh
282
+ - lib/generator_templates/templates/gvc.yml
283
+ - lib/generator_templates/templates/postgres.yml
284
+ - lib/generator_templates/templates/rails.yml
277
285
  - rakelib/create_release.rake
278
286
  - script/add_command
279
287
  - script/check_command_docs
@@ -308,7 +316,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
308
316
  - !ruby/object:Gem::Version
309
317
  version: '0'
310
318
  requirements: []
311
- rubygems_version: 3.4.12
319
+ rubygems_version: 3.4.21
312
320
  signing_key:
313
321
  specification_version: 4
314
322
  summary: Heroku to Control Plane