recommend-me 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []