odysseus-core 0.3.2 → 0.9.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 +4 -4
- data/CHANGELOG.md +485 -1
- data/LICENSE.txt +25 -7
- data/README.md +12 -3
- data/lib/odysseus/builder/client.rb +15 -15
- data/lib/odysseus/caddy/client.rb +119 -42
- data/lib/odysseus/command_redaction.rb +38 -0
- data/lib/odysseus/config/parser.rb +43 -18
- data/lib/odysseus/core/deploy_versioning.rb +42 -0
- data/lib/odysseus/core/environment.rb +63 -0
- data/lib/odysseus/core/version.rb +1 -1
- data/lib/odysseus/core/volume_namespacer.rb +0 -0
- data/lib/odysseus/core.rb +2 -2
- data/lib/odysseus/deploy_log.rb +120 -0
- data/lib/odysseus/deploy_version.rb +9 -0
- data/lib/odysseus/deployer/dependency_manager.rb +121 -0
- data/lib/odysseus/deployer/executor.rb +213 -161
- data/lib/odysseus/deployer/retention_sweeper.rb +94 -0
- data/lib/odysseus/deployer/ssh.rb +92 -18
- data/lib/odysseus/docker/client.rb +240 -48
- data/lib/odysseus/docker/labels.rb +43 -0
- data/lib/odysseus/errors.rb +10 -0
- data/lib/odysseus/git.rb +70 -0
- data/lib/odysseus/host_paths.rb +79 -0
- data/lib/odysseus/host_providers/base.rb +1 -1
- data/lib/odysseus/host_providers/static.rb +1 -1
- data/lib/odysseus/host_providers.rb +3 -4
- data/lib/odysseus/host_verifier.rb +156 -0
- data/lib/odysseus/host_versions.rb +59 -0
- data/lib/odysseus/orchestrator/{accessory_deploy.rb → dependency_deploy.rb} +84 -88
- data/lib/odysseus/orchestrator/job_deploy.rb +31 -43
- data/lib/odysseus/orchestrator/web_deploy.rb +61 -55
- data/lib/odysseus/plugins.rb +72 -0
- data/lib/odysseus/retention_plan.rb +14 -0
- data/lib/odysseus/retention_planner.rb +58 -0
- data/lib/odysseus/rollback_plan.rb +20 -0
- data/lib/odysseus/rollback_planner.rb +107 -0
- data/lib/odysseus/sails.rb +0 -0
- data/lib/odysseus/secrets/encrypted_file.rb +5 -7
- data/lib/odysseus/secrets/loader.rb +1 -3
- data/lib/odysseus/setup/docker_apt.rb +178 -0
- data/lib/odysseus/setup/escalation.rb +73 -0
- data/lib/odysseus/setup/preparer.rb +372 -0
- data/lib/odysseus/setup/public_key.rb +127 -0
- data/lib/odysseus/validators/config.rb +38 -25
- data/lib/odysseus/version_resolver.rb +80 -0
- data/lib/odysseus.rb +0 -0
- data/sig/odysseus/core.rbs +0 -0
- metadata +48 -27
- data/Rakefile +0 -12
- data/lib/odysseus/version.rb +0 -5
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# lib/odysseus/setup/public_key.rb
|
|
2
|
+
|
|
3
|
+
require 'open3'
|
|
4
|
+
|
|
5
|
+
module Odysseus
|
|
6
|
+
module Setup
|
|
7
|
+
# The public keys `odysseus setup` installs for the user it creates,
|
|
8
|
+
# resolved entirely on THIS machine before the host is touched.
|
|
9
|
+
#
|
|
10
|
+
# Getting this wrong produces the worst outcome the command has: a created
|
|
11
|
+
# user nobody can log in as. So it runs first, and it raises rather than
|
|
12
|
+
# returning an empty list — there is no sensible way to continue.
|
|
13
|
+
module PublicKey
|
|
14
|
+
# A recognised SSH public-key line: key type, whitespace, base64 body,
|
|
15
|
+
# optional comment (which may itself contain spaces). Anything that
|
|
16
|
+
# doesn't match -- a private key's PEM body, a mangled file, plain
|
|
17
|
+
# garbage -- must never survive to become an authorized_keys entry on a
|
|
18
|
+
# real host.
|
|
19
|
+
LINE_PATTERN = %r{
|
|
20
|
+
\A
|
|
21
|
+
(?: ssh-rsa | ssh-dss | ssh-ed25519
|
|
22
|
+
| ecdsa-sha2-\S+
|
|
23
|
+
| sk-ecdsa-sha2-\S+@openssh\.com
|
|
24
|
+
| sk-ssh-ed25519@openssh\.com )
|
|
25
|
+
[ \t]+
|
|
26
|
+
[A-Za-z0-9+/]+=*
|
|
27
|
+
(?: [ \t]+ \S .* )?
|
|
28
|
+
\z
|
|
29
|
+
}x
|
|
30
|
+
|
|
31
|
+
# @param keys [Array<String>] ssh.keys entries (private key paths)
|
|
32
|
+
# @param explicit [Array<String>] paths given with --key, which win
|
|
33
|
+
# @return [Array<String>] authorized_keys lines, newline-free
|
|
34
|
+
# @raise [Odysseus::SetupError] when nothing can be resolved
|
|
35
|
+
def self.resolve(keys:, explicit: [])
|
|
36
|
+
looked_at = []
|
|
37
|
+
from_explicit = explicit.any?
|
|
38
|
+
|
|
39
|
+
lines = (from_explicit ? explicit : Array(keys)).flat_map do |path|
|
|
40
|
+
expanded = File.expand_path(path)
|
|
41
|
+
looked_at << expanded
|
|
42
|
+
found = from_path(expanded, explicit: from_explicit)
|
|
43
|
+
|
|
44
|
+
# A --key path the operator named is not optional. Falling back to
|
|
45
|
+
# another one, or to ssh.keys, would install a different key than
|
|
46
|
+
# the one they asked for -- worse than refusing, because they would
|
|
47
|
+
# believe the named key was authorised when it was not.
|
|
48
|
+
if from_explicit && found.empty?
|
|
49
|
+
raise Odysseus::SetupError,
|
|
50
|
+
"#{expanded} does not contain a valid SSH public key. --key must point " \
|
|
51
|
+
'at a public key (usually the file ending in .pub), not a private key.'
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
found
|
|
55
|
+
end.uniq
|
|
56
|
+
|
|
57
|
+
return lines if lines.any?
|
|
58
|
+
|
|
59
|
+
raise Odysseus::SetupError,
|
|
60
|
+
'Found no public key to install, so the user would be created with no way ' \
|
|
61
|
+
"to log in. Looked at: #{looked_at.join(', ')}. Pass --key with a path to a " \
|
|
62
|
+
'public key, or check ssh.keys in deploy.yml.'
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# An explicit --key path must be a public key itself; an ssh.keys entry
|
|
66
|
+
# is a private key whose public half is read from its .pub sibling.
|
|
67
|
+
#
|
|
68
|
+
# A sibling with nothing written in it -- missing, empty, or
|
|
69
|
+
# whitespace-only -- is silently derived from the private key: nothing
|
|
70
|
+
# was expressed there, so deriving is helpful, not presumptuous. A
|
|
71
|
+
# sibling that has content but none of it validates (for example a
|
|
72
|
+
# restricted `command="..."` line, which LINE_PATTERN deliberately does
|
|
73
|
+
# not accept -- see its comment) is refused rather than derived around:
|
|
74
|
+
# silently substituting a different, less restricted key is the same
|
|
75
|
+
# "operator believes X is installed, Y is installed instead" failure
|
|
76
|
+
# the explicit --key raise below exists to prevent, just reached by the
|
|
77
|
+
# implicit path instead.
|
|
78
|
+
def self.from_path(path, explicit:)
|
|
79
|
+
return valid_lines(path) if explicit
|
|
80
|
+
|
|
81
|
+
sibling = "#{path}.pub"
|
|
82
|
+
sibling_lines = valid_lines(sibling)
|
|
83
|
+
return sibling_lines if sibling_lines.any?
|
|
84
|
+
return derive(path) unless content?(sibling)
|
|
85
|
+
|
|
86
|
+
raise Odysseus::SetupError,
|
|
87
|
+
"#{sibling} exists but has no valid, unrestricted public key in it, so " \
|
|
88
|
+
'odysseus will not silently derive a different key in its place. Fix the ' \
|
|
89
|
+
'file, remove it so the key is derived from the private key instead, or ' \
|
|
90
|
+
'pass --key with the key to install.'
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# @return [Array<String>] the valid public-key lines in the file, in
|
|
94
|
+
# order; blank or invalid lines are dropped rather than passed through
|
|
95
|
+
def self.valid_lines(path)
|
|
96
|
+
return [] unless File.file?(path)
|
|
97
|
+
|
|
98
|
+
File.readlines(path).filter_map do |raw|
|
|
99
|
+
line = raw.strip
|
|
100
|
+
line if !line.empty? && LINE_PATTERN.match?(line)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# @return [Boolean] whether the file exists and has more than
|
|
105
|
+
# whitespace in it -- distinguishes "nothing was expressed here" from
|
|
106
|
+
# "something was expressed here, and it didn't validate"
|
|
107
|
+
def self.content?(path)
|
|
108
|
+
File.file?(path) && !File.read(path).strip.empty?
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# `ssh-keygen -y` prints the public half of a private key. It fails
|
|
112
|
+
# loudly on an encrypted key, which is the right outcome: odysseus cannot
|
|
113
|
+
# answer a passphrase prompt any more than it can answer sudo's.
|
|
114
|
+
def self.derive(private_key_path)
|
|
115
|
+
return [] unless File.file?(private_key_path)
|
|
116
|
+
|
|
117
|
+
out, _err, status = Open3.capture3('ssh-keygen', '-y', '-f', private_key_path)
|
|
118
|
+
return [] unless status.success?
|
|
119
|
+
|
|
120
|
+
line = out.strip
|
|
121
|
+
LINE_PATTERN.match?(line) ? [line] : []
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
private_class_method :from_path, :valid_lines, :content?, :derive
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
module Odysseus
|
|
4
4
|
module Validators
|
|
5
5
|
class Config
|
|
6
|
-
REQUIRED_KEYS = [
|
|
6
|
+
REQUIRED_KEYS = %w[service image servers].freeze
|
|
7
7
|
|
|
8
8
|
def initialize(config)
|
|
9
9
|
@config = config
|
|
@@ -17,6 +17,7 @@ module Odysseus
|
|
|
17
17
|
validate_proxy! if @config['proxy']
|
|
18
18
|
validate_env! if @config['env']
|
|
19
19
|
validate_ssh! if @config['ssh']
|
|
20
|
+
validate_retain_versions! if @config.key?('retain_versions')
|
|
20
21
|
end
|
|
21
22
|
|
|
22
23
|
private
|
|
@@ -31,13 +32,16 @@ module Odysseus
|
|
|
31
32
|
|
|
32
33
|
def validate_servers!
|
|
33
34
|
servers = @config['servers']
|
|
34
|
-
|
|
35
|
-
|
|
35
|
+
unless servers.is_a?(Hash)
|
|
36
|
+
raise Odysseus::ConfigValidationError,
|
|
37
|
+
'servers must be a hash'
|
|
38
|
+
end
|
|
36
39
|
|
|
37
40
|
servers.each do |role, config|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
unless config.is_a?(Hash) && config['hosts'].is_a?(Array)
|
|
42
|
+
raise Odysseus::ConfigValidationError,
|
|
43
|
+
"server role '#{role}' must have 'hosts' array"
|
|
44
|
+
end
|
|
41
45
|
|
|
42
46
|
validate_containers!(role, config['containers']) if config['containers']
|
|
43
47
|
validate_deploy!(role, config['deploy']) if config['deploy']
|
|
@@ -48,37 +52,35 @@ module Odysseus
|
|
|
48
52
|
proxy = @config['proxy']
|
|
49
53
|
return if proxy.nil?
|
|
50
54
|
|
|
55
|
+
return if proxy['app_port']
|
|
56
|
+
|
|
51
57
|
raise Odysseus::ConfigValidationError,
|
|
52
|
-
"proxy must have 'app_port'"
|
|
58
|
+
"proxy must have 'app_port'"
|
|
53
59
|
end
|
|
54
60
|
|
|
55
61
|
def validate_env!
|
|
56
62
|
env = @config['env']
|
|
57
63
|
return if env.nil?
|
|
58
64
|
|
|
59
|
-
unless env.is_a?(Hash)
|
|
60
|
-
raise Odysseus::ConfigValidationError, "env must be a hash"
|
|
61
|
-
end
|
|
65
|
+
raise Odysseus::ConfigValidationError, 'env must be a hash' unless env.is_a?(Hash)
|
|
62
66
|
|
|
63
67
|
clear = env['clear']
|
|
64
|
-
unless clear.nil? || clear.is_a?(Hash)
|
|
65
|
-
raise Odysseus::ConfigValidationError, "env.clear must be a hash"
|
|
66
|
-
end
|
|
68
|
+
raise Odysseus::ConfigValidationError, 'env.clear must be a hash' unless clear.nil? || clear.is_a?(Hash)
|
|
67
69
|
|
|
68
70
|
secret = env['secret']
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
71
|
+
return if secret.nil? || secret.is_a?(Array)
|
|
72
|
+
|
|
73
|
+
raise Odysseus::ConfigValidationError, 'env.secret must be an array'
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
def validate_containers!(role, containers)
|
|
75
77
|
return unless containers.is_a?(Hash)
|
|
76
78
|
|
|
77
79
|
count = containers['count']
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
return unless count && (!count.is_a?(Integer) || count < 1)
|
|
81
|
+
|
|
82
|
+
raise Odysseus::ConfigValidationError,
|
|
83
|
+
"servers.#{role}.containers.count must be an integer >= 1"
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
def validate_deploy!(role, deploy)
|
|
@@ -94,7 +96,7 @@ module Odysseus
|
|
|
94
96
|
val = deploy[key]
|
|
95
97
|
next unless val
|
|
96
98
|
|
|
97
|
-
unless val.is_a?(Integer) && val
|
|
99
|
+
unless val.is_a?(Integer) && val.positive?
|
|
98
100
|
raise Odysseus::ConfigValidationError,
|
|
99
101
|
"servers.#{role}.deploy.#{key} must be a positive integer"
|
|
100
102
|
end
|
|
@@ -105,13 +107,24 @@ module Odysseus
|
|
|
105
107
|
ssh = @config['ssh']
|
|
106
108
|
return if ssh.nil?
|
|
107
109
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
+
unless ssh.is_a?(Hash)
|
|
111
|
+
raise Odysseus::ConfigValidationError,
|
|
112
|
+
'ssh must be a hash'
|
|
113
|
+
end
|
|
110
114
|
|
|
111
115
|
keys = ssh['keys']
|
|
116
|
+
return if keys.nil? || keys.is_a?(Array)
|
|
117
|
+
|
|
118
|
+
raise Odysseus::ConfigValidationError,
|
|
119
|
+
'ssh.keys must be an array'
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def validate_retain_versions!
|
|
123
|
+
value = @config['retain_versions']
|
|
124
|
+
return if value.is_a?(Integer) && value >= 1
|
|
125
|
+
|
|
112
126
|
raise Odysseus::ConfigValidationError,
|
|
113
|
-
"
|
|
114
|
-
unless keys.nil? || keys.is_a?(Array)
|
|
127
|
+
"retain_versions must be an integer of 1 or more, got #{value.inspect}"
|
|
115
128
|
end
|
|
116
129
|
end
|
|
117
130
|
end
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# lib/odysseus/version_resolver.rb
|
|
2
|
+
|
|
3
|
+
module Odysseus
|
|
4
|
+
# Turns an optional --image tag plus the state of the work tree into the
|
|
5
|
+
# version a deploy will use. The rules live here rather than in Executor so
|
|
6
|
+
# they can be tested without a config file or an SSH connection.
|
|
7
|
+
class VersionResolver
|
|
8
|
+
SHA_LENGTH = 12
|
|
9
|
+
|
|
10
|
+
# @param config_dir [String] directory holding deploy.yml
|
|
11
|
+
# @param logger [Object, nil] responds to #info and #warn
|
|
12
|
+
def initialize(config_dir:, logger: nil)
|
|
13
|
+
@config_dir = config_dir
|
|
14
|
+
@logger = logger
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# @param image_tag [String, nil] explicit tag; wins over git when given
|
|
18
|
+
# @return [DeployVersion]
|
|
19
|
+
# @raise [Odysseus::ConfigError] when no version can be established
|
|
20
|
+
def resolve(image_tag: nil)
|
|
21
|
+
# ref stays nil here: an arbitrary explicit tag has no commit it honestly
|
|
22
|
+
# identifies, and recording HEAD would assert a link that may not exist.
|
|
23
|
+
# (The no-tag path below refuses on uncommitted changes for exactly this
|
|
24
|
+
# reason — so that when it does record a ref, the tag actually identifies
|
|
25
|
+
# the code.) deployer is available regardless, so there is no such reason
|
|
26
|
+
# to withhold it.
|
|
27
|
+
return DeployVersion.new(version: image_tag, ref: nil, deployer: deployer) if image_tag
|
|
28
|
+
|
|
29
|
+
unless git.repository?
|
|
30
|
+
raise Odysseus::ConfigError,
|
|
31
|
+
"#{@config_dir} is not a git repository, so the version cannot be taken from a " \
|
|
32
|
+
'commit. Pass --image to name the version explicitly.'
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
if git.uncommitted_changes?
|
|
36
|
+
raise Odysseus::ConfigError,
|
|
37
|
+
'The working tree has uncommitted changes, so the image tag would not identify ' \
|
|
38
|
+
'the code being deployed. Commit them, or pass --image to name the version.'
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
sha = git.head_sha(length: SHA_LENGTH)
|
|
42
|
+
|
|
43
|
+
unless sha
|
|
44
|
+
raise Odysseus::ConfigError,
|
|
45
|
+
"#{@config_dir} is a git repository with no commits yet, so there is no version to " \
|
|
46
|
+
'deploy. Commit first, or pass --image to name the version.'
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
warn_about_untracked_files
|
|
50
|
+
|
|
51
|
+
DeployVersion.new(version: sha, ref: git.ref, deployer: deployer)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
# Who is running this command: git's configured email, falling back to the
|
|
55
|
+
# shell user. Works outside a repository — `git config user.email` reads
|
|
56
|
+
# global config — so a rollback can name a deployer even when the version
|
|
57
|
+
# came from a host rather than a commit.
|
|
58
|
+
#
|
|
59
|
+
# @return [String]
|
|
60
|
+
def deployer
|
|
61
|
+
git.committer_email || ENV.fetch('USER', 'unknown')
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
private
|
|
65
|
+
|
|
66
|
+
def git
|
|
67
|
+
@git ||= Odysseus::Git.new(@config_dir)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# The build context includes untracked files unless .dockerignore excludes
|
|
71
|
+
# them, so they can change the image while the tag stays the same. Worth
|
|
72
|
+
# saying out loud; not worth refusing over.
|
|
73
|
+
def warn_about_untracked_files
|
|
74
|
+
return unless git.untracked_files?
|
|
75
|
+
return unless @logger.respond_to?(:warn)
|
|
76
|
+
|
|
77
|
+
@logger.warn('Working tree has untracked files; they may enter the image without changing its tag')
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
data/lib/odysseus.rb
CHANGED
|
File without changes
|
data/sig/odysseus/core.rbs
CHANGED
|
File without changes
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: odysseus-core
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.9.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Thomas
|
|
@@ -10,61 +10,61 @@ cert_chain: []
|
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
|
-
name:
|
|
13
|
+
name: base64
|
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
|
15
15
|
requirements:
|
|
16
|
-
- - "
|
|
16
|
+
- - ">="
|
|
17
17
|
- !ruby/object:Gem::Version
|
|
18
|
-
version: '
|
|
18
|
+
version: '0'
|
|
19
19
|
type: :runtime
|
|
20
20
|
prerelease: false
|
|
21
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
22
22
|
requirements:
|
|
23
|
-
- - "
|
|
23
|
+
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
|
-
version: '
|
|
25
|
+
version: '0'
|
|
26
26
|
- !ruby/object:Gem::Dependency
|
|
27
|
-
name:
|
|
27
|
+
name: logger
|
|
28
28
|
requirement: !ruby/object:Gem::Requirement
|
|
29
29
|
requirements:
|
|
30
|
-
- - "
|
|
30
|
+
- - ">="
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '
|
|
32
|
+
version: '0'
|
|
33
33
|
type: :runtime
|
|
34
34
|
prerelease: false
|
|
35
35
|
version_requirements: !ruby/object:Gem::Requirement
|
|
36
36
|
requirements:
|
|
37
|
-
- - "
|
|
37
|
+
- - ">="
|
|
38
38
|
- !ruby/object:Gem::Version
|
|
39
|
-
version: '
|
|
39
|
+
version: '0'
|
|
40
40
|
- !ruby/object:Gem::Dependency
|
|
41
|
-
name:
|
|
41
|
+
name: net-scp
|
|
42
42
|
requirement: !ruby/object:Gem::Requirement
|
|
43
43
|
requirements:
|
|
44
|
-
- - "
|
|
44
|
+
- - "~>"
|
|
45
45
|
- !ruby/object:Gem::Version
|
|
46
|
-
version: '0'
|
|
46
|
+
version: '4.0'
|
|
47
47
|
type: :runtime
|
|
48
48
|
prerelease: false
|
|
49
49
|
version_requirements: !ruby/object:Gem::Requirement
|
|
50
50
|
requirements:
|
|
51
|
-
- - "
|
|
51
|
+
- - "~>"
|
|
52
52
|
- !ruby/object:Gem::Version
|
|
53
|
-
version: '0'
|
|
53
|
+
version: '4.0'
|
|
54
54
|
- !ruby/object:Gem::Dependency
|
|
55
|
-
name:
|
|
55
|
+
name: net-ssh
|
|
56
56
|
requirement: !ruby/object:Gem::Requirement
|
|
57
57
|
requirements:
|
|
58
|
-
- - "
|
|
58
|
+
- - "~>"
|
|
59
59
|
- !ruby/object:Gem::Version
|
|
60
|
-
version: '
|
|
60
|
+
version: '7.2'
|
|
61
61
|
type: :runtime
|
|
62
62
|
prerelease: false
|
|
63
63
|
version_requirements: !ruby/object:Gem::Requirement
|
|
64
64
|
requirements:
|
|
65
|
-
- - "
|
|
65
|
+
- - "~>"
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
|
-
version: '
|
|
67
|
+
version: '7.2'
|
|
68
68
|
- !ruby/object:Gem::Dependency
|
|
69
69
|
name: zeitwerk
|
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -90,38 +90,59 @@ files:
|
|
|
90
90
|
- CHANGELOG.md
|
|
91
91
|
- LICENSE.txt
|
|
92
92
|
- README.md
|
|
93
|
-
- Rakefile
|
|
94
93
|
- lib/odysseus.rb
|
|
95
94
|
- lib/odysseus/builder/client.rb
|
|
96
95
|
- lib/odysseus/caddy/client.rb
|
|
96
|
+
- lib/odysseus/command_redaction.rb
|
|
97
97
|
- lib/odysseus/config/parser.rb
|
|
98
98
|
- lib/odysseus/core.rb
|
|
99
|
+
- lib/odysseus/core/deploy_versioning.rb
|
|
100
|
+
- lib/odysseus/core/environment.rb
|
|
99
101
|
- lib/odysseus/core/version.rb
|
|
100
102
|
- lib/odysseus/core/volume_namespacer.rb
|
|
103
|
+
- lib/odysseus/deploy_log.rb
|
|
104
|
+
- lib/odysseus/deploy_version.rb
|
|
105
|
+
- lib/odysseus/deployer/dependency_manager.rb
|
|
101
106
|
- lib/odysseus/deployer/executor.rb
|
|
107
|
+
- lib/odysseus/deployer/retention_sweeper.rb
|
|
102
108
|
- lib/odysseus/deployer/ssh.rb
|
|
103
109
|
- lib/odysseus/docker/client.rb
|
|
110
|
+
- lib/odysseus/docker/labels.rb
|
|
104
111
|
- lib/odysseus/errors.rb
|
|
112
|
+
- lib/odysseus/git.rb
|
|
113
|
+
- lib/odysseus/host_paths.rb
|
|
105
114
|
- lib/odysseus/host_providers.rb
|
|
106
115
|
- lib/odysseus/host_providers/base.rb
|
|
107
116
|
- lib/odysseus/host_providers/static.rb
|
|
108
|
-
- lib/odysseus/
|
|
117
|
+
- lib/odysseus/host_verifier.rb
|
|
118
|
+
- lib/odysseus/host_versions.rb
|
|
119
|
+
- lib/odysseus/orchestrator/dependency_deploy.rb
|
|
109
120
|
- lib/odysseus/orchestrator/job_deploy.rb
|
|
110
121
|
- lib/odysseus/orchestrator/web_deploy.rb
|
|
122
|
+
- lib/odysseus/plugins.rb
|
|
123
|
+
- lib/odysseus/retention_plan.rb
|
|
124
|
+
- lib/odysseus/retention_planner.rb
|
|
125
|
+
- lib/odysseus/rollback_plan.rb
|
|
126
|
+
- lib/odysseus/rollback_planner.rb
|
|
111
127
|
- lib/odysseus/sails.rb
|
|
112
128
|
- lib/odysseus/secrets/encrypted_file.rb
|
|
113
129
|
- lib/odysseus/secrets/loader.rb
|
|
130
|
+
- lib/odysseus/setup/docker_apt.rb
|
|
131
|
+
- lib/odysseus/setup/escalation.rb
|
|
132
|
+
- lib/odysseus/setup/preparer.rb
|
|
133
|
+
- lib/odysseus/setup/public_key.rb
|
|
114
134
|
- lib/odysseus/validators/config.rb
|
|
115
|
-
- lib/odysseus/
|
|
135
|
+
- lib/odysseus/version_resolver.rb
|
|
116
136
|
- sig/odysseus/core.rbs
|
|
117
137
|
homepage: https://github.com/WA-Systems-EU/odysseus
|
|
118
138
|
licenses:
|
|
119
|
-
-
|
|
139
|
+
- MIT
|
|
120
140
|
metadata:
|
|
121
141
|
allowed_push_host: https://rubygems.org
|
|
122
142
|
homepage_uri: https://github.com/WA-Systems-EU/odysseus
|
|
123
143
|
source_code_uri: https://github.com/WA-Systems-EU/odysseus
|
|
124
|
-
changelog_uri: https://github.com/WA-Systems-EU/odysseus/blob/trunk/CHANGELOG.md
|
|
144
|
+
changelog_uri: https://github.com/WA-Systems-EU/odysseus/blob/trunk/odysseus-core/CHANGELOG.md
|
|
145
|
+
rubygems_mfa_required: 'true'
|
|
125
146
|
rdoc_options: []
|
|
126
147
|
require_paths:
|
|
127
148
|
- lib
|
|
@@ -136,7 +157,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
136
157
|
- !ruby/object:Gem::Version
|
|
137
158
|
version: '0'
|
|
138
159
|
requirements: []
|
|
139
|
-
rubygems_version:
|
|
160
|
+
rubygems_version: 4.0.16
|
|
140
161
|
specification_version: 4
|
|
141
162
|
summary: Core library for Odysseus deployment tool
|
|
142
163
|
test_files: []
|
data/Rakefile
DELETED