recommend-me 0.0.1

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,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 706c7fff69a6c1efa7419890d9ff3a2f42935129
4
+ data.tar.gz: 788922210696833e2d5126e178407ae80728421c
5
+ SHA512:
6
+ metadata.gz: 67edffc23213bce9c3ccc3e13aef8288ae27374e2748c713974102205827c2bca6436d0f4126f2e38f7296f5cdfc319972b1f483720dbd13efb6bbbc77562ec4
7
+ data.tar.gz: 4bff3bf8b5952804d6e006b4ba788229d80a5a08964ac117fc2047a3a31a4ec5c39253407f53f520a17897c2f50de12464470246a46444cc6c73bff45a57bafe
@@ -0,0 +1,47 @@
1
+ # Recommend-me
2
+
3
+ Recommend-me gem is used to generate Dockerfile or Deployment.yml from a templates
4
+
5
+ ## Installation
6
+
7
+ You can install it by using a command:
8
+ `gem install recommend-me`
9
+
10
+ ## Dependencies
11
+
12
+ Cookbook Creator during its installation will also install required gems:
13
+ * chef
14
+
15
+ ## Usage
16
+
17
+ `recommend_me_generate <template> <options>`
18
+
19
+ Where:
20
+ * <template> is obligatory
21
+ * <options> can be:
22
+ - `-p, --project <project_name>`
23
+ - `-l, --location <environment location : local or gce>`
24
+
25
+ ## Config options
26
+
27
+ Config file could has following options:
28
+ - `project '<project_name>'`
29
+ - `location '<environment location : local or gce>'`
30
+
31
+ ## Config locations
32
+
33
+ By default Recommend-me will search for config file in following places:
34
+ * Under `env['RECOMMEND_ME_HOME']/recommend.rb` if set
35
+ * Under `Current directory/recommend.rb`
36
+ * Under `Current directory/.recommend/recommend.rb`
37
+ * Under `$HOME/.recommend/recommend.rb`
38
+
39
+ ## Options merging
40
+
41
+ Options will be merged in the following order:
42
+ * Initially will be build hash with default options from CLI
43
+ * CLI options will be overwritten by the options within config file
44
+ * Config file options will be overwritten by any arguments which will be passed to the script
45
+
46
+ *WARNING:* Recommend-me can have some bugs.
47
+ Please report to serghei.anicheev@gmail.com if you will find any.
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2016 Nemo AI, All Rights Reserved.
4
+ #
5
+
6
+ Kernel.trap(:INT) { print("\n"); exit 1 }
7
+
8
+ $:.unshift(File.expand_path(File.join(File.dirname(__FILE__), "..", "lib")))
9
+ require 'recommend_me/main'
10
+
11
+ RecommendMe::Main.new(ARGV.clone).run
@@ -0,0 +1,44 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+
6
+ require 'mixlib/cli'
7
+
8
+ module RecommendMe
9
+ class MCLI
10
+ include Mixlib::CLI
11
+
12
+ option :config_file,
13
+ :short => "-c config_file",
14
+ :long => "--config",
15
+ :description => "The configuration file to use",
16
+ :default => ConfigLoader.new(nil, nil).config_location
17
+
18
+ option :project_name,
19
+ :short => "-p project_name",
20
+ :long => "--project-name",
21
+ :description => "Project name to use in templates",
22
+ :default => 'recommend-me'
23
+
24
+ option :location,
25
+ :short => "-l location",
26
+ :long => "--location",
27
+ :description => 'Location to use in a templates',
28
+ :default => 'local'
29
+
30
+ option :help,
31
+ :short => "-h",
32
+ :long => "--help",
33
+ :description => "Show this message",
34
+ :on => :tail,
35
+ :boolean => true,
36
+ :show_options => true,
37
+ :exit => 0
38
+
39
+ def run(argv=[])
40
+ parse_options(argv)
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,15 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+
6
+ require 'mixlib/config'
7
+
8
+ module RecommendMe
9
+ class Config
10
+ extend Mixlib::Config
11
+ config_strict_mode true
12
+ configurable :project_name
13
+ configurable :location
14
+ end
15
+ end
@@ -0,0 +1,157 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+ # Initially this code block was developed by Chef community.
6
+ # But in order to fit for our needs it was modified
7
+ #
8
+
9
+
10
+ require 'recommend_me/null_logger'
11
+ require 'recommend_me/pathhelper'
12
+ require 'pathname'
13
+
14
+ module RecommendMe
15
+ class ConfigLoader
16
+
17
+ # Path to a config file requested by user, (e.g., via command line option). Can be nil
18
+ attr_accessor :explicit_config_file
19
+
20
+ def initialize(explicit_config_file, logger=nil)
21
+ @explicit_config_file = explicit_config_file
22
+ @recommend_config_dir = nil
23
+ @config_location = nil
24
+ @logger = logger || NullLogger.new
25
+ end
26
+
27
+ def no_config_found?
28
+ config_location.nil?
29
+ end
30
+
31
+ def config_location
32
+ @config_location ||= (explicit_config_file || locate_local_config)
33
+ end
34
+
35
+ def recommend_config_dir
36
+ if @recommend_config_dir.nil?
37
+ @recommend_config_dir = false
38
+ full_path = working_directory.split(File::SEPARATOR)
39
+ (full_path.length - 1).downto(0) do |i|
40
+ candidate_directory = File.join(full_path[0..i] + [".recommend"])
41
+ if File.exist?(candidate_directory) && File.directory?(candidate_directory)
42
+ @recommend_config_dir = candidate_directory
43
+ break
44
+ end
45
+ end
46
+ end
47
+ @recommend_config_dir
48
+ end
49
+
50
+ def load
51
+ # Ignore it if there's no explicit_config_file and can't find one at a
52
+ # default path.
53
+ return false if config_location.nil?
54
+
55
+ if explicit_config_file && !path_exists?(config_location)
56
+ raise "Specified config file #{config_location} does not exist"
57
+ end
58
+
59
+ # Have to set Config.config_file b/c other config is derived from it.
60
+ Config.config_file = config_location
61
+ read_config(IO.read(config_location), config_location)
62
+ end
63
+
64
+ # (Private API, public for test purposes)
65
+ def env
66
+ ENV
67
+ end
68
+
69
+ # (Private API, public for test purposes)
70
+ def path_exists?(path)
71
+ Pathname.new(path).expand_path.exist?
72
+ end
73
+
74
+ private
75
+
76
+ def have_config?(path)
77
+ if path_exists?(path)
78
+ logger.info("Using config at #{path}")
79
+ true
80
+ else
81
+ logger.debug("Config not found at #{path}, trying next option")
82
+ false
83
+ end
84
+ end
85
+
86
+ def locate_local_config
87
+ candidate_configs = []
88
+
89
+ # Look for $RECOMMEND_ME_HOME/recommend.rb (allow multiple recommend config on same machine)
90
+ if env['RECOMMEND_ME_HOME']
91
+ candidate_configs << File.join(env['RECOMMEND_ME_HOME'], 'recommend.rb')
92
+ end
93
+ # Look for $PWD/recommend.rb
94
+ if Dir.pwd
95
+ candidate_configs << File.join(Dir.pwd, 'recommend.rb')
96
+ end
97
+ # Look for $UPWARD/.recommend/recommend.rb
98
+ if recommend_config_dir
99
+ candidate_configs << File.join(recommend_config_dir, 'recommend.rb')
100
+ end
101
+ # Look for $HOME/.recommend/recommend.rb
102
+ PathHelper.home('.recommend') do |dot_recommend_dir|
103
+ candidate_configs << File.join(dot_recommend_dir, 'recommend.rb')
104
+ end
105
+
106
+ candidate_configs.find do | candidate_config |
107
+ have_config?(candidate_config)
108
+ end
109
+ end
110
+
111
+ def working_directory
112
+ Dir.pwd
113
+ end
114
+
115
+ def read_config(config_content, config_file_path)
116
+ Config.from_string(config_content, config_file_path)
117
+ rescue SignalException
118
+ raise
119
+ rescue SyntaxError => e
120
+ message = ""
121
+ message << "You have invalid ruby syntax in your config file #{config_file_path}\n\n"
122
+ message << "#{e.class.name}: #{e.message}\n"
123
+ if file_line = e.message[/#{Regexp.escape(config_file_path)}:[\d]+/]
124
+ line = file_line[/:([\d]+)$/, 1].to_i
125
+ message << highlight_config_error(config_file_path, line)
126
+ end
127
+ raise StandardError::ArgumentError, message
128
+ rescue Exception => e
129
+ message = "You have an error in your config file #{config_file_path}\n\n"
130
+ message << "#{e.class.name}: #{e.message}\n"
131
+ filtered_trace = e.backtrace.grep(/#{Regexp.escape(config_file_path)}/)
132
+ filtered_trace.each {|bt_line| message << " " << bt_line << "\n" }
133
+ if !filtered_trace.empty?
134
+ line_nr = filtered_trace.first[/#{Regexp.escape(config_file_path)}:([\d]+)/, 1]
135
+ message << highlight_config_error(config_file_path, line_nr.to_i)
136
+ end
137
+ raise StandardError::ArgumentError, message
138
+ end
139
+
140
+
141
+ def highlight_config_error(file, line)
142
+ config_file_lines = []
143
+ IO.readlines(file).each_with_index {|l, i| config_file_lines << "#{(i + 1).to_s.rjust(3)}: #{l.chomp}"}
144
+ if line == 1
145
+ lines = config_file_lines[0..3]
146
+ else
147
+ lines = config_file_lines[Range.new(line - 2, line)]
148
+ end
149
+ "Relevant file content:\n" + lines.join("\n") + "\n"
150
+ end
151
+
152
+ def logger
153
+ @logger
154
+ end
155
+
156
+ end
157
+ end
@@ -0,0 +1,17 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+
6
+ require 'erb'
7
+
8
+ module RecommendMe
9
+ class Generator
10
+ def self.generate_file(variables, template, file)
11
+ puts "CREATING FILE : #{file} FROM TEMPLATE : #{template}, USING VARIABLES : #{variables}\n"
12
+ template = Helpers.read_file(template)
13
+ data = ERB.new(template).result(binding)
14
+ Helpers.write_file(file, data)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,35 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+
6
+ module RecommendMe
7
+ class Helpers
8
+
9
+ def self.load_config_file(default_options, modified_options)
10
+ config_file = default_options.merge!(modified_options)[:config_file]
11
+ File.exists?(config_file) ? config_file : raise_er
12
+ end
13
+
14
+ def raise_er
15
+ raise 'Selected config file does not exists or does not have read permissions'
16
+ end
17
+
18
+ def self.merge_configs(default_config, config, sym_hash)
19
+ combined_config = default_config.merge!(sym_hash)
20
+ combined_config_options = combined_config.merge(config)
21
+ config.replace(combined_config_options)
22
+ end
23
+
24
+ def self.read_file(path)
25
+ p "OPENING FILE : #{path} FOR READ\n"
26
+ ::File.open(path, 'r') { |f| f.read }
27
+ end
28
+
29
+ def self.write_file(path, data)
30
+ p "WRITING DATA : #{data} TO FILE : #{path}\n"
31
+ ::File.open(path, 'w') { |f| f.write(data) }
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,38 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+
6
+ require 'mixlib/cli'
7
+ require 'mixlib/config'
8
+ require 'recommend_me/config_loader'
9
+ require 'recommend_me/cli'
10
+ require 'recommend_me/helpers'
11
+ require 'recommend_me/config'
12
+ require 'recommend_me/generator'
13
+
14
+ module RecommendMe
15
+ class Main
16
+
17
+ attr_reader :params
18
+
19
+ def initialize(argv=[])
20
+ @template = argv[0]
21
+ @params = argv
22
+ @file = argv[0].split('.erb').first
23
+ end
24
+
25
+ def run
26
+ config_location = ConfigLoader.new(nil, nil).config_location
27
+ MCLI.use_separate_default_options true
28
+ cli = RecommendMe::MCLI.new
29
+ cli.run(@params)
30
+ generator_config = Helpers::load_config_file(cli.default_config, cli.config)
31
+ Config.from_file(generator_config)
32
+ sym_hash = Config.configuration.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
33
+ Helpers.merge_configs(cli.default_config, cli.config, sym_hash)
34
+ Generator.generate_file(cli.config, @template, @file)
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,70 @@
1
+ #
2
+ # Author:: Daniel DeLeo (<dan@getchef.com>)
3
+ # Copyright:: Copyright (c) 2014 Chef Software, Inc
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+
19
+ # Null logger implementation that just ignores everything. This is used by
20
+ # classes that are intended to be reused outside of Chef, but need to offer
21
+ # logging functionality when used by other Chef code.
22
+ #
23
+ # It does not define the full interface provided by Logger, just enough to be
24
+ # a reasonable duck type. In particular, methods setting the log level, log
25
+ # device, etc., are not implemented because any code calling those methods
26
+ # probably expected a real logger and not this "fake" one.
27
+ class NullLogger
28
+
29
+ def fatal(message, &block)
30
+ end
31
+
32
+ def error(message, &block)
33
+ end
34
+
35
+ def warn(message, &block)
36
+ end
37
+
38
+ def info(message, &block)
39
+ end
40
+
41
+ def debug(message, &block)
42
+ end
43
+
44
+ def add(severity, message=nil, progname=nil)
45
+ end
46
+
47
+ def <<(message)
48
+ end
49
+
50
+ def fatal?
51
+ false
52
+ end
53
+
54
+ def error?
55
+ false
56
+ end
57
+
58
+ def warn?
59
+ false
60
+ end
61
+
62
+ def info?
63
+ false
64
+ end
65
+
66
+ def debug?
67
+ false
68
+ end
69
+
70
+ end
@@ -0,0 +1,41 @@
1
+ #
2
+ # Author:: Anicheev Serghei (<serghei.anicheev@gmail.com>)
3
+ # Copyright:: Copyright (c) 2016 Nemo AI.
4
+ #
5
+ # Initially this code block was developed by Chef community.
6
+ # But in order to fit for our needs it was modified
7
+ #
8
+
9
+ class PathHelper
10
+ def self.home(*args)
11
+ @@home_dir ||= self.all_homes { |p| break p }
12
+ if @@home_dir
13
+ path = File.join(@@home_dir, *args)
14
+ block_given? ? (yield path) : path
15
+ end
16
+ end
17
+
18
+ def self.all_homes(*args)
19
+ paths = []
20
+ paths << Dir.home if ENV['HOME']
21
+
22
+ paths = paths.map { |home_path| home_path.gsub(path_separator, ::File::SEPARATOR) if home_path }
23
+
24
+ # Filter out duplicate paths and paths that don't exist.
25
+ valid_paths = paths.select { |home_path| home_path && Dir.exists?(home_path) }
26
+ valid_paths = valid_paths.uniq
27
+
28
+ # Join all optional path elements at the end.
29
+ # If a block is provided, invoke it - otherwise just return what we've got.
30
+ joined_paths = valid_paths.map { |home_path| File.join(home_path, *args) }
31
+ if block_given?
32
+ joined_paths.each { |p| yield p }
33
+ else
34
+ joined_paths
35
+ end
36
+ end
37
+
38
+ def self.path_separator
39
+ File::SEPARATOR
40
+ end
41
+ end
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'recommend-me'
3
+ s.version = '0.0.1'
4
+ s.date = '2016-05-25'
5
+ s.summary = 'Required to generate Dcokerfile or Deployment.yml'
6
+ s.description = 'This gem is used to generate Dcokerfile or Deployment.yml'
7
+ s.authors = ['Serghei Anicheev']
8
+ s.email = 'serghei.anicheev@gmail.com'
9
+ s.require_paths = ['lib']
10
+ s.required_ruby_version = '>= 2.0.0'
11
+ s.bindir = 'bin'
12
+ s.executables = [ 'recommend_me_generate' ]
13
+ s.files = %w(README.md) + Dir.glob("*.gemspec") + Dir.glob("{lib,spec}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory?(f) }
14
+
15
+ s.add_dependency "chef-zero", "~> 4.4.0"
16
+
17
+ s.homepage =
18
+ 'http://rubygems.org/gems/recommend-me'
19
+ s.license = 'Free License'
20
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: recommend-me
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Serghei Anicheev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-05-25 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: chef-zero
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.4.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.4.0
27
+ description: This gem is used to generate Dcokerfile or Deployment.yml
28
+ email: serghei.anicheev@gmail.com
29
+ executables:
30
+ - recommend_me_generate
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - README.md
35
+ - bin/recommend_me_generate
36
+ - lib/recommend_me/cli.rb
37
+ - lib/recommend_me/config.rb
38
+ - lib/recommend_me/config_loader.rb
39
+ - lib/recommend_me/generator.rb
40
+ - lib/recommend_me/helpers.rb
41
+ - lib/recommend_me/main.rb
42
+ - lib/recommend_me/null_logger.rb
43
+ - lib/recommend_me/pathhelper.rb
44
+ - recommend_me.gemspec
45
+ homepage: http://rubygems.org/gems/recommend-me
46
+ licenses:
47
+ - Free License
48
+ metadata: {}
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ version: 2.0.0
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 2.4.8
66
+ signing_key:
67
+ specification_version: 4
68
+ summary: Required to generate Dcokerfile or Deployment.yml
69
+ test_files: []