kube-platform 3.3.1.gk.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +31 -0
- data/README.md +192 -0
- data/bin/kube-platform +37 -0
- data/lib/kube-platform/application.rb +203 -0
- data/lib/kube-platform/cli.rb +114 -0
- data/lib/kube-platform/client.rb +217 -0
- data/lib/kube-platform/cluster.rb +224 -0
- data/lib/kube-platform/cluster_definition.rb +115 -0
- data/lib/kube-platform/configuration.rb +145 -0
- data/lib/kube-platform/exceptions.rb +9 -0
- data/lib/kube-platform/handlers/dockerhub_secret_copy.rb +52 -0
- data/lib/kube-platform/handlers/ebs_from_snapshot.rb +108 -0
- data/lib/kube-platform/handlers/handler.rb +36 -0
- data/lib/kube-platform/handlers/recreate_resource.rb +11 -0
- data/lib/kube-platform/handlers/secret_copy.rb +43 -0
- data/lib/kube-platform/handlers/wait_for_job_completion.rb +69 -0
- data/lib/kube-platform/handlers/wait_for_termination.rb +47 -0
- data/lib/kube-platform/health_check.rb +19 -0
- data/lib/kube-platform/health_checks/pods_ready.rb +188 -0
- data/lib/kube-platform/health_checks/r53_records.rb +82 -0
- data/lib/kube-platform/helpers/retry.rb +20 -0
- data/lib/kube-platform/images/descriptor.rb +49 -0
- data/lib/kube-platform/images/docker_hub_image.rb +49 -0
- data/lib/kube-platform/images/dockerhub_image_factory.rb +64 -0
- data/lib/kube-platform/images/kubernetes_docker_hub_secret_provider.rb +44 -0
- data/lib/kube-platform/images/repository.rb +77 -0
- data/lib/kube-platform/images/tag_associator.rb +80 -0
- data/lib/kube-platform/images/tagged_dockerhub_image.rb +36 -0
- data/lib/kube-platform/logger.rb +32 -0
- data/lib/kube-platform/manifest.rb +61 -0
- data/lib/kube-platform/pre_checks/r53_records.rb +66 -0
- data/lib/kube-platform/pre_checks/valid_platform_dependencies.rb +52 -0
- data/lib/kube-platform/pre_checks.rb +19 -0
- data/lib/kube-platform/resource.rb +152 -0
- data/lib/kube-platform/resource_repository.rb +73 -0
- data/lib/kube-platform/thor/descriptor_to_option_adapter.rb +33 -0
- data/lib/kube-platform/update_checker.rb +39 -0
- data/lib/kube-platform/version.rb +5 -0
- data/lib/kube-platform.rb +40 -0
- metadata +179 -0
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
|
5
|
+
module KubePlatform
|
6
|
+
module Images
|
7
|
+
class Descriptor
|
8
|
+
DEFAULT_IMAGE_CONFIG = "../../../config/images.yaml"
|
9
|
+
|
10
|
+
attr_reader :name, :default_tag, :default_tag_from_key, :key, :description, :key_alias
|
11
|
+
|
12
|
+
def initialize(name:, default_tag:, default_tag_from_key:, key:, description:, key_alias: nil)
|
13
|
+
@name = name
|
14
|
+
@default_tag = default_tag
|
15
|
+
@default_tag_from_key = default_tag_from_key
|
16
|
+
@key = key.to_sym
|
17
|
+
@description = description
|
18
|
+
@key_alias = key_alias&.to_sym
|
19
|
+
end
|
20
|
+
|
21
|
+
class << self
|
22
|
+
def with_image_defaults
|
23
|
+
images_path = File.expand_path(File.join(__dir__, DEFAULT_IMAGE_CONFIG))
|
24
|
+
array_from_yaml_file(filename: images_path)
|
25
|
+
end
|
26
|
+
|
27
|
+
def array_from_yaml_file(filename:)
|
28
|
+
yaml_to_hash(filename).map do |item|
|
29
|
+
new(
|
30
|
+
name: item[:name],
|
31
|
+
default_tag: item[:default_tag],
|
32
|
+
default_tag_from_key: item[:default_tag_from_key],
|
33
|
+
key: item[:key],
|
34
|
+
description: item[:description],
|
35
|
+
key_alias: item[:key_alias]
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def yaml_to_hash(filename)
|
43
|
+
YAML.load_file(filename).with_indifferent_access[:images] or # TODO: get rid of indifferent access
|
44
|
+
raise ConfigException, "#{filename} does not contain a set of valid image descriptors"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "base64"
|
4
|
+
|
5
|
+
module KubePlatform
|
6
|
+
module Images
|
7
|
+
class DockerHubImage
|
8
|
+
include Logger
|
9
|
+
|
10
|
+
attr_reader :image_name, :secret_provider
|
11
|
+
|
12
|
+
def initialize(image_name:, secret_provider:)
|
13
|
+
@image_name = image_name
|
14
|
+
@secret_provider = secret_provider
|
15
|
+
end
|
16
|
+
|
17
|
+
def tag_exist?(tag)
|
18
|
+
response = RestClient.get(
|
19
|
+
"https://index.docker.io/v2/#{image_name}/manifests/#{tag}",
|
20
|
+
Authorization: "Bearer #{dockerhub_token}", Accept: "application/json"
|
21
|
+
)
|
22
|
+
response.code == 200
|
23
|
+
rescue RestClient::RequestFailed
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def basic_auth_secret
|
30
|
+
secret_provider.secret
|
31
|
+
end
|
32
|
+
|
33
|
+
def dockerhub_token
|
34
|
+
@dockerhub_token ||= read_dockerhub_token
|
35
|
+
end
|
36
|
+
|
37
|
+
def read_dockerhub_token
|
38
|
+
response = RestClient.get(
|
39
|
+
"https://auth.docker.io/token?service=registry.docker.io&scope=repository:#{image_name}:pull",
|
40
|
+
Authorization: "Basic #{basic_auth_secret}", Accept: "application/json"
|
41
|
+
)
|
42
|
+
|
43
|
+
JSON.parse(response.body)["token"]
|
44
|
+
rescue RestClient::RequestFailed => e
|
45
|
+
raise KubePlatformException, "Could not retrieve Docker Hub token: #{e.message}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
module Images
|
5
|
+
class DockerHubImageFactory
|
6
|
+
def initialize(secret_provider:)
|
7
|
+
@secret_provider = secret_provider
|
8
|
+
@image_cache = {}
|
9
|
+
@tagged_image_cache = {}
|
10
|
+
end
|
11
|
+
|
12
|
+
def build(image_name:, tag:)
|
13
|
+
if fully_qualified_docker_image?(tag)
|
14
|
+
parsed_tag = parse_tag_for_full_docker_image(tag)
|
15
|
+
tagged_dockerhub_image(parsed_tag[:image_name], parsed_tag[:image_tag])
|
16
|
+
else
|
17
|
+
tagged_dockerhub_image(image_name, tag)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def fully_qualified_docker_image?(image_tag)
|
24
|
+
image_tag.split(":").count > 1
|
25
|
+
end
|
26
|
+
|
27
|
+
def parse_tag_for_full_docker_image(image_tag)
|
28
|
+
split_tag = image_tag.split(":")
|
29
|
+
{ image_name: split_tag[0], image_tag: split_tag[1] }
|
30
|
+
end
|
31
|
+
|
32
|
+
def tagged_dockerhub_image(image_name, image_tag)
|
33
|
+
retrieve_tagged_image(image_name, image_tag) || create_tagged_dockerhub_image(image_name, image_tag)
|
34
|
+
end
|
35
|
+
|
36
|
+
def retrieve_tagged_image(image_name, image_tag)
|
37
|
+
@tagged_image_cache[tagged_image_hash_key(image_name, image_tag)]
|
38
|
+
end
|
39
|
+
|
40
|
+
def tagged_image_hash_key(image_name, image_tag)
|
41
|
+
[image_name, image_tag]
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_tagged_dockerhub_image(image_name, image_tag)
|
45
|
+
dockerhub_image = dockerhub_image(image_name)
|
46
|
+
@tagged_image_cache[tagged_image_hash_key(image_name, image_tag)] = KubePlatform::Images::TaggedDockerHubImage.new(
|
47
|
+
image: dockerhub_image, tag: image_tag
|
48
|
+
)
|
49
|
+
end
|
50
|
+
|
51
|
+
def dockerhub_image(image_name)
|
52
|
+
retrieve_cached_image(image_name) || create_dockerhub_image(image_name)
|
53
|
+
end
|
54
|
+
|
55
|
+
def retrieve_cached_image(image_name)
|
56
|
+
@image_cache[image_name]
|
57
|
+
end
|
58
|
+
|
59
|
+
def create_dockerhub_image(image_name)
|
60
|
+
@image_cache[image_name] = KubePlatform::Images::DockerHubImage.new(image_name: image_name, secret_provider: @secret_provider)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
module Images
|
5
|
+
class KubernetesDockerHubSecretProvider
|
6
|
+
include Logger
|
7
|
+
|
8
|
+
attr_reader :client, :secret_namespace, :secret_name
|
9
|
+
|
10
|
+
def initialize(client:, secret_name:, secret_namespace:)
|
11
|
+
@client = client
|
12
|
+
@secret_name = secret_name
|
13
|
+
@secret_namespace = secret_namespace
|
14
|
+
end
|
15
|
+
|
16
|
+
def secret
|
17
|
+
basic_auth_secret
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def basic_auth_secret
|
23
|
+
resource = client.get(secret_resource)
|
24
|
+
if resource.nil?
|
25
|
+
message = "Could not retrieve Docker Hub secret from #{secret_namespace}/#{secret_name}"
|
26
|
+
logger.error(message) # TODO: don't double-log this
|
27
|
+
raise KubePlatform::KubePlatformException, message
|
28
|
+
end
|
29
|
+
|
30
|
+
decode_token(resource.unwrap.data[".dockercfg"])
|
31
|
+
end
|
32
|
+
|
33
|
+
def secret_resource
|
34
|
+
@secret_resource ||= KubePlatform::Resource.from_spec(apiVersion: "v1", kind: "Secret",
|
35
|
+
metadata: { name: secret_name, namespace: secret_namespace })
|
36
|
+
end
|
37
|
+
|
38
|
+
def decode_token(data)
|
39
|
+
decoded = Base64.decode64(data)
|
40
|
+
JSON.parse(decoded).dig("https://index.docker.io/v1/", "auth") or raise TokenNotFound, "Token not found in #{decoded}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
module Images
|
5
|
+
class Repository
|
6
|
+
def initialize(image_descriptors:, image_tags:, image_factory:)
|
7
|
+
@image_descriptors = image_descriptors
|
8
|
+
@image_tags = image_tags.compact
|
9
|
+
@image_factory = image_factory
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(key)
|
13
|
+
registry[key.to_sym]
|
14
|
+
end
|
15
|
+
|
16
|
+
def missing_images
|
17
|
+
registry.values.reject(&:exist?)
|
18
|
+
end
|
19
|
+
|
20
|
+
def key_tag_pairs
|
21
|
+
registry.each_with_object({}) { |(key, image), pairs| pairs[key] = image.tag }
|
22
|
+
end
|
23
|
+
|
24
|
+
def key_tag_pairs_without_defaults
|
25
|
+
@image_tags
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_key_tag_pairs(additional_pairs)
|
29
|
+
@image_tags.merge!(additional_pairs) { |_key, old, _new| old }
|
30
|
+
rebuild_registry
|
31
|
+
end
|
32
|
+
|
33
|
+
def update_image_tag_defaults(key_tag_pairs)
|
34
|
+
(keys_with_default_tags & key_tag_pairs.keys).each do |key|
|
35
|
+
descriptor = descriptor_for_key(key)
|
36
|
+
registry[key] = @image_factory.build(image_name: descriptor.name, tag: key_tag_pairs[key])
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def registry
|
43
|
+
@registry ||= build_registry
|
44
|
+
end
|
45
|
+
|
46
|
+
def build_registry
|
47
|
+
image_key_tag_map = associate_tags(@image_descriptors, @image_tags)
|
48
|
+
|
49
|
+
@image_descriptors.each_with_object({}) do |descriptor, registry|
|
50
|
+
key = descriptor.key
|
51
|
+
registry[key] = @image_factory.build(image_name: descriptor.name, tag: image_key_tag_map[key])
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def rebuild_registry
|
56
|
+
@registry = nil
|
57
|
+
registry
|
58
|
+
end
|
59
|
+
|
60
|
+
def associate_tags(image_descriptors, image_tags)
|
61
|
+
TagAssociator.new(image_descriptors: image_descriptors, image_tags: image_tags).run
|
62
|
+
end
|
63
|
+
|
64
|
+
def keys_with_default_tags
|
65
|
+
registry.keys - @image_tags.keys
|
66
|
+
end
|
67
|
+
|
68
|
+
def descriptor_for_key(key)
|
69
|
+
key_descriptor_map[key]
|
70
|
+
end
|
71
|
+
|
72
|
+
def key_descriptor_map
|
73
|
+
@key_descriptor_map ||= @image_descriptors.each_with_object({}) { |descriptor, hash| hash[descriptor.key] = descriptor }
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
module Images
|
5
|
+
class TagAssociator
|
6
|
+
DescriptorTagPair = Struct.new(:descriptor, :tag)
|
7
|
+
|
8
|
+
def initialize(image_descriptors:, image_tags:)
|
9
|
+
@image_descriptors = image_descriptors
|
10
|
+
@image_tags = image_tags
|
11
|
+
@associated = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def run
|
15
|
+
descriptors_with_image_tags, descriptors_requiring_defaults = @image_descriptors.partition { |d| @image_tags.key?(d.key) }
|
16
|
+
associate_descriptors_with_image_tags(descriptors_with_image_tags)
|
17
|
+
associate_descriptors_with_defaults(descriptors_requiring_defaults)
|
18
|
+
transform_descriptor_tag_map_to_image_key_tag_map
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def associate_descriptors_with_image_tags(descriptors)
|
24
|
+
descriptors.each { |d| associate_tag_to_descriptor(d, @image_tags[d.key]) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def associate_tag_to_descriptor(descriptor, tag)
|
28
|
+
@associated[descriptor.key] = DescriptorTagPair.new(descriptor, tag)
|
29
|
+
end
|
30
|
+
|
31
|
+
def associate_descriptors_with_defaults(descriptors)
|
32
|
+
remaining_untagged = associate_tags_to_descriptors_containing_default_tag_attributes(descriptors)
|
33
|
+
remaining_untagged = associate_tags_to_descriptors_containing_references_to_other_descriptors(remaining_untagged)
|
34
|
+
remaining_untagged.empty? or
|
35
|
+
raise ConfigException, "No tag could be found for image with key '#{remaining_untagged.first.key}'"
|
36
|
+
end
|
37
|
+
|
38
|
+
def associate_tags_to_descriptors_containing_default_tag_attributes(descriptors)
|
39
|
+
descriptors.reject do |d|
|
40
|
+
if (tag = d.default_tag)
|
41
|
+
associate_tag_to_descriptor(d, tag)
|
42
|
+
true
|
43
|
+
else
|
44
|
+
false
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def associate_tags_to_descriptors_containing_references_to_other_descriptors(descriptors)
|
50
|
+
descriptors.reject do |d|
|
51
|
+
if (ref = d.default_tag_from_key)
|
52
|
+
resolve_descriptor_reference(d, ref)
|
53
|
+
true
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def resolve_descriptor_reference(descriptor, ref)
|
61
|
+
descriptor_tag_pair = @associated[ref.to_sym] or
|
62
|
+
raise ConfigException,
|
63
|
+
"#{descriptor.key} wants to use the image tag from the image with key '#{ref}', but that image does not have a tag"
|
64
|
+
|
65
|
+
if descriptor.name != descriptor_tag_pair.descriptor.name &&
|
66
|
+
([descriptor.name, descriptor_tag_pair.descriptor.name] - ['invocaops/web_app', 'invocaops/ringswitch']).any?
|
67
|
+
raise ConfigException,
|
68
|
+
"#{descriptor.key} is trying to use the default_tag_from_key directive against #{ref}, "\
|
69
|
+
"but the image names don't match"
|
70
|
+
end
|
71
|
+
|
72
|
+
associate_tag_to_descriptor(descriptor, descriptor_tag_pair.tag)
|
73
|
+
end
|
74
|
+
|
75
|
+
def transform_descriptor_tag_map_to_image_key_tag_map
|
76
|
+
@associated.each_with_object({}) { |(key, descriptor_tag_pair), hash| hash[key] = descriptor_tag_pair.tag }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
module Images
|
5
|
+
class TaggedDockerHubImage
|
6
|
+
include Logger
|
7
|
+
|
8
|
+
attr_reader :tag
|
9
|
+
|
10
|
+
def initialize(image:, tag:)
|
11
|
+
@image = image
|
12
|
+
@tag = tag
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
"#{@image.image_name}:#{@tag}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def exist?
|
20
|
+
defined?(@exists) or @exists = log_success_fail(@image.tag_exist?(@tag))
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def log_success_fail(success)
|
26
|
+
if success
|
27
|
+
logger.info("Successfully located Docker Hub image for #{name}")
|
28
|
+
else
|
29
|
+
logger.info("Could not locate Docker Hub image for #{name}")
|
30
|
+
end
|
31
|
+
|
32
|
+
success
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "logger"
|
4
|
+
|
5
|
+
module KubePlatform
|
6
|
+
module Logger
|
7
|
+
ANSI_ESCAPE = "\x1B"
|
8
|
+
ANSI_GOTO_START_OF_LINE = ANSI_ESCAPE + "[0F"
|
9
|
+
ANSI_CLEAR_TO_END_OF_LINE = ANSI_ESCAPE + "[J"
|
10
|
+
|
11
|
+
class << self
|
12
|
+
attr_accessor :verbose
|
13
|
+
attr_writer :logger
|
14
|
+
|
15
|
+
def logger
|
16
|
+
@logger ||= ::Logger.new(STDOUT).tap do |logger|
|
17
|
+
logger.formatter = -> (severity, time, programname, msg) do
|
18
|
+
if STDOUT.isatty && !verbose
|
19
|
+
ANSI_GOTO_START_OF_LINE + ANSI_CLEAR_TO_END_OF_LINE + "%5s %s\n" % [severity, msg]
|
20
|
+
else
|
21
|
+
::Logger::Formatter.new.call(severity, time, programname, msg)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def logger
|
29
|
+
Logger.logger
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash"
|
4
|
+
require "active_support/core_ext/string"
|
5
|
+
require "jsonnet"
|
6
|
+
|
7
|
+
module KubePlatform
|
8
|
+
class Manifest
|
9
|
+
attr_reader :resource_dir, :filename, :config
|
10
|
+
|
11
|
+
FILENAME_ANNOTATION = "invoca.com/resource_filename"
|
12
|
+
|
13
|
+
def initialize(filename:, resource_dir:, config:)
|
14
|
+
@filename = filename
|
15
|
+
@resource_dir = resource_dir
|
16
|
+
@config = config
|
17
|
+
end
|
18
|
+
|
19
|
+
def cluster_definition_by_name(name)
|
20
|
+
raise_if_definition_not_found(name)
|
21
|
+
definitions[name]
|
22
|
+
end
|
23
|
+
|
24
|
+
def version
|
25
|
+
manifest[:version] or raise ManifestException, "The manifest does not contain a 'version' key"
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def raise_if_definition_not_found(definition_name)
|
31
|
+
definitions[definition_name] or raise ManifestException, "A platform definition named #{definition_name} was not found in #{filename}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def definitions
|
35
|
+
@definitions ||= manifest[:definitions].each_with_object({}) do |(name, definition), clusters|
|
36
|
+
clusters[name] = ClusterDefinition.new(name: name, definition: definition, resource_dir: resource_dir, config: config)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def manifest
|
41
|
+
@manifest ||= case filename
|
42
|
+
when /\.jsonnet$/
|
43
|
+
load_jsonnet_manifest
|
44
|
+
else
|
45
|
+
load_yaml_manifest
|
46
|
+
end.with_indifferent_access
|
47
|
+
end
|
48
|
+
|
49
|
+
def load_yaml_manifest
|
50
|
+
template = File.read(filename)
|
51
|
+
renderer = ERB.new(template)
|
52
|
+
YAML.safe_load(renderer.result(config.binding), aliases: true)
|
53
|
+
end
|
54
|
+
|
55
|
+
def load_jsonnet_manifest
|
56
|
+
vm = Jsonnet::VM.new
|
57
|
+
vm.tla_code("vars", config.to_json)
|
58
|
+
JSON.parse(vm.evaluate_file(filename))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "aws-sdk-route53"
|
4
|
+
require_relative "../logger"
|
5
|
+
require_relative "../helpers/retry"
|
6
|
+
|
7
|
+
module KubePlatform
|
8
|
+
module PreChecks
|
9
|
+
class R53Records < PreCheck
|
10
|
+
include Logger
|
11
|
+
|
12
|
+
DEFAULT_CONFIG = { }.freeze
|
13
|
+
|
14
|
+
def initialize(name, config)
|
15
|
+
super(name, config.apply_defaults(DEFAULT_CONFIG))
|
16
|
+
end
|
17
|
+
|
18
|
+
def run(_client, _cluster_definition)
|
19
|
+
logger.info("Checking for Route53 DNS records")
|
20
|
+
|
21
|
+
exists = []
|
22
|
+
|
23
|
+
fully_qualified_names.each do |record|
|
24
|
+
if record_exists?(record)
|
25
|
+
exists << record
|
26
|
+
logger.error("Route53 record #{record} already exists!")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
exists.length > 0 ? false : true
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def fully_qualified_names
|
36
|
+
@fully_qualified_names ||= r53_records.map { |record| record.end_with?(".") ? record : "#{record}." }
|
37
|
+
end
|
38
|
+
|
39
|
+
def record_exists?(record)
|
40
|
+
response = r53_client.list_resource_record_sets(
|
41
|
+
hosted_zone_id: r53_zone_id,
|
42
|
+
start_record_name: record,
|
43
|
+
start_record_type: "A",
|
44
|
+
max_items: 1
|
45
|
+
)
|
46
|
+
response.resource_record_sets.first&.name == record
|
47
|
+
end
|
48
|
+
|
49
|
+
def r53_client
|
50
|
+
@r53_client ||= Aws::Route53::Client.new(region: region)
|
51
|
+
end
|
52
|
+
|
53
|
+
def region
|
54
|
+
config[:region]
|
55
|
+
end
|
56
|
+
|
57
|
+
def r53_zone_id
|
58
|
+
config[:r53_zone_id]
|
59
|
+
end
|
60
|
+
|
61
|
+
def r53_records
|
62
|
+
@r53_records ||= config[:r53_records]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../health_check"
|
4
|
+
require_relative "../logger"
|
5
|
+
|
6
|
+
module KubePlatform
|
7
|
+
module PreChecks
|
8
|
+
class ValidPlatformDependencies < PreCheck
|
9
|
+
PlatformDependencyException = Class.new(KubePlatformException)
|
10
|
+
|
11
|
+
include Logger
|
12
|
+
|
13
|
+
def run(_client, cluster_definition)
|
14
|
+
pod_names = Set.new(cluster_definition.resources.map(&:name))
|
15
|
+
pods_with_invalid_dependencies = invalid_platform_startup_dependencies(cluster_definition, pod_names)
|
16
|
+
pods_with_invalid_dependencies.empty? or raise PlatformDependencyException, invalid_dependency_details(pods_with_invalid_dependencies)
|
17
|
+
logger.info("Platform startup dependencies are valid")
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def invalid_platform_startup_dependencies(cluster_definition, pod_names)
|
24
|
+
cluster_definition.resources.map do |resource|
|
25
|
+
if (dependencies_csv = resource.pod_annotation(:platform_startup_dependencies))
|
26
|
+
unless valid_dependency_list?(dependencies_csv, pod_names)
|
27
|
+
{ name: resource.name, dependencies: dependencies_csv }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end.compact
|
31
|
+
end
|
32
|
+
|
33
|
+
def valid_dependency_list?(dependencies_csv, expected_pod_names)
|
34
|
+
dependencies_csv.split(/, */).all? { |dependency| expected_pod_names.include?(dependency) }
|
35
|
+
end
|
36
|
+
|
37
|
+
def invalid_dependency_details(pods_with_invalid_dependencies)
|
38
|
+
if pods_with_invalid_dependencies.size > 5
|
39
|
+
<<~EOS.chomp
|
40
|
+
Found #{pods_with_invalid_dependencies.size} pod templates with startup dependencies that don't match existing pod names. Showing the first 5.
|
41
|
+
#{pods_with_invalid_dependencies.first(5).join("\n")}
|
42
|
+
EOS
|
43
|
+
else
|
44
|
+
<<~EOS.chomp
|
45
|
+
Found pod templates with startup dependencies that don't match existing pod names.
|
46
|
+
#{pods_with_invalid_dependencies.join("\n")}
|
47
|
+
EOS
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module KubePlatform
|
4
|
+
class PreCheck
|
5
|
+
attr_reader :name, :config
|
6
|
+
|
7
|
+
def initialize(name, config)
|
8
|
+
@name = name
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
class << self
|
13
|
+
def load(class_name:, name:, config:)
|
14
|
+
klass = "KubePlatform::PreChecks::#{class_name}".constantize
|
15
|
+
klass.new(name, config)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|