rna 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ spec/project/config/s3.yml
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
19
+ output
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.2
4
+ - 1.9.3
5
+ bundler_args: --without development
data/CHANGELOG ADDED
@@ -0,0 +1 @@
1
+ 0.1.0 Initial Release
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,9 @@
1
+ guard 'bundler' do
2
+ watch('Gemfile')
3
+ end
4
+
5
+ guard 'rspec' do
6
+ watch(%r{^spec/.+_spec\.rb$})
7
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
8
+ # watch('spec/spec_helper.rb') { "spec" }
9
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Tung Nguyen
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,89 @@
1
+ Rna gem
2
+ ===========
3
+
4
+ Rna is a ruby gem that provides simple DSL for generating node.json files required by chef-solo.
5
+
6
+ Requirements
7
+ ------------
8
+
9
+ <pre>
10
+ $ gem install rna
11
+ </pre>
12
+
13
+ Usage
14
+ ------------
15
+
16
+ <pre>
17
+ $ mkdir rna_project
18
+ $ cd rna_project
19
+ $ rna init
20
+ </pre>
21
+
22
+ This will sets starter config/rna.rb and config/s3.yml files.
23
+
24
+ Example rna.rb file
25
+ ------------
26
+
27
+ ```ruby
28
+ # This is starter example rna template.
29
+ # This is meant be be modified to your needs.
30
+ ###################################
31
+ # Settings
32
+ default_inherits 'base'
33
+ global_attributes(:except => ['base']) do
34
+ set 'framework_env', 'production'
35
+ end
36
+
37
+ ###################################
38
+ # Post processing rules that run at the end
39
+ rule do
40
+ set 'framework_env', 'production' if name =~ /^prod/
41
+ set 'framework_env', 'staging' if name =~ /^stag/
42
+ end
43
+
44
+ ###################################
45
+ # Roles
46
+ # base
47
+ role 'base' do
48
+ run_list ['base']
49
+ end
50
+ # api
51
+ role 'prod-api-redis', 'stag-api-redis'
52
+ role 'prod-api-app', 'stag-api-app' do
53
+ run_list ['base','api_app']
54
+ set 'application', 'api'
55
+ set 'deploy_code', true
56
+ set 'repository', 'git@github.com:br/api.git'
57
+ end
58
+ role 'prod-api-resque', 'stag-api-resque' do
59
+ inherits 'prod-api-app'
60
+ set 'workers', 8
61
+ end
62
+ ```
63
+
64
+ <pre>
65
+ $ rna build
66
+ </pre>
67
+
68
+ If you're using the starter config/rna.rb, this should build:
69
+
70
+ * nodejson/base.json
71
+ * nodejson/prod-api-app.json
72
+ * nodejson/prod-api-redis.json
73
+ * nodejson/prod-api-resque.json
74
+ * nodejson/stag-api-app.json
75
+ * nodejson/stag-api-redis.json
76
+ * nodejson/stag-api-resque.json
77
+
78
+ <pre>
79
+ $ rna build -o s3 # saves s3 based on config/s3.yml settings
80
+ </pre>
81
+
82
+ The config/s3.yml should look like this:
83
+
84
+ ```yaml
85
+ access_key_id: hocuspocus
86
+ secret_access_key: opensesame
87
+ bucket: my-bucket
88
+ folder: chef/nodejson
89
+ ```
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ require "rspec/core/rake_task"
4
+
5
+ task :default => :spec
6
+
7
+ RSpec::Core::RakeTask.new
8
+
9
+ require 'bundler/gem_tasks'
data/bin/rna ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ $:.unshift(File.expand_path('../../lib', __FILE__))
6
+ require 'rna'
7
+
8
+ Rna::CLI.start
data/lib/files/rna.rb ADDED
@@ -0,0 +1,34 @@
1
+ # This is starter example rna template.
2
+ # This is meant be be modified to your needs.
3
+ ###################################
4
+ # Settings
5
+ default_inherits 'base'
6
+ global_attributes(:except => ['base']) do
7
+ set 'framework_env', 'production'
8
+ end
9
+
10
+ ###################################
11
+ # Post processing rules that run at the end
12
+ rule do
13
+ set 'framework_env', 'production' if name =~ /^prod/
14
+ set 'framework_env', 'staging' if name =~ /^stag/
15
+ end
16
+
17
+ ###################################
18
+ # Roles
19
+ # base
20
+ role 'base' do
21
+ run_list ['base']
22
+ end
23
+ # api
24
+ role 'prod-api-redis', 'stag-api-redis'
25
+ role 'prod-api-app', 'stag-api-app' do
26
+ run_list ['base','api_app']
27
+ set 'application', 'api'
28
+ set 'deploy_code', true
29
+ set 'repository', 'git@github.com:br/api.git'
30
+ end
31
+ role 'prod-api-resque', 'stag-api-resque' do
32
+ inherits 'prod-api-app'
33
+ set 'workers', 8
34
+ end
data/lib/files/s3.yml ADDED
@@ -0,0 +1,4 @@
1
+ access_key_id: hocuspocus
2
+ secret_access_key: opensesame
3
+ bucket: my-bucket
4
+ folder: chef/nodejson
data/lib/rna/cli.rb ADDED
@@ -0,0 +1,29 @@
1
+ module Rna
2
+ class CLI < Thor
3
+
4
+ desc "init", "Setup rna project"
5
+ long_desc "Sets up config/rna.rb"
6
+ def init
7
+ Rna::Tasks.init
8
+ end
9
+
10
+ desc "build", "Builds node.json files"
11
+ long_desc <<EOL
12
+ Examples:
13
+
14
+ 1. rna build
15
+
16
+ Builds the node.json files based on config/rna.rb and writes them to the nodejson folder on the filesystem.
17
+
18
+ 2. rna --output s3 build
19
+
20
+ Builds the node.json files based on config/rna.rb and writes them to s3 based on the s3 settings in config/s3.yml.
21
+ EOL
22
+ method_option :output, :aliases => '-o', :desc => "specify where to output the generated files to", :default => 'filesystem'
23
+ method_option :public_read, :aliases => '-p', :desc => "make s3 files readable by public, default private", :default => false, :type => :boolean
24
+ def build
25
+ Rna::Tasks.build(options.dup)
26
+ end
27
+ end
28
+
29
+ end
data/lib/rna/dsl.rb ADDED
@@ -0,0 +1,129 @@
1
+ module Rna
2
+ class DSL
3
+ @@default_inherits = nil
4
+ attr_reader :attributes, :rules, :nodejsons
5
+ def initialize(config_path='config/rna.rb')
6
+ @path = config_path
7
+ @scope = nil
8
+ @rules = []
9
+ @roles = []
10
+ @attributes = {}
11
+ @nodejsons = {}
12
+ end
13
+
14
+ def evaluate
15
+ instance_eval(File.read(@path), @path)
16
+ end
17
+
18
+ def build
19
+ # process roles
20
+ @roles.each do |role|
21
+ @nodejsons[role] = process_role(role)
22
+ end
23
+ @nodejsons
24
+ end
25
+
26
+ # builds node.json
27
+ # 1. global attributes
28
+ # 2. parent inherited attributes all the way up the inheritance chain
29
+ # each descendent role overrides it's parent role
30
+ # 3. final attributes from the desired role is built last
31
+ def process_role(role, exclude_global=nil)
32
+ # only compute exclude_global on on top level call and continue passing down recursive stack call
33
+ if exclude_global.nil?
34
+ exclude_global = @attributes['global']['except'].include?(role)
35
+ end
36
+
37
+ inherits = @attributes[role]['inherits']
38
+ if inherits
39
+ nodejson = process_role(inherits, exclude_global)
40
+ else
41
+ if exclude_global
42
+ nodejson = {}
43
+ else
44
+ attributes = @attributes['global']['attributes'] || {}
45
+ nodejson = attributes.clone
46
+ end
47
+ end
48
+
49
+ # apply each rule to each role's attributes before we do the merge
50
+ @rules.each do |block|
51
+ set_scope(role)
52
+ self.instance_eval(&block)
53
+ end
54
+
55
+ attributes = @attributes[role]['attributes'] || {}
56
+ nodejson.merge!(attributes)
57
+ nodejson
58
+ end
59
+
60
+ def output(options={})
61
+ jsons = {}
62
+ nodejsons.each do |role,data|
63
+ jsons[role] = JSON.pretty_generate(data)
64
+ end
65
+
66
+ outputer = options[:output] || 'filesystem'
67
+ outputer_class = Rna.const_get(outputer.capitalize)
68
+ outputer_class.new(options).run(jsons)
69
+ end
70
+
71
+ # must be called before every instance_eval of the dsl to set the @scope
72
+ def set_scope(scope,type=Hash)
73
+ @scope = scope
74
+ @attributes[@scope] ||= type.new
75
+ end
76
+
77
+ def global_attributes(options={},&block)
78
+ set_scope('global')
79
+ @attributes['global']['except'] = [options[:except]].flatten
80
+ self.instance_eval(&block)
81
+ end
82
+ def default_inherits(role)
83
+ @@default_inherits = role
84
+ end
85
+ # rules are stored in a different place than attributes
86
+ def rule(name=nil,&block)
87
+ @rules << block
88
+ end
89
+ def role(*names,&block)
90
+ names.each do |name|
91
+ evaluate_role(name,&block)
92
+ end
93
+ end
94
+ def evaluate_role(name,&block)
95
+ @roles << name
96
+ set_scope(name)
97
+ instance_eval(&default_block)
98
+ instance_eval(&block) if block_given?
99
+ end
100
+
101
+ def default_block
102
+ Proc.new do
103
+ @attributes[@scope]['name'] = @scope
104
+ set 'role', name
105
+ inherits @@default_inherits
106
+ end
107
+ end
108
+
109
+ # methods in blocks, right now I'm mixing all the methods from role, rule, global_attributes together, because there's not a lot and its simple this way
110
+ # methods rely on @scope being already via set_scope method
111
+ def name
112
+ @attributes[@scope]['name']
113
+ end
114
+ def set(key, value)
115
+ # puts "%%% @scope #{@scope.inspect}"
116
+ # pp @attributes
117
+ @attributes[@scope]['attributes'] ||= {}
118
+ @attributes[@scope]['attributes'][key] = value
119
+ end
120
+ def inherits(role)
121
+ role = nil if role == @scope # can't inherit itself
122
+ @attributes[@scope]['inherits'] = role
123
+ end
124
+ def run_list(list)
125
+ list = list.collect {|i| "role[#{i}]"}
126
+ set('run_list', list)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,46 @@
1
+ module Rna
2
+ class Outputer
3
+ attr_reader :options
4
+ def initialize(options={})
5
+ @options = options
6
+ end
7
+ end
8
+
9
+ class Filesystem < Outputer
10
+ def run(jsons)
11
+ # options[:output_path] only used for specs
12
+ output_path = options[:output_path] || "nodejson"
13
+ FileUtils.mkdir(output_path) unless File.exist?(output_path)
14
+ jsons.each do |role,json|
15
+ File.open("#{output_path}/#{role}.json", 'w') {|f| f.write(json) }
16
+ end
17
+ end
18
+ end
19
+
20
+ class S3 < Outputer
21
+ attr_reader :config, :s3
22
+ def run(jsons)
23
+ acl_options = @options[:public_read] ? {:acl => :public_read} : {}
24
+ # options[:config] only used for specs
25
+ s3_config_path = options[:s3_config_path] || 'config/s3.yml'
26
+ @config ||= YAML.load(File.read(s3_config_path))
27
+ AWS.config(@config)
28
+ @s3 = AWS::S3.new
29
+ bucket = @s3.buckets[@config['bucket']]
30
+ jsons.each do |role,json|
31
+ bucket.objects.create("#{@config['folder']}/#{role}.json", json, s3_options)
32
+ end
33
+ self # return outputer object for specs
34
+ end
35
+ end
36
+
37
+ class Stdout < Outputer
38
+ def run(jsons)
39
+ jsons.each do |role,json|
40
+ puts "-" * 60
41
+ puts "#{role}:"
42
+ puts json
43
+ end
44
+ end
45
+ end
46
+ end
data/lib/rna/tasks.rb ADDED
@@ -0,0 +1,31 @@
1
+ module Rna
2
+ class Tasks
3
+ def self.init(project_root=".",options={})
4
+ puts "Settin up rna project" unless options[:quiet]
5
+ FileUtils.mkdir("#{project_root}/config") unless File.exist?("#{project_root}/config")
6
+ %w/rna.rb s3.yml/.each do |name|
7
+ source = File.expand_path("../../files/#{name}", __FILE__)
8
+ dest = "#{project_root}/config/#{File.basename(source)}"
9
+ if File.exist?(dest)
10
+ puts "already exists: #{dest}" unless options[:quiet]
11
+ else
12
+ puts "creating: #{dest}" unless options[:quiet]
13
+ FileUtils.cp(source, dest)
14
+ end
15
+ end
16
+ end
17
+ def self.build(options)
18
+ new(options).build
19
+ end
20
+
21
+ def initialize(options={})
22
+ @options = options
23
+ @dsl = DSL.new
24
+ end
25
+ def build
26
+ @dsl.evaluate
27
+ @dsl.build
28
+ @dsl.output(@options)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,3 @@
1
+ module Rna
2
+ VERSION = '0.1.0'
3
+ end
data/lib/rna.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'json'
2
+ require 'thor'
3
+ require 'yaml'
4
+ require 'aws-sdk'
5
+ require 'pp'
6
+
7
+ $:.unshift File.dirname(__FILE__)
8
+ require 'rna/version'
9
+ require 'rna/cli'
10
+ require 'rna/tasks'
11
+ require 'rna/dsl'
12
+ require 'rna/outputers'
data/rna.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/rna/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Tung Nguyen"]
6
+ gem.email = ["tongueroo@gmail.com"]
7
+ gem.description = %q{Rna DSL generates chef solo node.json files.}
8
+ gem.summary = %q{Rna DSL generates chef solo node.json files.}
9
+ gem.homepage = ""
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "rna"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Rna::VERSION
17
+
18
+ gem.add_dependency "json"
19
+ gem.add_dependency "thor"
20
+ gem.add_dependency "aws-sdk"
21
+
22
+ gem.add_development_dependency 'rspec'
23
+ gem.add_development_dependency 'guard'
24
+ gem.add_development_dependency 'guard-rspec'
25
+ gem.add_development_dependency 'guard-bundler'
26
+ gem.add_development_dependency 'rb-fsevent'
27
+
28
+ end
@@ -0,0 +1,192 @@
1
+ require 'rna'
2
+ require 'rspec'
3
+ require 'pp'
4
+
5
+ describe Rna do
6
+ before(:each) do
7
+ @project_root = File.expand_path("../../project", __FILE__)
8
+ @project2_root = File.expand_path("../../project2", __FILE__)
9
+ @dsl = Rna::DSL.new("#{@project_root}/config/rna.rb")
10
+ @dsl.evaluate
11
+ end
12
+
13
+ after(:each) do
14
+ FileUtils.rm_rf("#{@project_root}/nodejson")
15
+ end
16
+
17
+ it "evaluate global attributes data to be used later to merge the nodejson structures together" do
18
+ attributes = @dsl.attributes
19
+ attributes.should be_a(Hash)
20
+ # pp attributes
21
+ attributes['global']['attributes']['application'].should be_nil
22
+ attributes['global']['attributes']['deploy_code'].should be_false
23
+ attributes['global']['attributes']['framework_env'].should == 'production'
24
+ attributes['global']['attributes']['repository'].should be_nil
25
+ end
26
+
27
+ it "evaluate base attributes data that does not include the global attributes" do
28
+ attributes = @dsl.attributes
29
+ attributes.should be_a(Hash)
30
+ attributes['base']['attributes'].keys.should_not include('application')
31
+ attributes['base']['attributes']['run_list'].should == ["role[base]"]
32
+ end
33
+
34
+ it "evaluate base attributes data should not inherit itself" do
35
+ attributes = @dsl.attributes
36
+ attributes.should be_a(Hash)
37
+ attributes['base']['inherits'].should be_nil
38
+ end
39
+
40
+ it "roles without blocks should run the default block" do
41
+ attributes = @dsl.attributes
42
+ # running the default block will set inherits attribute
43
+ attributes['prod-api-redis']['inherits'].should == 'base'
44
+ end
45
+
46
+ it "roles with blocks should run the default block and then their own block" do
47
+ attributes = @dsl.attributes
48
+ # hard to read test, but after the default block runs, the passed in role block rusn and overrides the default_blocks inherits attribuute
49
+ attributes['prod-api-resque']['inherits'].should == 'prod-api-app'
50
+ end
51
+
52
+ it "roles with blocks should override the global attributes" do
53
+ attributes = @dsl.attributes
54
+ attributes['prod-masta-android']['attributes']['application'].should == 'masta'
55
+ attributes['prod-masta-android']['attributes']['deploy_code'].should be_true
56
+ attributes['prod-masta-android']['attributes']['repository'].should == 'git@github.com:arockwell/masta_blasta.git'
57
+ end
58
+
59
+ it "base node.json should not include global attributes" do
60
+ @dsl.build
61
+ @dsl.nodejsons['base']['run_list'].should == ["role[base]"]
62
+ @dsl.nodejsons['base']['role'].should == 'base'
63
+ @dsl.nodejsons['base'].keys.should_not include('application')
64
+ @dsl.nodejsons['base'].keys.should_not include('repository')
65
+ end
66
+
67
+ it "prod-api-redis node.json should include base plus global attributes" do
68
+ @dsl.build
69
+ @dsl.nodejsons['prod-api-redis']['run_list'].should == ["role[base]"]
70
+ @dsl.nodejsons['prod-api-redis']['deploy_code'].should be_false
71
+ end
72
+
73
+ it "prod-api-app node.json should include global attributes plus additional attributes" do
74
+ @dsl.build
75
+ @dsl.nodejsons['prod-api-app']['run_list'].should == ["role[base]", "role[api_app]"]
76
+ @dsl.nodejsons['prod-api-app']['deploy_code'].should be_true
77
+ @dsl.nodejsons['prod-api-app'].keys.should include('scout')
78
+ end
79
+
80
+ it "prod-api-resque node.json inherit attributes from prod-api-app" do
81
+ @dsl.build
82
+ @dsl.nodejsons['prod-api-resque']['run_list'].should == @dsl.nodejsons['prod-api-app']['run_list']
83
+ @dsl.nodejsons['prod-api-resque']['deploy_code'].should == @dsl.nodejsons['prod-api-app']['deploy_code']
84
+ end
85
+
86
+ it "should respect rules and change framework_env" do
87
+ @dsl.build
88
+ @dsl.nodejsons['stag-masta-android']['application'].should == 'masta'
89
+ @dsl.nodejsons['stag-masta-android']['framework_env'].should == 'staging'
90
+ @dsl.nodejsons['prod-masta-android']['framework_env'].should == 'production'
91
+ @dsl.nodejsons
92
+ end
93
+
94
+ it "should write json files to outputs folder" do
95
+ @dsl.build
96
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
97
+ Dir.glob("#{@project_root}/nodejson/*").size.should > 0
98
+ end
99
+
100
+ # complete end to end tests
101
+ it "base.json should contain correct attributes" do
102
+ @dsl.build
103
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
104
+ base = JSON.load(IO.read("#{@project_root}/nodejson/base.json"))
105
+ base['role'].should == 'base'
106
+ base['run_list'].should == ["role[base]"]
107
+ end
108
+
109
+ it "base.json should not contain global attributes" do
110
+ @dsl.build
111
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
112
+ base = JSON.load(IO.read("#{@project_root}/nodejson/base.json"))
113
+ base['framework_env'].should be_nil
114
+ base['deploy_code'].should be_nil
115
+ end
116
+
117
+ it "prod-api-redis.json should contain base and global attributes" do
118
+ @dsl.build
119
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
120
+ json = JSON.load(IO.read("#{@project_root}/nodejson/prod-api-redis.json"))
121
+ json['role'].should == 'prod-api-redis'
122
+ json['run_list'].should == ["role[base]"]
123
+ json['framework_env'].should == 'production'
124
+ json['deploy_code'].should == false
125
+ end
126
+
127
+ it "stag-api-redis.json should contain base and global attributes and apply rules" do
128
+ @dsl.build
129
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
130
+ json = JSON.load(IO.read("#{@project_root}/nodejson/stag-api-redis.json"))
131
+ json['role'].should == 'stag-api-redis'
132
+ json['run_list'].should == ["role[base]"]
133
+ json['deploy_code'].should == false
134
+ json['framework_env'].should == 'staging' # this is tests the rule
135
+ end
136
+
137
+ it "prod-api-app.json should contain base and global attributes" do
138
+ @dsl.build
139
+ @dsl.output(:output => 'filesystem', :output_path => "#{@project_root}/nodejson")
140
+ json = JSON.load(IO.read("#{@project_root}/nodejson/prod-api-app.json"))
141
+ json['role'].should == 'prod-api-app'
142
+ json['run_list'].should == ["role[base]","role[api_app]"]
143
+ json['deploy_code'].should == true
144
+ json['framework_env'].should == 'production'
145
+ json['scout'].should be_a(Hash)
146
+ end
147
+
148
+ # only run when S3=1, will need to setup spec/project/config/s3.yml
149
+ it "should upload to s3" do
150
+ @dsl.build
151
+ outputer = @dsl.output(:output => 's3', :s3_config_path => "#{@project_root}/config/s3.yml")
152
+
153
+ config = outputer.config
154
+ s3 = outputer.s3
155
+ bucket = s3.buckets[config['bucket']]
156
+ raw = bucket.objects["#{config['folder']}/prod-api-app.json"].read
157
+
158
+ json = JSON.load(raw)
159
+ json['role'].should == 'prod-api-app'
160
+ json['run_list'].should == ["role[base]","role[api_app]"]
161
+ json['deploy_code'].should == true
162
+ json['framework_env'].should == 'production'
163
+ json['scout'].should be_a(Hash)
164
+ # clean up
165
+ tree = bucket.as_tree(:prefix => config['folder'])
166
+ tree.children.select(&:leaf?).each do |leaf|
167
+ leaf.object.delete
168
+ end
169
+ end if ENV['S3'] == '1'
170
+
171
+ it "task init should set up project" do
172
+ File.exist?("#{@project2_root}/config/s3.yml").should be_false
173
+ File.exist?("#{@project2_root}/config/rna.rb").should be_false
174
+ Rna::Tasks.init(@project2_root, :quiet => true)
175
+ File.exist?("#{@project2_root}/config/s3.yml").should be_true
176
+ File.exist?("#{@project2_root}/config/rna.rb").should be_true
177
+ FileUtils.rm_rf("#{@project2_root}/config")
178
+ end
179
+
180
+ it "task build should generate node.json files" do
181
+ Rna::Tasks.build(
182
+ :config_path => "#{@project_root}/config/rna.rb",
183
+ :output_path => "#{@project_root}/nodejson"
184
+ )
185
+ json = JSON.load(IO.read("#{@project_root}/nodejson/prod-api-app.json"))
186
+ json['role'].should == 'prod-api-app'
187
+ json['run_list'].should == ["role[base]","role[api_app]"]
188
+ json['deploy_code'].should == true
189
+ json['framework_env'].should == 'production'
190
+ json['scout'].should be_a(Hash)
191
+ end
192
+ end
@@ -0,0 +1,47 @@
1
+ ###################################
2
+ # Settings
3
+ default_inherits 'base'
4
+ global_attributes(:except => 'base') do
5
+ set 'application', nil
6
+ set 'deploy_code', false
7
+ set 'framework_env', 'production'
8
+ set 'repository', nil
9
+ end
10
+
11
+ ###################################
12
+ # Post processing rules that run at the end
13
+ rule do
14
+ set 'framework_env', 'production' if name =~ /^prod/
15
+ set 'framework_env', 'staging' if name =~ /^stag/
16
+ end
17
+
18
+ ###################################
19
+ # Roles
20
+ # base
21
+ role 'base' do
22
+ run_list ['base']
23
+ end
24
+ # api
25
+ role 'prod-api-redis', 'stag-api-redis'
26
+ role 'prod-api-resque', 'stag-api-resque' do
27
+ inherits 'prod-api-app'
28
+ end
29
+ role 'prod-api-app', 'stag-api-app' do
30
+ run_list ['base','api_app']
31
+ set 'application', 'api'
32
+ set 'deploy_code', true
33
+ set 'repository', 'git@github.com:br/api.git'
34
+ set 'scout', {
35
+ 'key' => 'abc',
36
+ 'gems' => {
37
+ 'redis' => nil
38
+ }
39
+ }
40
+ end
41
+ # masta
42
+ role 'prod-masta-redis', 'stag-masta-redis'
43
+ role 'prod-masta-android', 'stag-masta-android' do
44
+ set 'application', 'masta'
45
+ set 'deploy_code', true
46
+ set 'repository', 'git@github.com:arockwell/masta_blasta.git'
47
+ end
@@ -0,0 +1,4 @@
1
+ access_key_id: hocuspocus
2
+ secret_access_key: opensesame
3
+ bucket: my-bucket
4
+ folder: chef/nodejson
File without changes
metadata ADDED
@@ -0,0 +1,201 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rna
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Tung Nguyen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-12-01 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: thor
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: aws-sdk
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: guard-rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: guard-bundler
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: rb-fsevent
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ description: Rna DSL generates chef solo node.json files.
143
+ email:
144
+ - tongueroo@gmail.com
145
+ executables:
146
+ - rna
147
+ extensions: []
148
+ extra_rdoc_files: []
149
+ files:
150
+ - .gitignore
151
+ - .rspec
152
+ - .travis.yml
153
+ - CHANGELOG
154
+ - Gemfile
155
+ - Guardfile
156
+ - LICENSE
157
+ - README.md
158
+ - Rakefile
159
+ - bin/rna
160
+ - lib/files/rna.rb
161
+ - lib/files/s3.yml
162
+ - lib/rna.rb
163
+ - lib/rna/cli.rb
164
+ - lib/rna/dsl.rb
165
+ - lib/rna/outputers.rb
166
+ - lib/rna/tasks.rb
167
+ - lib/rna/version.rb
168
+ - rna.gemspec
169
+ - spec/lib/rna_spec.rb
170
+ - spec/project/config/rna.rb
171
+ - spec/project/config/s3.example.yml
172
+ - spec/project2/.gitkeep
173
+ homepage: ''
174
+ licenses: []
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ none: false
181
+ requirements:
182
+ - - ! '>='
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ required_rubygems_version: !ruby/object:Gem::Requirement
186
+ none: false
187
+ requirements:
188
+ - - ! '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ requirements: []
192
+ rubyforge_project:
193
+ rubygems_version: 1.8.24
194
+ signing_key:
195
+ specification_version: 3
196
+ summary: Rna DSL generates chef solo node.json files.
197
+ test_files:
198
+ - spec/lib/rna_spec.rb
199
+ - spec/project/config/rna.rb
200
+ - spec/project/config/s3.example.yml
201
+ - spec/project2/.gitkeep