configgin 0.19.1 → 0.19.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/configgin.rb +81 -54
- data/lib/configgin/version.rb +1 -1
- data/lib/kube_link_generator.rb +12 -52
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '0954b0d8fe5cfb4809934ffe2320c96e93e95cdd20e89f590f0714ca8b5e717c'
|
4
|
+
data.tar.gz: 84e9ff63af4eb3af8f33e80d740bef408b762fa163266ddb849e689f3126adcd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c89cd26245c367e7181067eed17764d9c43eb5cdd2c1ee990ae367e39dc69d82d3bf2f94755e58278903da78fc1c5c1ef45c9b4b1faf041c86d56eda81f6bc9
|
7
|
+
data.tar.gz: 0e1fef57272d7cce1b56101a1d088e99bf100e0adabbf929428e5ff196243be600c99c55a34eff9a192430326429e39004bfe403678e3c25d7e4e49e9ed03075
|
data/Gemfile.lock
CHANGED
data/lib/configgin.rb
CHANGED
@@ -24,9 +24,8 @@ class Configgin
|
|
24
24
|
|
25
25
|
def run
|
26
26
|
jobs = generate_jobs(@job_configs, @templates)
|
27
|
-
|
27
|
+
export_job_properties(jobs)
|
28
28
|
render_job_templates(jobs, @job_configs)
|
29
|
-
restart_affected_pods expected_annotations(@job_configs, job_digests)
|
30
29
|
end
|
31
30
|
|
32
31
|
def generate_jobs(job_configs, templates)
|
@@ -58,73 +57,86 @@ class Configgin
|
|
58
57
|
jobs
|
59
58
|
end
|
60
59
|
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
def render_job_templates(jobs, job_configs)
|
61
|
+
jobs.each do |job_name, job|
|
62
|
+
dns_encoder = KubeDNSEncoder.new(job.spec['links'])
|
63
|
+
|
64
|
+
job_configs[job_name]['files'].each do |infile, outfile|
|
65
|
+
job.generate(infile, outfile, dns_encoder)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# Write exported properties to secret and potentially restart affected pods.
|
71
|
+
def export_job_properties(jobs)
|
72
|
+
# co-located containers don't get to export properties
|
73
|
+
return unless instance_group == ENV["KUBERNETES_CONTAINER_NAME"]
|
74
|
+
# jobs don't export properties
|
75
|
+
return unless self_pod['metadata']['ownerReferences'][0]['kind'] == "StatefulSet"
|
64
76
|
|
77
|
+
sts = kube_client_stateful_set.get_stateful_set(instance_group, kube_namespace)
|
78
|
+
|
79
|
+
# Make sure the secret attached to the stateful set exists.
|
80
|
+
# XXX This should probably be done by fissile via the helm chart.
|
65
81
|
secret = Kubeclient::Resource.new
|
66
|
-
secret.metadata = {
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
+
secret.metadata = {
|
83
|
+
name: sts.metadata.name,
|
84
|
+
namespace: kube_namespace,
|
85
|
+
ownerReferences: [
|
86
|
+
{
|
87
|
+
apiVersion: sts.apiVersion,
|
88
|
+
blockOwnerDeletion: false,
|
89
|
+
controller: false,
|
90
|
+
kind: sts.kind,
|
91
|
+
name: sts.metadata.name,
|
92
|
+
uid: sts.metadata.uid,
|
93
|
+
}
|
94
|
+
]
|
95
|
+
}
|
96
|
+
begin
|
97
|
+
kube_client.create_secret(secret)
|
98
|
+
rescue
|
99
|
+
end
|
100
|
+
secret = kube_client.get_secret(instance_group, kube_namespace)
|
101
|
+
secret.data ||= {}
|
102
|
+
|
103
|
+
version_tag = ENV["CONFIGGIN_VERSION_TAG"]
|
104
|
+
new_tag = !secret.data.has_key?(version_tag)
|
105
|
+
secret.data = {version_tag => ""} if new_tag # make sure old properties are deleted during upgrade
|
82
106
|
|
83
|
-
secret.data = {}
|
84
107
|
digests = {}
|
85
108
|
jobs.each do |name, job|
|
86
109
|
digests[name] = property_digest(job.exported_properties)
|
87
110
|
secret.data["skiff-exported-properties-#{name}"] = Base64.encode64(job.exported_properties.to_json)
|
88
|
-
secret.data["skiff-exported-digest-#{name}"] = Base64.encode64(digests[name])
|
89
|
-
end
|
90
111
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
112
|
+
encoded_digest = Base64.encode64(digests[name])
|
113
|
+
|
114
|
+
# Record initial digest values whenever the tag changes, in which case the pod startup
|
115
|
+
# order is already controlled by the "CONFIGGIN_IMPORT_#{role}" references to the new
|
116
|
+
# tags in the corresponding secrets. There is no annotation when importing this set of
|
117
|
+
# initial values because the helm chart doesn't include any annotations, and we don't
|
118
|
+
# want to trigger a pod restart by adding them.
|
119
|
+
if new_tag
|
120
|
+
secret.data["skiff-initial-digest-#{name}"] = encoded_digest
|
121
|
+
end
|
122
|
+
if secret.data["skiff-initial-digest-#{name}"] == encoded_digest
|
123
|
+
digests[name] = nil
|
96
124
|
end
|
97
|
-
kube_client.create_secret(secret)
|
98
125
|
end
|
99
126
|
|
100
|
-
|
101
|
-
end
|
127
|
+
kube_client.update_secret(secret)
|
102
128
|
|
103
|
-
|
104
|
-
jobs.each do |job_name, job|
|
105
|
-
dns_encoder = KubeDNSEncoder.new(job.spec['links'])
|
129
|
+
return if new_tag
|
106
130
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
end
|
112
|
-
|
113
|
-
# Some pods might have depended on the properties exported by this pod; given
|
114
|
-
# the annotations expected on the pods (keyed by the instance group name),
|
115
|
-
# patch the StatefulSets such that they will be restarted.
|
116
|
-
def restart_affected_pods(expected_annotations)
|
117
|
-
expected_annotations.each_pair do |instance_group_name, digests|
|
131
|
+
# Some pods might have depended on the properties exported by this pod; given
|
132
|
+
# the annotations expected on the pods (keyed by the instance group name),
|
133
|
+
# patch the StatefulSets such that they will be restarted.
|
134
|
+
expected_annotations(@job_configs, digests).each_pair do |instance_group_name, digests|
|
118
135
|
# Avoid restarting our own pod
|
119
136
|
next if instance_group_name == instance_group
|
120
137
|
|
121
138
|
begin
|
122
|
-
kube_client_stateful_set.
|
123
|
-
instance_group_name,
|
124
|
-
{ spec: { template: { metadata: { annotations: digests } } } },
|
125
|
-
kube_namespace
|
126
|
-
)
|
127
|
-
warn "Patched StatefulSet #{instance_group_name} for new exported digests"
|
139
|
+
sts = kube_client_stateful_set.get_stateful_set(instance_group_name, kube_namespace)
|
128
140
|
rescue KubeException => e
|
129
141
|
begin
|
130
142
|
begin
|
@@ -142,6 +154,18 @@ class Configgin
|
|
142
154
|
raise
|
143
155
|
end
|
144
156
|
end
|
157
|
+
|
158
|
+
annotations = sts.spec.template.metadata.annotations
|
159
|
+
digests.each_pair do |key, value|
|
160
|
+
annotations[key] = value
|
161
|
+
end
|
162
|
+
|
163
|
+
kube_client_stateful_set.merge_patch_stateful_set(
|
164
|
+
instance_group_name,
|
165
|
+
{ spec: { template: { metadata: { annotations: annotations } } } },
|
166
|
+
kube_namespace
|
167
|
+
)
|
168
|
+
warn "Patched StatefulSet #{instance_group_name} for new exported digests"
|
145
169
|
end
|
146
170
|
end
|
147
171
|
|
@@ -198,8 +222,11 @@ class Configgin
|
|
198
222
|
@kube_client_stateful_set ||= create_kube_client(path: '/apis/apps')
|
199
223
|
end
|
200
224
|
|
201
|
-
def
|
225
|
+
def self_pod
|
202
226
|
@pod ||= kube_client.get_pod(@self_name, kube_namespace)
|
203
|
-
|
227
|
+
end
|
228
|
+
|
229
|
+
def instance_group
|
230
|
+
self_pod['metadata']['labels']['app.kubernetes.io/component']
|
204
231
|
end
|
205
232
|
end
|
data/lib/configgin/version.rb
CHANGED
data/lib/kube_link_generator.rb
CHANGED
@@ -62,19 +62,8 @@ class KubeLinkSpecs
|
|
62
62
|
30.times do
|
63
63
|
1.times do
|
64
64
|
pods = _get_pods_for_role(role_name, sts_image)
|
65
|
-
good_pods = pods.select
|
66
|
-
next false unless pod.status.podIP
|
67
|
-
begin
|
68
|
-
secret = client.get_secret("#{pod.metadata.name}-#{pod.metadata.uid}", namespace)
|
69
|
-
next true if secret.data["skiff-exported-properties-#{job}"]
|
70
|
-
|
71
|
-
rescue
|
72
|
-
pod.metadata.annotations["skiff-exported-properties-#{job}"]
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
65
|
+
good_pods = pods.select { |pod| pod.status.podIP }
|
76
66
|
if options[:wait_for_all]
|
77
|
-
# Wait until all pods have IP addresses and properties
|
78
67
|
break unless good_pods.length == pods.length
|
79
68
|
end
|
80
69
|
return good_pods unless good_pods.empty?
|
@@ -86,43 +75,12 @@ class KubeLinkSpecs
|
|
86
75
|
end
|
87
76
|
end
|
88
77
|
|
89
|
-
def
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
)
|
95
|
-
end
|
96
|
-
|
97
|
-
def get_exported_properties(role_name, pod, job_name)
|
98
|
-
# Exported properties are stored in a secret linked to the pod by naming convention.
|
99
|
-
begin
|
100
|
-
secret = client.get_secret("#{pod.metadata.name}-#{pod.metadata.uid}", namespace)
|
101
|
-
rescue
|
102
|
-
end
|
103
|
-
|
104
|
-
if !secret.nil?
|
105
|
-
digest = secret.data["skiff-exported-digest-#{job_name}"]
|
106
|
-
# digest not being set only happens during the spec tests???
|
107
|
-
if digest
|
108
|
-
# Copy the digest over, so that if the source role changes we can be restarted.
|
109
|
-
patch_pod_with_imported_properties(role_name, job_name, Base64.decode64(digest))
|
110
|
-
end
|
111
|
-
JSON.parse(Base64.decode64(secret.data["skiff-exported-properties-#{job_name}"]))
|
112
|
-
|
113
|
-
# Older implementation stored exported properties in annotations (one per job).
|
114
|
-
elsif pod.metadata.annotations["skiff-exported-properties-#{job_name}"]
|
115
|
-
# digest not being set only happens during the spec tests???
|
116
|
-
if pod.metadata.annotations["skiff-exported-digest-#{job_name}"]
|
117
|
-
# Copy the digest over, so that if the source role changes we can be restarted.
|
118
|
-
digest = pod.metadata.annotations["skiff-exported-digest-#{job_name}"]
|
119
|
-
patch_pod_with_imported_properties(role_name, job_name, digest)
|
120
|
-
end
|
121
|
-
JSON.parse(pod.metadata.annotations["skiff-exported-properties-#{job_name}"])
|
122
|
-
|
123
|
-
else
|
124
|
-
{}
|
125
|
-
end
|
78
|
+
def get_exported_properties(role_name, job_name)
|
79
|
+
# Containers are not starting until all the properties they want to import already exist.
|
80
|
+
# This is done using the CONFIGGIN_IMPORT_ROLE environment variables referencing the version
|
81
|
+
# tag in the corresponding secret.
|
82
|
+
secret = client.get_secret(role_name, namespace)
|
83
|
+
JSON.parse(Base64.decode64(secret.data["skiff-exported-properties-#{job_name}"]))
|
126
84
|
end
|
127
85
|
|
128
86
|
def get_pod_instance_info(role_name, pod, job, pods_per_image)
|
@@ -134,7 +92,7 @@ class KubeLinkSpecs
|
|
134
92
|
'id' => pod.metadata.name,
|
135
93
|
'az' => pod.metadata.annotations['failure-domain.beta.kubernetes.io/zone'] || 'az0',
|
136
94
|
'address' => "#{pod.metadata.name}.#{pod.spec.subdomain}.#{ENV['KUBERNETES_NAMESPACE']}.svc.#{ENV['KUBERNETES_CLUSTER_DOMAIN']}",
|
137
|
-
'properties' => get_exported_properties(role_name,
|
95
|
+
'properties' => get_exported_properties(role_name, job),
|
138
96
|
'bootstrap' => pods_per_image[pod.metadata.uid] < 2
|
139
97
|
}
|
140
98
|
end
|
@@ -164,9 +122,10 @@ class KubeLinkSpecs
|
|
164
122
|
'name' => svc.metadata.name,
|
165
123
|
'index' => 0, # Completely made up index; there is only ever one service
|
166
124
|
'id' => svc.metadata.name,
|
125
|
+
# XXX bogus, but what can we do?
|
167
126
|
'az' => pod.metadata.annotations['failure-domain.beta.kubernetes.io/zone'] || 'az0',
|
168
127
|
'address' => svc.spec.clusterIP,
|
169
|
-
'properties' => get_exported_properties(role_name,
|
128
|
+
'properties' => get_exported_properties(role_name, job),
|
170
129
|
'bootstrap' => true
|
171
130
|
}
|
172
131
|
end
|
@@ -182,7 +141,8 @@ class KubeLinkSpecs
|
|
182
141
|
'id' => ss.metadata.name,
|
183
142
|
'az' => pod.metadata.annotations['failure-domain.beta.kubernetes.io/zone'] || 'az0',
|
184
143
|
'address' => "#{ss.metadata.name}-#{i}.#{ss.spec.serviceName}",
|
185
|
-
'properties' => get_exported_properties(role_name,
|
144
|
+
'properties' => get_exported_properties(role_name, job),
|
145
|
+
# XXX not actually correct during updates
|
186
146
|
'bootstrap' => i.zero?
|
187
147
|
}
|
188
148
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: configgin
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.19.
|
4
|
+
version: 0.19.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SUSE
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|