chapp 0.2.1 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b7400e9bd5d239d51f9da4e50f7e59b750f0f4c
4
- data.tar.gz: a640f10a2332bc0611be364cb5a4ddd2e051e0f9
3
+ metadata.gz: a55bf03c52c00bafbe28fa2f50706f45b0bdf0f5
4
+ data.tar.gz: 5a386ad53a944249f1915531c3edd8eb53789a38
5
5
  SHA512:
6
- metadata.gz: fe6fedbfcd25cf6c73851ac1f623582ad9a2c6ab66127090dec2194b33f43ca02478aa57ec9baa27fdcb9f3c1804ecc66e94790cc7fb4c381d14c81a570c57af
7
- data.tar.gz: 798403528dd3f6d8e31d21ae258bb4fb29c8e5c91767ae22801bd251c1ca3b2bcc743a2a5756f14cb835065f63c08bfbfa764a7d498146377be7bf5e68189443
6
+ metadata.gz: 69b6a02ba6e2cd304007a3721ee56aa3cc9360e0b145010e0527a4b6fdb82413d0a616d2992afef06c9ab27077d60db664b3d78a5304ffe927d97fcd8d4bffdb
7
+ data.tar.gz: e74ced9f3850c76c3fc8b075dc3a88fc03935fa8971ff337500a8187d7a5de759d628dc7e3b0ae2b9753c7db57ed77711647f20b6e80fbd1ed6f3df8a73d8dc1
@@ -4,7 +4,7 @@ require 'chapp/app_config'
4
4
  require 'chapp/wiring'
5
5
  require 'chapp/database'
6
6
  require 'chapp/provisioner'
7
- require 'chapp/provisioner/property_provisioner'
7
+ require 'chapp/provisioner/ec2_provisioner'
8
8
 
9
9
  module Chapp
10
10
 
@@ -14,7 +14,7 @@ module Chapp
14
14
 
15
15
  def self.provisioner
16
16
  # TODO: Make configurable
17
- Chapp::PropertyProvisioner.new
17
+ Chapp::EC2Provisioner.new
18
18
  end
19
19
 
20
20
  end
@@ -3,55 +3,37 @@ require 'chef/node/attribute'
3
3
 
4
4
  module Chapp
5
5
  class App
6
-
7
- def initialize id, db, config=nil, attributes=nil
6
+
7
+ attr_reader :id, :attributes, :instances
8
+
9
+ def initialize id, attributes, instances, db
8
10
  @id = id
9
11
  @db = db
10
- @config = config
11
12
  @attributes = attributes
12
- @instances = nil
13
+ @instances = instances
14
+ @config = nil
13
15
  @connected_apps = nil
14
16
  end
15
-
16
- def id
17
- @id
18
- end
19
-
17
+
20
18
  def config
21
19
  unless @config
22
20
  @config = @db.app_config @id
23
21
  end
24
-
22
+
25
23
  @config
26
24
  end
27
-
28
- def instances
29
- unless @instances
30
- @instances = @db.app_instances @id
31
- end
32
-
33
- @instances
34
- end
35
-
36
- def attributes
37
- unless @attributes
38
- @attributes = @db.app_attributes @id
39
- end
40
-
41
- @attributes
42
- end
43
-
25
+
44
26
  def connected_apps
45
27
  unless @connected_apps
46
28
  @connected_apps = Array.new
47
-
29
+
48
30
  @db.connected_app_ids(@id).each do |app_id|
49
- @connected_apps << App.new(app_id, @db)
31
+ @connected_apps << @db.app(app_id)
50
32
  end
51
33
  end
52
-
34
+
53
35
  @connected_apps
54
36
  end
55
-
37
+
56
38
  end
57
- end
39
+ end
@@ -0,0 +1,45 @@
1
+ require 'chapp'
2
+
3
+ module Chapp
4
+ class NodeApp < Chapp::App
5
+
6
+ def initialize id, db, config, attributes, node_name, fqdn
7
+ @id = id
8
+ @db = db
9
+ @config = config
10
+ @fqdn = fqdn
11
+ @node_name = node_name
12
+ @attributes = attributes
13
+
14
+ @instances = nil
15
+ @connected_apps = nil
16
+ end
17
+
18
+ def instances
19
+ unless @instances
20
+ app = @db.app id
21
+ app_instances = app.instances
22
+ @instances = []
23
+
24
+ # If we can't find our own instance add it to the list
25
+ found_node = false
26
+ app_instances.each do |instance|
27
+ if instance.node_name == @node_name
28
+ found_node = true
29
+ @instances << Chapp::AppInstance.new(id, @node_name, @fqdn)
30
+ break
31
+ else
32
+ @instances << instance
33
+ end
34
+ end
35
+
36
+ unless found_node
37
+ @instances << Chapp::AppInstance.new(id, @node_name, @fqdn)
38
+ end
39
+ end
40
+
41
+ @instances
42
+ end
43
+
44
+ end
45
+ end
@@ -41,6 +41,8 @@ module Chapp
41
41
  end
