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.
Files changed (157) hide show
  1. checksums.yaml +5 -5
  2. data/.envrc +1 -0
  3. data/.gitignore +2 -0
  4. data/.rubocop.yml +9 -0
  5. data/AGENTS.md +18 -0
  6. data/CHANGELOG.md +642 -0
  7. data/Gemfile +2 -0
  8. data/README.md +86 -8
  9. data/Rakefile +20 -0
  10. data/bin/console +1 -0
  11. data/bin/matsuri +6 -0
  12. data/bin/setup +2 -0
  13. data/docs/acceptors.md +181 -0
  14. data/docs/boot.md +101 -0
  15. data/docs/design/acceptors.md +157 -0
  16. data/docs/design/boot.md +131 -0
  17. data/docs/design/ssa.md +142 -0
  18. data/docs/design/stacks.md +153 -0
  19. data/docs/diff.md +85 -0
  20. data/docs/known-issues.md +19 -0
  21. data/docs/local-dev.md +173 -0
  22. data/docs/presenters.md +317 -0
  23. data/docs/resources.md +121 -0
  24. data/docs/setup.md +97 -0
  25. data/docs/ssa.md +149 -0
  26. data/docs/stacks.md +146 -0
  27. data/flake.lock +61 -0
  28. data/flake.nix +35 -0
  29. data/lib/matsuri/acceptor.rb +33 -0
  30. data/lib/matsuri/acceptors/image_tag.rb +15 -0
  31. data/lib/matsuri/cmd.rb +46 -0
  32. data/lib/matsuri/cmds/apply.rb +78 -0
  33. data/lib/matsuri/cmds/cli.rb +147 -0
  34. data/lib/matsuri/cmds/create.rb +87 -0
  35. data/lib/matsuri/cmds/delete.rb +86 -0
  36. data/lib/matsuri/cmds/diff.rb +105 -0
  37. data/lib/matsuri/cmds/generate.rb +24 -0
  38. data/lib/matsuri/cmds/kubectl.rb +16 -0
  39. data/lib/matsuri/cmds/recreate.rb +65 -0
  40. data/lib/matsuri/cmds/scale.rb +37 -0
  41. data/lib/matsuri/cmds/show.rb +123 -0
  42. data/lib/matsuri/cmds/status.rb +67 -0
  43. data/lib/matsuri/concerns/awaiting.rb +24 -0
  44. data/lib/matsuri/concerns/diffable.rb +135 -0
  45. data/lib/matsuri/concerns/export_manifest.rb +56 -0
  46. data/lib/matsuri/concerns/import_manifest.rb +64 -0
  47. data/lib/matsuri/concerns/pod_template.rb +37 -0
  48. data/lib/matsuri/concerns/pods/spread_pods.rb +47 -0
  49. data/lib/matsuri/concerns/pods/spread_topology.rb +63 -0
  50. data/lib/matsuri/concerns/registry_helpers.rb +59 -0
  51. data/lib/matsuri/config.rb +101 -0
  52. data/lib/matsuri/core_ext.rb +107 -0
  53. data/lib/matsuri/dsl/cluster/aggregated_cluster_role.rb +75 -0
  54. data/lib/matsuri/dsl/cluster/binding.rb +118 -0
  55. data/lib/matsuri/dsl/cluster/cluster_role.rb +41 -0
  56. data/lib/matsuri/dsl/cluster/role.rb +49 -0
  57. data/lib/matsuri/dsl/cluster/scope.rb +245 -0
  58. data/lib/matsuri/dsl/cluster/service_account.rb +76 -0
  59. data/lib/matsuri/dsl/concerns/default_binding.rb +34 -0
  60. data/lib/matsuri/dsl/concerns/manifest_set.rb +21 -0
  61. data/lib/matsuri/dsl/concerns/metadata.rb +56 -0
  62. data/lib/matsuri/dsl/concerns/rbac_rules.rb +39 -0
  63. data/lib/matsuri/initializer.rb +41 -0
  64. data/lib/matsuri/kubernetes/base.rb +107 -0
  65. data/lib/matsuri/kubernetes/config_map.rb +100 -0
  66. data/lib/matsuri/kubernetes/cron_job.rb +115 -0
  67. data/lib/matsuri/kubernetes/daemon_set.rb +62 -0
  68. data/lib/matsuri/kubernetes/deployment.rb +65 -0
  69. data/lib/matsuri/kubernetes/endpoints.rb +57 -0
  70. data/lib/matsuri/kubernetes/horizontal_pod_autoscaler.rb +116 -0
  71. data/lib/matsuri/kubernetes/imported_manifest.rb +61 -0
  72. data/lib/matsuri/kubernetes/ingress.rb +66 -0
  73. data/lib/matsuri/kubernetes/persistent_volume.rb +56 -0
  74. data/lib/matsuri/kubernetes/persistent_volume_claim.rb +41 -0
  75. data/lib/matsuri/kubernetes/pod.rb +355 -0
  76. data/lib/matsuri/kubernetes/replica_set.rb +46 -0
  77. data/lib/matsuri/kubernetes/secret.rb +86 -0
  78. data/lib/matsuri/kubernetes/service.rb +49 -0
  79. data/lib/matsuri/kubernetes/stateful_set.rb +75 -0
  80. data/lib/matsuri/kubernetes/storage_class.rb +45 -0
  81. data/lib/matsuri/platform.rb +38 -0
  82. data/lib/matsuri/presenter.rb +47 -0
  83. data/lib/matsuri/presenters/helpers.rb +39 -0
  84. data/lib/matsuri/presenters/prune_empty.rb +59 -0
  85. data/lib/matsuri/presenters/seed_image.rb +28 -0
  86. data/lib/matsuri/presenters/seed_replicas.rb +25 -0
  87. data/lib/matsuri/presenters/seed_resources.rb +29 -0
  88. data/lib/matsuri/registry.rb +267 -0
  89. data/lib/matsuri/shell_out.rb +119 -0
  90. data/lib/matsuri/stack.rb +276 -0
  91. data/lib/matsuri/task.rb +20 -0
  92. data/lib/matsuri/tasks/cluster.rb +79 -0
  93. data/lib/matsuri/tasks/docker.rb +25 -0
  94. data/lib/matsuri/tasks/hash_diff.rb +61 -0
  95. data/lib/matsuri/tasks/kubectl.rb +21 -0
  96. data/lib/matsuri/tasks/kubectl_ops/apply.rb +24 -0
  97. data/lib/matsuri/tasks/kubectl_ops/create.rb +27 -0
  98. data/lib/matsuri/tasks/kubectl_ops/delete.rb +21 -0
  99. data/lib/matsuri/tasks/kubectl_ops/diff.rb +47 -0
  100. data/lib/matsuri/tasks/kubectl_ops/get.rb +36 -0
  101. data/lib/matsuri/tasks/kubectl_ops/recreate.rb +35 -0
  102. data/lib/matsuri/tasks/kubectl_ops/replace.rb +29 -0
  103. data/lib/matsuri/tasks/kubectl_ops/rollout_status.rb +22 -0
  104. data/lib/matsuri/tasks/kubectl_ops/scale.rb +22 -0
  105. data/lib/matsuri/tasks/kubectl_ops/server_side_apply.rb +32 -0
  106. data/lib/matsuri/tasks/kubectl_ops/status.rb +20 -0
  107. data/lib/matsuri/tasks/kubectl_ops.rb +218 -0
  108. data/lib/matsuri/tasks/pod.rb +56 -0
  109. data/lib/matsuri/tasks/stacks/seed.rb +93 -0
  110. data/lib/matsuri/tasks/stacks.rb +31 -0
  111. data/lib/matsuri/transform/algebra.rb +52 -0
  112. data/lib/matsuri/transform/callable.rb +54 -0
  113. data/lib/matsuri/transform/combinators.rb +61 -0
  114. data/lib/matsuri/transform/env.rb +43 -0
  115. data/lib/matsuri/transform/kubernetes.rb +89 -0
  116. data/lib/matsuri/transform.rb +20 -0
  117. data/lib/matsuri/version.rb +3 -1
  118. data/lib/matsuri.rb +158 -2
  119. data/matsuri.gemspec +20 -7
  120. data/tests/bin/minikube-start.sh +27 -0
  121. data/tests/bin/probe-save-config.sh +46 -0
  122. data/tests/bin/probe-ssa.sh +206 -0
  123. data/tests/example/.gitignore +1 -0
  124. data/tests/example/Gemfile +7 -0
  125. data/tests/example/README.md +91 -0
  126. data/tests/example/bin/matsuri +14 -0
  127. data/tests/example/config/initializer.rb +12 -0
  128. data/tests/example/config/matsuri.rb +9 -0
  129. data/tests/example/config/platform.rb +39 -0
  130. data/tests/example/lib/acme/nodes/dedicated.rb +26 -0
  131. data/tests/example/lib/acme/nodes/preemptible.rb +17 -0
  132. data/tests/example/lib/acme/nodes/required_cores.rb +26 -0
  133. data/tests/example/lib/acme/nodes/resource_class.rb +26 -0
  134. data/tests/example/lib/acme/pods/cacerts.rb +15 -0
  135. data/tests/example/lib/acme/pods/healthcheck.rb +36 -0
  136. data/tests/example/lib/acme.rb +26 -0
  137. data/tests/example/platform/config_maps/billing-settings.rb +8 -0
  138. data/tests/example/platform/config_maps/cacerts.rb +9 -0
  139. data/tests/example/platform/deployments/billing-web.rb +5 -0
  140. data/tests/example/platform/deployments/checkout-web.rb +6 -0
  141. data/tests/example/platform/namespaces/billing-dev.yaml +7 -0
  142. data/tests/example/platform/namespaces/checkout-dev.yaml +7 -0
  143. data/tests/example/platform/pods/billing.rb +31 -0
  144. data/tests/example/platform/pods/checkout.rb +27 -0
  145. data/tests/example/platform/services/billing-web.rb +6 -0
  146. data/tests/example/platform/services/checkout-web.rb +4 -0
  147. data/tests/example/platform/stacks/billing.rb +8 -0
  148. data/tests/example/platform/stacks/checkout.rb +19 -0
  149. data/tests/k8s/save-config/deployment-declared.yaml +19 -0
  150. data/tests/k8s/save-config/deployment-seeded.yaml +20 -0
  151. data/tests/k8s/save-config/namespace.yaml +4 -0
  152. data/tests/k8s/ssa/declared-bumped.yaml +22 -0
  153. data/tests/k8s/ssa/declared.yaml +22 -0
  154. data/tests/k8s/ssa/namespace.yaml +4 -0
  155. data/tests/k8s/ssa/seed-via-create.yaml +24 -0
  156. metadata +288 -20
  157. 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