Class: Siren::Compose::Service

Inherits:
Struct
  • Object
show all
Defined in:
lib/siren/compose/service.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(compose, data = {}) ⇒ Service

Returns a new instance of Service.



12
13
14
15
16
17
18
19
20
21
# File 'lib/siren/compose/service.rb', line 12

def initialize (compose, data = {})
  self.compose = compose
  data.each do |key, value|
    self.__send__("#{key}=", value)
  end
  self.deploy = deploy ? Deploy.new(deploy) : Deploy.new
  self.ports ||= []
  self.volumes ||= []
  self.name = namify(self.name)
end

Instance Attribute Details

#buildObject

Returns the value of attribute build

Returns:

  • (Object)

    the current value of build



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def build
  @build
end

#commandObject

Returns the value of attribute command

Returns:

  • (Object)

    the current value of command



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def command
  @command
end

#composeObject

Returns the value of attribute compose

Returns:

  • (Object)

    the current value of compose



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def compose
  @compose
end

#configsObject

Returns the value of attribute configs

Returns:

  • (Object)

    the current value of configs



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def configs
  @configs
end

#container_nameObject

Returns the value of attribute container_name

Returns:

  • (Object)

    the current value of container_name



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def container_name
  @container_name
end

#credential_specObject

Returns the value of attribute credential_spec

Returns:

  • (Object)

    the current value of credential_spec



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def credential_spec
  @credential_spec
end

#deployObject

Returns the value of attribute deploy

Returns:

  • (Object)

    the current value of deploy



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def deploy
  @deploy
end

#dnsObject

Returns the value of attribute dns

Returns:

  • (Object)

    the current value of dns



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def dns
  @dns
end

#dns_searchObject

Returns the value of attribute dns_search

Returns:

  • (Object)

    the current value of dns_search



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def dns_search
  @dns_search
end

#domainnameObject

Returns the value of attribute domainname

Returns:

  • (Object)

    the current value of domainname



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def domainname
  @domainname
end

#entrypointObject

Returns the value of attribute entrypoint

Returns:

  • (Object)

    the current value of entrypoint



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def entrypoint
  @entrypoint
end

#environmentObject

Returns the value of attribute environment

Returns:

  • (Object)

    the current value of environment



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def environment
  @environment
end

#exposeObject

Returns the value of attribute expose

Returns:

  • (Object)

    the current value of expose



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def expose
  @expose
end

#extra_hostsObject

Returns the value of attribute extra_hosts

Returns:

  • (Object)

    the current value of extra_hosts



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def extra_hosts
  @extra_hosts
end

#healthcheckObject

Returns the value of attribute healthcheck

Returns:

  • (Object)

    the current value of healthcheck



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def healthcheck
  @healthcheck
end

#hostnameObject

Returns the value of attribute hostname

Returns:

  • (Object)

    the current value of hostname



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def hostname
  @hostname
end

#imageObject

Returns the value of attribute image

Returns:

  • (Object)

    the current value of image



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def image
  @image
end

#initObject

Returns the value of attribute init

Returns:

  • (Object)

    the current value of init



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def init
  @init
end

#ipcObject

Returns the value of attribute ipc

Returns:

  • (Object)

    the current value of ipc



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def ipc
  @ipc
end

#labelsObject

Returns the value of attribute labels

Returns:

  • (Object)

    the current value of labels



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def labels
  @labels
end

#loggingObject

Returns the value of attribute logging

Returns:

  • (Object)

    the current value of logging



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def logging
  @logging
end

#mac_addressObject

Returns the value of attribute mac_address

Returns:

  • (Object)

    the current value of mac_address



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def mac_address
  @mac_address
end

#nameObject

Returns the value of attribute name

Returns:

  • (Object)

    the current value of name



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def name
  @name
end

#networksObject

Returns the value of attribute networks

Returns:

  • (Object)

    the current value of networks



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def networks
  @networks
end

#pidObject

Returns the value of attribute pid

Returns:

  • (Object)

    the current value of pid



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def pid
  @pid
end

#portsObject

Returns the value of attribute ports

Returns:

  • (Object)

    the current value of ports



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def ports
  @ports
end

#privilegedObject

Returns the value of attribute privileged

Returns:

  • (Object)

    the current value of privileged



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def privileged
  @privileged
end

#read_onlyObject

Returns the value of attribute read_only

Returns:

  • (Object)

    the current value of read_only



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def read_only
  @read_only
