kozo 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.
- checksums.yaml +7 -0
- data/.github/dependabot.yml +14 -0
- data/.github/workflows/ci.yml +81 -0
- data/.gitignore +69 -0
- data/.overcommit.yml +31 -0
- data/.rspec +2 -0
- data/.rubocop.yml +70 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +9 -0
- data/Gemfile.lock +126 -0
- data/LICENSE.md +20 -0
- data/README.md +27 -0
- data/Rakefile +11 -0
- data/bin/bundle +118 -0
- data/bin/console +7 -0
- data/bin/kozo +9 -0
- data/bin/rspec +28 -0
- data/bin/version +62 -0
- data/config/application.rb +6 -0
- data/config/dependencies.rb +30 -0
- data/config/inflections.rb +8 -0
- data/kozo.gemspec +45 -0
- data/lib/kozo.rb +48 -0
- data/lib/kozo/backends/base.rb +31 -0
- data/lib/kozo/backends/local.rb +34 -0
- data/lib/kozo/cli.rb +64 -0
- data/lib/kozo/commands/base.rb +21 -0
- data/lib/kozo/commands/plan.rb +13 -0
- data/lib/kozo/configuration.rb +25 -0
- data/lib/kozo/container.rb +35 -0
- data/lib/kozo/dsl.rb +52 -0
- data/lib/kozo/environment.rb +27 -0
- data/lib/kozo/logger.rb +30 -0
- data/lib/kozo/options.rb +31 -0
- data/lib/kozo/provider.rb +7 -0
- data/lib/kozo/providers/hcloud/provider.rb +17 -0
- data/lib/kozo/providers/hcloud/resource.rb +11 -0
- data/lib/kozo/providers/hcloud/resources/ssh_key.rb +15 -0
- data/lib/kozo/providers/null/provider.rb +15 -0
- data/lib/kozo/providers/null/resource.rb +11 -0
- data/lib/kozo/providers/null/resources/null.rb +13 -0
- data/lib/kozo/resource.rb +13 -0
- data/lib/kozo/version.rb +16 -0
- data/log/.keep +0 -0
- metadata +304 -0
data/README.md
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# Kozo
|
2
|
+
|
3
|
+

|
4
|
+

