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.
@@ -0,0 +1,27 @@
1
+ # Kozo
2
+
3
+ ![Continuous Integration](https://github.com/floriandejonckheere/kozo/workflows/Continuous%20Integration/badge.svg)
4
+ ![Release](https://img.shields.io/github/v/release/floriandejonckheere/kozo?label=Latest%20release)
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).
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ begin
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task default: :spec
9
+ rescue LoadError
10
+ puts "RSpec not available."
11
+ end
@@ -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?
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../config/application"
5
+
6
+ require "irb"
7
+ IRB.start(__FILE__)
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../config/application"
5
+
6
+ require "kozo"
7
+ require "byebug"
8
+
9
+ Kozo::CLI.new(ARGV).start
@@ -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")
@@ -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,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ $LOAD_PATH.unshift File.expand_path(File.join(__dir__, "..", "lib"))
4
+
5
+ require "bundler/setup"
6
+ require "kozo"
@@ -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
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ loader.inflector.inflect(
4
+ "cli" => "CLI",
5
+ "dsl" => "DSL",
6
+ "hcloud" => "HCloud",
7
+ "ssh_key" => "SSHKey",
8
+ )
@@ -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
@@ -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