matsuri 0.1.0 → 0.3.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.
- checksums.yaml +5 -5
- data/.envrc +1 -0
- data/.gitignore +2 -0
- data/.rubocop.yml +9 -0
- data/AGENTS.md +18 -0
- data/CHANGELOG.md +642 -0
- data/Gemfile +2 -0
- data/README.md +86 -8
- data/Rakefile +20 -0
- data/bin/console +1 -0
- data/bin/matsuri +6 -0
- data/bin/setup +2 -0
- data/docs/acceptors.md +181 -0
- data/docs/boot.md +101 -0
- data/docs/design/acceptors.md +157 -0
- data/docs/design/boot.md +131 -0
- data/docs/design/ssa.md +142 -0
- data/docs/design/stacks.md +153 -0
- data/docs/diff.md +85 -0
- data/docs/known-issues.md +19 -0
- data/docs/local-dev.md +173 -0
- data/docs/presenters.md +317 -0
- data/docs/resources.md +121 -0
- data/docs/setup.md +97 -0
- data/docs/ssa.md +149 -0
- data/docs/stacks.md +146 -0
- data/flake.lock +61 -0
- data/flake.nix +35 -0
- data/lib/matsuri/acceptor.rb +33 -0
- data/lib/matsuri/acceptors/image_tag.rb +15 -0
- data/lib/matsuri/cmd.rb +46 -0
- data/lib/matsuri/cmds/apply.rb +78 -0
- data/lib/matsuri/cmds/cli.rb +147 -0
- data/lib/matsuri/cmds/create.rb +87 -0
- data/lib/matsuri/cmds/delete.rb +86 -0
- data/lib/matsuri/cmds/diff.rb +105 -0
- data/lib/matsuri/cmds/generate.rb +24 -0
- data/lib/matsuri/cmds/kubectl.rb +16 -0
- data/lib/matsuri/cmds/recreate.rb +65 -0
- data/lib/matsuri/cmds/scale.rb +37 -0
- data/lib/matsuri/cmds/show.rb +123 -0
- data/lib/matsuri/cmds/status.rb +67 -0
- data/lib/matsuri/concerns/awaiting.rb +24 -0
- data/lib/matsuri/concerns/diffable.rb +135 -0
- data/lib/matsuri/concerns/export_manifest.rb +56 -0
- data/lib/matsuri/concerns/import_manifest.rb +64 -0
- data/lib/matsuri/concerns/pod_template.rb +37 -0
- data/lib/matsuri/concerns/pods/spread_pods.rb +47 -0
- data/lib/matsuri/concerns/pods/spread_topology.rb +63 -0
- data/lib/matsuri/concerns/registry_helpers.rb +59 -0
- data/lib/matsuri/config.rb +101 -0
- data/lib/matsuri/core_ext.rb +107 -0
- data/lib/matsuri/dsl/cluster/aggregated_cluster_role.rb +75 -0
- data/lib/matsuri/dsl/cluster/binding.rb +118 -0
- data/lib/matsuri/dsl/cluster/cluster_role.rb +41 -0
- data/lib/matsuri/dsl/cluster/role.rb +49 -0
- data/lib/matsuri/dsl/cluster/scope.rb +245 -0
- data/lib/matsuri/dsl/cluster/service_account.rb +76 -0
- data/lib/matsuri/dsl/concerns/default_binding.rb +34 -0
- data/lib/matsuri/dsl/concerns/manifest_set.rb +21 -0
- data/lib/matsuri/dsl/concerns/metadata.rb +56 -0
- data/lib/matsuri/dsl/concerns/rbac_rules.rb +39 -0
- data/lib/matsuri/initializer.rb +41 -0
- data/lib/matsuri/kubernetes/base.rb +107 -0
- data/lib/matsuri/kubernetes/config_map.rb +100 -0
- data/lib/matsuri/kubernetes/cron_job.rb +115 -0
- data/lib/matsuri/kubernetes/daemon_set.rb +62 -0
- data/lib/matsuri/kubernetes/deployment.rb +65 -0
- data/lib/matsuri/kubernetes/endpoints.rb +57 -0
- data/lib/matsuri/kubernetes/horizontal_pod_autoscaler.rb +116 -0
- data/lib/matsuri/kubernetes/imported_manifest.rb +61 -0
- data/lib/matsuri/kubernetes/ingress.rb +66 -0
- data/lib/matsuri/kubernetes/persistent_volume.rb +56 -0
- data/lib/matsuri/kubernetes/persistent_volume_claim.rb +41 -0
- data/lib/matsuri/kubernetes/pod.rb +355 -0
- data/lib/matsuri/kubernetes/replica_set.rb +46 -0
- data/lib/matsuri/kubernetes/secret.rb +86 -0
- data/lib/matsuri/kubernetes/service.rb +49 -0
- data/lib/matsuri/kubernetes/stateful_set.rb +75 -0
- data/lib/matsuri/kubernetes/storage_class.rb +45 -0
- data/lib/matsuri/platform.rb +38 -0
- data/lib/matsuri/presenter.rb +47 -0
- data/lib/matsuri/presenters/helpers.rb +39 -0
- data/lib/matsuri/presenters/prune_empty.rb +59 -0
- data/lib/matsuri/presenters/seed_image.rb +28 -0
- data/lib/matsuri/presenters/seed_replicas.rb +25 -0
- data/lib/matsuri/presenters/seed_resources.rb +29 -0
- data/lib/matsuri/registry.rb +267 -0
- data/lib/matsuri/shell_out.rb +119 -0
- data/lib/matsuri/stack.rb +276 -0
- data/lib/matsuri/task.rb +20 -0
- data/lib/matsuri/tasks/cluster.rb +79 -0
- data/lib/matsuri/tasks/docker.rb +25 -0
- data/lib/matsuri/tasks/hash_diff.rb +61 -0
- data/lib/matsuri/tasks/kubectl.rb +21 -0
- data/lib/matsuri/tasks/kubectl_ops/apply.rb +24 -0
- data/lib/matsuri/tasks/kubectl_ops/create.rb +27 -0
- data/lib/matsuri/tasks/kubectl_ops/delete.rb +21 -0
- data/lib/matsuri/tasks/kubectl_ops/diff.rb +47 -0
- data/lib/matsuri/tasks/kubectl_ops/get.rb +36 -0
- data/lib/matsuri/tasks/kubectl_ops/recreate.rb +35 -0
- data/lib/matsuri/tasks/kubectl_ops/replace.rb +29 -0
- data/lib/matsuri/tasks/kubectl_ops/rollout_status.rb +22 -0
- data/lib/matsuri/tasks/kubectl_ops/scale.rb +22 -0
- data/lib/matsuri/tasks/kubectl_ops/server_side_apply.rb +32 -0
- data/lib/matsuri/tasks/kubectl_ops/status.rb +20 -0
- data/lib/matsuri/tasks/kubectl_ops.rb +218 -0
- data/lib/matsuri/tasks/pod.rb +56 -0
- data/lib/matsuri/tasks/stacks/seed.rb +93 -0
- data/lib/matsuri/tasks/stacks.rb +31 -0
- data/lib/matsuri/transform/algebra.rb +52 -0
- data/lib/matsuri/transform/callable.rb +54 -0
- data/lib/matsuri/transform/combinators.rb +61 -0
- data/lib/matsuri/transform/env.rb +43 -0
- data/lib/matsuri/transform/kubernetes.rb +89 -0
- data/lib/matsuri/transform.rb +20 -0
- data/lib/matsuri/version.rb +3 -1
- data/lib/matsuri.rb +158 -2
- data/matsuri.gemspec +20 -7
- data/tests/bin/minikube-start.sh +27 -0
- data/tests/bin/probe-save-config.sh +46 -0
- data/tests/bin/probe-ssa.sh +206 -0
- data/tests/example/.gitignore +1 -0
- data/tests/example/Gemfile +7 -0
- data/tests/example/README.md +91 -0
- data/tests/example/bin/matsuri +14 -0
- data/tests/example/config/initializer.rb +12 -0
- data/tests/example/config/matsuri.rb +9 -0
- data/tests/example/config/platform.rb +39 -0
- data/tests/example/lib/acme/nodes/dedicated.rb +26 -0
- data/tests/example/lib/acme/nodes/preemptible.rb +17 -0
- data/tests/example/lib/acme/nodes/required_cores.rb +26 -0
- data/tests/example/lib/acme/nodes/resource_class.rb +26 -0
- data/tests/example/lib/acme/pods/cacerts.rb +15 -0
- data/tests/example/lib/acme/pods/healthcheck.rb +36 -0
- data/tests/example/lib/acme.rb +26 -0
- data/tests/example/platform/config_maps/billing-settings.rb +8 -0
- data/tests/example/platform/config_maps/cacerts.rb +9 -0
- data/tests/example/platform/deployments/billing-web.rb +5 -0
- data/tests/example/platform/deployments/checkout-web.rb +6 -0
- data/tests/example/platform/namespaces/billing-dev.yaml +7 -0
- data/tests/example/platform/namespaces/checkout-dev.yaml +7 -0
- data/tests/example/platform/pods/billing.rb +31 -0
- data/tests/example/platform/pods/checkout.rb +27 -0
- data/tests/example/platform/services/billing-web.rb +6 -0
- data/tests/example/platform/services/checkout-web.rb +4 -0
- data/tests/example/platform/stacks/billing.rb +8 -0
- data/tests/example/platform/stacks/checkout.rb +19 -0
- data/tests/k8s/save-config/deployment-declared.yaml +19 -0
- data/tests/k8s/save-config/deployment-seeded.yaml +20 -0
- data/tests/k8s/save-config/namespace.yaml +4 -0
- data/tests/k8s/ssa/declared-bumped.yaml +22 -0
- data/tests/k8s/ssa/declared.yaml +22 -0
- data/tests/k8s/ssa/namespace.yaml +4 -0
- data/tests/k8s/ssa/seed-via-create.yaml +24 -0
- metadata +288 -20
- data/.travis.yml +0 -4
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
class Deployment < Matsuri::Kubernetes::Base
|
|
6
|
+
include Matsuri::Concerns::PodTemplate
|
|
7
|
+
|
|
8
|
+
let(:api_version) { 'apps/v1' } # K8S 1.10
|
|
9
|
+
let(:kind) { 'Deployment' } # http://kubernetes.io/docs/user-guide/deployments/
|
|
10
|
+
|
|
11
|
+
# Overridables
|
|
12
|
+
|
|
13
|
+
let(:spec) do
|
|
14
|
+
{
|
|
15
|
+
replicas: replicas,
|
|
16
|
+
selector: selector,
|
|
17
|
+
template: template,
|
|
18
|
+
strategy: strategy,
|
|
19
|
+
minReadySeconds: min_ready_seconds,
|
|
20
|
+
revisionHistoryLimit: revision_history_limit
|
|
21
|
+
}.compact
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
let(:selector) { { matchLabels: match_labels, matchExpressions: match_expressions } }
|
|
25
|
+
|
|
26
|
+
# Supplied by the owning stack through dep_options, or by the CLI
|
|
27
|
+
# positional; pod templates read it.
|
|
28
|
+
let(:image_tag) { options[:image_tag] }
|
|
29
|
+
|
|
30
|
+
# Explicitly define replicas
|
|
31
|
+
let(:replicas) { fail Matsuri::UndefinedLet, 'Must define let(:replicas)' }
|
|
32
|
+
let(:match_labels) { fail Matsuri::UndefinedLet, 'Must define let(:match_labels)' }
|
|
33
|
+
|
|
34
|
+
let(:match_expressions) { [] }
|
|
35
|
+
|
|
36
|
+
# Deployment Strategy. Defaults to Rolling Update. Recreate is the other one.
|
|
37
|
+
let(:strategy) { { type: 'RollingUpdate', rollingUpdate: rolling_update } }
|
|
38
|
+
let(:rolling_update) { { maxUnavailable: max_unavailable, maxSurge: max_surge } }
|
|
39
|
+
# See: http://kubernetes.io/docs/api-reference/extensions/v1beta1/definitions/#_v1beta1_rollingupdatedeployment
|
|
40
|
+
let(:max_unavailable) { 1 }
|
|
41
|
+
let(:max_surge) { 1 }
|
|
42
|
+
|
|
43
|
+
# Minimum number of seconds for which a newly created pod should be ready without
|
|
44
|
+
# any of its container crashing, for it to be considered available.
|
|
45
|
+
# Defaults to 0 (pod will be considered available as soon as it is ready)
|
|
46
|
+
let(:min_ready_seconds) { 0 }
|
|
47
|
+
|
|
48
|
+
# The number of old ReplicaSets to retain to allow rollback. This is a pointer to
|
|
49
|
+
# distinguish between explicit zero and not specified.
|
|
50
|
+
let(:revision_history_limit) { nil }
|
|
51
|
+
|
|
52
|
+
let(:primary_container_path) { ['spec', 'template', 'spec', 'containers', 0] }
|
|
53
|
+
|
|
54
|
+
class << self
|
|
55
|
+
def load_path
|
|
56
|
+
Matsuri::Config.deployments_path
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def definition_module_name
|
|
60
|
+
'Deployments'
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
class Endpoints < Matsuri::Kubernetes::Base
|
|
6
|
+
let(:api_version) { 'v1' } # K8S 1.10
|
|
7
|
+
let(:kind) { 'Endpoints' }
|
|
8
|
+
let(:manifest) do
|
|
9
|
+
{
|
|
10
|
+
apiVersion: api_version,
|
|
11
|
+
kind: kind,
|
|
12
|
+
metadata: final_metadata,
|
|
13
|
+
subsets: subsets
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Overridables
|
|
18
|
+
let(:subsets) { [subset] }
|
|
19
|
+
let(:subset) do
|
|
20
|
+
{
|
|
21
|
+
addresses: addresses,
|
|
22
|
+
ports: ports
|
|
23
|
+
}
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
let(:addresses) { [localhost, address] }
|
|
27
|
+
let(:localhost) { { ip: '127.0.0.1' } }
|
|
28
|
+
let(:address) { { ip: public_ip_address, targetRef: target_ref } }
|
|
29
|
+
let(:target_ref) { fail Matsuri::UndefinedLet, 'Must define let(:target_ref)' }
|
|
30
|
+
|
|
31
|
+
let(:ports) { [port(port_num)] }
|
|
32
|
+
let(:public_ip_address) { config.dev_addr }
|
|
33
|
+
let(:port_num) { fail Matsuri::UndefinedLet, 'Must define let(:port_num)' }
|
|
34
|
+
let(:port_proto) { 'tcp' }
|
|
35
|
+
|
|
36
|
+
# Helpers
|
|
37
|
+
# Optional:
|
|
38
|
+
# target_port: the port exposed externally
|
|
39
|
+
# protocol: connection protocol (ex: tcp)
|
|
40
|
+
def port(num, protocol: 'TCP', name: nil)
|
|
41
|
+
_port = { port: num, protocol: protocol.to_s }
|
|
42
|
+
_port[:name] = name.to_s if name
|
|
43
|
+
return _port
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
class << self
|
|
47
|
+
def load_path
|
|
48
|
+
Matsuri::Config.endpoints_path
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def definition_module_name
|
|
52
|
+
'Endpoints'
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
class HorizontalPodAutoscaler < Matsuri::Kubernetes::Base
|
|
6
|
+
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.22/#horizontalpodautoscalerspec-v2beta2-autoscaling
|
|
7
|
+
# https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/
|
|
8
|
+
# https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale-walkthrough/
|
|
9
|
+
let(:api_version) { 'autoscaling/v2beta2' } # K8S 1.16+
|
|
10
|
+
let(:kind) { 'HorizontalPodAutoscaler' }
|
|
11
|
+
|
|
12
|
+
let(:spec) do
|
|
13
|
+
{
|
|
14
|
+
scaleTargetRef: scale_target_ref,
|
|
15
|
+
minReplicas: min_replicas,
|
|
16
|
+
maxReplicas: max_replicas,
|
|
17
|
+
metrics: metrics,
|
|
18
|
+
behavior: behavior
|
|
19
|
+
}
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
let(:scale_target_ref) { fail Matsuri::UndefinedLet, 'Must define let(:scale_target_ref)' }
|
|
23
|
+
let(:min_replicas) { 1 }
|
|
24
|
+
let(:max_replicas) { nil }
|
|
25
|
+
|
|
26
|
+
let(:metrics) { [metric] }
|
|
27
|
+
let(:metric) { fail NotIm0lementedError, 'Must define let(:default_metric)' }
|
|
28
|
+
|
|
29
|
+
let(:behavior) { { scaleUp: scale_up_behavior, scaleDown: scale_down_behavior }.compact }
|
|
30
|
+
let(:scale_down_behavior) { nil }
|
|
31
|
+
let(:scale_up_behavior) { nil }
|
|
32
|
+
|
|
33
|
+
### Helpers
|
|
34
|
+
|
|
35
|
+
# Extracts the version, name, and kind from a Matsuri ref
|
|
36
|
+
# Example: resource_ref_from_def(deployment_spec('my-deployment'))
|
|
37
|
+
def resource_ref_from_def(resource_def)
|
|
38
|
+
{
|
|
39
|
+
apiVersion: resource_def.api_version,
|
|
40
|
+
kind: resource_def.kind,
|
|
41
|
+
name: resource_def.name
|
|
42
|
+
}
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def resource_metric_source(name, metric_target)
|
|
46
|
+
{
|
|
47
|
+
type: 'Resource',
|
|
48
|
+
resource: {
|
|
49
|
+
name: name,
|
|
50
|
+
target: metric_target
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def pod_metric_source(name, metric_target, metric_selector: nil)
|
|
56
|
+
{
|
|
57
|
+
type: 'Pods',
|
|
58
|
+
pods: {
|
|
59
|
+
metric: { name: name, selector: metric_selector }.compact,
|
|
60
|
+
target: metric_target
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def object_metric_source(name, metric_target, metric_selector: nil, described_object:)
|
|
66
|
+
{
|
|
67
|
+
type: 'Pods',
|
|
68
|
+
pods: {
|
|
69
|
+
metric: { name: name, selector: metric_selector }.compact,
|
|
70
|
+
describedObject: described_object,
|
|
71
|
+
target: metric_target
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def utilization_metric_target(target)
|
|
77
|
+
{ type: 'Utilization', averageUtilization: target }
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def average_value_metric_target(target)
|
|
81
|
+
{ type: 'AverageValue', averageValue: target }
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def value_metric_target(target)
|
|
85
|
+
{ type: 'Value', value: target }
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def hpa_scaling_rule(policies:, select_policy: 'MaxPolicySelect', stabilization_window_seconds: nil)
|
|
89
|
+
{
|
|
90
|
+
policies: policies,
|
|
91
|
+
selectPolicy: select_policy,
|
|
92
|
+
stabilizationWindowSeconds: stabilization_window_seconds
|
|
93
|
+
}.compact
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def hpa_scaling_policy(type:, value:, period_seconds:)
|
|
97
|
+
{
|
|
98
|
+
type: type,
|
|
99
|
+
value: value,
|
|
100
|
+
periodSeconds: period_seconds
|
|
101
|
+
}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
class << self
|
|
105
|
+
def load_path
|
|
106
|
+
Matsuri::Config.horizontal_pod_autoscalers_path
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def definition_module_name
|
|
110
|
+
'HorizontalPodAutoscalers'
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'matsuri/core_ext'
|
|
4
|
+
require 'json'
|
|
5
|
+
|
|
6
|
+
# rubocop:disable Lint/MissingCopEnableDirective
|
|
7
|
+
# rubocop:disable Style/Alias
|
|
8
|
+
module Matsuri
|
|
9
|
+
module Kubernetes
|
|
10
|
+
# Some quirks about this one:
|
|
11
|
+
# 1. The generated manifest is usually an array of hashes, not a hash
|
|
12
|
+
# 2. It isn't generated so much as imported from a raw manifest provided by an upstream vendor
|
|
13
|
+
# 3. There are helpers to transform the manifest and customize it locally
|
|
14
|
+
# 4. Apply-only: the CLI binds no other verb for imported manifests
|
|
15
|
+
class ImportedManifest < Matsuri::Kubernetes::Base
|
|
16
|
+
include Matsuri::Concerns::ImportManifest
|
|
17
|
+
|
|
18
|
+
# Override this to run transforms; the Transform::Kubernetes dialect
|
|
19
|
+
# is in scope (set_env, update_in, append_volume, ...)
|
|
20
|
+
let(:extracted_manifests) { imported_manifests }
|
|
21
|
+
let(:namespace) { fail Matsuri::UndefinedLet, "Must define let(:namespace); check the imported manifest and use the namespace found there" }
|
|
22
|
+
|
|
23
|
+
# Identity for delivery messages; there is no single kind to derive it from
|
|
24
|
+
let(:resource_type) { 'imported manifest' }
|
|
25
|
+
|
|
26
|
+
# Used to hook into ExportManifest concern
|
|
27
|
+
let(:manifest_for_export) { normalize_manifests(extracted_manifests) }
|
|
28
|
+
let(:applied_manifest_for_export) { normalize_manifests(extracted_manifests) }
|
|
29
|
+
|
|
30
|
+
def normalize_manifests(manifests)
|
|
31
|
+
Array(manifests).map(&:deep_stringify_keys)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Don't return a yaml array. Return a concated set of yaml files
|
|
35
|
+
def to_yaml
|
|
36
|
+
manifest_for_export.
|
|
37
|
+
map(&:to_yaml).
|
|
38
|
+
join('')
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def applied_to_yaml
|
|
42
|
+
applied_manifest_for_export.
|
|
43
|
+
map(&:to_yaml).
|
|
44
|
+
join('')
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
### Matsuri Registry
|
|
48
|
+
class << self
|
|
49
|
+
def load_path
|
|
50
|
+
Matsuri::Config.imported_manifests_path
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def definition_module_name
|
|
54
|
+
'ImportedManifests'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
class Ingress < Matsuri::Kubernetes::Base
|
|
6
|
+
let(:api_version) { 'networking.k8s.io/v1' }
|
|
7
|
+
let(:kind) { 'Ingress' }
|
|
8
|
+
|
|
9
|
+
let(:default_annotations) { ingress_annotations }
|
|
10
|
+
let(:ingress_annotations) { {} } # Reserved for ingress controller annotations
|
|
11
|
+
|
|
12
|
+
# Overridables
|
|
13
|
+
let(:spec) do
|
|
14
|
+
{
|
|
15
|
+
ingressClassName: ingress_class,
|
|
16
|
+
defaultBackend: default_backend,
|
|
17
|
+
rules: rules,
|
|
18
|
+
tls: tls
|
|
19
|
+
}.compact
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Names an IngressClass resource; replaces the retired
|
|
23
|
+
# kubernetes.io/ingress.class annotation.
|
|
24
|
+
let(:ingress_class) { nil }
|
|
25
|
+
let(:default_backend) { nil }
|
|
26
|
+
let(:rules) { nil }
|
|
27
|
+
let(:tls) { nil }
|
|
28
|
+
|
|
29
|
+
### Helpers
|
|
30
|
+
def http_rule(host:, paths:)
|
|
31
|
+
{ host: host, http: { paths: maybe_array(paths) } }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# pathType is required in networking.k8s.io/v1: Prefix, Exact, or
|
|
35
|
+
# ImplementationSpecific. path may be omitted only for
|
|
36
|
+
# ImplementationSpecific.
|
|
37
|
+
def path(path = nil, service:, port:, path_type: 'Prefix')
|
|
38
|
+
{ path: path, pathType: path_type, backend: backend(service: service, port: port) }.compact
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def backend(service:, port:)
|
|
42
|
+
{ service: { name: service, port: service_port(port) } }
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# An Integer is a port number; anything else names a port.
|
|
46
|
+
def service_port(port)
|
|
47
|
+
port.is_a?(Integer) ? { number: port } : { name: port }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Passing a hash to an array does not do this
|
|
51
|
+
def maybe_array(x)
|
|
52
|
+
x.is_a?(Array) ? x : [x]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
class << self
|
|
56
|
+
def load_path
|
|
57
|
+
Matsuri::Config.ingresses_path
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def definition_module_name
|
|
61
|
+
'Ingresses'
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
# Kubernetes Persistent Volume
|
|
6
|
+
class PersistentVolume < Matsuri::Kubernetes::Base
|
|
7
|
+
let(:api_version) { 'v1' }
|
|
8
|
+
let(:kind) { 'PersistentVolume' }
|
|
9
|
+
let(:default_annotations) { { 'volume.beta.kubernetes.io/storage-class' => storage_class } } # http://kubernetes.io/docs/user-guide/persistent-volumes/
|
|
10
|
+
|
|
11
|
+
let(:spec) do
|
|
12
|
+
{
|
|
13
|
+
capacity: capacity,
|
|
14
|
+
accessModes: Array(access_modes),
|
|
15
|
+
persistentVolumeReclaimPolicy: reclaim_policy
|
|
16
|
+
}.merge(plugin_spec)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
let(:storage_class) { fail Matsuri::UndefinedLet, 'Must define let(:storage_class)' }
|
|
20
|
+
let(:access_modes) { fail Matsuri::UndefinedLet, 'Must define let(:access_modes): ReadWriteOnce, ReadOnlyMany, ReadWriteMany' }
|
|
21
|
+
let(:capacity) { { storage: storage_size } } # http://kubernetes.io/docs/user-guide/persistent-volumes/#capacity
|
|
22
|
+
let(:storage_size) { fail Matsuri::UndefinedLet, 'Must define let(:storage_size)' }
|
|
23
|
+
let(:reclaim_policy) { fail Matsuri::UndefinedLet, 'Must define let(:reclaim_policy): Retain, Recycle, Delete' }
|
|
24
|
+
let(:plugin_spec) { fail Matsuri::UndefinedLet, 'Must define let(:public_spec). Ex: gce_persistent_disk' }
|
|
25
|
+
|
|
26
|
+
# GCE peristant disk plugin
|
|
27
|
+
# http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_gcepersistentdiskvolumesource
|
|
28
|
+
let(:gce_persistent_disk) do
|
|
29
|
+
{
|
|
30
|
+
gcePersistentDisk: {
|
|
31
|
+
pdName: gce_pd_name,
|
|
32
|
+
fsType: gce_fstype,
|
|
33
|
+
partition: gce_partition,
|
|
34
|
+
readOnly: gce_read_only?
|
|
35
|
+
}.compact
|
|
36
|
+
}
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
let(:gce_pd_name) { fail Matsuri::UndefinedLet, 'Must define let(:gce_pd_name) to unique PD resource on GCE' }
|
|
40
|
+
let(:gce_fstype) { 'ext4' } # Examples: ext4, xfs, ntfs
|
|
41
|
+
let(:gce_partition) { nil }
|
|
42
|
+
let(:gce_read_only?) { false }
|
|
43
|
+
|
|
44
|
+
class << self
|
|
45
|
+
# Registry helpers
|
|
46
|
+
def load_path
|
|
47
|
+
Matsuri::Config.persistent_volumes_path
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def definition_module_name
|
|
51
|
+
'PersistentVolumes'
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Matsuri
|
|
4
|
+
module Kubernetes
|
|
5
|
+
# Kubernetes Persistent Volume Claim
|
|
6
|
+
# http://kubernetes.io/docs/user-guide/persistent-volumes/#persistentvolumeclaims
|
|
7
|
+
class PersistentVolumeClaim < Matsuri::Kubernetes::Base
|
|
8
|
+
let(:api_version) { 'v1' }
|
|
9
|
+
let(:kind) { 'PersistentVolumeClaim' }
|
|
10
|
+
let(:default_annotations) { { 'volume.beta.kubernetes.io/storage-class' => storage_class } } # http://kubernetes.io/docs/user-guide/persistent-volumes/
|
|
11
|
+
|
|
12
|
+
let(:spec) do
|
|
13
|
+
{
|
|
14
|
+
resources: resources,
|
|
15
|
+
accessModes: Array(access_modes),
|
|
16
|
+
selector: selector
|
|
17
|
+
}
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
let(:resources) { { limits: limits, requests: requests }.compact }
|
|
21
|
+
let(:limits) { nil }
|
|
22
|
+
let(:requests) { { storage: storage_size } }
|
|
23
|
+
let(:storage_size) { fail Matsuri::UndefinedLet, 'Must define let(:storage_size)' }
|
|
24
|
+
let(:selector) { { matchLabels: match_labels, matchExpressions: match_expressions }.compact }
|
|
25
|
+
|
|
26
|
+
let(:match_labels) { fail Matsuri::UndefinedLet, 'Must define let(:match_labels)' }
|
|
27
|
+
let(:match_expressions) { nil }
|
|
28
|
+
|
|
29
|
+
class << self
|
|
30
|
+
# Registry helpers
|
|
31
|
+
def load_path
|
|
32
|
+
Matsuri::Config.persistent_volume_claims_path
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def definition_module_name
|
|
36
|
+
'PersistentVolumeClaims'
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|