triton-ops 0.18.4.pre
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 +7 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.org +40 -0
- data/bin/triton-ops-collect +76 -0
- data/bin/triton-ops-report +93 -0
- data/lib/triton-ops/resource/image.rb +195 -0
- data/lib/triton-ops/resource/platform.rb +81 -0
- data/lib/triton-ops/resource/server.rb +188 -0
- data/lib/triton-ops/resource/user.rb +206 -0
- data/lib/triton-ops/resource/virtual_machine.rb +298 -0
- data/lib/triton-ops/resource/virtual_machine/disk.rb +123 -0
- data/lib/triton-ops/resource/virtual_machine/network_interface.rb +119 -0
- data/lib/triton-ops/resource/vm.rb +14 -0
- data/lib/triton-ops/resources.rb +11 -0
- data/lib/triton-ops/snapshot.rb +56 -0
- data/lib/triton-ops/snapshot/catalog.rb +42 -0
- data/lib/triton-ops/snapshot/collector.rb +96 -0
- data/lib/triton-ops/snapshot/explorer.rb +70 -0
- data/lib/triton-ops/snapshot/reporter.rb +99 -0
- data/lib/triton-ops/snapshots.rb +8 -0
- data/lib/triton-ops/support/feature/comparable_as_hash.rb +14 -0
- data/lib/triton-ops/support/feature/hash_from_initialization_contract.rb +25 -0
- data/lib/triton-ops/support/type_coercion.rb +70 -0
- data/lib/triton-ops/support/types.rb +20 -0
- data/tests/exercise +70 -0
- data/tests/run +70 -0
- data/triton-ops.gemspec +21 -0
- metadata +192 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 23ccae6a1a3b477925806a3cf9d86a1154990c67fff3b1b9aaec9b9b3cd9a9f2
|
4
|
+
data.tar.gz: b4a5d9451580ebecb5e410a347e53e763844f35e1a9bc60bfeedca4faf5f95c6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 88b343686ee3114d4c8738df04fe268de7e069195d06b0ce5228dcf96577d1333293fed49d057d1879b9190b69451fe0d8e5ded0ddb1d34641755e6b272883c5
|
7
|
+
data.tar.gz: 07df2db88ef327805083f2b02001a5b1db70454b9a76e851b5f1c0360e4494685609c87b5d07ef8eca5f6c4c34e0f91ebecf44b1d9467284b85ce6463f314748
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
|
2
|
+
The MIT License (MIT)
|
3
|
+
Copyright © 2018 Chris Olstrom <chris@olstrom.com>
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the “Software”), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.org
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#+TITLE: Triton-Ops - A Ruby Interface for Triton Operators
|
2
|
+
#+LATEX: \pagebreak
|
3
|
+
|
4
|
+
* Overview
|
5
|
+
|
6
|
+
~triton-ops~ provides Contract-based models for working with the parts of
|
7
|
+
Triton that aren't exposed through the Cloud API. Specifically, it consumes
|
8
|
+
JSON produced by tools on a Triton Headnode over SSH, records a snapshot of
|
9
|
+
that data, and provides a predictable set of Objects to explore those
|
10
|
+
snapshots.
|
11
|
+
|
12
|
+
* Requirements
|
13
|
+
|
14
|
+
- SSH Access to a Triton Headnode
|
15
|
+
- A local Redis to record snapshots.
|
16
|
+
|
17
|
+
* Usage
|
18
|
+
|
19
|
+
~triton-ops~ includes two utilities to get you started. For more detailed
|
20
|
+
usage, invoke them with =--help=.
|
21
|
+
|
22
|
+
** triton-ops-collect
|
23
|
+
|
24
|
+
This program connects to a headnode over SSH, collects data using standard
|
25
|
+
tools included with Triton, and records this information to Redis.
|
26
|
+
|
27
|
+
** triton-ops-report
|
28
|
+
|
29
|
+
This program generates usage reports from snapshots recorded by
|
30
|
+
~triton-ops-collect~.
|
31
|
+
|
32
|
+
* License
|
33
|
+
|
34
|
+
~triton-ops~ is available under the [[https://tldrlegal.com/license/mit-license][MIT License]]. See ~LICENSE.txt~ for the
|
35
|
+
full text.
|
36
|
+
|
37
|
+
* Contributors
|
38
|
+
|
39
|
+
- [[https://colstrom.github.io/][Chris Olstrom]] | [[mailto:chris@olstrom.com][e-mail]] | [[https://twitter.com/ChrisOlstrom][Twitter]]
|
40
|
+
- Mark Yen
|
@@ -0,0 +1,76 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'json' # Ruby Standard Library
|
5
|
+
require 'optparse' # Ruby Standard Library
|
6
|
+
require 'pry' # MIT License
|
7
|
+
require 'tty-spinner' # MIT License
|
8
|
+
|
9
|
+
require_relative '../lib/triton-ops/snapshot/collector'
|
10
|
+
require_relative '../lib/triton-ops/snapshot/explorer'
|
11
|
+
|
12
|
+
feature = {
|
13
|
+
interactive: ENV.fetch('INTERACTIVE') { STDIN.tty? } != 'false',
|
14
|
+
namespace: ENV.fetch('NAMESPACE') { '' },
|
15
|
+
}
|
16
|
+
|
17
|
+
####################################
|
18
|
+
# Option Handling and Program Help #
|
19
|
+
####################################
|
20
|
+
|
21
|
+
OptionParser.new do |options|
|
22
|
+
program = File.basename $PROGRAM_NAME
|
23
|
+
|
24
|
+
# Interactive and non-interactive usage differ slightly. While the form is
|
25
|
+
# consistent, non-interactive usage *requires* arguments, which could
|
26
|
+
# otherwise be resolved with interactive prompts.
|
27
|
+
banner = {
|
28
|
+
'interactive' => "usage: #{program} [--interactive] [options] [headnode]",
|
29
|
+
'non-interactive' => "usage: #{program} --non-interactive [options] <headnode>",
|
30
|
+
}
|
31
|
+
|
32
|
+
# To emphasize the difference between interactive and non-interactive usage,
|
33
|
+
# the currently *active* mode is presented in bold typeface.
|
34
|
+
options.on('-h', '--help', "Show this help text") do
|
35
|
+
active = feature[:interactive] ? 'interactive' : 'non-interactive'
|
36
|
+
banner[active] = Pastel.new.bold banner[active]
|
37
|
+
options.banner = banner.values.join("\n")
|
38
|
+
|
39
|
+
puts options
|
40
|
+
exit
|
41
|
+
end
|
42
|
+
|
43
|
+
options.on('-i', '--interactive', "Enable interactive prompts (default)") { feature[:interactive] = true }
|
44
|
+
options.on('-n', '--non-interactive', "Disable interactive prompts") { feature[:interactive] = false }
|
45
|
+
options.on('-N', '--namespace NAMESPACE', "Use NAMESPACE for Redis keys") { |o| feature[:namespace] = o }
|
46
|
+
end.parse!
|
47
|
+
|
48
|
+
#####################
|
49
|
+
# Argument Handling #
|
50
|
+
#####################
|
51
|
+
|
52
|
+
begin
|
53
|
+
interactive = ::TritonOps::Snapshot::Explorer.new namespace: feature[:namespace]
|
54
|
+
headnode = ARGV.shift || (interactive.headnode if feature[:interactive])
|
55
|
+
rescue Interrupt, TTY::Reader::InputInterrupt
|
56
|
+
exit Errno::EINTR::Errno
|
57
|
+
end
|
58
|
+
|
59
|
+
exit Errno::EINVAL::Errno if [headnode].any?(&:nil?)
|
60
|
+
|
61
|
+
################
|
62
|
+
# Main Program #
|
63
|
+
################
|
64
|
+
|
65
|
+
collector = TritonOps::Snapshot::Collector.new headnode, namespace: feature[:namespace]
|
66
|
+
|
67
|
+
%w(VMs Users Images Servers Platforms).map do |target|
|
68
|
+
TTY::Spinner.new("[:spinner] Collecting #{target} ...", format: :arrow_pulse).run('done!') do
|
69
|
+
target.downcase!
|
70
|
+
collector.record target, collector.method(target).call
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
puts "#{headnode} #{collector.timestamp.iso8601}"
|
75
|
+
|
76
|
+
binding.pry if ENV.fetch('HACKING', 'false') != 'false'
|
@@ -0,0 +1,93 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'json' # Ruby Standard Library
|
5
|
+
require 'optparse' # Ruby Standard Library
|
6
|
+
require 'pry' # MIT License
|
7
|
+
|
8
|
+
require_relative '../lib/triton-ops/snapshot'
|
9
|
+
require_relative '../lib/triton-ops/snapshot/explorer'
|
10
|
+
require_relative '../lib/triton-ops/snapshot/reporter'
|
11
|
+
|
12
|
+
feature = {
|
13
|
+
exclude: [],
|
14
|
+
format: :unicode,
|
15
|
+
interactive: ENV.fetch('INTERACTIVE') { STDIN.tty? } != 'false',
|
16
|
+
namespace: ENV.fetch('NAMESPACE') { '' },
|
17
|
+
}
|
18
|
+
|
19
|
+
####################################
|
20
|
+
# Option Handling and Program Help #
|
21
|
+
####################################
|
22
|
+
|
23
|
+
OptionParser.new do |options|
|
24
|
+
program = File.basename $PROGRAM_NAME
|
25
|
+
|
26
|
+
# Interactive and non-interactive usage differ slightly. While the form is
|
27
|
+
# consistent, non-interactive usage *requires* arguments, which could
|
28
|
+
# otherwise be resolved with interactive prompts.
|
29
|
+
banner = {
|
30
|
+
'interactive' => "usage: #{program} [--interactive] [options] [headnode] [snapshot] [user ...]",
|
31
|
+
'non-interactive' => "usage: #{program} --non-interactive [options] <headnode> <snapshot> [user ...]",
|
32
|
+
}
|
33
|
+
|
34
|
+
# To emphasize the difference between interactive and non-interactive usage,
|
35
|
+
# the currently *active* mode is presented in bold typeface.
|
36
|
+
options.on('-h', '--help', "Show this help text") do
|
37
|
+
active = feature[:interactive] ? 'interactive' : 'non-interactive'
|
38
|
+
banner[active] = Pastel.new.bold banner[active]
|
39
|
+
options.banner = banner.values.join("\n")
|
40
|
+
|
41
|
+
puts options
|
42
|
+
exit
|
43
|
+
end
|
44
|
+
|
45
|
+
options.on('-i', '--interactive', "Enable interactive prompts (default)") { feature[:interactive] = true }
|
46
|
+
options.on('-n', '--non-interactive', "Disable interactive prompts") { feature[:interactive] = false }
|
47
|
+
options.on('-N', '--namespace NAMESPACE', "Use NAMESPACE for Redis keys") { |o| feature[:namespace] = o }
|
48
|
+
options.on('-E', '--exclude LOGIN', "Exclude LOGIN from report") { |o| feature[:exclude] << o }
|
49
|
+
options.on('-F', '--format FORMAT', "Format output as (basic|ascii|unicode). Defaults to unicode.") do |o|
|
50
|
+
feature[:format] = case o
|
51
|
+
when /^b(asic)?$/
|
52
|
+
:basic
|
53
|
+
when /^a(scii)?$/
|
54
|
+
:ascii
|
55
|
+
when /^u(nicode)?$/
|
56
|
+
:unicode
|
57
|
+
else
|
58
|
+
STDERR.puts Pastel.new.red "#{program}: error: option (--format): #{Pastel.new.bold o} is not one of ([b]asic|[a]scii|[u]nicode)"
|
59
|
+
exit Errno::EINVAL::Errno
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end.parse!
|
64
|
+
|
65
|
+
#####################
|
66
|
+
# Argument Handling #
|
67
|
+
#####################
|
68
|
+
|
69
|
+
begin
|
70
|
+
interactive = ::TritonOps::Snapshot::Explorer.new namespace: feature[:namespace]
|
71
|
+
headnode = ARGV.shift || (interactive.headnode if feature[:interactive])
|
72
|
+
timestamp = ARGV.shift || (interactive.snapshot headnode if feature[:interactive])
|
73
|
+
rescue Interrupt, TTY::Reader::InputInterrupt
|
74
|
+
exit Errno::EINTR::Errno
|
75
|
+
end
|
76
|
+
|
77
|
+
exit Errno::EINVAL::Errno if [headnode, timestamp].any?(&:nil?)
|
78
|
+
|
79
|
+
################
|
80
|
+
# Main Program #
|
81
|
+
################
|
82
|
+
|
83
|
+
snapshot = TritonOps::Snapshot.new headnode, timestamp
|
84
|
+
|
85
|
+
reporter = TritonOps::Snapshot::Reporter.new(
|
86
|
+
snapshot,
|
87
|
+
format: feature[:format],
|
88
|
+
exclude: feature[:exclude],
|
89
|
+
targets: ARGV)
|
90
|
+
|
91
|
+
reporter.usage
|
92
|
+
|
93
|
+
binding.pry if ENV.fetch('HACKING', 'false') != 'false'
|
@@ -0,0 +1,195 @@
|
|
1
|
+
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'contracts' # BSD-2-Clause License
|
5
|
+
|
6
|
+
require_relative '../support/feature/comparable_as_hash'
|
7
|
+
require_relative '../support/feature/hash_from_initialization_contract'
|
8
|
+
require_relative '../support/types'
|
9
|
+
require_relative '../support/type_coercion'
|
10
|
+
require_relative 'user'
|
11
|
+
|
12
|
+
module TritonOps
|
13
|
+
module Resource
|
14
|
+
class Image
|
15
|
+
include ::Contracts::Core
|
16
|
+
include ::Contracts::Builtin
|
17
|
+
include ::TritonOps::Support::Feature::ComparableAsHash
|
18
|
+
include ::TritonOps::Support::Feature::HashFromInitializationContract
|
19
|
+
include ::TritonOps::Support::Types
|
20
|
+
include ::TritonOps::Support::TypeCoercion
|
21
|
+
|
22
|
+
Type = Enum[*%w(zone-dataset docker lx-dataset zvol other)]
|
23
|
+
OS = Enum[*%w(smartos linux other bsd)]
|
24
|
+
State = Enum[*%w(active)]
|
25
|
+
NICDriver = Enum[*%w(virtio)]
|
26
|
+
DiskDriver = Enum[*%w(virtio)]
|
27
|
+
CPU = Enum[*%w(host)]
|
28
|
+
|
29
|
+
Contract ({
|
30
|
+
:v => Integer,
|
31
|
+
:uuid => String,
|
32
|
+
:owner => String,
|
33
|
+
:name => String,
|
34
|
+
:version => String,
|
35
|
+
:state => State,
|
36
|
+
:disabled => Bool,
|
37
|
+
:public => Bool,
|
38
|
+
:published_at => Or[String, Time],
|
39
|
+
:type => Type,
|
40
|
+
:os => OS,
|
41
|
+
:files => ArrayOf[HashOf[Or[String, Symbol], Any]],
|
42
|
+
|
43
|
+
:description => Maybe[String],
|
44
|
+
:requirements => Maybe[HashOf[Or[String, Symbol], Any]],
|
45
|
+
:tags => Maybe[HashOf[Or[String, Symbol], Any]],
|
46
|
+
:homepage => Maybe[String],
|
47
|
+
:origin => Maybe[String],
|
48
|
+
:urn => Maybe[String],
|
49
|
+
:users => Maybe[ArrayOf[HashOf[Or[String, Symbol], Any]]],
|
50
|
+
:nic_driver => Maybe[NICDriver],
|
51
|
+
:disk_driver => Maybe[DiskDriver],
|
52
|
+
:cpu_type => Maybe[CPU],
|
53
|
+
:image_size => Maybe[Integer],
|
54
|
+
}) => Image
|
55
|
+
def initialize(**options)
|
56
|
+
@options = options
|
57
|
+
self.to_h
|
58
|
+
remove_instance_variable '@options'
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
#######################
|
63
|
+
# Required Properties #
|
64
|
+
#######################
|
65
|
+
|
66
|
+
Contract None => Integer
|
67
|
+
def v
|
68
|
+
@v ||= @options.fetch :v
|
69
|
+
end
|
70
|
+
|
71
|
+
Contract None => String
|
72
|
+
def uuid
|
73
|
+
@uuid ||= @options.fetch :uuid
|
74
|
+
end
|
75
|
+
|
76
|
+
Contract None => String
|
77
|
+
def owner
|
78
|
+
@owner ||= @options.fetch :owner
|
79
|
+
end
|
80
|
+
|
81
|
+
Contract None => String
|
82
|
+
def name
|
83
|
+
@name ||= @options.fetch :owner
|
84
|
+
end
|
85
|
+
|
86
|
+
Contract None => String
|
87
|
+
def version
|
88
|
+
@version ||= @options.fetch :owner
|
89
|
+
end
|
90
|
+
|
91
|
+
Contract None => State
|
92
|
+
def state
|
93
|
+
@state ||= @options.fetch :state
|
94
|
+
end
|
95
|
+
|
96
|
+
Contract None => Bool
|
97
|
+
def disabled
|
98
|
+
@disabled ||= (@options || {}).fetch :disabled, false
|
99
|
+
end
|
100
|
+
|
101
|
+
Contract None => Bool
|
102
|
+
def public
|
103
|
+
@public ||= (@options || {}).fetch :public, false
|
104
|
+
end
|
105
|
+
|
106
|
+
Contract None => Time
|
107
|
+
def published_at
|
108
|
+
@published_at ||= Coerce.to_time @options.fetch :published_at
|
109
|
+
end
|
110
|
+
|
111
|
+
Contract None => Type
|
112
|
+
def type
|
113
|
+
@type ||= @options.fetch :type
|
114
|
+
end
|
115
|
+
|
116
|
+
Contract None => OS
|
117
|
+
def os
|
118
|
+
@os ||= @options.fetch :os
|
119
|
+
end
|
120
|
+
|
121
|
+
Contract None => ArrayOf[HashOf[Symbol, Any]]
|
122
|
+
def files
|
123
|
+
@files ||= @options.fetch(:files).map { |file| file.transform_keys(&:to_sym) }
|
124
|
+
end
|
125
|
+
|
126
|
+
alias disabled? disabled
|
127
|
+
alias public? public
|
128
|
+
|
129
|
+
################################################
|
130
|
+
# Optional Properties (with sensible defaults) #
|
131
|
+
################################################
|
132
|
+
|
133
|
+
Contract None => HashOf[Symbol, Any]
|
134
|
+
def requirements
|
135
|
+
@requirements ||= @options.fetch(:requirements, {}).transform_keys(&:to_sym)
|
136
|
+
end
|
137
|
+
|
138
|
+
Contract None => HashOf[String, Any]
|
139
|
+
def tags
|
140
|
+
@tags ||= @options.fetch(:tags, {}).transform_keys(&:to_s)
|
141
|
+
end
|
142
|
+
|
143
|
+
Contract None => ArrayOf[HashOf[Symbol, String]]
|
144
|
+
def users
|
145
|
+
@users ||= @options.fetch :users, []
|
146
|
+
end
|
147
|
+
|
148
|
+
##########################################
|
149
|
+
# Optional Properties (without defaults) #
|
150
|
+
##########################################
|
151
|
+
|
152
|
+
Contract None => Maybe[String]
|
153
|
+
def description
|
154
|
+
@description ||= (@options || {}).fetch :description, nil
|
155
|
+
end
|
156
|
+
|
157
|
+
Contract None => Maybe[String]
|
158
|
+
def homepage
|
159
|
+
@homepage ||= (@options || {}).fetch :homepage, nil
|
160
|
+
end
|
161
|
+
|
162
|
+
Contract None => Maybe[String]
|
163
|
+
def origin
|
164
|
+
@origin ||= (@options || {}).fetch :origin, nil
|
165
|
+
end
|
166
|
+
|
167
|
+
Contract None => Maybe[String]
|
168
|
+
def urn
|
169
|
+
@urn ||= (@options || {}).fetch :urn, nil
|
170
|
+
end
|
171
|
+
|
172
|
+
Contract None => Maybe[NICDriver]
|
173
|
+
def nic_driver
|
174
|
+
@nic_driver ||= (@options || {}).fetch :nic_driver, nil
|
175
|
+
end
|
176
|
+
|
177
|
+
Contract None => Maybe[DiskDriver]
|
178
|
+
def disk_driver
|
179
|
+
@disk_driver ||= (@options || {}).fetch :disk_driver, nil
|
180
|
+
end
|
181
|
+
|
182
|
+
Contract None => Maybe[CPU]
|
183
|
+
def cpu_type
|
184
|
+
@cpu_type ||= (@options || {}).fetch :cpu_type, nil
|
185
|
+
end
|
186
|
+
|
187
|
+
Contract None => Maybe[Integer]
|
188
|
+
def image_size
|
189
|
+
@image_size ||= (@options || {}).fetch :image_size, nil
|
190
|
+
end
|
191
|
+
|
192
|
+
alias size image_size
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
|
2
|
+
# -*- ruby -*-
|
3
|
+
|
4
|
+
require 'contracts' # BSD-2-Clause License
|
5
|
+
require 'time' # Ruby Standard Library
|
6
|
+
|
7
|
+
require_relative '../support/feature/comparable_as_hash'
|
8
|
+
require_relative '../support/feature/hash_from_initialization_contract'
|
9
|
+
require_relative '../support/type_coercion'
|
10
|
+
require_relative '../support/types'
|
11
|
+
|
12
|
+
module TritonOps
|
13
|
+
module Resource
|
14
|
+
class Platform
|
15
|
+
include ::Contracts::Core
|
16
|
+
include ::Contracts::Builtin
|
17
|
+
include ::TritonOps::Support::Feature::ComparableAsHash
|
18
|
+
include ::TritonOps::Support::Feature::HashFromInitializationContract
|
19
|
+
include ::TritonOps::Support::TypeCoercion
|
20
|
+
include ::TritonOps::Support::Types
|
21
|
+
|
22
|
+
ServerReference = {
|
23
|
+
hostname: String,
|
24
|
+
uuid: String,
|
25
|
+
}
|
26
|
+
|
27
|
+
Contract ({
|
28
|
+
:boot_platform => ArrayOf[ServerReference],
|
29
|
+
:current_platform => ArrayOf[ServerReference],
|
30
|
+
:default => Bool,
|
31
|
+
:latest => Bool,
|
32
|
+
:usb_key => Bool,
|
33
|
+
:version => Castable::Time,
|
34
|
+
}) => Platform
|
35
|
+
def initialize(**options)
|
36
|
+
@options = options
|
37
|
+
self.to_h
|
38
|
+
remove_instance_variable '@options'
|
39
|
+
self
|
40
|
+
end
|
41
|
+
|
42
|
+
#######################
|
43
|
+
# Required Properties #
|
44
|
+
#######################
|
45
|
+
|
46
|
+
Contract None => Time
|
47
|
+
def version
|
48
|
+
@version ||= Coerce.to_time @options.fetch :version
|
49
|
+
end
|
50
|
+
|
51
|
+
Contract None => ArrayOf[ServerReference]
|
52
|
+
def boot_platform
|
53
|
+
@boot_platform ||= @options.fetch(:boot_platform).map { |hash| hash.transform_keys(&:to_sym) }
|
54
|
+
end
|
55
|
+
|
56
|
+
Contract None => ArrayOf[ServerReference]
|
57
|
+
def current_platform
|
58
|
+
@current_platform ||= @options.fetch(:current_platform).map { |hash| hash.transform_keys(&:to_sym) }
|
59
|
+
end
|
60
|
+
|
61
|
+
Contract None => Bool
|
62
|
+
def latest
|
63
|
+
@latest ||= (@options || {}).fetch(:latest, false)
|
64
|
+
end
|
65
|
+
|
66
|
+
Contract None => Bool
|
67
|
+
def default
|
68
|
+
@default ||= (@options || {}).fetch(:default, false)
|
69
|
+
end
|
70
|
+
|
71
|
+
Contract None => Bool
|
72
|
+
def usb_key
|
73
|
+
@usb_key ||= (@options || {}).fetch(:usb_key, false)
|
74
|
+
end
|
75
|
+
|
76
|
+
alias latest? latest
|
77
|
+
alias default? default
|
78
|
+
alias usb_key? usb_key
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|