42
42
  end
43
43
 
44
+ app.cloud app_hash["cloud"]
45
+
44
46
  app.node Chef::Node::Attribute.new({}, app_hash["node"], {}, {}).default
45
47
  app.environment app_hash["environment"]
46
48
 
@@ -63,6 +65,7 @@ module Chapp
63
65
  @group = nil
64
66
  @name = nil
65
67
  @used_apps = Hash.new
68
+ @cloud = Hash.new
66
69
  @dependencies = Hash.new
67
70
  @pre_run_list = Array.new
68
71
  @post_run_list = Array.new
@@ -139,6 +142,10 @@ module Chapp
139
142
  set_or_return :node, node
140
143
  end
141
144
 
145
+ def cloud cloud=nil
146
+ set_or_return :cloud, cloud
147
+ end
148
+
142
149
  def run_list run_list=nil
143
150
  set_or_return :run_list, run_list
144
151
  end
@@ -154,6 +161,8 @@ module Chapp
154
161
  hash.store "name", name
155
162
  hash.store "used_apps", used_apps
156
163
 
164
+ hash.store "cloud", cloud
165
+
157
166
  hash.store "pre_run_list", pre_run_list
158
167
  hash.store "post_run_list", post_run_list
159
168
 
@@ -7,167 +7,151 @@ require 'chef/search/query'
7
7
 
8
8
  module Chapp
9
9
  class Database
10
-
10
+
11
11
  APPS_CONFIG_DATA_BAG_NAME = "chapp_apps_config"
12
12
  APP_ATTRIBUTES_DATA_BAG_NAME = "chapp_app_attributes"
13
-
13
+
14
14
  def app_ids
15
15
  apps_config_databag.keys
16
16
  end
17
-
17
+
18
18
  def app_config app_id
19
-
19
+
20
20
  unless app_exists? app_id
21
21
  raise AppNotExistsException.new, "App [#{app_id}] does not exist"
22
22
  end
23
-
23
+
24
24
  AppConfig.from_hash apps_config_databag_item(app_id).raw_data["app"]
25
25
  end
26
-
26
+
27
27
  def app_exists? app_id
28
28
  apps_config_databag.has_key? app_id
29
29
  end
30
-
30
+
31
31
  def connected_app_ids app_id
32
32
  app_ids = Array.new
33
-
33
+
34
34
  query = Chef::Search::Query.new
35
35
  query.search APPS_CONFIG_DATA_BAG_NAME, "used_apps:#{app_id}" do |databag_item|
36
36
  app_config = AppConfig.from_hash databag_item.raw_data["app"]
37
37
  app_ids.push app_config.id
38
38
  end
39
-
39
+
40
40
  app_ids
41
41
  end
42
42
 
43
43
  def write_app_config app_config
44
-
44
+
45
45
  # TODO Verify used_apps exist
46
46
  # TODO Verify cookbooks exist
47
-
47
+
48
48
  app_role_name = app_config.role_name
49
-
49
+
50
50
  attributes = app_config.node
51
51
  attributes["chapp"]["app_id"] = app_config.id
52
-
52
+
53
53
  # Build/Save role
54
54
  role = Chef::Role.new
55
55
  role.name app_role_name
56
56
  role.description "Used to define the App [#{app_config.id}]"
57
57
  role.default_attributes attributes.to_hash
58
- role.run_list "recipe[chapp]", *app_config.pre_run_list, "recipe[#{app_config.cookbook}::#{app_config.recipe}]", *app_config.post_run_list, "recipe[chapp::publish_app_attributes]"
58
+ role.run_list "recipe[chapp]", *app_config.pre_run_list, "recipe[#{app_config.cookbook}::#{app_config.recipe}]", *app_config.post_run_list
59
59
  role.save
60
-
60
+
61
61
  # Set run_list of app to role
62
62
  app_config.run_list ["role[#{app_role_name}]"]
63
-
63
+
64
64
  environment_name = app_config.environment_name
65
-
65
+
66
66
  # Build/Save environment
67
67
  environment = Chef::Environment.new
68
68
  environment.name environment_name
