runa-chef 0.8.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.
- data/LICENSE +201 -0
- data/README.rdoc +136 -0
- data/bin/chef-client +26 -0
- data/bin/chef-solo +26 -0
- data/bin/knife +27 -0
- data/bin/shef +45 -0
- data/distro/README +2 -0
- data/distro/common/man/man1/chef-indexer.1 +42 -0
- data/distro/common/man/man1/chef-server.1 +108 -0
- data/distro/common/man/man8/chef-client.8 +61 -0
- data/distro/common/man/man8/chef-solo.8 +58 -0
- data/distro/common/man/man8/knife.8 +359 -0
- data/distro/debian/etc/init.d/chef-client +175 -0
- data/distro/debian/etc/init.d/chef-indexer +175 -0
- data/distro/debian/etc/init.d/chef-server +120 -0
- data/distro/redhat/etc/init.d/chef-client +78 -0
- data/distro/redhat/etc/init.d/chef-indexer +76 -0
- data/distro/redhat/etc/init.d/chef-server +78 -0
- data/distro/redhat/etc/sysconfig/chef-client +10 -0
- data/distro/redhat/etc/sysconfig/chef-indexer +8 -0
- data/distro/redhat/etc/sysconfig/chef-server +10 -0
- data/distro/suse/etc/init.d/chef-client +121 -0
- data/lib/chef.rb +49 -0
- data/lib/chef/api_client.rb +269 -0
- data/lib/chef/application.rb +98 -0
- data/lib/chef/application/agent.rb +18 -0
- data/lib/chef/application/client.rb +214 -0
- data/lib/chef/application/knife.rb +138 -0
- data/lib/chef/application/server.rb +19 -0
- data/lib/chef/application/solo.rb +214 -0
- data/lib/chef/cache.rb +61 -0
- data/lib/chef/cache/checksum.rb +70 -0
- data/lib/chef/certificate.rb +154 -0
- data/lib/chef/client.rb +323 -0
- data/lib/chef/compile.rb +158 -0
- data/lib/chef/config.rb +195 -0
- data/lib/chef/cookbook.rb +198 -0
- data/lib/chef/cookbook/metadata.rb +487 -0
- data/lib/chef/cookbook/metadata/version.rb +87 -0
- data/lib/chef/cookbook_loader.rb +180 -0
- data/lib/chef/couchdb.rb +273 -0
- data/lib/chef/daemon.rb +170 -0
- data/lib/chef/data_bag.rb +216 -0
- data/lib/chef/data_bag_item.rb +227 -0
- data/lib/chef/exceptions.rb +39 -0
- data/lib/chef/file_cache.rb +205 -0
- data/lib/chef/knife.rb +300 -0
- data/lib/chef/knife/client_bulk_delete.rb +41 -0
- data/lib/chef/knife/client_create.rb +55 -0
- data/lib/chef/knife/client_delete.rb +37 -0
- data/lib/chef/knife/client_edit.rb +37 -0
- data/lib/chef/knife/client_list.rb +40 -0
- data/lib/chef/knife/client_reregister.rb +48 -0
- data/lib/chef/knife/client_show.rb +42 -0
- data/lib/chef/knife/configure.rb +84 -0
- data/lib/chef/knife/cookbook_bulk_delete.rb +47 -0
- data/lib/chef/knife/cookbook_delete.rb +41 -0
- data/lib/chef/knife/cookbook_download.rb +57 -0
- data/lib/chef/knife/cookbook_list.rb +41 -0
- data/lib/chef/knife/cookbook_metadata.rb +87 -0
- data/lib/chef/knife/cookbook_show.rb +75 -0
- data/lib/chef/knife/cookbook_upload.rb +173 -0
- data/lib/chef/knife/data_bag_create.rb +43 -0
- data/lib/chef/knife/data_bag_delete.rb +43 -0
- data/lib/chef/knife/data_bag_edit.rb +49 -0
- data/lib/chef/knife/data_bag_list.rb +42 -0
- data/lib/chef/knife/data_bag_show.rb +40 -0
- data/lib/chef/knife/ec2_instance_data.rb +46 -0
- data/lib/chef/knife/node_bulk_delete.rb +44 -0
- data/lib/chef/knife/node_create.rb +39 -0
- data/lib/chef/knife/node_delete.rb +36 -0
- data/lib/chef/knife/node_edit.rb +36 -0
- data/lib/chef/knife/node_from_file.rb +42 -0
- data/lib/chef/knife/node_list.rb +41 -0
- data/lib/chef/knife/node_run_list_add.rb +64 -0
- data/lib/chef/knife/node_run_list_remove.rb +45 -0
- data/lib/chef/knife/node_show.rb +46 -0
- data/lib/chef/knife/role_bulk_delete.rb +45 -0
- data/lib/chef/knife/role_create.rb +44 -0
- data/lib/chef/knife/role_delete.rb +36 -0
- data/lib/chef/knife/role_edit.rb +37 -0
- data/lib/chef/knife/role_from_file.rb +46 -0
- data/lib/chef/knife/role_list.rb +40 -0
- data/lib/chef/knife/role_show.rb +43 -0
- data/lib/chef/knife/search.rb +94 -0
- data/lib/chef/log.rb +39 -0
- data/lib/chef/mixin/check_helper.rb +31 -0
- data/lib/chef/mixin/checksum.rb +32 -0
- data/lib/chef/mixin/command.rb +390 -0
- data/lib/chef/mixin/convert_to_class_name.rb +57 -0
- data/lib/chef/mixin/create_path.rb +56 -0
- data/lib/chef/mixin/deep_merge.rb +33 -0
- data/lib/chef/mixin/find_preferred_file.rb +92 -0
- data/lib/chef/mixin/from_file.rb +50 -0
- data/lib/chef/mixin/generate_url.rb +58 -0
- data/lib/chef/mixin/language.rb +107 -0
- data/lib/chef/mixin/language_include_attribute.rb +56 -0
- data/lib/chef/mixin/language_include_recipe.rb +53 -0
- data/lib/chef/mixin/params_validate.rb +197 -0
- data/lib/chef/mixin/recipe_definition_dsl_core.rb +79 -0
- data/lib/chef/mixin/template.rb +94 -0
- data/lib/chef/nanite.rb +100 -0
- data/lib/chef/node.rb +463 -0
- data/lib/chef/node/attribute.rb +412 -0
- data/lib/chef/openid_registration.rb +181 -0
- data/lib/chef/platform.rb +268 -0
- data/lib/chef/provider.rb +101 -0
- data/lib/chef/provider/breakpoint.rb +36 -0
- data/lib/chef/provider/cron.rb +184 -0
- data/lib/chef/provider/deploy.rb +314 -0
- data/lib/chef/provider/deploy/revision.rb +70 -0
- data/lib/chef/provider/deploy/timestamped.rb +33 -0
- data/lib/chef/provider/directory.rb +72 -0
- data/lib/chef/provider/erl_call.rb +72 -0
- data/lib/chef/provider/execute.rb +58 -0
- data/lib/chef/provider/file.rb +195 -0
- data/lib/chef/provider/git.rb +203 -0
- data/lib/chef/provider/group.rb +120 -0
- data/lib/chef/provider/group/dscl.rb +128 -0
- data/lib/chef/provider/group/gpasswd.rb +50 -0
- data/lib/chef/provider/group/groupadd.rb +78 -0
- data/lib/chef/provider/group/pw.rb +88 -0
- data/lib/chef/provider/group/usermod.rb +57 -0
- data/lib/chef/provider/http_request.rb +106 -0
- data/lib/chef/provider/ifconfig.rb +131 -0
- data/lib/chef/provider/link.rb +157 -0
- data/lib/chef/provider/mdadm.rb +88 -0
- data/lib/chef/provider/mount.rb +117 -0
- data/lib/chef/provider/mount/mount.rb +208 -0
- data/lib/chef/provider/package.rb +160 -0
- data/lib/chef/provider/package/apt.rb +110 -0
- data/lib/chef/provider/package/dpkg.rb +109 -0
- data/lib/chef/provider/package/easy_install.rb +106 -0
- data/lib/chef/provider/package/freebsd.rb +153 -0
- data/lib/chef/provider/package/macports.rb +105 -0
- data/lib/chef/provider/package/portage.rb +124 -0
- data/lib/chef/provider/package/rpm.rb +99 -0
- data/lib/chef/provider/package/rubygems.rb +136 -0
- data/lib/chef/provider/package/yum-dump.py +125 -0
- data/lib/chef/provider/package/yum.rb +175 -0
- data/lib/chef/provider/package/zypper.rb +132 -0
- data/lib/chef/provider/remote_directory.rb +126 -0
- data/lib/chef/provider/remote_file.rb +141 -0
- data/lib/chef/provider/route.rb +118 -0
- data/lib/chef/provider/ruby_block.rb +33 -0
- data/lib/chef/provider/script.rb +42 -0
- data/lib/chef/provider/service.rb +135 -0
- data/lib/chef/provider/service/debian.rb +64 -0
- data/lib/chef/provider/service/freebsd.rb +156 -0
- data/lib/chef/provider/service/gentoo.rb +54 -0
- data/lib/chef/provider/service/init.rb +71 -0
- data/lib/chef/provider/service/redhat.rb +62 -0
- data/lib/chef/provider/service/simple.rb +114 -0
- data/lib/chef/provider/subversion.rb +156 -0
- data/lib/chef/provider/template.rb +175 -0
- data/lib/chef/provider/user.rb +170 -0
- data/lib/chef/provider/user/dscl.rb +280 -0
- data/lib/chef/provider/user/pw.rb +113 -0
- data/lib/chef/provider/user/useradd.rb +108 -0
- data/lib/chef/recipe.rb +105 -0
- data/lib/chef/resource.rb +380 -0
- data/lib/chef/resource/apt_package.rb +34 -0
- data/lib/chef/resource/bash.rb +33 -0
- data/lib/chef/resource/breakpoint.rb +35 -0
- data/lib/chef/resource/cron.rb +179 -0
- data/lib/chef/resource/csh.rb +33 -0
- data/lib/chef/resource/deploy.rb +359 -0
- data/lib/chef/resource/deploy_revision.rb +35 -0
- data/lib/chef/resource/directory.rb +76 -0
- data/lib/chef/resource/dpkg_package.rb +34 -0
- data/lib/chef/resource/easy_install_package.rb +41 -0
- data/lib/chef/resource/erl_call.rb +83 -0
- data/lib/chef/resource/execute.rb +127 -0
- data/lib/chef/resource/file.rb +84 -0
- data/lib/chef/resource/gem_package.rb +41 -0
- data/lib/chef/resource/git.rb +36 -0
- data/lib/chef/resource/group.rb +70 -0
- data/lib/chef/resource/http_request.rb +52 -0
- data/lib/chef/resource/ifconfig.rb +134 -0
- data/lib/chef/resource/link.rb +78 -0
- data/lib/chef/resource/macports_package.rb +29 -0
- data/lib/chef/resource/mdadm.rb +82 -0
- data/lib/chef/resource/mount.rb +135 -0
- data/lib/chef/resource/package.rb +80 -0
- data/lib/chef/resource/perl.rb +33 -0
- data/lib/chef/resource/portage_package.rb +33 -0
- data/lib/chef/resource/python.rb +33 -0
- data/lib/chef/resource/remote_directory.rb +91 -0
- data/lib/chef/resource/remote_file.rb +60 -0
- data/lib/chef/resource/route.rb +135 -0
- data/lib/chef/resource/ruby.rb +33 -0
- data/lib/chef/resource/ruby_block.rb +39 -0
- data/lib/chef/resource/scm.rb +137 -0
- data/lib/chef/resource/script.rb +51 -0
- data/lib/chef/resource/service.rb +134 -0
- data/lib/chef/resource/subversion.rb +34 -0
- data/lib/chef/resource/template.rb +60 -0
- data/lib/chef/resource/timestamped_deploy.rb +31 -0
- data/lib/chef/resource/user.rb +101 -0
- data/lib/chef/resource_collection.rb +212 -0
- data/lib/chef/resource_collection/stepable_iterator.rb +124 -0
- data/lib/chef/resource_definition.rb +67 -0
- data/lib/chef/rest.rb +298 -0
- data/lib/chef/role.rb +301 -0
- data/lib/chef/run_list.rb +164 -0
- data/lib/chef/runner.rb +130 -0
- data/lib/chef/search/query.rb +71 -0
- data/lib/chef/shef.rb +220 -0
- data/lib/chef/shef/ext.rb +297 -0
- data/lib/chef/shef/shef_session.rb +175 -0
- data/lib/chef/streaming_cookbook_uploader.rb +185 -0
- data/lib/chef/tasks/chef_repo.rake +245 -0
- data/lib/chef/util/file_edit.rb +125 -0
- data/lib/chef/util/fileedit.rb +121 -0
- data/lib/chef/webui_user.rb +231 -0
- metadata +398 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, 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
|
+
class Chef
|
|
19
|
+
class Exceptions
|
|
20
|
+
class Application < RuntimeError; end
|
|
21
|
+
class Cron < RuntimeError; end
|
|
22
|
+
class Exec < RuntimeError; end
|
|
23
|
+
class FileNotFound < RuntimeError; end
|
|
24
|
+
class Package < RuntimeError; end
|
|
25
|
+
class Service < RuntimeError; end
|
|
26
|
+
class Route < RuntimeError; end
|
|
27
|
+
class SearchIndex < RuntimeError; end
|
|
28
|
+
class Override < RuntimeError; end
|
|
29
|
+
class UnsupportedAction < RuntimeError; end
|
|
30
|
+
class MissingLibrary < RuntimeError; end
|
|
31
|
+
class User < RuntimeError; end
|
|
32
|
+
class Group < RuntimeError; end
|
|
33
|
+
class Link < RuntimeError; end
|
|
34
|
+
class Mount < RuntimeError; end
|
|
35
|
+
class CouchDBNotFound < RuntimeError; end
|
|
36
|
+
class PrivateKeyMissing < RuntimeError; end
|
|
37
|
+
class CannotWritePrivateKey < RuntimeError; end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2008 Opscode, 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
|
+
require 'chef/mixin/params_validate'
|
|
19
|
+
require 'chef/mixin/create_path'
|
|
20
|
+
require 'chef/exceptions'
|
|
21
|
+
require 'json'
|
|
22
|
+
require 'fileutils'
|
|
23
|
+
|
|
24
|
+
class Chef
|
|
25
|
+
class FileCache
|
|
26
|
+
class << self
|
|
27
|
+
include Chef::Mixin::ParamsValidate
|
|
28
|
+
include Chef::Mixin::CreatePath
|
|
29
|
+
|
|
30
|
+
# Write a file to the File Cache.
|
|
31
|
+
#
|
|
32
|
+
# === Parameters
|
|
33
|
+
# path<String>:: The path to the file you want to put in the cache - should
|
|
34
|
+
# be relative to Chef::Config[:file_cache_path]
|
|
35
|
+
# contents<String>:: A string with the contents you want written to the file
|
|
36
|
+
#
|
|
37
|
+
# === Returns
|
|
38
|
+
# true
|
|
39
|
+
def store(path, contents)
|
|
40
|
+
validate(
|
|
41
|
+
{
|
|
42
|
+
:path => path,
|
|
43
|
+
:contents => contents
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
:path => { :kind_of => String },
|
|
47
|
+
:contents => { :kind_of => String },
|
|
48
|
+
}
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
file_path_array = File.split(path)
|
|
52
|
+
file_name = file_path_array.pop
|
|
53
|
+
cache_path = create_cache_path(File.join(file_path_array))
|
|
54
|
+
io = File.open(File.join(cache_path, file_name), "w")
|
|
55
|
+
io.print(contents)
|
|
56
|
+
io.close
|
|
57
|
+
true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# Move a file in to the cache. Useful with the REST raw file output.
|
|
61
|
+
#
|
|
62
|
+
# === Parameteres
|
|
63
|
+
# file<String>:: The path to the file you want in the cache
|
|
64
|
+
# path<String>:: The relative name you want the new file to use
|
|
65
|
+
def move_to(file, path)
|
|
66
|
+
validate(
|
|
67
|
+
{
|
|
68
|
+
:file => file,
|
|
69
|
+
:path => path
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
:file => { :kind_of => String },
|
|
73
|
+
:path => { :kind_of => String },
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
file_path_array = File.split(path)
|
|
78
|
+
file_name = file_path_array.pop
|
|
79
|
+
if File.exists?(file) && File.writable?(file)
|
|
80
|
+
FileUtils.mv(
|
|
81
|
+
file,
|
|
82
|
+
File.join(create_cache_path(File.join(file_path_array), true), file_name)
|
|
83
|
+
)
|
|
84
|
+
else
|
|
85
|
+
raise RuntimeError, "Cannot move #{file} to #{path}!"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
# Read a file from the File Cache
|
|
90
|
+
#
|
|
91
|
+
# === Parameters
|
|
92
|
+
# path<String>:: The path to the file you want to load - should
|
|
93
|
+
# be relative to Chef::Config[:file_cache_path]
|
|
94
|
+
# read<True/False>:: Whether to return the file contents, or the path.
|
|
95
|
+
# Defaults to true.
|
|
96
|
+
#
|
|
97
|
+
# === Returns
|
|
98
|
+
# String:: A string with the file contents, or the path to the file.
|
|
99
|
+
#
|
|
100
|
+
# === Raises
|
|
101
|
+
# Chef::Exceptions::FileNotFound:: If it cannot find the file in the cache
|
|
102
|
+
def load(path, read=true)
|
|
103
|
+
validate(
|
|
104
|
+
{
|
|
105
|
+
:path => path
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
:path => { :kind_of => String }
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
cache_path = create_cache_path(path, false)
|
|
112
|
+
raise Chef::Exceptions::FileNotFound, "Cannot find #{cache_path} for #{path}!" unless File.exists?(cache_path)
|
|
113
|
+
if read
|
|
114
|
+
File.read(cache_path)
|
|
115
|
+
else
|
|
116
|
+
cache_path
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# Delete a file from the File Cache
|
|
121
|
+
#
|
|
122
|
+
# === Parameters
|
|
123
|
+
# path<String>:: The path to the file you want to delete - should
|
|
124
|
+
# be relative to Chef::Config[:file_cache_path]
|
|
125
|
+
#
|
|
126
|
+
# === Returns
|
|
127
|
+
# true
|
|
128
|
+
def delete(path)
|
|
129
|
+
validate(
|
|
130
|
+
{
|
|
131
|
+
:path => path
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
:path => { :kind_of => String },
|
|
135
|
+
}
|
|
136
|
+
)
|
|
137
|
+
cache_path = create_cache_path(path, false)
|
|
138
|
+
if File.exists?(cache_path)
|
|
139
|
+
File.unlink(cache_path)
|
|
140
|
+
end
|
|
141
|
+
true
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# List all the files in the Cache
|
|
145
|
+
#
|
|
146
|
+
# === Returns
|
|
147
|
+
# Array:: An array of files in the cache, suitable for use with load, delete and store
|
|
148
|
+
def list()
|
|
149
|
+
keys = Array.new
|
|
150
|
+
Dir[File.join(Chef::Config[:file_cache_path], '**', '*')].each do |f|
|
|
151
|
+
if File.file?(f)
|
|
152
|
+
path = f.match("^#{Chef::Config[:file_cache_path]}\/(.+)")[1]
|
|
153
|
+
keys << path
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
keys
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Whether or not this file exists in the Cache
|
|
160
|
+
#
|
|
161
|
+
# === Parameters
|
|
162
|
+
# path:: The path to the file you want to check - is relative
|
|
163
|
+
# to Chef::Config[:file_cache_path]
|
|
164
|
+
#
|
|
165
|
+
# === Returns
|
|
166
|
+
# True:: If the file exists
|
|
167
|
+
# False:: If it does not
|
|
168
|
+
def has_key?(path)
|
|
169
|
+
validate(
|
|
170
|
+
{
|
|
171
|
+
:path => path
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
:path => { :kind_of => String },
|
|
175
|
+
}
|
|
176
|
+
)
|
|
177
|
+
full_path = create_cache_path(path, false)
|
|
178
|
+
if File.exists?(full_path)
|
|
179
|
+
true
|
|
180
|
+
else
|
|
181
|
+
false
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
# Create a full path to a given file in the cache. By default,
|
|
186
|
+
# also creates the path if it does not exist.
|
|
187
|
+
#
|
|
188
|
+
# === Parameters
|
|
189
|
+
# path:: The path to create, relative to Chef::Config[:file_cache_path]
|
|
190
|
+
# create_if_missing:: True by default - whether to create the path if it does not exist
|
|
191
|
+
#
|
|
192
|
+
# === Returns
|
|
193
|
+
# String:: The fully expanded path
|
|
194
|
+
def create_cache_path(path, create_if_missing=true)
|
|
195
|
+
cache_dir = File.expand_path(File.join(Chef::Config[:file_cache_path], path))
|
|
196
|
+
if create_if_missing
|
|
197
|
+
create_path(cache_dir)
|
|
198
|
+
else
|
|
199
|
+
cache_dir
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
data/lib/chef/knife.rb
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Author:: Adam Jacob (<adam@opscode.com>)
|
|
3
|
+
# Copyright:: Copyright (c) 2009 Opscode, 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
|
+
require 'mixlib/cli'
|
|
20
|
+
require 'chef/mixin/convert_to_class_name'
|
|
21
|
+
|
|
22
|
+
class Chef
|
|
23
|
+
class Knife
|
|
24
|
+
include Mixlib::CLI
|
|
25
|
+
extend Chef::Mixin::ConvertToClassName
|
|
26
|
+
|
|
27
|
+
attr_accessor :name_args
|
|
28
|
+
|
|
29
|
+
# Load all the sub-commands
|
|
30
|
+
def self.load_commands
|
|
31
|
+
@sub_classes = Hash.new
|
|
32
|
+
Dir[
|
|
33
|
+
File.expand_path(File.join(File.dirname(__FILE__), 'knife', '*.rb'))
|
|
34
|
+
].each do |knife_file|
|
|
35
|
+
require knife_file
|
|
36
|
+
snake_case_file_name = File.basename(knife_file).sub(/\.rb$/, '')
|
|
37
|
+
@sub_classes[snake_case_file_name] = convert_to_class_name(snake_case_file_name)
|
|
38
|
+
end
|
|
39
|
+
@sub_classes
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def self.list_commands
|
|
43
|
+
load_commands
|
|
44
|
+
@sub_classes.keys.sort.each do |snake_case|
|
|
45
|
+
klass_instance = build_sub_class(snake_case)
|
|
46
|
+
klass_instance.parse_options
|
|
47
|
+
puts klass_instance.opt_parser
|
|
48
|
+
puts
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.build_sub_class(snake_case, merge_opts=nil)
|
|
53
|
+
klass = Chef::Knife.const_get(@sub_classes[snake_case])
|
|
54
|
+
klass.options.merge!(merge_opts) if merge_opts
|
|
55
|
+
klass.new
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def self.find_command(args=ARGV, merge_opts={})
|
|
59
|
+
load_commands
|
|
60
|
+
|
|
61
|
+
non_dash_args = Array.new
|
|
62
|
+
args.each do |arg|
|
|
63
|
+
non_dash_args << arg if arg =~ /^([[:alnum:]]|_)+$/
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
to_try = non_dash_args.length
|
|
67
|
+
klass_instance = nil
|
|
68
|
+
cli_bits = nil
|
|
69
|
+
|
|
70
|
+
while(to_try >= 0)
|
|
71
|
+
cli_bits = non_dash_args[0..to_try]
|
|
72
|
+
snake_case_class_name = cli_bits.join("_")
|
|
73
|
+
|
|
74
|
+
if @sub_classes.has_key?(snake_case_class_name)
|
|
75
|
+
klass_instance = build_sub_class(snake_case_class_name, merge_opts)
|
|
76
|
+
break
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
to_try = to_try - 1
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
unless klass_instance
|
|
83
|
+
Chef::Log.fatal("Cannot find sub command for: #{args.join(' ')}")
|
|
84
|
+
Chef::Knife.list_commands
|
|
85
|
+
exit 10
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
extra = klass_instance.parse_options(args)
|
|
89
|
+
if klass_instance.config[:help]
|
|
90
|
+
puts klass_instance.opt_parser
|
|
91
|
+
exit 1
|
|
92
|
+
end
|
|
93
|
+
klass_instance.name_args = (extra - cli_bits) || []
|
|
94
|
+
klass_instance.configure_chef
|
|
95
|
+
klass_instance
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def ask_question(q)
|
|
99
|
+
print q
|
|
100
|
+
a = STDIN.readline
|
|
101
|
+
a.chomp!
|
|
102
|
+
a
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def configure_chef
|
|
106
|
+
if !config[:config_file].nil? && File.exists?(config[:config_file]) && File.readable?(config[:config_file])
|
|
107
|
+
Chef::Config.from_file(config[:config_file])
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
Chef::Config[:log_level] = config[:log_level] if config[:log_level]
|
|
111
|
+
Chef::Config[:log_location] = config[:log_location] if config[:log_location]
|
|
112
|
+
Chef::Config[:node_name] = config[:node_name] if config[:node_name]
|
|
113
|
+
Chef::Config[:client_key] = config[:client_key] if config[:client_key]
|
|
114
|
+
Chef::Config[:chef_server_url] = config[:chef_server_url] if config[:chef_server_url]
|
|
115
|
+
Chef::Log::Formatter.show_time = false
|
|
116
|
+
Chef::Log.init(Chef::Config[:log_location])
|
|
117
|
+
Chef::Log.level(Chef::Config[:log_level])
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def pretty_print(data)
|
|
121
|
+
puts data
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def json_pretty_print(data)
|
|
125
|
+
puts JSON.pretty_generate(data)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def format_list_for_display(list)
|
|
129
|
+
config[:with_uri] ? list : list.keys.sort { |a,b| a <=> b }
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def format_for_display(item)
|
|
133
|
+
data = item.kind_of?(Chef::DataBagItem) ? item.raw_data : item
|
|
134
|
+
|
|
135
|
+
if config[:attribute]
|
|
136
|
+
config[:attribute].split(".").each do |attr|
|
|
137
|
+
if data.respond_to?(:[])
|
|
138
|
+
data = data[attr]
|
|
139
|
+
else
|
|
140
|
+
data = data.send(attr.to_sym)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
{ config[:attribute] => data.kind_of?(Chef::Node::Attribute) ? data.to_hash: data }
|
|
144
|
+
elsif config[:run_list]
|
|
145
|
+
data = data.run_list.run_list
|
|
146
|
+
{ "run_list" => data }
|
|
147
|
+
elsif config[:id_only]
|
|
148
|
+
data.respond_to?(:name) ? data.name : data["id"]
|
|
149
|
+
else
|
|
150
|
+
data
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def edit_data(data, parse_output=true)
|
|
155
|
+
filename = "knife-edit-"
|
|
156
|
+
0.upto(20) { filename += rand(9).to_s }
|
|
157
|
+
filename << ".js"
|
|
158
|
+
filename = File.join(Dir.tmpdir, filename)
|
|
159
|
+
tf = File.open(filename, "w")
|
|
160
|
+
tf.sync = true
|
|
161
|
+
tf.puts JSON.pretty_generate(data)
|
|
162
|
+
tf.close
|
|
163
|
+
raise "Please set EDITOR environment variable" unless system("#{config[:editor]} #{tf.path}")
|
|
164
|
+
tf = File.open(filename, "r")
|
|
165
|
+
output = tf.gets(nil)
|
|
166
|
+
tf.close
|
|
167
|
+
File.unlink(filename)
|
|
168
|
+
|
|
169
|
+
parse_output ? JSON.parse(output) : output
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def confirm(question)
|
|
173
|
+
return true if config[:yes]
|
|
174
|
+
|
|
175
|
+
print "#{question}? (Y/N) "
|
|
176
|
+
answer = STDIN.readline
|
|
177
|
+
answer.chomp!
|
|
178
|
+
case answer
|
|
179
|
+
when "Y", "y"
|
|
180
|
+
true
|
|
181
|
+
when "N", "n"
|
|
182
|
+
Chef::Log.info("You said no, so I'm done here.")
|
|
183
|
+
exit 3
|
|
184
|
+
else
|
|
185
|
+
Chef::Log.error("I have no idea what to do with #{answer}")
|
|
186
|
+
Chef::Log.error("Just say Y or N, please.")
|
|
187
|
+
confirm(question)
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def load_from_file(klass, from_file)
|
|
192
|
+
from_file = @name_args[0]
|
|
193
|
+
relative_file = File.expand_path(File.join(Dir.pwd, 'roles', from_file))
|
|
194
|
+
filename = nil
|
|
195
|
+
|
|
196
|
+
if file_exists_and_is_readable?(from_file)
|
|
197
|
+
filename = from_file
|
|
198
|
+
elsif file_exists_and_is_readable?(relative_file)
|
|
199
|
+
filename = relative_file
|
|
200
|
+
else
|
|
201
|
+
Chef::Log.fatal("Cannot find file #{from_file}")
|
|
202
|
+
exit 30
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
case from_file
|
|
206
|
+
when /\.(js|json)$/
|
|
207
|
+
JSON.parse(IO.read(filename))
|
|
208
|
+
when /\.rb$/
|
|
209
|
+
r = klass.new
|
|
210
|
+
r.from_file(filename)
|
|
211
|
+
r
|
|
212
|
+
else
|
|
213
|
+
Chef::Log.fatal("File must end in .js, .json, or .rb")
|
|
214
|
+
exit 30
|
|
215
|
+
end
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
def file_exists_and_is_readable?(file)
|
|
219
|
+
File.exists?(file) && File.readable?(file)
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def edit_object(klass, name)
|
|
223
|
+
object = klass.load(name)
|
|
224
|
+
|
|
225
|
+
output = edit_data(object)
|
|
226
|
+
|
|
227
|
+
output.save
|
|
228
|
+
|
|
229
|
+
Chef::Log.info("Saved #{output}")
|
|
230
|
+
|
|
231
|
+
json_pretty_print(format_for_display(object)) if config[:print_after]
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def create_object(object, pretty_name=nil, &block)
|
|
235
|
+
output = edit_data(object)
|
|
236
|
+
|
|
237
|
+
if Kernel.block_given?
|
|
238
|
+
output = block.call(output)
|
|
239
|
+
else
|
|
240
|
+
output.save
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
pretty_name ||= output
|
|
244
|
+
|
|
245
|
+
Chef::Log.info("Created (or updated) #{pretty_name}")
|
|
246
|
+
|
|
247
|
+
json_pretty_print(output) if config[:print_after]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def delete_object(klass, name, delete_name=nil, &block)
|
|
251
|
+
confirm("Do you really want to delete #{name}")
|
|
252
|
+
|
|
253
|
+
if Kernel.block_given?
|
|
254
|
+
object = block.call
|
|
255
|
+
else
|
|
256
|
+
object = klass.load(name)
|
|
257
|
+
object.destroy
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
json_pretty_print(format_for_display(object)) if config[:print_after]
|
|
261
|
+
|
|
262
|
+
obj_name = delete_name ? "#{delete_name}[#{name}]" : object
|
|
263
|
+
Chef::Log.warn("Deleted #{obj_name}!")
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def bulk_delete(klass, fancy_name, delete_name=nil, list=nil, &block)
|
|
267
|
+
object_list = list ? list : klass.list(true)
|
|
268
|
+
|
|
269
|
+
if config[:regex]
|
|
270
|
+
to_delete = Hash.new
|
|
271
|
+
object_list.each_key do |object|
|
|
272
|
+
next if config[:regex] && object !~ /#{config[:regex]}/
|
|
273
|
+
to_delete[object] = object_list[object]
|
|
274
|
+
end
|
|
275
|
+
else
|
|
276
|
+
to_delete = object_list
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
json_pretty_print(format_list_for_display(to_delete))
|
|
280
|
+
|
|
281
|
+
confirm("Do you really want to delete the above items")
|
|
282
|
+
|
|
283
|
+
to_delete.each do |name, object|
|
|
284
|
+
if Kernel.block_given?
|
|
285
|
+
block.call(name, object)
|
|
286
|
+
else
|
|
287
|
+
object.destroy
|
|
288
|
+
end
|
|
289
|
+
json_pretty_print(format_for_display(object)) if config[:print_after]
|
|
290
|
+
Chef::Log.warn("Deleted #{fancy_name} #{name}")
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
294
|
+
def rest
|
|
295
|
+
@rest ||= Chef::REST.new(Chef::Config[:chef_server_url])
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|