kozo 0.2.0 → 0.3.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 +2 -0
- data/CHANGELOG.md +15 -3
- data/Gemfile +1 -3
- data/Gemfile.lock +44 -51
- data/README.md +2 -0
- data/kozo.gemspec +2 -2
- data/lib/core_ext/boolean.rb +8 -0
- data/lib/core_ext/date.rb +15 -0
- data/lib/core_ext/enumerable.rb +27 -0
- data/lib/core_ext/float.rb +15 -0
- data/lib/core_ext/hash.rb +23 -0
- data/lib/core_ext/integer.rb +15 -0
- data/lib/core_ext/nil_class.rb +8 -0
- data/lib/core_ext/string.rb +11 -0
- data/lib/core_ext/symbol.rb +11 -0
- data/lib/core_ext/time.rb +16 -0
- data/lib/kozo/backend.rb +2 -13
- data/lib/kozo/backends/git.rb +1 -1
- data/lib/kozo/backends/local.rb +12 -4
- data/lib/kozo/cli.rb +11 -3
- data/lib/kozo/command.rb +6 -15
- data/lib/kozo/commands/apply.rb +2 -2
- data/lib/kozo/commands/import.rb +4 -2
- data/lib/kozo/commands/plan.rb +16 -7
- data/lib/kozo/commands/state/delete.rb +39 -0
- data/lib/kozo/commands/state/list.rb +21 -0
- data/lib/kozo/commands/state/show.rb +30 -0
- data/lib/kozo/commands/state/upgrade.rb +45 -0
- data/lib/kozo/commands/state.rb +2 -38
- data/lib/kozo/concerns/attributes.rb +59 -32
- data/lib/kozo/concerns/read_write.rb +45 -0
- data/lib/kozo/configuration.rb +28 -17
- data/lib/kozo/dsl.rb +15 -0
- data/lib/kozo/error.rb +13 -2
- data/lib/kozo/inflector.rb +11 -0
- data/lib/kozo/logger.rb +13 -7
- data/lib/kozo/operation.rb +0 -25
- data/lib/kozo/operations/create.rb +12 -6
- data/lib/kozo/operations/destroy.rb +12 -6
- data/lib/kozo/operations/show.rb +17 -0
- data/lib/kozo/operations/update.rb +17 -0
- data/lib/kozo/options.rb +24 -0
- data/lib/kozo/providers/dummy/resources/dummy.rb +11 -0
- data/lib/kozo/providers/hcloud/provider.rb +1 -1
- data/lib/kozo/providers/hcloud/resource.rb +30 -7
- data/lib/kozo/providers/hcloud/resources/server.rb +16 -8
- data/lib/kozo/providers/hcloud/resources/ssh_key.rb +6 -1
- data/lib/kozo/reference.rb +58 -0
- data/lib/kozo/resource.rb +35 -7
- data/lib/kozo/state.rb +11 -5
- data/lib/kozo/type.rb +3 -3
- data/lib/kozo/types/boolean.rb +0 -4
- data/lib/kozo/types/date.rb +0 -4
- data/lib/kozo/types/float.rb +0 -4
- data/lib/kozo/types/hash.rb +0 -4
- data/lib/kozo/types/integer.rb +0 -4
- data/lib/kozo/types/reference.rb +17 -0
- data/lib/kozo/types/string.rb +0 -4
- data/lib/kozo/types/time.rb +0 -4
- data/lib/kozo/upgrade/1_initial.rb +9 -0
- data/lib/kozo/upgrade/2_remove_kozo_version.rb +11 -0
- data/lib/kozo/upgrade.rb +15 -0
- data/lib/kozo/version.rb +1 -1
- data/lib/kozo.rb +7 -1
- metadata +42 -19
- data/lib/kozo/concerns/mark.rb +0 -25
data/lib/kozo/commands/plan.rb
CHANGED
@@ -7,17 +7,26 @@ module Kozo
|
|
7
7
|
|
8
8
|
attr_reader :operations
|
9
9
|
|
10
|
-
def initialize(*_args)
|
10
|
+
def initialize(configuration, *_args)
|
11
|
+
super(configuration)
|
12
|
+
|
11
13
|
@operations = []
|
12
14
|
end
|
13
15
|
|
14
16
|
def start
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
Refresh.new(configuration).start
|
18
|
+
|
19
|
+
@operations = changes.filter_map do |resource|
|
20
|
+
if !resource.id?
|
21
|
+
if resource.id_changed?
|
22
|
+
# ID changed to nil (resource should be destroyed)
|
23
|
+
Operations::Destroy.new(resource)
|
24
|
+
else
|
25
|
+
# ID is nil (resource should be created)
|
26
|
+
Operations::Create.new(resource)
|
27
|
+
end
|
20
28
|
elsif resource.changed?
|
29
|
+
# Resource should be updated
|
21
30
|
Operations::Update.new(resource)
|
22
31
|
end
|
23
32
|
end
|
@@ -30,7 +39,7 @@ module Kozo
|
|
30
39
|
|
31
40
|
return Kozo.logger.info "\nNo actions have to be performed." if operations.empty?
|
32
41
|
|
33
|
-
Kozo.logger.info "\nKozo will perform the following actions
|
42
|
+
Kozo.logger.info "\nKozo will perform the following actions:\n"
|
34
43
|
|
35
44
|
operations.each { |o| Kozo.logger.info o.to_s }
|
36
45
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Commands
|
5
|
+
class State
|
6
|
+
class Delete < State
|
7
|
+
self.description = "Delete a resource from the state"
|
8
|
+
|
9
|
+
attr_reader :address
|
10
|
+
|
11
|
+
def initialize(configuration, *args)
|
12
|
+
@configuration = configuration
|
13
|
+
@address = args.shift
|
14
|
+
|
15
|
+
raise UsageError, "address not specified" unless address
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
resource = state
|
20
|
+
.resources
|
21
|
+
.find { |r| r.address == address }
|
22
|
+
|
23
|
+
raise StateError, "no such resource address: #{address}" unless resource
|
24
|
+
|
25
|
+
state
|
26
|
+
.resources
|
27
|
+
.delete_if { |r| r.address == address }
|
28
|
+
|
29
|
+
Kozo.logger.info resource.address
|
30
|
+
|
31
|
+
# Write state
|
32
|
+
configuration
|
33
|
+
.backend
|
34
|
+
.state = state
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Commands
|
5
|
+
class State
|
6
|
+
class List < State
|
7
|
+
self.description = "List resources in the state"
|
8
|
+
|
9
|
+
def initialize(configuration, *_args)
|
10
|
+
@configuration = configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def start
|
14
|
+
state
|
15
|
+
.resources
|
16
|
+
.each { |r| Kozo.logger.info r.address }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Commands
|
5
|
+
class State
|
6
|
+
class Show < State
|
7
|
+
self.description = "Show a resource in the state"
|
8
|
+
|
9
|
+
attr_reader :address
|
10
|
+
|
11
|
+
def initialize(configuration, *args)
|
12
|
+
@configuration = configuration
|
13
|
+
@address = args.shift
|
14
|
+
|
15
|
+
raise UsageError, "address not specified" unless address
|
16
|
+
end
|
17
|
+
|
18
|
+
def start
|
19
|
+
resource = state
|
20
|
+
.resources
|
21
|
+
.find { |r| r.address == address }
|
22
|
+
|
23
|
+
raise StateError, "no such resource address: #{address}" unless resource
|
24
|
+
|
25
|
+
Kozo.logger.info Operations::Show.new(resource).to_s
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Commands
|
5
|
+
class State
|
6
|
+
class Upgrade < State
|
7
|
+
self.description = "Upgrade the state file to the latest version"
|
8
|
+
|
9
|
+
def initialize(configuration, *_args)
|
10
|
+
@configuration = configuration
|
11
|
+
end
|
12
|
+
|
13
|
+
def start
|
14
|
+
return Kozo.logger.info "State file already up to date." if state.compatible?
|
15
|
+
|
16
|
+
((state.version + 1)..Kozo::State::VERSION).each do |version|
|
17
|
+
file = Dir[Kozo.root.join("lib/kozo/upgrade/#{version}_*")].first
|
18
|
+
|
19
|
+
raise NotImplementedError, "upgrade file to version #{version} not found" unless file
|
20
|
+
|
21
|
+
Kozo.logger.info "Upgrading state file to version #{version}"
|
22
|
+
|
23
|
+
klass = File
|
24
|
+
.basename(file, ".rb")
|
25
|
+
.delete_prefix("#{version}_")
|
26
|
+
.prepend("kozo/upgrade/")
|
27
|
+
.camelize
|
28
|
+
.constantize
|
29
|
+
|
30
|
+
# Write state
|
31
|
+
configuration.backend.state = klass
|
32
|
+
.new(state)
|
33
|
+
.upgrade
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def state
|
38
|
+
@state ||= configuration
|
39
|
+
.backend
|
40
|
+
.state(verify: false)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/kozo/commands/state.rb
CHANGED
@@ -7,7 +7,7 @@ module Kozo
|
|
7
7
|
|
8
8
|
attr_reader :subcommand
|
9
9
|
|
10
|
-
def initialize(*args)
|
10
|
+
def initialize(configuration, *args)
|
11
11
|
subcommand = args.shift
|
12
12
|
|
13
13
|
raise UsageError unless subcommand
|
@@ -16,49 +16,13 @@ module Kozo
|
|
16
16
|
|
17
17
|
raise UsageError, "unknown subcommand: state #{subcommand}" unless klass
|
18
18
|
|
19
|
-
@subcommand = klass.new(*args)
|
19
|
+
@subcommand = klass.new(configuration, *args)
|
20
20
|
end
|
21
21
|
|
22
22
|
def start
|
23
23
|
subcommand
|
24
24
|
.start
|
25
25
|
end
|
26
|
-
|
27
|
-
class List < State
|
28
|
-
self.description = "List resources in the state"
|
29
|
-
|
30
|
-
def initialize(*_args); end
|
31
|
-
|
32
|
-
def start
|
33
|
-
state
|
34
|
-
.resources
|
35
|
-
.each { |r| Kozo.logger.info r.address }
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
class Show < State
|
40
|
-
self.description = "Show a resource in the state"
|
41
|
-
|
42
|
-
attr_reader :address
|
43
|
-
|
44
|
-
def initialize(*args)
|
45
|
-
address = args.shift
|
46
|
-
|
47
|
-
raise UsageError, "address not specified" unless address
|
48
|
-
|
49
|
-
@address = address
|
50
|
-
end
|
51
|
-
|
52
|
-
def start
|
53
|
-
resource = state
|
54
|
-
.resources
|
55
|
-
.find { |r| r.address == address }
|
56
|
-
|
57
|
-
raise StateError, "no such resource address: #{address}" unless resource
|
58
|
-
|
59
|
-
Kozo.logger.info Operations::Show.new(resource).to_s
|
60
|
-
end
|
61
|
-
end
|
62
26
|
end
|
63
27
|
end
|
64
28
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
3
4
|
module Kozo
|
4
5
|
module Attributes
|
5
6
|
extend ActiveSupport::Concern
|
@@ -17,19 +18,54 @@ module Kozo
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def write_attribute(name, value)
|
21
|
+
attribute_types[name] => { multiple:, type:, wrapped: }
|
22
|
+
|
20
23
|
try(:track_change!, name, value)
|
21
24
|
|
22
|
-
value
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
# Unwrap value(s) (call #name on receiver)
|
26
|
+
value = value.send_wrap { |v| v.try(:name) || v } if wrapped
|
27
|
+
|
28
|
+
# Cast value(s)
|
29
|
+
value = value.send_wrap { |v| type.cast(v) }
|
30
|
+
|
31
|
+
# Convert value(s) to array
|
32
|
+
value = Array(value) if multiple
|
27
33
|
|
34
|
+
# Set value(s)
|
28
35
|
instance_variable_set(:"@#{name}", value)
|
29
36
|
end
|
37
|
+
|
38
|
+
def attributes
|
39
|
+
attribute_names
|
40
|
+
.to_h { |name| [name, read_attribute(name)] }
|
41
|
+
end
|
42
|
+
|
43
|
+
def readable_attributes
|
44
|
+
readable_attribute_names
|
45
|
+
.to_h { |name| [name, read_attribute(name)] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def writeable_attributes
|
49
|
+
writeable_attribute_names
|
50
|
+
.to_h { |name| [name, read_attribute(name)] }
|
51
|
+
end
|
52
|
+
|
53
|
+
def creatable_attributes
|
54
|
+
creatable_attribute_names
|
55
|
+
.to_h { |name| [name, read_attribute(name).send_wrap(:as_h)] }
|
56
|
+
end
|
57
|
+
|
58
|
+
def updatable_attributes
|
59
|
+
updatable_attribute_names
|
60
|
+
.to_h { |name| [name, read_attribute(name).send_wrap(:as_h)] }
|
61
|
+
end
|
62
|
+
|
63
|
+
delegate :attribute_names,
|
64
|
+
:readable_attribute_names,
|
65
|
+
:writeable_attribute_names,
|
66
|
+
to: :class
|
30
67
|
end
|
31
68
|
|
32
|
-
# rubocop:disable Metrics/BlockLength
|
33
69
|
class_methods do
|
34
70
|
def inherited(sub_class)
|
35
71
|
super
|
@@ -43,12 +79,13 @@ module Kozo
|
|
43
79
|
|
44
80
|
try(:track, name)
|
45
81
|
|
46
|
-
|
82
|
+
attribute_types[name] = {
|
47
83
|
multiple: !!options[:multiple],
|
48
|
-
|
49
|
-
argument: !!options.fetch(:argument, true),
|
84
|
+
wrapped: !!options.fetch(:wrapped, false),
|
50
85
|
type: type,
|
51
86
|
default: options[:default],
|
87
|
+
read: read?,
|
88
|
+
write: write?,
|
52
89
|
}
|
53
90
|
|
54
91
|
# Define getter
|
@@ -57,43 +94,33 @@ module Kozo
|
|
57
94
|
define_method(:"#{name}?") { !!read_attribute(name) }
|
58
95
|
end
|
59
96
|
|
60
|
-
# Set visibility to
|
61
|
-
|
97
|
+
# Set getter visibility to private if it's writeonly
|
98
|
+
private(name) if writeonly?
|
62
99
|
|
63
100
|
# Define setter
|
64
101
|
define_method(:"#{name}=") { |value| write_attribute(name, value) } unless method_defined? :"#{name}="
|
65
102
|
|
66
|
-
# Set visibility to
|
67
|
-
|
103
|
+
# Set setter visibility to private if it's readonly
|
104
|
+
private(:"#{name}=") if readonly?
|
68
105
|
end
|
69
106
|
|
70
107
|
def attribute_names
|
71
108
|
@attribute_names ||= attribute_types
|
72
|
-
.select { |_k, v| v[:attribute] }
|
73
109
|
.keys
|
74
110
|
end
|
75
111
|
|
76
|
-
def
|
77
|
-
|
78
|
-
.select { |_k, v| v[:
|
112
|
+
def readable_attribute_names
|
113
|
+
attribute_types
|
114
|
+
.select { |_k, v| v[:read] }
|
79
115
|
.keys
|
80
116
|
end
|
81
|
-
end
|
82
|
-
# rubocop:enable Metrics/BlockLength
|
83
117
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
def arguments
|
91
|
-
argument_names
|
92
|
-
.map { |name| [name, read_attribute(name)] }
|
93
|
-
.to_h
|
118
|
+
def writeable_attribute_names
|
119
|
+
attribute_types
|
120
|
+
.select { |_k, v| v[:write] }
|
121
|
+
.keys
|
122
|
+
end
|
94
123
|
end
|
95
|
-
|
96
|
-
delegate :attribute_names, to: :class
|
97
|
-
delegate :argument_names, to: :class
|
98
124
|
end
|
99
125
|
end
|
126
|
+
# rubocop:enable Metrics/BlockLength
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module ReadWrite
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :mode, default: :readwrite
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
def readwrite
|
13
|
+
self.mode = :readwrite
|
14
|
+
end
|
15
|
+
|
16
|
+
def readwrite?
|
17
|
+
mode == :readwrite
|
18
|
+
end
|
19
|
+
|
20
|
+
def readonly
|
21
|
+
self.mode = :read
|
22
|
+
end
|
23
|
+
|
24
|
+
def readonly?
|
25
|
+
mode == :read
|
26
|
+
end
|
27
|
+
|
28
|
+
def read?
|
29
|
+
mode == :read || mode == :readwrite
|
30
|
+
end
|
31
|
+
|
32
|
+
def writeonly
|
33
|
+
self.mode = :write
|
34
|
+
end
|
35
|
+
|
36
|
+
def writeonly?
|
37
|
+
mode == :write
|
38
|
+
end
|
39
|
+
|
40
|
+
def write?
|
41
|
+
mode == :write || mode == :readwrite
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/kozo/configuration.rb
CHANGED
@@ -11,42 +11,53 @@ module Kozo
|
|
11
11
|
@resources = Set.new
|
12
12
|
end
|
13
13
|
|
14
|
-
def backend
|
15
|
-
@backend ||= Kozo
|
16
|
-
.container
|
17
|
-
.resolve("backend.local", self, directory)
|
18
|
-
end
|
19
|
-
|
20
14
|
def changes
|
21
15
|
@changes ||= begin
|
22
16
|
# Copy resources in state
|
23
|
-
changes =
|
24
|
-
.state
|
17
|
+
changes = state
|
25
18
|
.resources
|
26
19
|
.map(&:dup)
|
27
20
|
.each(&:clear_changes)
|
28
21
|
.each do |resource|
|
22
|
+
# Find resource in configuration
|
29
23
|
configured = resources.find { |r| r.address == resource.address }
|
30
24
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
25
|
+
if configured
|
26
|
+
# Assign updated attributes (mark for update)
|
27
|
+
resource.assign_attributes(configured&.readable_attributes&.slice(*configured&.updatable_attribute_names))
|
28
|
+
else
|
29
|
+
# Set attributes to nil (mark for destruction)
|
30
|
+
resource.assign_attributes(resource.readable_attributes.transform_values { nil })
|
31
|
+
end
|
36
32
|
end
|
37
33
|
|
38
|
-
# Append resources not in state
|
34
|
+
# Append resources not in state (mark for creation)
|
39
35
|
changes += resources
|
40
|
-
.reject { |r|
|
41
|
-
.map { |r| r.class.new(state_name: r.state_name, **r.
|
42
|
-
|
36
|
+
.reject { |r| state.resources.any? { |res| res.address == r.address } }
|
37
|
+
.map { |r| r.class.new(state_name: r.state_name, **r.writeable_attributes) }
|
38
|
+
|
39
|
+
# Resolve references
|
40
|
+
changes
|
41
|
+
.each { |c| c.writeable_attributes.each_value { |r| r.send_wrap(:try, :resolve, self) } }
|
43
42
|
|
44
43
|
changes
|
45
44
|
end
|
46
45
|
end
|
47
46
|
|
47
|
+
def backend
|
48
|
+
@backend ||= Kozo
|
49
|
+
.container
|
50
|
+
.resolve("backend.local", self, directory)
|
51
|
+
end
|
52
|
+
|
53
|
+
delegate :state, to: :backend
|
54
|
+
|
48
55
|
def to_s
|
49
56
|
"directory: #{directory}"
|
50
57
|
end
|
58
|
+
|
59
|
+
def inspect
|
60
|
+
"#<#{self.class.name} #{self}>"
|
61
|
+
end
|
51
62
|
end
|
52
63
|
end
|
data/lib/kozo/dsl.rb
CHANGED
@@ -45,6 +45,21 @@ module Kozo
|
|
45
45
|
configuration.resources << resource
|
46
46
|
end
|
47
47
|
|
48
|
+
def method_missing(method_name, *arguments, &block)
|
49
|
+
resource_class = Kozo
|
50
|
+
.container
|
51
|
+
.resolve("resource.#{method_name}")
|
52
|
+
.class
|
53
|
+
|
54
|
+
Reference.new(resource_class: resource_class)
|
55
|
+
rescue Dinja::Container::DependencyNotRegistered
|
56
|
+
super
|
57
|
+
end
|
58
|
+
|
59
|
+
def respond_to_missing?(method_name, include_private = false)
|
60
|
+
Kozo.container.resolve!("resource.#{method_name}").present? || super
|
61
|
+
end
|
62
|
+
|
48
63
|
private
|
49
64
|
|
50
65
|
def resolve(resource, type, *args)
|
data/lib/kozo/error.rb
CHANGED
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Kozo
|
4
|
+
# Base class
|
4
5
|
class Error < StandardError; end
|
5
6
|
|
6
|
-
|
7
|
-
|
7
|
+
# Raised when usage is printed
|
8
8
|
class ExitError < Error; end
|
9
9
|
|
10
|
+
# Raised when CLI arguments are invalid
|
10
11
|
class UsageError < Error; end
|
11
12
|
|
13
|
+
# Raised when a resource definition was invalid
|
14
|
+
class InvalidResource < Error; end
|
15
|
+
|
16
|
+
# Raised when a resource cannot match constraints (uniqueness, etc.)
|
17
|
+
class ResourceError < Error; end
|
18
|
+
|
19
|
+
# Raised when state invalid or resource not found in state
|
12
20
|
class StateError < Error; end
|
21
|
+
|
22
|
+
# Raised when performing an operation on a resource that was not persisted yet
|
23
|
+
class NotPersisted < Error; end
|
13
24
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
class Inflector < Zeitwerk::GemInflector
|
5
|
+
def camelize(basename, abspath)
|
6
|
+
return super(Regexp.last_match(2), abspath) if basename =~ /\A(\d+)_(.*)/ && abspath.include?("kozo/upgrade")
|
7
|
+
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
data/lib/kozo/logger.rb
CHANGED
@@ -12,16 +12,12 @@ module Kozo
|
|
12
12
|
private
|
13
13
|
|
14
14
|
def level
|
15
|
-
Kozo.options.verbose? ? "debug" :
|
15
|
+
Kozo.options.verbose? ? "debug" : "info"
|
16
16
|
end
|
17
17
|
|
18
18
|
def formatter
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
class Formatter < ::Logger::Formatter
|
23
|
-
def call(severity, _time, _progname, msg)
|
24
|
-
abort("#{File.basename($PROGRAM_NAME)}: #{msg[0].downcase}#{msg[1..]}".white.on_red) if severity == "FATAL"
|
19
|
+
proc do |severity, _time, _progname, msg|
|
20
|
+
abort("#{File.basename($PROGRAM_NAME)}: #{msg}".white.on_red) if severity == "FATAL"
|
25
21
|
|
26
22
|
msg = "#{msg}\n"
|
27
23
|
msg = msg.yellow if severity == "DEBUG"
|
@@ -30,5 +26,15 @@ module Kozo
|
|
30
26
|
msg
|
31
27
|
end
|
32
28
|
end
|
29
|
+
|
30
|
+
class Debug < Logger
|
31
|
+
def level
|
32
|
+
Kozo.options.debug? ? "debug" : "fatal"
|
33
|
+
end
|
34
|
+
|
35
|
+
def formatter
|
36
|
+
->(_severity, _time, _progname, msg) { msg.magenta }
|
37
|
+
end
|
38
|
+
end
|
33
39
|
end
|
34
40
|
end
|
data/lib/kozo/operation.rb
CHANGED
@@ -13,30 +13,5 @@ module Kozo
|
|
13
13
|
def apply(_state)
|
14
14
|
raise NotImplementedError
|
15
15
|
end
|
16
|
-
|
17
|
-
def to_s
|
18
|
-
resource_to_s
|
19
|
-
end
|
20
|
-
|
21
|
-
protected
|
22
|
-
|
23
|
-
def resource_to_s
|
24
|
-
<<~DSL.chomp
|
25
|
-
#{"# #{resource.address}:".bold}
|
26
|
-
#{display_symbol} resource "#{resource.resource_name}", "#{resource.state_name}" do |r|
|
27
|
-
#{attributes_to_s}
|
28
|
-
end
|
29
|
-
|
30
|
-
DSL
|
31
|
-
end
|
32
|
-
|
33
|
-
def attributes_to_s
|
34
|
-
l = resource.attribute_names.map(&:length).max || 1
|
35
|
-
|
36
|
-
resource
|
37
|
-
.attributes
|
38
|
-
.map { |k, v| "#{resource.changes.key?(k) ? display_symbol : ' '} r.#{k.to_s.ljust(l)} = \"#{v.to_s.chomp.truncate(75)}\"" }
|
39
|
-
.join("\n ")
|
40
|
-
end
|
41
16
|
end
|
42
17
|
end
|
@@ -14,15 +14,21 @@ module Kozo
|
|
14
14
|
state.resources << resource
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
def attributes_to_s
|
17
|
+
def to_s
|
20
18
|
l = resource.attribute_names.map(&:length).max || 1
|
21
19
|
|
22
|
-
resource
|
20
|
+
attrs = resource
|
23
21
|
.attributes
|
24
|
-
.map { |k, v| "#{resource.changes.key?(k) ? display_symbol : ' '}
|
25
|
-
.join("\n
|
22
|
+
.map { |k, v| " #{resource.changes.key?(k) ? display_symbol : ' '} r.#{k.to_s.ljust(l)} = #{v.blank? && resource.writeable_attribute_names.exclude?(k) ? '(known after apply)' : (v.as_s.indent(4)[4..]).to_s}" }
|
23
|
+
.join("\n")
|
24
|
+
|
25
|
+
<<~DSL.chomp
|
26
|
+
#{"# #{resource.address}:".bold}
|
27
|
+
#{display_symbol} resource "#{resource.resource_name}", "#{resource.state_name}" do |r|
|
28
|
+
#{attrs}
|
29
|
+
end
|
30
|
+
|
31
|
+
DSL
|
26
32
|
end
|
27
33
|
end
|
28
34
|
end
|
@@ -14,15 +14,21 @@ module Kozo
|
|
14
14
|
state.resources.delete(resource)
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
def attributes_to_s
|
17
|
+
def to_s
|
20
18
|
l = resource.attribute_names.map(&:length).max || 1
|
21
19
|
|
22
|
-
resource
|
20
|
+
attrs = resource
|
23
21
|
.attribute_names
|
24
|
-
.map { |k| "#{display_symbol}
|
25
|
-
.join("\n
|
22
|
+
.map { |k| " #{display_symbol} r.#{k.to_s.ljust(l)} = #{resource.send(:"#{k}_was").as_s.indent(4)[4..]}" }
|
23
|
+
.join("\n")
|
24
|
+
|
25
|
+
<<~DSL.chomp
|
26
|
+
#{"# #{resource.address}:".bold}
|
27
|
+
#{display_symbol} resource "#{resource.resource_name}", "#{resource.state_name}" do |r|
|
28
|
+
#{attrs}
|
29
|
+
end
|
30
|
+
|
31
|
+
DSL
|
26
32
|
end
|
27
33
|
end
|
28
34
|
end
|