69
69
  environment.description "Used to define the dependencies of App [#{app_config.id}]"
70
-
70
+
71
71
  app_config.dependencies.each do |cookbook, version|
72
72
  environment.cookbook cookbook, version
73
73
  end
74
-
74
+
75
75
  environment.save
76
-
77
- # Set environment of app
76
+
77
+ # Set environment of app
78
78
  app_config.environment environment_name
79
-
79
+
80
80
  # Update app databag item
81
81
  databag_item = apps_config_databag_item app_config.id
82
82
  databag_item.raw_data["app"] = app_config.to_hash
83
83
  databag_item.save
84
-
84
+
85
85
  end
86
-
86
+
87
87
  def delete_app app_name
88
88
  # TODO (not necessary for now)
89
89
  # Delete role/environment, app config databag item, app attribute databag item, app instances
90
90
  end
91
-
92
- def app_instances app_id
93
- app_instances = Array.new
94
-
91
+
92
+ def app app_id
93
+ app_instances = []
94
+ app_attributes = {}
95
+ latest_time = 0
96
+
95
97
  query = Chef::Search::Query.new
96
98
  # TODO Figure out how to get role name more appropriately
97
99
  query.search(:node, "role:chapp_#{app_id}") do |node|
98
100
  app_instances.push Chapp::AppInstance.new(app_id, node.name, node["fqdn"])
101
+
102
+ if node.has_key?("ohai_time") && node.has_key?("chapp") && node["chapp"].has_key?("app_attributes") && node["ohai_time"] > latest_time
103
+ latest_time = node["ohai_time"]
104
+ app_attributes = node["chapp"]["app_attributes"].to_hash
105
+ end
99
106
  end
100
-
101
- app_instances
107
+
108
+ Chapp::App.new app_id, app_attributes, app_instances, self
102
109
  end
103
-
110
+
104
111
  def write_app_instance app_instance
105
112
  # NOOP (uses Chef Search)
106
113
  end
107
-
114
+
108
115
  def delete_app_instance app_instance
109
116
  # TODO: Delete node/client (not necessary for now)
110
117
  end
111
-
118
+
112
119
  def app_attributes app_id
113
120
  databag = app_attributes_databag
114
-
121
+
115
122
  unless databag.has_key? app_id
116
123
  raise AppAttributesNotExistsException.new, "Attributes for app [#{app_id}] do not exist"
117
124
  end
118
-
125
+
119
126
  app_attributes_databag_item(app_id).raw_data["app_attributes"]
120
127
  end
121
-
122
- def write_app_attributes app_id, app_attributes
123
- databag_item = app_attributes_databag_item app_id
124
- databag_item.raw_data["app_attributes"] = app_attributes
125
- databag_item.save
126
- end
127
-
128
- def delete_app_attributes app_id
129
- databag = app_attributes_databag
130
-
131
- if databag.has_key? app_id
132
- app_attributes_databag_item(app_id).destroy
133
- end
134
-
135
- end
136
-
128
+
137
129
  class AppAttributesNotExistsException < StandardError; end
138
130
  class AppNotExistsException < StandardError; end
139
-
131
+
140
132
  private
141
-
133
+
142
134
  def apps_config_databag
143
135
  get_or_create_databag APPS_CONFIG_DATA_BAG_NAME
144
136
  end
145
-
137
+
146
138
  def apps_config_databag_item app_id
147
139
  load_or_build_databag_item apps_config_databag, APPS_CONFIG_DATA_BAG_NAME, app_id
148
140
  end
149
-
150
- def app_attributes_databag
151
- get_or_create_databag APP_ATTRIBUTES_DATA_BAG_NAME
152
- end
153
-
154
- def app_attributes_databag_item app_id
155
- load_or_build_databag_item app_attributes_databag, APP_ATTRIBUTES_DATA_BAG_NAME, app_id
156
- end
157
-
141
+
158
142
  def get_or_create_databag databag_name
159
143
  databags = Chef::DataBag.list
160
-
144
+
161
145
  unless databags.include? databag_name
162
146
  # Create databag if it does not exist
163
147
  databag = Chef::DataBag.new
164
148
  databag.name databag_name
165
149
  databag.save
166
150
  end
167
-
151
+
168
152
  Chef::DataBag.load databag_name
169
153
  end
170
-
154
+
171
155
  def load_or_build_databag_item databag, databag_name, databag_item_name
172
156
  if databag.keys.include? databag_item_name
173
157
  databag_item = Chef::DataBagItem.load databag_name, databag_item_name
