knife-topo 0.0.3

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,110 @@
1
+ #
2
+ # Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
3
+ # Copyright:: Copyright (c) 2014 ThirdWave Insights LLC
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
+ require 'chef/knife'
20
+ require_relative 'topo_cookbook_upload'
21
+
22
+ class Chef
23
+ class Knife
24
+ class TopoUpdate < Chef::Knife
25
+
26
+ deps do
27
+ Chef::Knife::TopoCookbookUpload.load_deps
28
+ end
29
+
30
+ banner "knife topo update [ TOPOLOGY ] (options)"
31
+
32
+ option :data_bag,
33
+ :short => '-D DATA_BAG',
34
+ :long => "--data-bag DATA_BAG",
35
+ :description => "The data bag the topologies are stored in"
36
+
37
+ # Make called command options available
38
+ self.options = Chef::Knife::TopoCookbookUpload.options.merge(self.options)
39
+
40
+ def initialize (args)
41
+ super
42
+ @topo_upload_args = initialize_cmd_args(args, [ 'topo', 'cookbook', 'upload', '' ])
43
+
44
+ # All called commands need to accept union of options
45
+ Chef::Knife::TopoCookbookUpload.options = options
46
+ end
47
+
48
+ def run
49
+
50
+ bag_name = topo_bag_name(config[:data_bag])
51
+
52
+ if !@name_args[0]
53
+ ui.confirm("Do you want to update all topologies in the #{bag_name} data bag", true, true)
54
+ end
55
+
56
+ topo_name = @name_args[0]
57
+
58
+ if topo_name
59
+ # update a specific topo
60
+ ui.info "Updating topology: #{topo_name} in data bag: #{bag_name}"
61
+
62
+ unless current_topo = load_from_server(bag_name, topo_name)
63
+ ui.fatal "Topology #{bag_name}/#{topo_name} does not exist on server - use 'knife topo create' first"
64
+ exit(1)
65
+ end
66
+
67
+ unless topo = load_from_file(bag_name, topo_name)
68
+ ui.info "No topology found in #{topologies_path}/#{bag_name}/#{topo_name}.json - exiting without action"
69
+ exit(0)
70
+ end
71
+
72
+ update_topo(topo)
73
+
74
+ else
75
+ # find all topologies from server then update them from file, skipping any that have no file
76
+ ui.info "Updating all topologies in data bag: #{bag_name}"
77
+
78
+ unless dbag = load_from_server(bag_name)
79
+ ui.fatal "Data bag #{bag_name} does not exist on server - use 'knife topo create' first"
80
+ exit(1)
81
+ end
82
+
83
+ dbag.keys.each do |topo_name|
84
+
85
+ topo = load_from_file(bag_name, topo_name)
86
+ if !topo
87
+ # do not update topologies that are not in the local workspace
88
+ ui.info("No topology file found in #{topologies_path}/#{bag_name}/#{topo_name}.json - skipping")
89
+ else
90
+ ui.info("Updating topology #{topo_name}")
91
+ update_topo(topo)
92
+ end
93
+ end
94
+ end
95
+ ui.info "Updates done"
96
+
97
+ end
98
+
99
+ def update_topo(topo)
100
+ topo.save
101
+ @topo_upload_args[3] = topo['name']
102
+ upload_cookbooks(@topo_upload_args) if (!config[:no_upload])
103
+ create_or_update_nodes(topo)
104
+ end
105
+
106
+ include Chef::Knife::TopologyHelper
107
+
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,280 @@
1
+ #
2
+ # Author:: Christine Draper (<christine_draper@thirdwaveinsights.com>)
3
+ # Copyright:: Copyright (c) 2014 ThirdWave Insights LLC
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
+ require 'chef/data_bag'
20
+ require 'chef/encrypted_data_bag_item'
21
+ require 'chef/knife/core/object_loader'
22
+
23
+ class Chef
24
+ class Knife
25
+ module TopologyHelper
26
+
27
+ # load one or more topologies from file
28
+ def load_topologies(topology_file_path)
29
+
30
+ if ! topology_file_path.end_with?('.js', '.json')
31
+ show_usage
32
+ ui.fatal "TOPOLOGY_FILE must be a '.js' or '.json' file"
33
+ exit(1)
34
+ end
35
+
36
+ topologies = loader.object_from_file(topology_file_path)
37
+ topologies = [topologies] if !topologies.kind_of?(Array)
38
+
39
+ topologies
40
+ end
41
+
42
+ # create the topology data bag
43
+ def create_bag(bag_name)
44
+ # check that the name is valid
45
+ begin
46
+ Chef::DataBag.validate_name!(bag_name)
47
+ rescue Chef::Exceptions::InvalidDataBagName => e
48
+ ui.fatal(e.message)
49
+ exit(1)
50
+ end
51
+
52
+ # create the data bag
53
+ begin
54
+ data_bag = Chef::DataBag.new
55
+ data_bag.name(bag_name)
56
+ data_bag.create
57
+ ui.info("Created topology data bag [#{bag_name}]")
58
+ rescue Net::HTTPServerException => e
59
+ raise unless e.to_s =~ /^409/
60
+ data_bag = Chef::DataBag.load(bag_name)
61
+ ui.info("Topology data bag #{bag_name} already exists")
62
+ end
63
+
64
+ data_bag
65
+ end
66
+
67
+ # make sure the chef environment exists
68
+ def check_chef_env(chef_env_name)
69
+
70
+ if chef_env_name
71
+ begin
72
+ chef_env = Chef::Environment.load(chef_env_name)
73
+ rescue Net::HTTPServerException => e
74
+ raise unless e.to_s =~ /^404/
75
+ ui.info "Creating chef environment " + chef_env_name
76
+ chef_env = Chef::Environment.new()
77
+ chef_env.name(chef_env_name)
78
+ chef_env.create
79
+ end
80
+ end
81
+
82
+ chef_env
83
+ end
84
+
85
+ # Merges topology properties into nodes, returning the merged nodes
86
+ def merge_topo_properties(nodes, topo_hash)
87
+
88
+ if nodes
89
+ merged_nodes = nodes.clone
90
+ merged_nodes.each do |nodeprops|
91
+
92
+ nodeprops['chef_environment'] ||= topo_hash['chef_environment'] if topo_hash['chef_environment']
93
+
94
+ # merge in the topology tags
95
+ nodeprops['tags'] |= topo_hash['tags'] if topo_hash['tags']
96
+
97
+ normal_defaults = topo_hash['normal'] || {}
98
+ nodeprops['normal'] = normal_defaults.merge(nodeprops['normal'] || {})
99
+
100
+ end
101
+ end
102
+
103
+ merged_nodes
104
+
105
+ end
106
+
107
+ # Get nodes from the topology, create them and/or set their run lists
108
+ def create_or_update_nodes(topo)
109
+
110
+ topo_hash = topo.raw_data
111
+ nodes = merge_topo_properties(topo_hash['nodes'], topo_hash)
112
+ config[:disable_editing] = true
113
+
114
+ if nodes.length > 0
115
+ nodes.each do |updates|
116
+ node_name = updates['name']
117
+ begin
118
+ # load then update and save the node
119
+ node = Chef::Node.load(node_name)
120
+ if updated_values = update_node_with_values(node, updates)
121
+ ui.info "Updating #{updated_values.join(', ')} on node #{node.name}"
122
+ node.save
123
+ ui.output(format_for_display(node)) if config[:print_after]
124
+ else
125
+ ui.info "No updates found for node #{node.name}"
126
+ end
127
+
128
+ rescue Net::HTTPServerException => e
129
+ raise unless e.to_s =~ /^404/
130
+ # Create the node
131
+ node = Chef::Node.new
132
+ node.name(node_name)
133
+ update_node_with_values(node, updates)
134
+ create_object(node)
135
+ end
136
+ end
137
+ else
138
+ ui.info "No nodes found for topology #{topo_hash.name}"
139
+ end
140
+ end
141
+
142
+ # Make updates into the original node, returning the list of updated properties.
143
+ def update_node_with_values(node, updates)
144
+ updated_properties = []
145
+
146
+ if updates['run_list']
147
+ updated_run_list = RunList.new
148
+ updates['run_list'].each { |e| updated_run_list << e }
149
+ if (updated_run_list != node.run_list)
150
+ updated_properties << 'run_list'
151
+ node.run_list(*updated_run_list)
152
+ end
153
+ end
154
+
155
+ new_chef_environment = updates['chef_environment']
156
+ if new_chef_environment && new_chef_environment != node.chef_environment
157
+ updated_properties << 'chef_environment'
158
+ node.chef_environment(new_chef_environment)
159
+ end
160
+
161
+ orig_num_tags = node.tags.length
162
+ updates['tags'] ||= [] # make sure tags are initialized
163
+ node.tag(*updates['tags'])
164
+ updated_properties << 'tags' if node.tags.length > orig_num_tags
165
+
166
+ normal_updates = updates['normal'] || {}
167
+ normal_updates.each do |key, value|
168
+ if (value != node.normal[key])
169
+ updated_properties << "normal.#{key}"
170
+ node.normal[key] = value
171
+ end
172
+ end
173
+
174
+ # return false if no updates, else return array of property names
175
+ updated_properties.length > 0 && updated_properties
176
+ end
177
+
178
+ # Load a topology from local data bag item file
179
+ def load_from_file(bag_name, topo_name)
180
+ return unless topo_file = loader.find_file("#{topologies_path}", bag_name, topo_name + '.json')
181
+
182
+ item_data = loader.object_from_file(topo_file)
183
+ item_data = if use_encryption
184
+ secret = read_secret
185
+ Chef::EncryptedDataBagItem.encrypt_data_bag_item(item_data, secret)
186
+ else
187
+ item_data
188
+ end
189
+ item = Chef::DataBagItem.new
190
+ item.data_bag(bag_name)
191
+ item.raw_data = item_data
192
+ item
193
+ end
194
+
195
+ # read in the topology bag item
196
+ def load_from_server(bag_name, item_name = nil)
197
+ begin
198
+ if (item_name)
199
+ item = Chef::DataBagItem.load(bag_name, item_name)
200
+ item = Chef::EncryptedDataBagItem.new(item.raw_data, read_secret) if use_encryption
201
+ else
202
+ item = Chef::DataBag.load(bag_name)
203
+ end
204
+ rescue Net::HTTPServerException => e
205
+ raise unless e.to_s =~ /^404/
206
+ end
207
+ item
208
+ end
209
+
210
+ # Replace existing run list in a node
211
+ def set_run_list(node, entries)
212
+ node.run_list.run_list_items.clear
213
+ entries.each { |e| node.run_list << e }
214
+ end
215
+
216
+ # Name of the topology bag
217
+ def topo_bag_name(name=nil)
218
+ @topo_bag_name = name if (name)
219
+ @topo_bag_name ||= "topologies"
220
+ end
221
+
222
+ # Path for the topologies data bags.
223
+ # For now, use the standard data_bags path for our topologies bags
224
+ def topologies_path
225
+ @topologies_path ||= "data_bags"
226
+ end
227
+
228
+ # Loader to get data bag items from file
229
+ def loader
230
+ @loader ||= Knife::Core::ObjectLoader.new(DataBagItem, ui)
231
+ end
232
+
233
+ # Determine if the bag items are/should be encrypted on server
234
+ # NOTE: This option isnt currently enabled
235
+ def use_encryption
236
+ if config[:secret] && config[:secret_file]
237
+ ui.fatal("please specify only one of --secret, --secret-file")
238
+ exit(1)
239
+ end
240
+ config[:secret] || config[:secret_file]
241
+ end
242
+
243
+ # Return the secret key to encrypt/decrypt data bag items
244
+ def read_secret
245
+ if config[:secret]
246
+ config[:secret]
247
+ else
248
+ Chef::EncryptedDataBagItem.load_secret(config[:secret_file])
249
+ end
250
+ end
251
+
252
+ # initialize args for another knife command
253
+ def initialize_cmd_args(args, new_name_args)
254
+ args = args.dup
255
+ args.shift(2 + @name_args.length)
256
+ cmd_args = new_name_args + args
257
+ end
258
+
259
+ # run another knife command
260
+ def run_cmd(command_class, args)
261
+ command = command_class.new(args)
262
+ command.config[:config_file] = config[:config_file]
263
+ command.configure_chef
264
+ command.run
265
+
266
+ command
267
+ end
268
+
269
+ # upload cookbooks - will warn and continue if upload fails (e.g. may be frozen)
270
+ def upload_cookbooks(args)
271
+ begin
272
+ run_cmd(Chef::Knife::TopoCookbookUpload, args)
273
+ rescue Exception => e
274
+ raise if Chef::Config[:verbosity] == 2
275
+ end
276
+ end
277
+
278
+ end
279
+ end
280
+ end
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAqZszg6n+ukMvore53ROFNQAAZhEfW0H9erLqC/4Go/lkRhwl
3
+ d/BOu3bexV2bQFh8Eqg/0VfP0/eOGx4pt6lOP1W20isWr0sGnf8DID2oB/Vi/NhS
4
+ +zfnos/TMXbJSvXryfpMUB6YKhraC645Q0zuBDHm+3fjGol6nND/tVWCW9h+og7d
5
+ WTZLOVUbbD949F7WBVEcbNp66e49AaZ5yYevVJtjCQRQQ1E9d+/WsMM0Nv24VEc2
6
+ oEmbH4U0/+g+WKiJB4m/IDJ4RXco3JtFNpkM/HeKHcc0Niw1A8aLVv5Bp3hYkEnh
7
+ VidA+H2nZ7IxNOzF3wzJAUwxmg89hC2X1t9WUQIDAQABAoIBAGCZrBKOrS3LfIMy
8
+ H6NiLdmNAa0gjXp9sHDFHHbuHTwhnFIuT8zrSvyM7L7+3KEehLRfrdF/MTjqY77g
9
+ RCR+QrniCPnVXttCYSd2CoK/e0flJJccYs8A/WaG9iPTIz0VqlFkxThQ5Jv+pThH
10
+ 6AeD9oDfJ08M7oW7zeEpTKssY84JKE7iAPjBoRF8wMjJPbJB6HEDKPT6pPL9fyjF
11
+ +FkD01XxaI4Ip5vXsc0+Lckf9uItD5SP4CDcFVxFtU+4m/iJjBrUxeUDrzWCzOY4
12
+ SgfD9aJ3J79acQ4omtvD0iGUSu/4CwSpAyuw0qzBOS2tmYyaiz0EK2YGg3IbE9xz
13
+ jPjnj40CgYEA1ai6cb/9PBfF82sG6e23fie2odHN6Lt5Ex7AmCjGg7yVly1rLm7f
14
+ LxCA+bJfwyOmx7/rptECAFnQeahVcsLQ3KXDwm0IP8Ow60s83Tk0HNrejlIK7f5i
15
+ 8PlvO7Z+bhbTqKDI12YuKJ74pBw4WCP7U4fmxWNryFj1/7o8gPgsqesCgYEAyzeZ
16
+ 3lbya3Txl3gYhS5Ppeuqave/q1jcCYUmoTqCfyZxqQyCmuVpMN/S6zx/vTAlFqHK
17
+ OsE5v9GD+NuvfhXga4+9FH4nMdbdhYntHLSwgAW/WPShVsNM2WCibIZtkOoI3Bkl
18
+ wYQF+PZNGPmAChaEsE7oq6vavHD5DHeVmn3M1bMCgYBbLeZjJMutGXggqUwKCKiF
19
+ 7ezCogZ9i4Pf5P/L75rIHXK5UWisKCSWsTRZWwYDAPPryruGNSvlem69fFj64KjB
20
+ gPxJvL4IeDrILxOKVR8oMT9I/Tos1qLis5AEq5zI3nT1Qah0Q+bu7uitIF3rP2/B
21
+ 9f1Fv2f/1/cjaxbm8wIcgQKBgBx4t8gc6m3/vnF4VAcky+f1MrU17Na25m03CIiC
22
+ SBJEcpw6snm9NpWwZj6rBUKeYjPfixPcSpkDY7gUH2xM6FppkxYx7o/fCL5S6rOg
23
+ 5TGqnHp8G7aqOjQig98snmE1SPR9WXrZYnTVHUwoeLXxHboN9C9JLqZENcB3aLBy
24
+ e6ZdAoGACeT2RLyEngm2XVcdNeiXbtwu8+qhoK4FHX5eFKmO2hm+xDo/601acaH+
25
+ LdFDMKfGevjqTCVS9ZD3SgELSk+KpAvXpVmOzXaX/n/eGCVOYxsWPEKhwpEUsIml
26
+ 9rq1jU/phQw7627WvP8UbwMbNl1u1SDCJwFTFssVmZ3pDI4nth8=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,13 @@
1
+ # See http://docs.opscode.com/config_rb_knife.html for more information on knife configuration options
2
+
3
+ current_dir = File.dirname(__FILE__)
4
+ log_level :info
5
+ log_location STDOUT
6
+ node_name "workstation"
7
+ client_key "#{current_dir}/dummy.pem"
8
+ validation_client_name "validator"
9
+ validation_key "#{current_dir}/dummy.pem"
10
+ chef_server_url "http://10.0.1.1:8889"
11
+ cache_type 'BasicFile'
12
+ cache_options( :path => "#{ENV['HOME']}/.chef/checksums" )
13
+ cookbook_path ["#{current_dir}/../cookbooks"]
@@ -0,0 +1,4 @@
1
+ source "https://api.berkshelf.com"
2
+
3
+ cookbook 'testapp', :path => './cookbooks/testapp'
4
+
@@ -0,0 +1,48 @@
1
+ # Assumptions for this demo: chefDK, Vagrant, VirtualBox and chef-zero
2
+
3
+ # chefDK can be obtained from:
4
+ http://www.getchef.com/downloads/chef-dk/
5
+
6
+ # vagrant can be installed from:
7
+ https://www.vagrantup.com/downloads.html
8
+
9
+ # VirtualBox can be obtained from:
10
+ https://www.virtualbox.org/wiki/Downloads
11
+
12
+ # If you have chefDK installed, you can use the embedded chef-zero
13
+ /opt/chefdk/embedded/bin/chef-zero
14
+
15
+ # or install it
16
+ sudo gem install chef-zero
17
+
18
+ # Copy test-repo into a working directory, either downloading it from github or copying it from the installed
19
+ # knife-topo gem. You can use
20
+ gem env
21
+ # to get the path to your gems and then
22
+ cp -R <path-to-gem>/knife-topo/test-repo ~
23
+ cd ~/test-repo
24
+
25
+ # From the test-repo, do the following to start the virtual machines on a private network using vagrant -
26
+ # Note: you may be prompted to select the network to bridge to
27
+ vagrant up
28
+
29
+ # Once the virtual machines are created, start chef-zero listening on the same private network:
30
+ chef-zero -H 10.0.1.1
31
+
32
+ # In another terminal, in test-repo:
33
+ berks install
34
+ berks upload
35
+
36
+ # To create and bootstrap the test1 topology
37
+ knife topo import exchange.json
38
+ knife topo create sys1_test test1
39
+ knife topo bootstrap sys1_test test1 -x vagrant -P vagrant --sudo
40
+
41
+
42
+ # To check the bootstrap has succeeded, browse to:
43
+ http://localhost:3031
44
+ # You should see a "Welcome" message
45
+
46
+
47
+
48
+
@@ -0,0 +1,67 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ # This Vagrantfile was inspired by Joshua Timberman's blog
5
+ # http://jtimberman.housepub.org/blog/2012/03/18/multivm-vagrantfile-for-chef/
6
+
7
+ #
8
+ # Vagrantfile for two-machine test topology. Runs with a private network
9
+ # and port forwarding from 3001 on appserver guest, to port 303n on host (i.e. 3031 for topo with id 1).
10
+ # ipaddresses are 10.0.1.2, 10.0.1.3 for dbserver, appserver.
11
+
12
+ # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
13
+ VAGRANTFILE_API_VERSION = "2"
14
+
15
+ id = 1
16
+ qual = "0#{id}"
17
+
18
+ # Define the options for each node
19
+ nodes = {
20
+ :dbserver => {
21
+ :hostname => "dbserver#{qual}",
22
+ :ipaddress => "10.0.#{id}.2"
23
+ },
24
+ :appserver => {
25
+ :hostname => "appserver#{qual}",
26
+ :ipaddress => "10.0.#{id}.3",
27
+ :forwardports => [
28
+ {
29
+ :guest => 3001,
30
+ :host => (3030 + id)
31
+ }
32
+ ]
33
+ }
34
+ }
35
+
36
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
37
+
38
+ # setup each node using config ("options") defined above
39
+ nodes.each do |node, options|
40
+ config.vm.define node do |node_config|
41
+
42
+ # setup networking using private network, with port forwarding where needed to access
43
+ # TODO how to let ip be optional in either case
44
+ net_type = ( options.has_key?(:public)) ? :public_network : :private_network
45
+ if options.has_key?(:public)
46
+ node_config.vm.network net_type, ip: options[:ipaddress]
47
+ else
48
+ node_config.vm.network net_type, ip: options[:ipaddress]
49
+ end
50
+
51
+ if options.has_key?(:forwardports)
52
+ options[:forwardports].each do |port|
53
+ node_config.vm.network :forwarded_port, guest: port[:guest], host: port[:host]
54
+ end
55
+ end
56
+ node_config.vm.hostname = options[:hostname]
57
+ end
58
+ end
59
+
60
+ # Setup the generic config across both servers
61
+ config.vm.box = "ubuntu64"
62
+
63
+ # The url from where the 'config.vm.box' box will be fetched if it
64
+ # doesn't already exist on the user's system.
65
+ config.vm.box_url = "http://files.vagrantup.com/precise64.box"
66
+
67
+ end
@@ -0,0 +1,54 @@
1
+ This directory contains the cookbooks used to configure systems in your infrastructure with Chef.
2
+
3
+ Knife needs to be configured to know where the cookbooks are located with the `cookbook_path` setting. If this is not set, then several cookbook operations will fail to work properly.
4
+
5
+ cookbook_path ["./cookbooks"]
6
+
7
+ This setting tells knife to look for the cookbooks directory in the present working directory. This means the knife cookbook subcommands need to be run in the `chef-repo` directory itself. To make sure that the cookbooks can be found elsewhere inside the repository, use an absolute path. This is a Ruby file, so something like the following can be used:
8
+
9
+ current_dir = File.dirname(__FILE__)
10
+ cookbook_path ["#{current_dir}/../cookbooks"]
11
+
12
+ Which will set `current_dir` to the location of the knife.rb file itself (e.g. `~/chef-repo/.chef/knife.rb`).
13
+
14
+ Configure knife to use your preferred copyright holder, email contact and license. Add the following lines to `.chef/knife.rb`.
15
+
16
+ cookbook_copyright "Example, Com."
17
+ cookbook_email "cookbooks@example.com"
18
+ cookbook_license "apachev2"
19
+
20
+ Supported values for `cookbook_license` are "apachev2", "mit","gplv2","gplv3", or "none". These settings are used to prefill comments in the default recipe, and the corresponding values in the metadata.rb. You are free to change the the comments in those files.
21
+
22
+ Create new cookbooks in this directory with Knife.
23
+
24
+ knife cookbook create COOKBOOK
25
+
26
+ This will create all the cookbook directory components. You don't need to use them all, and can delete the ones you don't need. It also creates a README file, metadata.rb and default recipe.
27
+
28
+ You can also download cookbooks directly from the Opscode Cookbook Site. There are two subcommands to help with this depending on what your preference is.
29
+
30
+ The first and recommended method is to use a vendor branch if you're using Git. This is automatically handled with Knife.
31
+
32
+ knife cookbook site install COOKBOOK
33
+
34
+ This will:
35
+
36
+ * Download the cookbook tarball from cookbooks.opscode.com.
37
+ * Ensure its on the git master branch.
38
+ * Checks for an existing vendor branch, and creates if it doesn't.
39
+ * Checks out the vendor branch (chef-vendor-COOKBOOK).
40
+ * Removes the existing (old) version.
41
+ * Untars the cookbook tarball it downloaded in the first step.
42
+ * Adds the cookbook files to the git index and commits.
43
+ * Creates a tag for the version downloaded.
44
+ * Checks out the master branch again.
45
+ * Merges the cookbook into master.
46
+ * Repeats the above for all the cookbooks dependencies, downloading them from the community site
47
+
48
+ The last step will ensure that any local changes or modifications you have made to the cookbook are preserved, so you can keep your changes through upstream updates.
49
+
50
+ If you're not using Git, use the site download subcommand to download the tarball.
51
+
52
+ knife cookbook site download COOKBOOK
53
+
54
+ This creates the COOKBOOK.tar.gz from in the current directory (e.g., `~/chef-repo`). We recommend following a workflow similar to the above for your version control tool.
@@ -0,0 +1,10 @@
1
+ testapp CHANGELOG
2
+ =================
3
+
4
+ This file is used to list changes made in each version of the testapp cookbook.
5
+
6
+ 0.1.0
7
+ -----
8
+ - Christine Draper - Initial release of testapp
9
+
10
+ - - -
@@ -0,0 +1,26 @@
1
+ Test Application Cookbook
2
+ =========================
3
+ A simple nodejs application that puts up a welcome page.
4
+
5
+ Requirements
6
+ ------------
7
+ Tested on Ubuntu 12.04 LTS.
8
+
9
+ #### packages
10
+ - `nodejs` - The test application is a nodejs application
11
+ - ` mongodb` - In the future, the test application will have a connection to a database
12
+
13
+ Attributes
14
+ ----------
15
+ None
16
+
17
+
18
+ Recipes
19
+ -------
20
+ #### testapp::default
21
+
22
+
23
+
24
+ License and Authors
25
+ -------------------
26
+ Authors: Christine Draper, ThirdWave Insights, LLC
@@ -0,0 +1,13 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
6
+ <title>YPO Test Application</title>
7
+
8
+ </head>
9
+ <body>
10
+ <p> Welcome ! You can find the knife topo plugin on Github:</p>
11
+ <a href="https://github.com">https://github.com/thirdwaveinsights/knife-topo</a>
12
+ </body>
13
+ </html>
@@ -0,0 +1,14 @@
1
+ {
2
+ "name": "testapp",
3
+ "description": "A dummy application for testing knife-topo",
4
+ "author": "ThirdWave Insights LLC <contact@thirdwaveinsights.com>",
5
+ "version": "0.0.1",
6
+ "private": true,
7
+ "main": "server.js",
8
+ "dependencies": {
9
+ "express": "3.3.4",
10
+ "ejs": "0.8.4",
11
+ "connect": "2.8.4"
12
+ },
13
+ "engine": "node 0.10.15"
14
+ }