cpflow 4.1.0 → 4.1.1
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 +4 -4
- data/.gitignore +4 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile.lock +1 -1
- data/README.md +7 -7
- data/docs/commands.md +16 -0
- data/docs/terraform/details.md +415 -0
- data/docs/terraform/example/.controlplane/controlplane.yml +29 -0
- data/docs/terraform/example/.controlplane/templates/app.yml +38 -0
- data/docs/terraform/example/.controlplane/templates/postgres.yml +30 -0
- data/docs/terraform/example/.controlplane/templates/rails.yml +26 -0
- data/docs/terraform/overview.md +105 -0
- data/lib/command/base.rb +29 -5
- data/lib/command/base_sub_command.rb +15 -0
- data/lib/command/generate.rb +1 -1
- data/lib/command/ps.rb +1 -1
- data/lib/command/ps_stop.rb +2 -1
- data/lib/command/run.rb +1 -1
- data/lib/command/terraform/base.rb +35 -0
- data/lib/command/terraform/generate.rb +99 -0
- data/lib/command/terraform/import.rb +79 -0
- data/lib/core/controlplane.rb +3 -3
- data/lib/core/shell.rb +9 -4
- data/lib/core/terraform_config/agent.rb +31 -0
- data/lib/core/terraform_config/audit_context.rb +31 -0
- data/lib/core/terraform_config/base.rb +25 -0
- data/lib/core/terraform_config/dsl.rb +102 -0
- data/lib/core/terraform_config/generator.rb +184 -0
- data/lib/core/terraform_config/gvc.rb +63 -0
- data/lib/core/terraform_config/identity.rb +35 -0
- data/lib/core/terraform_config/local_variable.rb +30 -0
- data/lib/core/terraform_config/policy.rb +151 -0
- data/lib/core/terraform_config/provider.rb +22 -0
- data/lib/core/terraform_config/required_provider.rb +23 -0
- data/lib/core/terraform_config/secret.rb +138 -0
- data/lib/core/terraform_config/volume_set.rb +155 -0
- data/lib/core/terraform_config/workload/main.tf +316 -0
- data/lib/core/terraform_config/workload/required_providers.tf +8 -0
- data/lib/core/terraform_config/workload/variables.tf +263 -0
- data/lib/core/terraform_config/workload.rb +132 -0
- data/lib/cpflow/version.rb +1 -1
- data/lib/cpflow.rb +50 -9
- data/lib/generator_templates/templates/postgres.yml +1 -1
- data/lib/patches/array.rb +8 -0
- data/lib/patches/hash.rb +47 -0
- data/lib/patches/string.rb +34 -0
- data/script/update_command_docs +6 -2
- metadata +33 -3
@@ -0,0 +1,155 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TerraformConfig
|
4
|
+
class VolumeSet < Base # rubocop:disable Metrics/ClassLength
|
5
|
+
PERFORMANCE_CLASSES = %w[general-purpose-ssd high-throughput-ssd].freeze
|
6
|
+
FILE_SYSTEM_TYPES = %w[xfs ext4].freeze
|
7
|
+
MIN_CAPACITY = 10
|
8
|
+
MIN_SCALING_FACTOR = 1.1
|
9
|
+
|
10
|
+
attr_reader :gvc, :name, :initial_capacity, :performance_class, :file_system_type,
|
11
|
+
:storage_class_suffix, :description, :tags, :snapshots, :autoscaling
|
12
|
+
|
13
|
+
def initialize( # rubocop:disable Metrics/ParameterLists, Metrics/MethodLength
|
14
|
+
gvc:,
|
15
|
+
name:,
|
16
|
+
initial_capacity:,
|
17
|
+
performance_class:,
|
18
|
+
file_system_type:,
|
19
|
+
storage_class_suffix: nil,
|
20
|
+
description: nil,
|
21
|
+
tags: nil,
|
22
|
+
snapshots: nil,
|
23
|
+
autoscaling: nil
|
24
|
+
)
|
25
|
+
super()
|
26
|
+
|
27
|
+
@gvc = gvc
|
28
|
+
@name = name
|
29
|
+
@initial_capacity = initial_capacity
|
30
|
+
@performance_class = performance_class
|
31
|
+
@file_system_type = file_system_type
|
32
|
+
@storage_class_suffix = storage_class_suffix
|
33
|
+
@description = description
|
34
|
+
@tags = tags
|
35
|
+
@snapshots = snapshots
|
36
|
+
@autoscaling = autoscaling
|
37
|
+
|
38
|
+
validate_attributes!
|
39
|
+
end
|
40
|
+
|
41
|
+
def importable?
|
42
|
+
true
|
43
|
+
end
|
44
|
+
|
45
|
+
def reference
|
46
|
+
"cpln_volume_set.#{name}"
|
47
|
+
end
|
48
|
+
|
49
|
+
def to_tf
|
50
|
+
block :resource, :cpln_volume_set, name do
|
51
|
+
base_arguments_tf
|
52
|
+
snapshots_tf
|
53
|
+
autoscaling_tf
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def validate_attributes!
|
60
|
+
validate_initial_capacity!
|
61
|
+
validate_performance_class!
|
62
|
+
validate_file_system_type!
|
63
|
+
validate_autoscaling! if autoscaling
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_initial_capacity!
|
67
|
+
raise ArgumentError, "Initial capacity must be numeric" unless initial_capacity.is_a?(Numeric)
|
68
|
+
return if initial_capacity >= MIN_CAPACITY
|
69
|
+
|
70
|
+
raise ArgumentError, "Initial capacity should be >= #{MIN_CAPACITY}"
|
71
|
+
end
|
72
|
+
|
73
|
+
def validate_performance_class!
|
74
|
+
return if PERFORMANCE_CLASSES.include?(performance_class.to_s)
|
75
|
+
|
76
|
+
raise ArgumentError,
|
77
|
+
"Invalid performance class: #{performance_class}. Choose from #{PERFORMANCE_CLASSES.join(', ')}"
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_file_system_type!
|
81
|
+
return if FILE_SYSTEM_TYPES.include?(file_system_type.to_s)
|
82
|
+
|
83
|
+
raise ArgumentError, "Invalid file system type: #{file_system_type}. Choose from #{FILE_SYSTEM_TYPES.join(', ')}"
|
84
|
+
end
|
85
|
+
|
86
|
+
def validate_autoscaling!
|
87
|
+
validate_max_capacity!
|
88
|
+
validate_min_free_percentage!
|
89
|
+
validate_scaling_factor!
|
90
|
+
end
|
91
|
+
|
92
|
+
def validate_max_capacity!
|
93
|
+
max_capacity = autoscaling.fetch(:max_capacity, nil)
|
94
|
+
return if max_capacity.nil?
|
95
|
+
|
96
|
+
raise ArgumentError, "autoscaling.max_capacity must be numeric" unless max_capacity.is_a?(Numeric)
|
97
|
+
return if max_capacity >= MIN_CAPACITY
|
98
|
+
|
99
|
+
raise ArgumentError, "autoscaling.max_capacity should be >= #{MIN_CAPACITY}"
|
100
|
+
end
|
101
|
+
|
102
|
+
def validate_min_free_percentage!
|
103
|
+
min_free_percentage = autoscaling.fetch(:min_free_percentage, nil)
|
104
|
+
return if min_free_percentage.nil?
|
105
|
+
|
106
|
+
raise ArgumentError, "autoscaling.min_free_percentage must be numeric" unless min_free_percentage.is_a?(Numeric)
|
107
|
+
return if min_free_percentage.between?(1, 100)
|
108
|
+
|
109
|
+
raise ArgumentError, "autoscaling.min_free_percentage should be between 1 and 100"
|
110
|
+
end
|
111
|
+
|
112
|
+
def validate_scaling_factor!
|
113
|
+
scaling_factor = autoscaling.fetch(:scaling_factor, nil)
|
114
|
+
return if scaling_factor.nil?
|
115
|
+
|
116
|
+
raise ArgumentError, "autoscaling.scaling_factor must be numeric" unless scaling_factor.is_a?(Numeric)
|
117
|
+
return if scaling_factor >= MIN_SCALING_FACTOR
|
118
|
+
|
119
|
+
raise ArgumentError, "autoscaling.scaling_factor should be >= #{MIN_SCALING_FACTOR}"
|
120
|
+
end
|
121
|
+
|
122
|
+
def base_arguments_tf
|
123
|
+
argument :gvc, gvc
|
124
|
+
|
125
|
+
argument :name, name
|
126
|
+
argument :description, description, optional: true
|
127
|
+
argument :tags, tags, optional: true
|
128
|
+
|
129
|
+
argument :initial_capacity, initial_capacity
|
130
|
+
argument :performance_class, performance_class
|
131
|
+
argument :storage_class_suffix, storage_class_suffix, optional: true
|
132
|
+
argument :file_system_type, file_system_type
|
133
|
+
end
|
134
|
+
|
135
|
+
def snapshots_tf
|
136
|
+
return if snapshots.nil?
|
137
|
+
|
138
|
+
block :snapshots do
|
139
|
+
%i[create_final_snapshot retention_duration schedule].each do |arg_name|
|
140
|
+
argument arg_name, snapshots.fetch(arg_name, nil), optional: true
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
def autoscaling_tf
|
146
|
+
return if autoscaling.nil?
|
147
|
+
|
148
|
+
block :autoscaling do
|
149
|
+
%i[max_capacity min_free_percentage scaling_factor].each do |arg_name|
|
150
|
+
argument arg_name, autoscaling.fetch(arg_name, nil), optional: true
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
@@ -0,0 +1,316 @@
|
|
1
|
+
resource "cpln_workload" "workload" {
|
2
|
+
type = var.type
|
3
|
+
|
4
|
+
gvc = var.gvc
|
5
|
+
identity_link = var.identity_link
|
6
|
+
|
7
|
+
name = var.name
|
8
|
+
description = var.description
|
9
|
+
|
10
|
+
tags = var.tags
|
11
|
+
support_dynamic_tags = var.support_dynamic_tags
|
12
|
+
|
13
|
+
dynamic "container" {
|
14
|
+
for_each = var.containers
|
15
|
+
iterator = container
|
16
|
+
content {
|
17
|
+
name = container.key
|
18
|
+
|
19
|
+
args = container.value.args
|
20
|
+
command = container.value.command
|
21
|
+
env = container.value.envs
|
22
|
+
inherit_env = container.value.inherit_env
|
23
|
+
image = container.value.image
|
24
|
+
|
25
|
+
cpu = container.value.cpu
|
26
|
+
memory = container.value.memory
|
27
|
+
|
28
|
+
dynamic "lifecycle" {
|
29
|
+
for_each = container.value.post_start_command != null || container.value.pre_stop_command != null ? [1] : []
|
30
|
+
content {
|
31
|
+
dynamic "post_start" {
|
32
|
+
for_each = container.value.post_start_command != null ? [1] : []
|
33
|
+
content {
|
34
|
+
exec {
|
35
|
+
command = [
|
36
|
+
"/bin/bash",
|
37
|
+
"-c",
|
38
|
+
"[ -f ${container.value.post_start_command} ] && ${container.value.post_start_command} || true",
|
39
|
+
]
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
dynamic "pre_stop" {
|
44
|
+
for_each = container.value.pre_stop_command != null ? [1] : []
|
45
|
+
content {
|
46
|
+
exec {
|
47
|
+
command = [
|
48
|
+
"/bin/bash",
|
49
|
+
"-c",
|
50
|
+
"[ -f ${container.value.pre_stop_command} ] && ${container.value.pre_stop_command} || true",
|
51
|
+
]
|
52
|
+
}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
}
|
56
|
+
}
|
57
|
+
|
58
|
+
dynamic "liveness_probe" {
|
59
|
+
for_each = container.value.liveness_probe != null ? [container.value.liveness_probe] : []
|
60
|
+
iterator = liveness
|
61
|
+
content {
|
62
|
+
dynamic "exec" {
|
63
|
+
for_each = liveness.value.exec != null ? [liveness.value.exec] : []
|
64
|
+
iterator = exec
|
65
|
+
content {
|
66
|
+
command = exec.value.command
|
67
|
+
}
|
68
|
+
}
|
69
|
+
dynamic "http_get" {
|
70
|
+
for_each = liveness.value.http_get != null ? [liveness.value.http_get] : []
|
71
|
+
iterator = http_get
|
72
|
+
content {
|
73
|
+
path = http_get.value.path
|
74
|
+
port = http_get.value.port
|
75
|
+
scheme = http_get.value.scheme
|
76
|
+
http_headers = http_get.value.http_headers
|
77
|
+
}
|
78
|
+
}
|
79
|
+
dynamic "tcp_socket" {
|
80
|
+
for_each = liveness.value.tcp_socket != null ? [liveness.value.tcp_socket] : []
|
81
|
+
iterator = tcp_socket
|
82
|
+
content {
|
83
|
+
port = tcp_socket.value.port
|
84
|
+
}
|
85
|
+
}
|
86
|
+
dynamic "grpc" {
|
87
|
+
for_each = liveness.value.grpc != null ? [liveness.value.grpc] : []
|
88
|
+
iterator = grpc
|
89
|
+
content {
|
90
|
+
port = grpc.value.port
|
91
|
+
}
|
92
|
+
}
|
93
|
+
failure_threshold = liveness.value.failure_threshold
|
94
|
+
initial_delay_seconds = liveness.value.initial_delay_seconds
|
95
|
+
period_seconds = liveness.value.period_seconds
|
96
|
+
success_threshold = liveness.value.success_threshold
|
97
|
+
timeout_seconds = liveness.value.timeout_seconds
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
dynamic "readiness_probe" {
|
102
|
+
for_each = container.value.readiness_probe != null ? [container.value.readiness_probe] : []
|
103
|
+
iterator = readiness
|
104
|
+
content {
|
105
|
+
dynamic "exec" {
|
106
|
+
for_each = readiness.value.exec != null ? [readiness.value.exec] : []
|
107
|
+
iterator = exec
|
108
|
+
content {
|
109
|
+
command = exec.value.command
|
110
|
+
}
|
111
|
+
}
|
112
|
+
dynamic "http_get" {
|
113
|
+
for_each = readiness.value.http_get != null ? [readiness.value.http_get] : []
|
114
|
+
iterator = http_get
|
115
|
+
content {
|
116
|
+
path = http_get.value.path
|
117
|
+
port = http_get.value.port
|
118
|
+
scheme = http_get.value.scheme
|
119
|
+
http_headers = http_get.value.http_headers
|
120
|
+
}
|
121
|
+
}
|
122
|
+
dynamic "tcp_socket" {
|
123
|
+
for_each = readiness.value.tcp_socket != null ? [readiness.value.tcp_socket] : []
|
124
|
+
iterator = tcp_socket
|
125
|
+
content {
|
126
|
+
port = tcp_socket.value.port
|
127
|
+
}
|
128
|
+
}
|
129
|
+
dynamic "grpc" {
|
130
|
+
for_each = readiness.value.grpc != null ? [readiness.value.grpc] : []
|
131
|
+
iterator = grpc
|
132
|
+
content {
|
133
|
+
port = grpc.value.port
|
134
|
+
}
|
135
|
+
}
|
136
|
+
failure_threshold = readiness.value.failure_threshold
|
137
|
+
initial_delay_seconds = readiness.value.initial_delay_seconds
|
138
|
+
period_seconds = readiness.value.period_seconds
|
139
|
+
success_threshold = readiness.value.success_threshold
|
140
|
+
timeout_seconds = readiness.value.timeout_seconds
|
141
|
+
}
|
142
|
+
}
|
143
|
+
|
144
|
+
dynamic "ports" {
|
145
|
+
for_each = container.value.ports
|
146
|
+
iterator = port
|
147
|
+
content {
|
148
|
+
number = port.value.number
|
149
|
+
protocol = port.value.protocol
|
150
|
+
}
|
151
|
+
}
|
152
|
+
|
153
|
+
dynamic "volume" {
|
154
|
+
for_each = container.value.volumes
|
155
|
+
iterator = volume
|
156
|
+
content {
|
157
|
+
uri = volume.value.uri
|
158
|
+
path = volume.value.path
|
159
|
+
}
|
160
|
+
}
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
dynamic "options" {
|
165
|
+
for_each = var.options != null ? [var.options] : []
|
166
|
+
iterator = options
|
167
|
+
content {
|
168
|
+
dynamic "autoscaling" {
|
169
|
+
for_each = options.value.autoscaling != null ? [options.value.autoscaling] : []
|
170
|
+
iterator = autoscaling
|
171
|
+
content {
|
172
|
+
metric = autoscaling.value.metric
|
173
|
+
metric_percentile = autoscaling.value.metric_percentile
|
174
|
+
max_scale = autoscaling.value.max_scale
|
175
|
+
min_scale = autoscaling.value.min_scale
|
176
|
+
target = autoscaling.value.target
|
177
|
+
scale_to_zero_delay = autoscaling.value.scale_to_zero_delay
|
178
|
+
max_concurrency = autoscaling.value.max_concurrency
|
179
|
+
}
|
180
|
+
}
|
181
|
+
capacity_ai = options.value.capacity_ai
|
182
|
+
suspend = options.value.suspend
|
183
|
+
timeout_seconds = options.value.timeout_seconds
|
184
|
+
debug = options.value.debug
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
dynamic "local_options" {
|
189
|
+
for_each = var.local_options != null ? [var.local_options] : []
|
190
|
+
iterator = options
|
191
|
+
content {
|
192
|
+
dynamic "autoscaling" {
|
193
|
+
for_each = options.value.autoscaling != null ? [options.value.autoscaling] : []
|
194
|
+
iterator = autoscaling
|
195
|
+
content {
|
196
|
+
metric = autoscaling.value.metric
|
197
|
+
metric_percentile = autoscaling.value.metric_percentile
|
198
|
+
max_scale = autoscaling.value.max_scale
|
199
|
+
min_scale = autoscaling.value.min_scale
|
200
|
+
target = autoscaling.value.target
|
201
|
+
scale_to_zero_delay = autoscaling.value.scale_to_zero_delay
|
202
|
+
max_concurrency = autoscaling.value.max_concurrency
|
203
|
+
}
|
204
|
+
}
|
205
|
+
location = options.value.location
|
206
|
+
capacity_ai = options.value.capacity_ai
|
207
|
+
suspend = options.value.suspend
|
208
|
+
timeout_seconds = options.value.timeout_seconds
|
209
|
+
debug = options.value.debug
|
210
|
+
}
|
211
|
+
}
|
212
|
+
|
213
|
+
dynamic "rollout_options" {
|
214
|
+
for_each = var.rollout_options != null ? [var.rollout_options] : []
|
215
|
+
iterator = rollout_options
|
216
|
+
content {
|
217
|
+
min_ready_seconds = rollout_options.value.min_ready_seconds
|
218
|
+
max_unavailable_replicas = rollout_options.value.max_unavailable_replicas
|
219
|
+
max_surge_replicas = rollout_options.value.max_surge_replicas
|
220
|
+
scaling_policy = rollout_options.value.scaling_policy
|
221
|
+
}
|
222
|
+
}
|
223
|
+
|
224
|
+
dynamic "security_options" {
|
225
|
+
for_each = var.security_options != null ? [var.security_options] : []
|
226
|
+
iterator = security_options
|
227
|
+
content {
|
228
|
+
file_system_group_id = security_options.value.file_system_group_id
|
229
|
+
}
|
230
|
+
}
|
231
|
+
|
232
|
+
dynamic "firewall_spec" {
|
233
|
+
for_each = var.firewall_spec != null ? [var.firewall_spec] : []
|
234
|
+
iterator = firewall_spec
|
235
|
+
content {
|
236
|
+
dynamic "external" {
|
237
|
+
for_each = firewall_spec.value.external != null ? [firewall_spec.value.external] : []
|
238
|
+
iterator = external
|
239
|
+
content {
|
240
|
+
inbound_allow_cidr = external.value.inbound_allow_cidr
|
241
|
+
outbound_allow_hostname = external.value.outbound_allow_hostname
|
242
|
+
outbound_allow_cidr = external.value.outbound_allow_cidr
|
243
|
+
dynamic "outbound_allow_port" {
|
244
|
+
for_each = external.value.outbound_allow_port
|
245
|
+
iterator = outbound_allow_port
|
246
|
+
content {
|
247
|
+
protocol = outbound_allow_port.value.protocol
|
248
|
+
number = outbound_allow_port.value.number
|
249
|
+
}
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
dynamic "internal" {
|
254
|
+
for_each = firewall_spec.value.internal != null ? [firewall_spec.value.internal] : []
|
255
|
+
iterator = internal
|
256
|
+
content {
|
257
|
+
inbound_allow_type = internal.value.inbound_allow_type
|
258
|
+
inbound_allow_workload = internal.value.inbound_allow_workload
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
}
|
263
|
+
|
264
|
+
dynamic "load_balancer" {
|
265
|
+
for_each = var.load_balancer != null ? [var.load_balancer] : []
|
266
|
+
iterator = load_balancer
|
267
|
+
content {
|
268
|
+
dynamic "direct" {
|
269
|
+
for_each = load_balancer.value.direct != null ? [load_balancer.value.direct] : []
|
270
|
+
iterator = direct
|
271
|
+
content {
|
272
|
+
enabled = direct.value.enabled
|
273
|
+
dynamic "port" {
|
274
|
+
for_each = direct.value.port
|
275
|
+
iterator = port
|
276
|
+
content {
|
277
|
+
external_port = port.value.external_port
|
278
|
+
protocol = port.value.protocol
|
279
|
+
scheme = port.value.scheme
|
280
|
+
container_port = port.value.container_port
|
281
|
+
}
|
282
|
+
}
|
283
|
+
}
|
284
|
+
}
|
285
|
+
dynamic "geo_location" {
|
286
|
+
for_each = load_balancer.value.geo_location != null ? [load_balancer.value.geo_location] : []
|
287
|
+
iterator = geo_location
|
288
|
+
content {
|
289
|
+
enabled = geo_location.value.enabled
|
290
|
+
dynamic "headers" {
|
291
|
+
for_each = geo_location.value.headers != null ? [geo_location.value.headers] : []
|
292
|
+
iterator = headers
|
293
|
+
content {
|
294
|
+
asn = headers.value.asn
|
295
|
+
city = headers.value.city
|
296
|
+
country = headers.value.country
|
297
|
+
region = headers.value.region
|
298
|
+
}
|
299
|
+
}
|
300
|
+
}
|
301
|
+
}
|
302
|
+
}
|
303
|
+
}
|
304
|
+
|
305
|
+
dynamic "job" {
|
306
|
+
for_each = var.job != null ? [var.job] : []
|
307
|
+
iterator = job
|
308
|
+
content {
|
309
|
+
schedule = job.value.schedule
|
310
|
+
concurrency_policy = job.value.concurrency_policy
|
311
|
+
history_limit = job.value.history_limit
|
312
|
+
restart_policy = job.value.restart_policy
|
313
|
+
active_deadline_seconds = job.value.active_deadline_seconds
|
314
|
+
}
|
315
|
+
}
|
316
|
+
}
|