holodekk 0.1.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.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.md +19 -0
  3. data/README.md +6 -0
  4. data/bin/holodekk-ruby +13 -0
  5. data/holodekk.gemspec +24 -0
  6. data/lib/holodekk/builder/instruction.rb +43 -0
  7. data/lib/holodekk/builder/option.rb +22 -0
  8. data/lib/holodekk/builder.rb +33 -0
  9. data/lib/holodekk/docker/dockerfile/instruction_builder/flag.rb +37 -0
  10. data/lib/holodekk/docker/dockerfile/instruction_builder/key_pair.rb +22 -0
  11. data/lib/holodekk/docker/dockerfile/instruction_builder/option.rb +22 -0
  12. data/lib/holodekk/docker/dockerfile/instruction_builder/quoted_string.rb +21 -0
  13. data/lib/holodekk/docker/dockerfile/instruction_builder/raw_value.rb +21 -0
  14. data/lib/holodekk/docker/dockerfile/instruction_builder/value_array.rb +21 -0
  15. data/lib/holodekk/docker/dockerfile/instruction_builder/value_list.rb +21 -0
  16. data/lib/holodekk/docker/dockerfile/instruction_builder.rb +71 -0
  17. data/lib/holodekk/docker/dockerfile.rb +3 -0
  18. data/lib/holodekk/docker.rb +3 -0
  19. data/lib/holodekk/image/instructions/add.rb +45 -0
  20. data/lib/holodekk/image/instructions/arg.rb +27 -0
  21. data/lib/holodekk/image/instructions/cmd.rb +27 -0
  22. data/lib/holodekk/image/instructions/copy.rb +42 -0
  23. data/lib/holodekk/image/instructions/entrypoint.rb +11 -0
  24. data/lib/holodekk/image/instructions/env.rb +25 -0
  25. data/lib/holodekk/image/instructions/expose.rb +24 -0
  26. data/lib/holodekk/image/instructions/from.rb +30 -0
  27. data/lib/holodekk/image/instructions/healthcheck.rb +27 -0
  28. data/lib/holodekk/image/instructions/label.rb +31 -0
  29. data/lib/holodekk/image/instructions/onbuild.rb +23 -0
  30. data/lib/holodekk/image/instructions/run/options/with_bind_mount.rb +31 -0
  31. data/lib/holodekk/image/instructions/run/options/with_cache_mount.rb +40 -0
  32. data/lib/holodekk/image/instructions/run/options/with_secret_mount.rb +59 -0
  33. data/lib/holodekk/image/instructions/run/options/with_ssh_mount.rb +17 -0
  34. data/lib/holodekk/image/instructions/run/options/with_tmpfs_mount.rb +17 -0
  35. data/lib/holodekk/image/instructions/run.rb +69 -0
  36. data/lib/holodekk/image/instructions/shell.rb +23 -0
  37. data/lib/holodekk/image/instructions/stopsignal.rb +23 -0
  38. data/lib/holodekk/image/instructions/user.rb +26 -0
  39. data/lib/holodekk/image/instructions/volume.rb +27 -0
  40. data/lib/holodekk/image/instructions/workdir.rb +23 -0
  41. data/lib/holodekk/image.rb +66 -0
  42. data/lib/holodekk/version.rb +5 -0
  43. data/lib/holodekk.rb +14 -0
  44. metadata +114 -0
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Healthcheck < Holodekk::Builder::Instruction
7
+ attr_accessor :cmd, :interval, :timeout, :start, :retries
8
+
9
+ validates :cmd, presence: true
10
+
11
+ def self.build(cmd, **kwargs)
12
+ new({ cmd: cmd }.merge(kwargs))
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ add_option(builder, 'interval')
18
+ add_option(builder, 'timeout')
19
+ add_option(builder, 'start')
20
+ add_option(builder, 'retries')
21
+ builder.raw_value(cmd)
22
+ builder.output
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Label < Holodekk::Builder::Instruction
7
+ attr_accessor :labels
8
+
9
+ validates :labels, presence: true
10
+
11
+ def self.build(labels)
12
+ new({ labels: labels })
13
+ end
14
+
15
+ def as_json(options = {}); end
16
+
17
+ def to_dockerfile
18
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
19
+ lines = labels.each_pair.map do |key, value|
20
+ builder.key_pair(
21
+ Docker::Dockerfile::InstructionBuilder::QuotedString.new(key),
22
+ Docker::Dockerfile::InstructionBuilder::QuotedString.new(value)
23
+ )
24
+ builder.output!
25
+ end
26
+ lines.join("\n")
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Onbuild < Holodekk::Builder::Instruction
7
+ attr_accessor :cmd
8
+
9
+ validates :cmd, presence: true
10
+
11
+ def self.build(cmd)
12
+ new({ cmd: cmd })
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ builder.raw_value(cmd)
18
+ builder.output
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run
7
+ module Options
8
+ class WithBindMount < Holodekk::Builder::Option
9
+ attr_accessor :source, :target, :from, :readonly
10
+
11
+ alias readonly? readonly
12
+
13
+ def self.build(source, target, **kwargs)
14
+ new({ source: source, target: target }.merge(kwargs))
15
+ end
16
+
17
+ def to_dockerfile
18
+ chunks = []
19
+ chunks << '--mount=type=bind'
20
+ chunks << "source=#{source}"
21
+ chunks << "target=#{target}"
22
+ chunks << "from=#{from}" unless from.nil?
23
+ chunks << 'readwrite' unless readonly?
24
+ chunks.join(',')
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run
7
+ module Options
8
+ class WithCacheMount < Holodekk::Builder::Option
9
+ attr_accessor :target, :from, :gid, :id, :mode, :readonly, :sharing, :source, :uid
10
+
11
+ alias readonly? readonly
12
+
13
+ def self.build(target, **kwargs)
14
+ new({ target: target }.merge(kwargs))
15
+ end
16
+
17
+ def to_dockerfile
18
+ ''
19
+ end
20
+
21
+ # def to_dockerfile
22
+ # chunks = []
23
+ # chunks << '--mount=type=cache'
24
+ # chunks << "target=#{target}"
25
+ # chunks << "from=#{from}" unless from.nil?
26
+ # chunks << "gid=#{gid}" unless gid.nil?
27
+ # chunks << "id=#{id}" unless id.nil?
28
+ # chunks << "mode=#{mode}" unless mode.nil?
29
+ # chunks << 'readonly' if readonly?
30
+ # chunks << "sharing=#{sharing}" unless sharing.nil?
31
+ # chunks << "source=#{source}" unless source.nil?
32
+ # chunks << "uid=#{uid}" unless uid.nil?
33
+ # chunks.join(',')
34
+ # end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run
7
+ module Options
8
+ class WithSecretMount < Holodekk::Builder::Option
9
+ attr_accessor :target, :from, :gid, :id, :mode, :readonly, :sharing, :source, :uid
10
+
11
+ alias readonly? readonly
12
+
13
+ def self.buld(target, **kwargs)
14
+ new({ target: target }.merge(kwargs))
15
+ end
16
+
17
+ def to_dockerfile
18
+ builder = OptionBuilder.new('mount=type=cache')
19
+ builder.build do
20
+ pair 'target', target
21
+ %i[from gid id mode sharing source uid].each do |key|
22
+ v = send(key)
23
+ pair key, v unless v.nil?
24
+ flag 'readonly' if readonly?
25
+ end
26
+ end
27
+ builder.output
28
+ end
29
+
30
+ class OptionBuilder
31
+ attr_accessor :name, :pairs
32
+
33
+ def initialize(name)
34
+ @name = name
35
+ @pairs = []
36
+ end
37
+
38
+ def build(&block)
39
+ instance_eval(&block)
40
+ end
41
+
42
+ def pair(key, value)
43
+ pairs << [key, value]
44
+ end
45
+
46
+ def output
47
+ chunks = ["--#{name}"]
48
+ pairs.each do |pair|
49
+ chunks << "#{pair[0]}=#{pair[1]}"
50
+ end
51
+ chunks.join(',')
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run
7
+ module Options
8
+ class WithSshMount < Holodekk::Builder::Option
9
+ def process; end
10
+
11
+ def to_dockerfile; end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run
7
+ module Options
8
+ class WithTmpfsMount < Holodekk::Builder::Option
9
+ def process; end
10
+
11
+ def to_dockerfile; end
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Run < Holodekk::Builder::Instruction
7
+ def self.build(cmd = nil, &block)
8
+ run = new
9
+ builder = Builder.new(run.instructions, run.options)
10
+ builder.run(cmd) unless cmd.nil?
11
+ builder.instance_eval(&block) if block_given?
12
+ run
13
+ end
14
+
15
+ def instructions
16
+ @instructions ||= []
17
+ end
18
+
19
+ def options
20
+ @options ||= []
21
+ end
22
+
23
+ def to_dockerfile
24
+ # builder = InstructionBuilder.new('RUN')
25
+ # builder.build do
26
+ # options.each do |o|
27
+ # option o.to_dockerfile
28
+ # end
29
+ # end
30
+ res = 'RUN '.dup
31
+ unless options.empty?
32
+ res << options.map(&:to_dockerfile).join(',')
33
+ res << " \\\n\t"
34
+ end
35
+ res << instructions.map(&:to_dockerfile).join(" && \\\n\t")
36
+ res
37
+ end
38
+
39
+ module Instructions
40
+ class Run < Holodekk::Builder::Instruction
41
+ attr_accessor :cmd
42
+
43
+ def self.build(cmd)
44
+ new(cmd: cmd)
45
+ end
46
+
47
+ def to_dockerfile
48
+ cmd
49
+ end
50
+ end
51
+ end
52
+
53
+ class Builder < Holodekk::Builder
54
+ require_relative 'run/options/with_bind_mount'
55
+ require_relative 'run/options/with_cache_mount'
56
+ require_relative 'run/options/with_secret_mount'
57
+ require_relative 'run/options/with_ssh_mount'
58
+ require_relative 'run/options/with_tmpfs_mount'
59
+
60
+ instruction Instructions::Run
61
+ option Options::WithBindMount
62
+ option Options::WithCacheMount
63
+ option Options::WithSecretMount
64
+ option Options::WithSshMount
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Shell < Holodekk::Builder::Instruction
7
+ attr_accessor :shell
8
+
9
+ validates :shell, presence: true
10
+
11
+ def self.build(*shell)
12
+ new(shell: shell)
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ builder.value_array(*shell.map { |s| Docker::Dockerfile::InstructionBuilder::QuotedString.new(s) })
18
+ builder.output
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Stopsignal < Holodekk::Builder::Instruction
7
+ attr_accessor :signal
8
+
9
+ validates :signal, presence: true
10
+
11
+ def self.build(signal)
12
+ new(signal: signal)
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ builder.raw_value(signal)
18
+ builder.output
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class User < Holodekk::Builder::Instruction
7
+ attr_accessor :user, :group
8
+
9
+ validates :user, presence: true, format: { with: Holodekk::USER_RE }
10
+ validates :group, format: { with: Holodekk::USER_RE }, allow_blank: true
11
+
12
+ def self.build(user, group = nil)
13
+ new(user: user, group: group)
14
+ end
15
+
16
+ def to_dockerfile
17
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
18
+ val = user.dup
19
+ val << ":#{group}" if group.present?
20
+ builder.raw_value(val)
21
+ builder.output
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Volume < Holodekk::Builder::Instruction
7
+ attr_accessor :volumes
8
+
9
+ validates :volumes, presence: true
10
+
11
+ def self.build(*volumes)
12
+ new({ volumes: volumes })
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ builder.value_array(
18
+ *volumes.map do |v|
19
+ Docker::Dockerfile::InstructionBuilder::QuotedString.new(v)
20
+ end
21
+ )
22
+ builder.output
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ class Image
5
+ module Instructions
6
+ class Workdir < Holodekk::Builder::Instruction
7
+ attr_accessor :workdir
8
+
9
+ validates :workdir, presence: true
10
+
11
+ def self.build(workdir)
12
+ new(workdir: workdir)
13
+ end
14
+
15
+ def to_dockerfile
16
+ builder = Docker::Dockerfile::InstructionBuilder.new(self)
17
+ builder.raw_value(workdir)
18
+ builder.output
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,66 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'image/instructions/add'
4
+ require_relative 'image/instructions/arg'
5
+ require_relative 'image/instructions/cmd'
6
+ require_relative 'image/instructions/copy'
7
+ require_relative 'image/instructions/entrypoint'
8
+ require_relative 'image/instructions/env'
9
+ require_relative 'image/instructions/expose'
10
+ require_relative 'image/instructions/from'
11
+ require_relative 'image/instructions/healthcheck'
12
+ require_relative 'image/instructions/label'
13
+ require_relative 'image/instructions/onbuild'
14
+ require_relative 'image/instructions/run'
15
+ require_relative 'image/instructions/shell'
16
+ require_relative 'image/instructions/stopsignal'
17
+ require_relative 'image/instructions/user'
18
+ require_relative 'image/instructions/volume'
19
+ require_relative 'image/instructions/workdir'
20
+
21
+ module Holodekk
22
+ class Image
23
+ attr_reader :name
24
+
25
+ def initialize(name)
26
+ @name = name
27
+ end
28
+
29
+ def instructions
30
+ @instructions ||= []
31
+ end
32
+
33
+ def to_dockerfile
34
+ instructions.map(&:to_dockerfile).join("\n\n")
35
+ end
36
+
37
+ def self.build(name, &block)
38
+ image = new(name)
39
+ if block_given?
40
+ builder = Image::Builder.new(image.instructions)
41
+ builder.instance_eval(&block)
42
+ end
43
+ image
44
+ end
45
+
46
+ class Builder < Holodekk::Builder
47
+ instruction Image::Instructions::Add
48
+ instruction Image::Instructions::Arg
49
+ instruction Image::Instructions::Cmd
50
+ instruction Image::Instructions::Copy
51
+ instruction Image::Instructions::Entrypoint
52
+ instruction Image::Instructions::Env
53
+ instruction Image::Instructions::Expose
54
+ instruction Image::Instructions::From
55
+ instruction Image::Instructions::Healthcheck
56
+ instruction Image::Instructions::Label
57
+ instruction Image::Instructions::Onbuild
58
+ instruction Image::Instructions::Run
59
+ instruction Image::Instructions::Shell
60
+ instruction Image::Instructions::Stopsignal
61
+ instruction Image::Instructions::User
62
+ instruction Image::Instructions::Volume
63
+ instruction Image::Instructions::Workdir
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Holodekk
4
+ VERSION = '0.1.0'
5
+ end
data/lib/holodekk.rb ADDED
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_model'
5
+
6
+ module Holodekk
7
+ LNAME_RE = '[a-z_]([a-z0-9_-]{0,31}|[a-z0-9_-]{0,30}\$)'
8
+ USER_RE = Regexp.new(/\A#{LNAME_RE}\Z/)
9
+ CHOWN_RE = Regexp.new(/\A#{LNAME_RE}(:#{LNAME_RE})?\Z/)
10
+ end
11
+
12
+ require_relative 'holodekk/builder'
13
+ require_relative 'holodekk/docker'
14
+ require_relative 'holodekk/image'
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: holodekk
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Josh Williams
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2023-03-09 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activemodel
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '6.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '6.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '6.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '6.0'
41
+ description: Ruby interfaces for the Holodekk platform.
42
+ email: jdubz@holodekk.io
43
+ executables:
44
+ - holodekk-ruby
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - LICENSE.md
49
+ - README.md
50
+ - bin/holodekk-ruby
51
+ - holodekk.gemspec
52
+ - lib/holodekk.rb
53
+ - lib/holodekk/builder.rb
54
+ - lib/holodekk/builder/instruction.rb
55
+ - lib/holodekk/builder/option.rb
56
+ - lib/holodekk/docker.rb
57
+ - lib/holodekk/docker/dockerfile.rb
58
+ - lib/holodekk/docker/dockerfile/instruction_builder.rb
59
+ - lib/holodekk/docker/dockerfile/instruction_builder/flag.rb
60
+ - lib/holodekk/docker/dockerfile/instruction_builder/key_pair.rb
61
+ - lib/holodekk/docker/dockerfile/instruction_builder/option.rb
62
+ - lib/holodekk/docker/dockerfile/instruction_builder/quoted_string.rb
63
+ - lib/holodekk/docker/dockerfile/instruction_builder/raw_value.rb
64
+ - lib/holodekk/docker/dockerfile/instruction_builder/value_array.rb
65
+ - lib/holodekk/docker/dockerfile/instruction_builder/value_list.rb
66
+ - lib/holodekk/image.rb
67
+ - lib/holodekk/image/instructions/add.rb
68
+ - lib/holodekk/image/instructions/arg.rb
69
+ - lib/holodekk/image/instructions/cmd.rb
70
+ - lib/holodekk/image/instructions/copy.rb
71
+ - lib/holodekk/image/instructions/entrypoint.rb
72
+ - lib/holodekk/image/instructions/env.rb
73
+ - lib/holodekk/image/instructions/expose.rb
74
+ - lib/holodekk/image/instructions/from.rb
75
+ - lib/holodekk/image/instructions/healthcheck.rb
76
+ - lib/holodekk/image/instructions/label.rb
77
+ - lib/holodekk/image/instructions/onbuild.rb
78
+ - lib/holodekk/image/instructions/run.rb
79
+ - lib/holodekk/image/instructions/run/options/with_bind_mount.rb
80
+ - lib/holodekk/image/instructions/run/options/with_cache_mount.rb
81
+ - lib/holodekk/image/instructions/run/options/with_secret_mount.rb
82
+ - lib/holodekk/image/instructions/run/options/with_ssh_mount.rb
83
+ - lib/holodekk/image/instructions/run/options/with_tmpfs_mount.rb
84
+ - lib/holodekk/image/instructions/shell.rb
85
+ - lib/holodekk/image/instructions/stopsignal.rb
86
+ - lib/holodekk/image/instructions/user.rb
87
+ - lib/holodekk/image/instructions/volume.rb
88
+ - lib/holodekk/image/instructions/workdir.rb
89
+ - lib/holodekk/version.rb
90
+ homepage: https://holodekk.io
91
+ licenses:
92
+ - MIT
93
+ metadata:
94
+ rubygems_mfa_required: 'true'
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 2.6.0
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubygems_version: 3.3.7
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Ruby interfaces for the Holodekk platform.
114
+ test_files: []