@@ -176,10 +160,10 @@ module Chapp
176
160
  databag_item = Chef::DataBagItem.new
177
161
  databag_item.data_bag databag_name
178
162
  databag_item.raw_data["id"] = databag_item_name
179
-
163
+
180
164
  databag_item
181
165
  end
182
166
  end
183
-
167
+
184
168
  end
185
169
  end
@@ -0,0 +1,67 @@
1
+ require 'chapp'
2
+ require 'aws'
3
+
4
+ module Chapp
5
+ class EC2Provisioner < Chapp::Provisioner
6
+
7
+ # Knife config
8
+ ACCESS_KEY = "ec2_access_key_id"
9
+ SECRET_KEY = "ec2_secret_access_key"
10
+ KEY_PAIR = "ec2_key_pair"
11
+
12
+ # App config
13
+ IMAGE_ID = "image_id"
14
+ INSTANCE_TYPE = "instance_type"
15
+
16
+ def build_server app_config, properties
17
+
18
+ errors = []
19
+
20
+ access_key = Chef::Config[ACCESS_KEY]
21
+ secret_key = Chef::Config[SECRET_KEY]
22
+ key_pair = Chef::Config[KEY_PAIR]
23
+
24
+ if access_key.nil?
25
+ errors << "#{ACCESS_KEY} must be specified in your knife config"
26
+ end
27
+
28
+ if secret_key.nil?
29
+ errors << "#{SECRET_KEY} must be specified in your knife config"
30
+ end
31
+
32
+ if key_pair.nil?
33
+ errors << "#{KEY_PAIR} must be specified in your knife config"
34
+ end
35
+
36
+ unless app_config.cloud.has_key? IMAGE_ID
37
+ errors << "#{IMAGE_ID} must be specified in your app's cloud config"
38
+ end
39
+
40
+ unless app_config.cloud.has_key? INSTANCE_TYPE
41
+ errors << "#{INSTANCE_TYPE} must be specified in your app's cloud config"
42
+ end
43
+
44
+ image_id = app_config.cloud[IMAGE_ID]
45
+ instance_type = app_config.cloud[INSTANCE_TYPE]
46
+
47
+ ec2 = AWS::EC2.new(:access_key_id => access_key, :secret_access_key => secret_key)
48
+
49
+ instance = ec2.instances.create(
50
+ :image_id => image_id,
51
+ :instance_type => instance_type,
52
+ :key_pair => ec2.key_pairs[key_pair]
53
+ )
54
+
55
+ puts "Waiting for new instance with id #{instance.id} to become available..."
56
+ sleep 1 while instance.status == :pending
57
+
58
+ puts "#{instance.dns_name} is ready"
59
+
60
+ # TODO: Wait for SSH to become available
61
+ sleep 70
62
+
63
+ instance.dns_name
64
+ end
65
+
66
+ end
67
+ end
@@ -1,19 +1,19 @@
1
1
  require 'chapp'
2
+ require 'chapp/app/node_app'
2
3
 
3
4
  module Chapp
4
5
 
5
6
  class Wiring
6
7
 
7
- attr_reader :announcements
8
8
  attr_reader :node
9
9
 
10
10
  def initialize app_config, db, node
11
- @announcements = Hash.new
12
11
  @used_apps = Hash.new
13
12
 
14
13
  @db = db
15
14
  @node = node
16
- @app = App.new app_config.id, db, app_config, @announcements
15
+ @app = Chapp::NodeApp.new app_config.id, db, app_config, node.default["chapp"]["app_attributes"],
16
+ Chef::Config[:node_name], node["fqdn"]
17
17
 
18
18
  app_config.used_apps.each do |type, app_ids|
19
19
  unless @used_apps.has_key? type
@@ -21,7 +21,7 @@ module Chapp
21
21
  end
22
22
 
23
23
  app_ids.each do |app_id|
24
- @used_apps[type] << App.new(app_id, db)
24
+ @used_apps[type] << app_id
25
25
  end
26
26
  end
27
27
  end
@@ -38,7 +38,7 @@ module Chapp
38
38
  raise "App uses many apps of [#{type}]"
39
39
  end
40
40
 
41
- @used_apps[type].first
41
+ @db.app @used_apps[type].first
42
42
  end
43
43
  end
44
44
 
@@ -47,7 +47,7 @@ module Chapp
47
47
  raise "App does not use app of type [#{type}]"
48
48
  end
49
49
 
50
- @used_apps[type]
50
+ @db.app @used_apps[type]
51
51
  end
52
52
 
53
53
  end
@@ -40,12 +40,13 @@ class Chef
40
40
 