end

#secretsObject

Returns the value of attribute secrets

Returns:

  • (Object)

    the current value of secrets



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def secrets
  @secrets
end

#shm_sizeObject

Returns the value of attribute shm_size

Returns:

  • (Object)

    the current value of shm_size



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def shm_size
  @shm_size
end

#stdin_openObject

Returns the value of attribute stdin_open

Returns:

  • (Object)

    the current value of stdin_open



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def stdin_open
  @stdin_open
end

#stop_grace_periodObject

Returns the value of attribute stop_grace_period

Returns:

  • (Object)

    the current value of stop_grace_period



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def stop_grace_period
  @stop_grace_period
end

#stop_signalObject

Returns the value of attribute stop_signal

Returns:

  • (Object)

    the current value of stop_signal



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def stop_signal
  @stop_signal
end

#sysctlsObject

Returns the value of attribute sysctls

Returns:

  • (Object)

    the current value of sysctls



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def sysctls
  @sysctls
end

#ttyObject

Returns the value of attribute tty

Returns:

  • (Object)

    the current value of tty



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def tty
  @tty
end

#ulimitsObject

Returns the value of attribute ulimits

Returns:

  • (Object)

    the current value of ulimits



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def ulimits
  @ulimits
end

#userObject

Returns the value of attribute user

Returns:

  • (Object)

    the current value of user



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def user
  @user
end

#volumesObject

Returns the value of attribute volumes

Returns:

  • (Object)

    the current value of volumes



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def volumes
  @volumes
end

#working_dirObject

Returns the value of attribute working_dir

Returns:

  • (Object)

    the current value of working_dir



7
8
9
# File 'lib/siren/compose/service.rb', line 7

def working_dir
  @working_dir
end

Instance Method Details

#emit_auth_middleware(stack) ⇒ Object



168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/siren/compose/service.rb', line 168

def emit_auth_middleware (stack)
  return if @did_emit_auth_middleware
  did_emit_auth_middleware = true
  stack << {
    kind: "Middleware",
    apiVersion: "traefik.containo.us/v1alpha1",
    metadata: {
      namespace: compose.name,
      name: "altaire-auth",
    },
    spec: {
      forwardAuth: {
        address: "http://auth-server.default.svc.cluster.local/auth",
      },
    },
  }
end

#emit_certificates(stack) ⇒ Object



261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/siren/compose/service.rb', line 261

def emit_certificates (stack)
  compose.xdomains.each do |xd|
    stack << {
      kind: "Certificate",
      apiVersion: "cert-manager.io/v1alpha2",
      metadata: {
        namespace: compose.name,
        name: namify(xd["name"]),
      },
      spec: {
        commonName: xd["name"],
        dnsNames: [xd["name"]],
        duration: "2160h0m0s",
        renewBefore: "360h0m0s",
        issuerRef: {
          kind: "ClusterIssuer",
          name: "letsencrypt-production",
        },
        secretName: namify(xd["name"]),
      },
    }
  end
end

#emit_deployment(stack) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/siren/compose/service.rb', line 90

def emit_deployment (stack)
  stack << {
    kind: "Deployment",
    apiVersion: "apps/v1",
    metadata: {
      namespace: compose.name,
      name: name,
    },
    spec: {
      replicas: deploy.replicas,
      selector: {
        matchLabels: {
          stack: compose.name,
          service: name,
        },
      },
      template: {
        metadata: {
          labels: {
            stack: compose.name,
            service: name,
          },
        },
        spec: {
          containers: [
            command: command,
            env: resolve_environment(environment),
            image: image,
            name: name,
            volumeMounts: volumes.map do |volume|
              name, path = volume.split(":", 2)
              {
                mountPath: path,
                name: name,
              }
            end
          ],
          hostname: hostname,
          imagePullSecrets: [{name: "image-pull-secrets"}],
          restartPolicy: { "none" => "Never", "on-failure" => "OnFailure" }[deploy.restart_policy&.condition],
          volumes: volumes.map do |volume|
            name = volume.split(":")[0]
            { name: name, persistentVolumeClaim: { claimName: name } }
          end
        },
      },
    },
  }
end

#emit_domains(stack) ⇒ Object



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
# File 'lib/siren/compose/service.rb', line 244

def emit_domains (stack)
  compose.xdomains.each do |xd|
    stack << {
      kind: "Domain",
      apiVersion: "altaire.com/v1alpha1",
      metadata: {
        namespace: compose.name,
        name: namify(xd["name"]),
      },
      spec: {
        domain: xd["name"],
        service: "traefik",
      },
    }
  end
end

#emit_ingress_routes(stack) ⇒ Object



206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/siren/compose/service.rb', line 206

def emit_ingress_routes (stack)
  compose.xdomains.each do |xd|
    next unless xd["service"] == name
    emit_auth_middleware stack if xd["auth"]
    stack << {
      kind: "IngressRoute",
      apiVersion: "traefik.containo.us/v1alpha1",
      metadata: {
        namespace: compose.name,
        name: namify(xd["name"], xd["path"]),
      },
      spec: {
        tls: {
          secretName: namify(xd["name"]),
        },
        routes: [{
          kind: "Rule",
          match: nil,
          middlewares: [
            xd["auth"] ? { name: "altaire-auth" } : nil,
            xd["path"] ? { name: namify(xd["name"], xd["path"], "strip-prefix") } : nil,
          ],
          services: [{
            name: name,
            port: 80
          }],
        }.merge(
          if xd["path"]
            {match: "Host(`#{xd["name"]}`) && PathPrefix(`#{xd["path"]}`)"}
          else
            {match: "Host(`#{xd["name"]}`)"}
          end
        )],
      },
    }
  end
end

#emit_middlewares(stack) ⇒ Object



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/siren/compose/service.rb', line 186

def emit_middlewares (stack)
  compose.xdomains.each do |xd|
    next unless xd["service"] == name
    next if xd["path"] == nil
    stack << {
      kind: "Middleware",
      apiVersion: "traefik.containo.us/v1alpha1",
      metadata: {
        namespace: compose.name,
        name: namify(xd["name"], xd["path"], "strip-prefix"),
      },
      spec: {
        stripPrefix: {
          prefixes: ["/#{xd["path"]}"],
        },
      },
    }
  end
end

#emit_services(stack) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/siren/compose/service.rb', line 140

def emit_services (stack)
  ports.group_by{|port|port["mode"]}.each do |mode, ports|
    stack << {
      kind: "Service",
      apiVersion: "v1",
      metadata: {
        namespace: compose.name,
        name: mode == "ingress" ? "#{name}-nodeport" : name,
      },
      spec: {
        ports: ports.map do |port|
          {
            name: ports.length == 1 ? nil : port["published"],
            port: port["published"].to_i,
            targetPort: port["target"] != port["published"] ? port["target"].to_i : nil,
            protocol: port["protocol"] == "udp" ? "UDP" : nil
          }
        end,
        selector: {
          stack: compose.name,
          service: name,
        },
        type: mode == "ingress" ? "NodePort" : nil,
      }
    }
  end
end

#emit_volumes(stack) ⇒ Object



285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/siren/compose/service.rb', line 285

def emit_volumes (stack)
  volumes.each do |volume|
    name, path = volume.split(":", 2)
    stack << {
      kind: "PersistentVolumeClaim",
      apiVersion: "v1",
      metadata: {
        namespace: compose.name,
        name: name,
      },
      spec: {
        accessModes: ["ReadWriteOnce"],
        resources: {
          requests: {
            storage: "1Gi",
          },
        },
        storageClassName: "do-block-storage",
      },
    }
  end
end

#namify(*items) ⇒ Object



86
87
88
# File 'lib/siren/compose/service.rb', line 86

def namify (*items)
  items.flatten.compact.join("-").downcase.gsub(/[^a-z\d]/, '-').gsub(/-+/, "-")
end

#resolve_environment(env) ⇒ Object



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/siren/compose/service.rb', line 65

def resolve_environment (env)
  if env.is_a?(Array)
    env = env.map do |line|
      key, value = line.split("=", 2)
      [key, value || "$#{key}"]
    end.to_h
  end
  env ||= {}
  env.transform_values! do |value|
    value.gsub(/\$[\dA-Z_a-z]+/) do |name|
      compose.xenv[name[1..-1]]
    end
  end
  env.map do |name, value|
    {
      name: name,
      value: value,
    }
  end
end

#to_stack(stack) ⇒ Object



308
309
310
311
312
313
314
315
316
# File 'lib/siren/compose/service.rb', line 308

def to_stack (stack)
  emit_deployment stack
  emit_services stack
  emit_middlewares stack
  emit_ingress_routes stack
  emit_domains stack
  emit_certificates stack
  emit_volumes stack
end