|
5
|
+
|
6
|
+
_Kōzō_ (構造) is an open-source tool to manage your cloud resources based on the [infrastructure as code](https://en.wikipedia.org/wiki/Infrastructure_as_code) principle.
|
7
|
+
It leverages the power of [Ruby](https://www.ruby-lang.org/en/) to allow you to declare your infrastructure in your favourite language.
|
8
|
+
|
9
|
+
## Release
|
10
|
+
|
11
|
+
Update the changelog and bump the version using the `bin/version` tool.
|
12
|
+
Run `bin/version --help` to see all parameters.
|
13
|
+
Create a git tag for the version and push it to Github.
|
14
|
+
A Ruby gem will automatically be built and pushed to the [RubyGems](https://www.rubygems.org/).
|
15
|
+
|
16
|
+
```sh
|
17
|
+
bin/version version 1.0.0
|
18
|
+
git add lib/kozo/version.rb
|
19
|
+
git commit -m "Bump version to v1.0.0"
|
20
|
+
git tag v1.0.0
|
21
|
+
git push origin master
|
22
|
+
git push origin v1.0.0
|
23
|
+
```
|
24
|
+
|
25
|
+
## License
|
26
|
+
|
27
|
+
See [LICENSE.md](LICENSE.md).
|
data/Rakefile
ADDED
data/bin/bundle
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'bundle' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "rubygems"
|
12
|
+
|
13
|
+
m = Module.new do
|
14
|
+
module_function
|
15
|
+
|
16
|
+
def invoked_as_script?
|
17
|
+
File.expand_path($PROGRAM_NAME) == File.expand_path(__FILE__)
|
18
|
+
end
|
19
|
+
|
20
|
+
def env_var_version
|
21
|
+
ENV["BUNDLER_VERSION"]
|
22
|
+
end
|
23
|
+
|
24
|
+
def cli_arg_version
|
25
|
+
return unless invoked_as_script? # don't want to hijack other binstubs
|
26
|
+
return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
|
27
|
+
|
28
|
+
bundler_version = nil
|
29
|
+
update_index = nil
|
30
|
+
ARGV.each_with_index do |a, i|
|
31
|
+
bundler_version = a if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
|
32
|
+
next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o
|
33
|
+
|
34
|
+
bundler_version = Regexp.last_match(1)
|
35
|
+
update_index = i
|
36
|
+
end
|
37
|
+
bundler_version
|
38
|
+
end
|
39
|
+
|
40
|
+
def gemfile
|
41
|
+
gemfile = ENV["BUNDLE_GEMFILE"]
|
42
|
+
return gemfile if gemfile && !gemfile.empty?
|
43
|
+
|
44
|
+
File.expand_path("../Gemfile", __dir__)
|
45
|
+
end
|
46
|
+
|
47
|
+
def lockfile
|
48
|
+
lockfile =
|
49
|
+
case File.basename(gemfile)
|
50
|
+
when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
|
51
|
+
else "#{gemfile}.lock"
|
52
|
+
end
|
53
|
+
File.expand_path(lockfile)
|
54
|
+
end
|
55
|
+
|
56
|
+
def lockfile_version
|
57
|
+
return unless File.file?(lockfile)
|
58
|
+
|
59
|
+
lockfile_contents = File.read(lockfile)
|
60
|
+
return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o
|
61
|
+
|
62
|
+
Regexp.last_match(1)
|
63
|
+
end
|
64
|
+
|
65
|
+
def bundler_version
|
66
|
+
@bundler_version ||=
|
67
|
+
env_var_version || cli_arg_version ||
|
68
|
+
lockfile_version
|
69
|
+
end
|
70
|
+
|
71
|
+
def bundler_requirement
|
72
|
+
return "#{Gem::Requirement.default}.a" unless bundler_version
|
73
|
+
|
74
|
+
bundler_gem_version = Gem::Version.new(bundler_version)
|
75
|
+
|
76
|
+
requirement = bundler_gem_version.approximate_recommendation
|
77
|
+
|
78
|
+
return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
|
79
|
+
|
80
|
+
requirement += ".a" if bundler_gem_version.prerelease?
|
81
|
+
|
82
|
+
requirement
|
83
|
+
end
|
84
|
+
|
85
|
+
def load_bundler!
|
86
|
+
ENV["BUNDLE_GEMFILE"] ||= gemfile
|
87
|
+
|
88
|
+
activate_bundler
|
89
|
+
end
|
90
|
+
|
91
|
+
def activate_bundler
|
92
|
+
gem_error = activation_error_handling do
|
93
|
+
gem "bundler", bundler_requirement
|
94
|
+
end
|
95
|
+
return if gem_error.nil?
|
96
|
+
|
97
|
+
require_error = activation_error_handling do
|
98
|
+
require "bundler/version"
|
99
|
+
end
|
100
|
+
if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
|
101
|
+
return
|
102
|
+
end
|
103
|
+
|
104
|
+
warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
|
105
|
+
exit 42
|
106
|
+
end
|
107
|
+
|
108
|
+
def activation_error_handling
|
109
|
+
yield
|
110
|
+
nil
|
111
|
+
rescue StandardError, LoadError => e
|
112
|
+
e
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
m.load_bundler!
|
117
|
+
|
118
|
+
load Gem.bin_path("bundler", "bundle") if m.invoked_as_script?
|
data/bin/console
ADDED
data/bin/kozo
ADDED
data/bin/rspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
#
|
5
|
+
# This file was generated by Bundler.
|
6
|
+
#
|
7
|
+
# The application 'rspec' is installed as part of a gem, and
|
8
|
+
# this file is here to facilitate running it.
|
9
|
+
#
|
10
|
+
|
11
|
+
require "pathname"
|
12
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", Pathname.new(__FILE__).realpath)
|
13
|
+
|
14
|
+
bundle_binstub = File.expand_path("bundle", __dir__)
|
15
|
+
|
16
|
+
if File.file?(bundle_binstub)
|
17
|
+
if /This file was generated by Bundler/.match?(File.read(bundle_binstub, 300))
|
18
|
+
load(bundle_binstub)
|
19
|
+
else
|
20
|
+
abort("Your `bin/bundle` was not generated by Bundler, so this binstub cannot run.
|
21
|
+
Replace `bin/bundle` by running `bundle binstubs bundler --force`, then run this command again.")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
require "rubygems"
|
26
|
+
require "bundler/setup"
|
27
|
+
|
28
|
+
load Gem.bin_path("rspec-core", "rspec")
|
data/bin/version
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
require_relative "../config/application"
|
5
|
+
|
6
|
+
FILE = Kozo.root.join("lib/kozo/version.rb")
|
7
|
+
|
8
|
+
def usage(error: false)
|
9
|
+
puts "Usage: #{$PROGRAM_NAME} [major [VERSION] | minor [VERSION] | patch [VERSION] | pre VERSION]"
|
10
|
+
puts " #{$PROGRAM_NAME} major\t\tIncrement major version number"
|
11
|
+
puts " #{$PROGRAM_NAME} major VERSION\tSet major version number"
|
12
|
+
puts " #{$PROGRAM_NAME} minor\t\tIncrement minor version number"
|
13
|
+
puts " #{$PROGRAM_NAME} minor VERSION\tSet minor version number"
|
14
|
+
puts " #{$PROGRAM_NAME} patch\t\tIncrement patch version number"
|
15
|
+
puts " #{$PROGRAM_NAME} patch VERSION\tSet patch version number"
|
16
|
+
puts " #{$PROGRAM_NAME} pre\t\tClear pre version number"
|
17
|
+
puts " #{$PROGRAM_NAME} pre VERSION\tSet pre version number"
|
18
|
+
puts " #{$PROGRAM_NAME} version VERSION\tSet entire version number"
|
19
|
+
|
20
|
+
exit 1 if error
|
21
|
+
end
|
22
|
+
|
23
|
+
def bump(hash)
|
24
|
+
hash.each do |level, version|
|
25
|
+
File.write FILE, File.read(FILE).gsub(/#{level}( +)= [^\n]*/) { "#{level}#{$LAST_MATCH_INFO[1]}= #{version}" }
|
26
|
+
end
|
27
|
+
|
28
|
+
silence_warnings { load FILE }
|
29
|
+
|
30
|
+
File.write FILE_JS, File.read(FILE_JS).gsub(/"version": "[^"]*"/) { "\"version\": \"#{Kozo::VERSION}\"" }
|
31
|
+
end
|
32
|
+
|
33
|
+
case ARGV.shift&.to_sym
|
34
|
+
when nil
|
35
|
+
# Print version
|
36
|
+
puts "v#{Kozo::VERSION}"
|
37
|
+
when :version
|
38
|
+
usage(error: true) unless ARGV.any?
|
39
|
+
|
40
|
+
version, pre = ARGV.shift.split("-")
|
41
|
+
major, minor, patch = version.split(".")
|
42
|
+
|
43
|
+
bump MAJOR: major, MINOR: minor, PATCH: patch, PRE: (pre ? "\"#{pre}\"" : "nil")
|
44
|
+
puts "Setting version to #{Kozo::VERSION}"
|
45
|
+
when :major
|
46
|
+
# Bump major version
|
47
|
+
bump MAJOR: (ARGV.pop || Kozo::Version::MAJOR + 1), MINOR: 0, PATCH: 0, PRE: "nil"
|
48
|
+
puts "Bumping version to #{Kozo::VERSION}"
|
49
|
+
when :minor
|
50
|
+
# Bump minor version
|
51
|
+
bump MINOR: (ARGV.pop || Kozo::Version::MINOR + 1), PATCH: 0, PRE: "nil"
|
52
|
+
puts "Bumping version to #{Kozo::VERSION}"
|
53
|
+
when :patch
|
54
|
+
# Bump patch version
|
55
|
+
bump PATCH: (ARGV.pop || Kozo::Version::PATCH + 1), PRE: "nil"
|
56
|
+
puts "Bumping version to #{Kozo::VERSION}"
|
57
|
+
when :pre
|
58
|
+
# Set or clear patch version
|
59
|
+
bump PRE: (ARGV.any? ? "\"#{ARGV.shift}\"" : "nil")
|
60
|
+
else
|
61
|
+
usage
|
62
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
##
|
4
|
+
# Backends
|
5
|
+
#
|
6
|
+
register("backend.local") do |directory|
|
7
|
+
Kozo::Backends::Local.new(directory)
|
8
|
+
end
|
9
|
+
|
10
|
+
##
|
11
|
+
# Null provider
|
12
|
+
#
|
13
|
+
register("provider.null") do
|
14
|
+
Kozo::Providers::Null::Provider.new
|
15
|
+
end
|
16
|
+
|
17
|
+
register("resource.null") do
|
18
|
+
Kozo::Providers::Null::Resources::Null.new
|
19
|
+
end
|
20
|
+
|
21
|
+
##
|
22
|
+
# HCloud
|
23
|
+
#
|
24
|
+
register("provider.hcloud") do
|
25
|
+
Kozo::Providers::HCloud::Provider.new
|
26
|
+
end
|
27
|
+
|
28
|
+
register("resource.hcloud_ssh_key") do
|
29
|
+
Kozo::Providers::HCloud::Resources::SSHKey.new
|
30
|
+
end
|
data/kozo.gemspec
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/kozo/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "kozo"
|
7
|
+
spec.version = Kozo::VERSION
|
8
|
+
spec.authors = ["Florian Dejonckheere"]
|
9
|
+
spec.email = ["florian@floriandejonckheere.be"]
|
10
|
+
|
11
|
+
spec.summary = "Declarative cloud infrastructure"
|
12
|
+
spec.description = "Declaratively create, modify and destroy cloud infrastructure in your favourite language"
|
13
|
+
spec.homepage = "http://github.com/floriandejonckheere/kozo"
|
14
|
+
spec.license = "MIT"
|
15
|
+
spec.required_ruby_version = Gem::Requirement.new(">= 2.7.2")
|
16
|
+
|
17
|
+
spec.metadata["source_code_uri"] = "https://github.com/floriandejonckheere/kozo"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
22
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
23
|
+
end
|
24
|
+
spec.bindir = "bin"
|
25
|
+
spec.executables = spec.files.grep(%r(^bin/)) { |f| File.basename(f) }
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_runtime_dependency "activesupport"
|
29
|
+
spec.add_runtime_dependency "zeitwerk"
|
30
|
+
|
31
|
+
spec.add_development_dependency "rubocop"
|
32
|
+
spec.add_development_dependency "rubocop-performance"
|
33
|
+
spec.add_development_dependency "rubocop-rspec"
|
34
|
+
|
35
|
+
spec.add_development_dependency "climate_control"
|
36
|
+
spec.add_development_dependency "factory_bot"
|
37
|
+
spec.add_development_dependency "ffaker"
|
38
|
+
spec.add_development_dependency "overcommit"
|
39
|
+
spec.add_development_dependency "pry-byebug"
|
40
|
+
spec.add_development_dependency "rspec", "~> 3.10"
|
41
|
+
spec.add_development_dependency "shoulda-matchers"
|
42
|
+
spec.add_development_dependency "super_diff"
|
43
|
+
spec.add_development_dependency "timecop"
|
44
|
+
spec.add_development_dependency "webmock"
|
45
|
+
end
|
data/lib/kozo.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "zeitwerk"
|
4
|
+
require "active_support/all"
|
5
|
+
|
6
|
+
module Kozo
|
7
|
+
class << self
|
8
|
+
attr_reader :loader
|
9
|
+
|
10
|
+
def root
|
11
|
+
@root ||= Pathname.new(File.expand_path(File.join("..", ".."), __FILE__))
|
12
|
+
end
|
13
|
+
|
14
|
+
def options
|
15
|
+
@options ||= Options.new
|
16
|
+
end
|
17
|
+
|
18
|
+
def container
|
19
|
+
@container ||= Container.new
|
20
|
+
end
|
21
|
+
|
22
|
+
def env
|
23
|
+
@env ||= Environment.new
|
24
|
+
end
|
25
|
+
|
26
|
+
def logger
|
27
|
+
@logger ||= Logger.new
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup
|
31
|
+
@loader = Zeitwerk::Loader.for_gem
|
32
|
+
|
33
|
+
instance_eval(File.read(root.join("config/inflections.rb")))
|
34
|
+
|
35
|
+
loader.enable_reloading
|
36
|
+
loader.setup
|
37
|
+
loader.eager_load
|
38
|
+
|
39
|
+
container.instance_eval(File.read(root.join("config/dependencies.rb")))
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def reload!
|
45
|
+
Kozo.loader.reload
|
46
|
+
end
|
47
|
+
|
48
|
+
Kozo.setup
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kozo
|
4
|
+
module Backends
|
5
|
+
class Base
|
6
|
+
attr_accessor :directory
|
7
|
+
|
8
|
+
def initialize(directory)
|
9
|
+
@directory = directory
|
10
|
+
end
|
11
|
+
|
12
|
+
def providers
|
13
|
+
state.fetch(:providers)
|
14
|
+
end
|
15
|
+
|
16
|
+
def resources
|
17
|
+
state.fetch(:resources)
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def state
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
def state=(_value)
|
27
|
+
raise NotImplementedError
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|