41
41
  app_config = db.app_config app_id
42
42
 
43
- # TODO: May need something better than Time
44
- node_name = "chapp_#{app_id}_#{Time.now.to_i}"
45
-
46
43
  # Provision the server and retrieve the host name
47
44
  host = provisioner.build_server app_config, properties
48
45
 
46
+ properties.each do |key, value|
47
+ @config[key.to_sym] = value
48
+ end
49
+
49
50
  # Tells bootstrap what environment to use
50
51
  Chef::Config[:environment] = app_config.environment_name
51
52
 
@@ -53,7 +54,7 @@ class Chef
53
54
  @config[:run_list] = "role[#{app_config.role_name}]"
54
55
 
55
56
  # Tells bootstrap what node name to use
56
- @config[:chef_node_name] = node_name
57
+ @config[:chef_node_name] = host
57
58
 
58
59
  # Tells bootstrap what ip/fqdn to use
59
60
  @name_args = host
@@ -63,7 +64,7 @@ class Chef
63
64
 
64
65
  # We have to save the node here since bootstrap wont actually assign the run_list
65
66
  node = Node.new
66
- node.name node_name
67
+ node.name host
67
68
  node.run_list = Chef::RunList.new "role[#{app_config.role_name}]"
68
69
  node.chef_environment = app_config.environment_name
69
70
  node.save
@@ -20,9 +20,9 @@ class Chef
20
20
 
21
21
  app_id = @name_args[0]
22
22
 
23
- db = Chapp.database
23
+ app = Chapp.database.app app_id
24
24
 
25
- app_config = db.app_config app_id
25
+ app_config = app.config
26
26
 
27
27
  puts "App :"
28
28
  puts " id : #{app_config.id}"
@@ -31,6 +31,7 @@ class Chef
31
31
  puts " type : #{app_config.type}"
32
32
  puts " cookbook : #{app_config.cookbook}"
33
33
  puts " recipe : #{app_config.recipe}"
34
+ puts " cloud : #{app_config.cloud}"
34
35
 
35
36
  puts " used_apps :"
36
37
  app_config.used_apps.each do |type, used_app_ids|
@@ -61,15 +62,10 @@ class Chef
61
62
  puts ""
62
63
 
63
64
  puts "App Attributes :"
64
- begin
65
- attributes = db.app_attributes app_id
66
- print_hash attributes, 2
67
- rescue Chapp::Database::AppAttributesNotExistsException => e
68
- puts " NONE"
69
- end
65
+ print_hash app.attributes, 2
70
66
 
71
67
  puts "App Instances :"
72
- db.app_instances(app_id).each do |app_instance|
68
+ app.instances.each do |app_instance|
73
69
  puts " #{app_instance.fqdn}"
74
70
  end
75
71
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chapp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bryan Baugher
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-04-24 00:00:00.000000000 Z
11
+ date: 2014-07-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chef
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
26
  version: '11.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: aws
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '2.10'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '2.10'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: rake
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -45,19 +59,21 @@ executables: []
45
59
  extensions: []
46
60
  extra_rdoc_files: []
47
61
  files:
48
- - Gemfile
49
- - lib/chapp.rb
62
+ - lib/chapp/app/node_app.rb
50
63
  - lib/chapp/app.rb
51
64
  - lib/chapp/app_config.rb
52
65
  - lib/chapp/app_instance.rb
53
66
  - lib/chapp/database.rb
54
- - lib/chapp/provisioner.rb
67
+ - lib/chapp/provisioner/ec2_provisioner.rb
55
68
  - lib/chapp/provisioner/property_provisioner.rb
69
+ - lib/chapp/provisioner.rb
56
70
  - lib/chapp/wiring.rb
71
+ - lib/chapp.rb
57
72
  - lib/chef/knife/app_instance_create.rb
58
73
  - lib/chef/knife/app_list.rb
59
74
  - lib/chef/knife/app_show.rb
60
75
  - lib/chef/knife/app_upload.rb
76
+ - Gemfile
61
77
  homepage: http://github.com/bbaugher/chapp
62
78
  licenses:
63
79
  - The MIT License (MIT)
@@ -78,8 +94,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
78
94
  version: '0'
79
95
  requirements: []
80
96
  rubyforge_project: nowarning
81
- rubygems_version: 2.2.1
97
+ rubygems_version: 2.0.3
82
98
  signing_key:
83
99
  specification_version: 4
84
100
  summary: A Chef knife plugin for creating Chef Apps
85
101
  test_files: []
102
+ has_rdoc: