kozo 0.1.0 → 0.2.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/.gitignore +7 -2
- data/.kzignore +1 -0
- data/.overcommit.yml +1 -0
- data/.rspec +1 -0
- data/.rubocop.yml +44 -5
- data/CHANGELOG.md +5 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +156 -48
- data/LICENSE.md +1 -1
- data/README.md +28 -0
- data/Rakefile +3 -7
- data/bin/kozo +6 -2
- data/config/application.rb +3 -0
- data/config/dependencies.rb +4 -25
- data/kozo.gemspec +20 -5
- data/lib/core_ext/boolean.rb +12 -0
- data/lib/core_ext/nil_class.rb +11 -0
- data/lib/core_ext/string.rb +25 -0
- data/lib/kozo/backend.rb +81 -0
- data/lib/kozo/backends/git.rb +50 -0
- data/lib/kozo/backends/local.rb +41 -15
- data/lib/kozo/backends/memory.rb +26 -0
- data/lib/kozo/cli.rb +30 -9
- data/lib/kozo/command.rb +32 -0
- data/lib/kozo/commands/apply.rb +44 -0
- data/lib/kozo/commands/console.rb +15 -0
- data/lib/kozo/commands/import.rb +47 -0
- data/lib/kozo/commands/init.rb +15 -0
- data/lib/kozo/commands/plan.rb +29 -3
- data/lib/kozo/commands/refresh.rb +21 -0
- data/lib/kozo/commands/show.rb +15 -0
- data/lib/kozo/commands/state.rb +64 -0
- data/lib/kozo/commands/validate.rb +13 -0
- data/lib/kozo/commands/version.rb +13 -0
- data/lib/kozo/concerns/assignment.rb +17 -0
- data/lib/kozo/concerns/attributes.rb +99 -0
- data/lib/kozo/concerns/mark.rb +25 -0
- data/lib/kozo/concerns/track.rb +47 -0
- data/lib/kozo/configuration.rb +34 -7
- data/lib/kozo/dsl.rb +18 -12
- data/lib/kozo/error.rb +13 -0
- data/lib/kozo/logger.rb +8 -4
- data/lib/kozo/operation.rb +42 -0
- data/lib/kozo/operations/create.rb +29 -0
- data/lib/kozo/operations/destroy.rb +29 -0
- data/lib/kozo/operations/show.rb +12 -0
- data/lib/kozo/operations/update.rb +19 -0
- data/lib/kozo/options.rb +9 -1
- data/lib/kozo/parser.rb +35 -0
- data/lib/kozo/provider.rb +7 -1
- data/lib/kozo/providers/dummy/dependencies.rb +9 -0
- data/lib/kozo/providers/{null → dummy}/provider.rb +2 -6
- data/lib/kozo/providers/dummy/resource.rb +19 -0
- data/lib/kozo/providers/dummy/resources/dummy.rb +16 -0
- data/lib/kozo/providers/hcloud/dependencies.rb +13 -0
- data/lib/kozo/providers/hcloud/provider.rb +7 -1
- data/lib/kozo/providers/hcloud/resource.rb +46 -1
- data/lib/kozo/providers/hcloud/resources/server.rb +29 -0
- data/lib/kozo/providers/hcloud/resources/ssh_key.rb +6 -2
- data/lib/kozo/resource.rb +110 -3
- data/lib/kozo/state.rb +25 -0
- data/lib/kozo/type.rb +15 -0
- data/lib/kozo/types/boolean.rb +30 -0
- data/lib/kozo/types/date.rb +20 -0
- data/lib/kozo/types/float.rb +17 -0
- data/lib/kozo/types/hash.rb +20 -0
- data/lib/kozo/types/integer.rb +17 -0
- data/lib/kozo/types/string.rb +17 -0
- data/lib/kozo/types/time.rb +18 -0
- data/lib/kozo/version.rb +1 -1
- data/lib/kozo.rb +13 -7
- metadata +195 -31
- data/.github/dependabot.yml +0 -14
- data/.github/workflows/ci.yml +0 -81
- data/bin/bundle +0 -118
- data/bin/console +0 -7
- data/bin/rspec +0 -28
- data/bin/version +0 -62
- data/lib/kozo/backends/base.rb +0 -31
- data/lib/kozo/commands/base.rb +0 -21
- data/lib/kozo/container.rb +0 -35
- data/lib/kozo/environment.rb +0 -27
- data/lib/kozo/providers/null/resource.rb +0 -11
- data/lib/kozo/providers/null/resources/null.rb +0 -13
- data/log/.keep +0 -0
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Providers
|
5
|
+
module HCloud
|
6
|
+
module Resources
|
7
|
+
class Server < Resource
|
8
|
+
self.resource_name = "hcloud_server"
|
9
|
+
|
10
|
+
attribute :name
|
11
|
+
attribute :image
|
12
|
+
attribute :server_type
|
13
|
+
attribute :location
|
14
|
+
attribute :datacenter
|
15
|
+
|
16
|
+
attribute :user_data
|
17
|
+
|
18
|
+
attribute :labels, type: :hash
|
19
|
+
|
20
|
+
attribute :ssh_keys, multiple: true
|
21
|
+
|
22
|
+
attribute :locked, argument: false, type: :boolean
|
23
|
+
|
24
|
+
attribute :created, argument: false, type: :time
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -5,9 +5,13 @@ module Kozo
|
|
5
5
|
module HCloud
|
6
6
|
module Resources
|
7
7
|
class SSHKey < Resource
|
8
|
-
|
8
|
+
self.resource_name = "hcloud_ssh_key"
|
9
9
|
|
10
|
-
|
10
|
+
attribute :name
|
11
|
+
attribute :public_key
|
12
|
+
attribute :labels, type: :hash
|
13
|
+
|
14
|
+
attribute :created, type: :time, argument: false
|
11
15
|
end
|
12
16
|
end
|
13
17
|
end
|
data/lib/kozo/resource.rb
CHANGED
@@ -2,12 +2,119 @@
|
|
2
2
|
|
3
3
|
module Kozo
|
4
4
|
class Resource
|
5
|
-
|
5
|
+
include Attributes
|
6
6
|
|
7
|
-
|
7
|
+
include Assignment
|
8
|
+
include Mark
|
9
|
+
include Track
|
10
|
+
|
11
|
+
attr_accessor :provider, :state_name
|
12
|
+
|
13
|
+
attribute :id
|
14
|
+
|
15
|
+
class_attribute :resource_name, :provider_name
|
16
|
+
|
17
|
+
def address
|
18
|
+
"#{resource_name}.#{state_name}"
|
19
|
+
end
|
8
20
|
|
9
21
|
def ==(other)
|
10
|
-
|
22
|
+
self.class == other.class &&
|
23
|
+
id == other.id &&
|
24
|
+
state_name == other.state_name
|
25
|
+
end
|
26
|
+
|
27
|
+
alias eql? ==
|
28
|
+
|
29
|
+
def hash
|
30
|
+
[self.class, id].hash
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_h
|
34
|
+
{
|
35
|
+
meta: meta,
|
36
|
+
data: attributes,
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.from_h(hash)
|
41
|
+
Kozo
|
42
|
+
.container
|
43
|
+
.resolve("resource.#{hash.dig(:meta, :resource)}")
|
44
|
+
.tap { |r| hash[:data].each { |k, v| r.send(:"#{k}=", v) } }
|
45
|
+
.tap { |r| r.state_name = hash.dig(:meta, :name) }
|
46
|
+
end
|
47
|
+
|
48
|
+
##
|
49
|
+
# Refetch resource from remote infrastructure
|
50
|
+
#
|
51
|
+
def refresh!
|
52
|
+
Kozo.logger.info "#{address}: refreshing state"
|
53
|
+
|
54
|
+
refresh
|
55
|
+
|
56
|
+
Kozo.logger.info "#{address}: refreshed state"
|
57
|
+
end
|
58
|
+
|
59
|
+
##
|
60
|
+
# Create resource in remote infrastructure
|
61
|
+
#
|
62
|
+
def create!
|
63
|
+
Kozo.logger.info "#{address}: creating resource"
|
64
|
+
|
65
|
+
create
|
66
|
+
|
67
|
+
Kozo.logger.info "#{address}: created resource"
|
68
|
+
end
|
69
|
+
|
70
|
+
##
|
71
|
+
# Update resource in remote infrastructure
|
72
|
+
#
|
73
|
+
def update!
|
74
|
+
Kozo.logger.info "#{address}: updating resource"
|
75
|
+
|
76
|
+
update
|
77
|
+
|
78
|
+
Kozo.logger.info "#{address}: updated resource"
|
79
|
+
end
|
80
|
+
|
81
|
+
##
|
82
|
+
# Destroy resource in remote infrastructure
|
83
|
+
#
|
84
|
+
def destroy!
|
85
|
+
Kozo.logger.info "#{address}: destroying resource"
|
86
|
+
|
87
|
+
destroy
|
88
|
+
|
89
|
+
Kozo.logger.info "#{address}: destroyed resource"
|
90
|
+
end
|
91
|
+
|
92
|
+
protected
|
93
|
+
|
94
|
+
def refresh
|
95
|
+
raise NotImplementedError
|
96
|
+
end
|
97
|
+
|
98
|
+
def create
|
99
|
+
raise NotImplementedError
|
100
|
+
end
|
101
|
+
|
102
|
+
def update
|
103
|
+
raise NotImplementedError
|
104
|
+
end
|
105
|
+
|
106
|
+
def destroy
|
107
|
+
raise NotImplementedError
|
108
|
+
end
|
109
|
+
|
110
|
+
private
|
111
|
+
|
112
|
+
def meta
|
113
|
+
{
|
114
|
+
name: state_name,
|
115
|
+
provider: provider_name,
|
116
|
+
resource: resource_name,
|
117
|
+
}
|
11
118
|
end
|
12
119
|
end
|
13
120
|
end
|
data/lib/kozo/state.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
class State
|
5
|
+
VERSION = 1
|
6
|
+
|
7
|
+
attr_accessor :resources
|
8
|
+
|
9
|
+
def initialize(resources = nil)
|
10
|
+
@resources = Set.new(resources)
|
11
|
+
end
|
12
|
+
|
13
|
+
def ==(other)
|
14
|
+
resources == other.resources
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_h
|
18
|
+
{
|
19
|
+
version: VERSION,
|
20
|
+
kozo_version: Kozo::VERSION,
|
21
|
+
resources: resources.map(&:to_h),
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/kozo/type.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
class Type
|
5
|
+
def self.lookup(type)
|
6
|
+
"Kozo::Types::#{type.to_s.camelize}".constantize
|
7
|
+
rescue NameError
|
8
|
+
raise ArgumentError, "No such type: #{type}"
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.cast(value); end
|
12
|
+
|
13
|
+
def self.serialize(value); end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Types
|
5
|
+
class Boolean < Type
|
6
|
+
# rubocop:disable Lint/BooleanSymbol
|
7
|
+
FALSE_VALUES = [
|
8
|
+
false, 0,
|
9
|
+
"0", :"0",
|
10
|
+
"f", :f,
|
11
|
+
"F", :F,
|
12
|
+
"false", :false,
|
13
|
+
"FALSE", :FALSE,
|
14
|
+
"off", :off,
|
15
|
+
"OFF", :OFF,
|
16
|
+
].freeze
|
17
|
+
# rubocop:enable Lint/BooleanSymbol
|
18
|
+
|
19
|
+
def self.cast(value)
|
20
|
+
return if value.nil?
|
21
|
+
|
22
|
+
!FALSE_VALUES.include?(value)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.serialize(value)
|
26
|
+
value
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Types
|
5
|
+
class Date < Type
|
6
|
+
def self.cast(value)
|
7
|
+
return unless value
|
8
|
+
return value if value.is_a?(::Date)
|
9
|
+
|
10
|
+
::Date.parse(value)
|
11
|
+
rescue ::Date::Error => e
|
12
|
+
raise ArgumentError, e
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.serialize(value)
|
16
|
+
value&.iso8601
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Types
|
5
|
+
class Hash < Type
|
6
|
+
def self.cast(value)
|
7
|
+
return unless value
|
8
|
+
return value if value.is_a?(::Hash)
|
9
|
+
|
10
|
+
value.to_h
|
11
|
+
rescue TypeError, NoMethodError => e
|
12
|
+
raise ArgumentError, e
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.serialize(value)
|
16
|
+
value
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Types
|
5
|
+
class Time < Type
|
6
|
+
def self.cast(value)
|
7
|
+
return unless value
|
8
|
+
return value if value.is_a?(::Time)
|
9
|
+
|
10
|
+
::Time.parse(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.serialize(value)
|
14
|
+
value&.iso8601
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/kozo/version.rb
CHANGED
data/lib/kozo.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "zeitwerk"
|
4
3
|
require "active_support/all"
|
4
|
+
require "active_model"
|
5
|
+
require "colorize"
|
6
|
+
require "dinja"
|
7
|
+
require "zeitwerk"
|
8
|
+
|
9
|
+
require "byebug" if ENV["ENV"] == "development"
|
5
10
|
|
6
11
|
module Kozo
|
7
12
|
class << self
|
@@ -16,11 +21,7 @@ module Kozo
|
|
16
21
|
end
|
17
22
|
|
18
23
|
def container
|
19
|
-
@container ||= Container.new
|
20
|
-
end
|
21
|
-
|
22
|
-
def env
|
23
|
-
@env ||= Environment.new
|
24
|
+
@container ||= Dinja::Container.new
|
24
25
|
end
|
25
26
|
|
26
27
|
def logger
|
@@ -30,13 +31,18 @@ module Kozo
|
|
30
31
|
def setup
|
31
32
|
@loader = Zeitwerk::Loader.for_gem
|
32
33
|
|
34
|
+
# Register inflections
|
33
35
|
instance_eval(File.read(root.join("config/inflections.rb")))
|
34
36
|
|
37
|
+
# Set up code loader
|
35
38
|
loader.enable_reloading
|
39
|
+
loader.ignore(root.join("lib/**/*/dependencies.rb"))
|
40
|
+
loader.collapse(root.join("lib/kozo/concerns"))
|
36
41
|
loader.setup
|
37
42
|
loader.eager_load
|
38
43
|
|
39
|
-
|
44
|
+
# Register dependencies
|
45
|
+
Dir[root.join("lib/**/*/dependencies.rb"), root.join("config/dependencies.rb")].each { |d| container.instance_eval(File.read(d)) }
|
40
46
|
end
|
41
47
|
end
|
42
48
|
end
|