kozo 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|