chef-server-api 0.9.18 → 0.10.0.beta.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.
@@ -48,11 +48,7 @@ class Roles < Application
48
48
  raise NotFound, "Cannot load role #{params[:id]}"
49
49
  end
50
50
 
51
- @role.description(params["inflated_object"].description)
52
- @role.recipes(params["inflated_object"].recipes) if defined?(params["inflated_object"].recipes)
53
- @role.run_list(params["inflated_object"].run_list)
54
- @role.default_attributes(params["inflated_object"].default_attributes)
55
- @role.override_attributes(params["inflated_object"].override_attributes)
51
+ @role.update_from!(params["inflated_object"])
56
52
  @role.cdb_save
57
53
  self.status = 200
58
54
  @role.couchdb_rev = nil
@@ -70,4 +66,26 @@ class Roles < Application
70
66
  display @role
71
67
  end
72
68
 
69
+ # GET /roles/:id/environments/:env_id
70
+ def environment
71
+ begin
72
+ @role = Chef::Role.cdb_load(params[:role_id])
73
+ rescue Chef::Exceptions::CouchDBNotFound => e
74
+ raise NotFound, "Cannot load role #{params[:role_id]}"
75
+ end
76
+ display("run_list" => @role.env_run_lists[params[:env_id]])
77
+ end
78
+
79
+ # GET /roles/:id/environments
80
+ def environments
81
+ begin
82
+ @role = Chef::Role.cdb_load(params[:role_id])
83
+ rescue Chef::Exceptions::CouchDBNotFound => e
84
+ raise NotFound, "Cannot load role #{params[:role_id]}"
85
+ end
86
+
87
+ display(@role.env_run_lists.keys.sort)
88
+ end
89
+
90
+
73
91
  end
@@ -17,7 +17,7 @@
17
17
  # limitations under the License.
18
18
 
19
19
 
20
- require 'chef/solr/query'
20
+ require 'chef/solr_query'
21
21
 
22
22
  class Search < Application
23
23
  provides :json
@@ -27,34 +27,24 @@ class Search < Application
27
27
 
28
28
  def index
29
29
  indexes = valid_indexes
30
- display(indexes.inject({}) { |r,i| r[i] = absolute_url(:search, i); r })
30
+ display(indexes.inject({}) { |r,i| r[i] = absolute_url(:search_show, i); r })
31
31
  end
32
32
 
33
33
  def valid_indexes
34
34
  indexes = Chef::DataBag.cdb_list(false)
35
- indexes += %w{ role node client }
35
+ indexes += %w{ role node client environment}
36
36
  end
37
37
 
38
38
  def show
39
39
  unless valid_indexes.include?(params[:id])
40
40
  raise NotFound, "I don't know how to search for #{params[:id]} data objects."
41
41
  end
42
-
43
- query = Chef::Solr::Query.new(Chef::Config[:solr_url])
44
- params[:q] ||= "*:*"
45
- params[:sort] ||= nil
46
- params[:start] ||= 0
47
- params[:rows] ||= 20
48
- objects, start, total = query.search(params[:id], params[:q], params[:sort], params[:start], params[:rows])
49
- display({
50
- "rows" => objects,
51
- "start" => start,
52
- "total" => total
53
- })
42
+ params[:type] = params.delete(:id)
43
+ display(Chef::SolrQuery.from_params(params).search)
54
44
  end
55
45
 
56
46
  def reindex
57
- display(Chef::Solr.new.rebuild_index)
47
+ display(Chef::SolrQuery.new.rebuild_index)
58
48
  end
59
49
 
60
50
  end
@@ -0,0 +1,72 @@
1
+ #
2
+ # Author:: Stephen Delano (<stephen@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 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
+ module Merb
20
+ module CookbookVersionHelper
21
+
22
+ include Merb::ControllerExceptions
23
+
24
+ # takes a cookbook_name and an array of versions and returns a hash
25
+ # params:
26
+ # - cookbook_name: the name of the cookbook
27
+ # - versions: a sorted list of version strings
28
+ #
29
+ # returns:
30
+ # {
31
+ # :url => http://url,
32
+ # :versions => [
33
+ # { :version => version, :url => http://url/version },
34
+ # { :version => version, :url => http://url/version }
35
+ # ]
36
+ # }
37
+ def expand_cookbook_urls(cookbook_name, versions, num_versions)
38
+ versions = versions[0...num_versions.to_i] unless num_versions == "all"
39
+ version_list = versions.inject([]) do |res, version|
40
+ res.push({
41
+ :url => absolute_url(:cookbook_version, :cookbook_name => cookbook_name, :cookbook_version => version),
42
+ :version => version
43
+ })
44
+ res
45
+ end
46
+ url = absolute_url(:cookbook, :cookbook_name => cookbook_name)
47
+ {:url => url, :versions => version_list}
48
+ end
49
+
50
+ # validate and return the number of versions requested
51
+ # by the user
52
+ #
53
+ # raises an exception if an invalid number is requested
54
+ #
55
+ # params:
56
+ # - default: the number of versions to default to
57
+ #
58
+ # valid num_versions query parameter:
59
+ # - an integer >= 0
60
+ # - the string "all"
61
+ def num_versions!(default="1")
62
+ input = params[:num_versions]
63
+ result = if input
64
+ valid_input = (input == "all" || Integer(input) >= 0) rescue false
65
+ raise BadRequest, "You have requested an invalid number of versions (x >= 0 || 'all')" unless valid_input
66
+ input
67
+ else
68
+ default
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,49 @@
1
+ <?xml version='1.0' encoding='utf-8' ?>
2
+ <!DOCTYPE html>
3
+ <html>
4
+ <head>
5
+ <meta content='text/html; charset=utf-8' http-equiv='content-type' />
6
+ <title>Chef Server</title>
7
+ <link href="/stylesheets/base.css" type="text/css" rel="Stylesheet" charset="utf-8" media="all" />
8
+ <link href="/stylesheets/themes/djime-cerulean/style.css" type="text/css" rel="Stylesheet" charset="utf-8" media="all" />
9
+ <link href="/stylesheets/chef.css" type="text/css" rel="Stylesheet" charset="utf-8" media="all" />
10
+ </head>
11
+ <body>
12
+ <div id='container'>
13
+ <div id='header'>
14
+ <h1><a href="<%= absolute_url(:top) -%>">Chef REST API</a></h1>
15
+ </div>
16
+ <div id='main-navigation'>
17
+ <div class='clear'></div>
18
+ </div>
19
+ <div id='wrapper'>
20
+ <div id='main'>
21
+ <div class='block' id='block-text'>
22
+ <div class='content'>
23
+ <h2 class='title'>The REST API</h2>
24
+ <div class='inner'>
25
+ This is the Chef API Server.
26
+ <% if @webui_url %>
27
+ <a href="<%= @webui_url -%>">Are you looking for the Web UI?</a>
28
+ <% end %>
29
+ </div>
30
+ <div class='inner'>
31
+ For more information about Chef, head on over to the <a href="http://wiki.opscode.com/">wiki.</a>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ <div id='footer'>
36
+ <div class='block'>
37
+ <p>Copyright &copy; 2009-2011 Opscode, Inc.</p>
38
+ </div>
39
+ </div>
40
+ </div>
41
+ <div id='sidebar'>
42
+ <div class='block notice' id='sidebar_block_notice'></div>
43
+ <div class='block' id='sidebar_block'></div>
44
+ </div>
45
+ <div class='clear'></div>
46
+ </div>
47
+ </div>
48
+ </body>
49
+ </html>
File without changes
data/bin/chef-server CHANGED
@@ -25,6 +25,7 @@ require "merb-core"
25
25
 
26
26
  # Load chef and chef-server-api from source rather than gem, if present
27
27
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef/lib/'))
28
+ $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../../chef-solr/lib/'))
28
29
  $:.unshift(File.expand_path(File.dirname(__FILE__) + '/../lib'))
29
30
 
30
31
  # Print the version if we have -v or --version
data/config/init.rb CHANGED
@@ -38,8 +38,10 @@ require 'chef/data_bag_item'
38
38
  require 'chef/cookbook_version'
39
39
  require 'chef/sandbox'
40
40
  require 'chef/checksum'
41
+ require 'chef/environment'
41
42
  require 'chef/monkey_patches/regexp'
42
43
 
44
+
43
45
  require 'mixlib/authentication'
44
46
 
45
47
  Mixlib::Authentication::Log.logger = Ohai::Log.logger = Chef::Log.logger
@@ -72,6 +74,7 @@ unless Merb::Config.environment == "test"
72
74
  Chef::CookbookVersion.create_design_document
73
75
  Chef::Sandbox.create_design_document
74
76
  Chef::Checksum.create_design_document
77
+ Chef::Environment.create_design_document
75
78
 
76
79
  # Create the signing key and certificate
77
80
  Chef::Certificate.generate_signing_ca
@@ -82,6 +85,9 @@ unless Merb::Config.environment == "test"
82
85
  # Generate the Web UI Key
83
86
  Chef::Certificate.gen_validation_key(Chef::Config[:web_ui_client_name], Chef::Config[:web_ui_key], true)
84
87
 
88
+ # Create the '_default' Environment
89
+ Chef::Environment.create_default_environment
90
+
85
91
  Chef::Log.info('Loading roles')
86
92
  Chef::Role.sync_from_disk_to_couchdb
87
93
  end
data/config/rack.rb CHANGED
@@ -19,5 +19,8 @@
19
19
  # Correctly set a content length.
20
20
  use Rack::ContentLength
21
21
 
22
+ # Serve assets for the html page from /public
23
+ use Merb::Rack::Static, Merb.dir_for(:public)
24
+
22
25
  # this is our main merb application
23
26
  run Merb::Rack::Application.new
data/config/router.rb CHANGED
@@ -27,7 +27,20 @@ Merb::Router.prepare do
27
27
  :method => 'get').
28
28
  to(:controller => "nodes", :action => "cookbooks")
29
29
  # Roles
30
- resources :roles
30
+ resources :roles do |r|
31
+ r.match('/environments', :method => 'get').to(:controller => "roles", :action => "environments")
32
+ r.match('/environments/:env_id', :method => 'get').to(:controller=>"roles", :action=>"environment")
33
+ end
34
+
35
+ # Environments
36
+ resources :environments do |e|
37
+ e.match("/cookbooks", :method => "get").to(:controller=>"environments", :action=>"list_cookbooks")
38
+ e.match("/cookbooks/:cookbook_id", :method => "get").to(:controller=>"environments", :action=>"cookbook")
39
+ e.match("/recipes", :method => "get").to(:controller=>"environments", :action=>"list_recipes")
40
+ e.match("/nodes", :method => "get").to(:controller=>"environments", :action=>"list_nodes")
41
+ e.match("/roles/:role_id", :method => "get").to(:controller=>"environments", :action => "role")
42
+ e.match("/cookbook_versions", :method => "post").to(:controller=>"environments", :action=>"cookbook_versions_for_run_list")
43
+ end
31
44
 
32
45
  # Status
33
46
  match("/status").to(:controller => "status", :action => "index").name(:status)
@@ -40,7 +53,9 @@ Merb::Router.prepare do
40
53
  match("/clients/:id", :id => /[\w\.-]+/, :method=>"delete").to(:controller=>'clients', :action=>'destroy')
41
54
 
42
55
  # Search
43
- resources :search
56
+ #resources :search
57
+ match('/search', :method => 'get').to(:controller => 'search', :action => 'index').name(:search)
58
+ match('/search/:id', :method => 'get').to(:controller => 'search', :action => 'show').name(:search_show)
44
59
  match('/search/reindex', :method => 'post').to(:controller => "search", :action => "reindex")
45
60
 
46
61
  # Cookbooks
@@ -48,9 +63,7 @@ Merb::Router.prepare do
48
63
 
49
64
  match("/cookbooks",
50
65
  :method => 'get'
51
- ).to(:controller => "cookbooks", :action => "index")
52
-
53
- match("/cookbooks/_latest", :method=>'get').to(:controller=>'cookbooks',:action=>'index_latest')
66
+ ).to(:controller => "cookbooks", :action => "index").name(:cookbooks)
54
67
 
55
68
  match("/cookbooks/_recipes", :method=>'get').to(:controller=>'cookbooks',:action=>'index_recipes')
56
69
 
@@ -120,10 +133,10 @@ Merb::Router.prepare do
120
133
  @json_params ||= begin
121
134
  if Merb::Const::JSON_MIME_TYPE_REGEXP.match(content_type)
122
135
  begin
123
- # Call Chef's JSON utility instead of the default in Merb,
136
+ # Call Chef's JSON utility instead of the default in Merb,
124
137
  # JSON.parse.
125
138
  jobj = Chef::JSONCompat.from_json(raw_post)
126
- jobj = jobj.to_mash if jobj.is_a?(Hash)
139
+ jobj = Mash.from_hash(jobj) if jobj.is_a?(Hash)
127
140
  rescue JSON::ParserError
128
141
  jobj = Mash.new
129
142
  end
@@ -1,3 +1,3 @@
1
1
  module ChefServerApi
2
- VERSION = '0.9.18'
2
+ VERSION = '0.10.0.beta.0'
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -1,6 +1,83 @@
1
- require 'rubygems'
2
- $:.unshift File.expand_path(File.dirname(__FILE__) + '/../app')
3
- $:.unshift File.expand_path(File.dirname(__FILE__) + '/../lib')
4
- $:.unshift File.expand_path(File.dirname(__FILE__) + '/../../chef/lib')
1
+ #
2
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 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 "rubygems"
20
+ require "merb-core"
21
+ require "rspec"
22
+
23
+ Merb.push_path(:spec_helpers, "spec" / "spec_helpers", "**/*.rb")
24
+ Merb.push_path(:spec_fixtures, "spec" / "fixtures", "**/*.rb")
25
+
26
+ Merb.start_environment(:testing => true, :adapter => 'runner', :environment => ENV['MERB_ENV'] || 'test')
27
+
28
+ RSpec.configure do |config|
29
+ config.include(Merb::Test::RouteHelper)
30
+ config.include(Merb::Test::ControllerHelper)
31
+ end
32
+
33
+ def get_json(path, params = {}, env = {}, &block)
34
+ request_json("GET", path, params, env, &block)
35
+ end
36
+
37
+ def post_json(path, post_body, env = {}, &block)
38
+ request_json("POST", path, {}, env) do |controller|
39
+ # Merb FakeRequest allows me no way to pass JSON across the
40
+ # FakeRequest/StringIO boundary, so we hack it here.
41
+ if post_body.is_a?(Hash)
42
+ controller.params.merge!(post_body)
43
+ else
44
+ controller.params['inflated_object'] = post_body
45
+ end
46
+ block.call if block
47
+ end
48
+ end
49
+
50
+ # Make an HTTP call of <method>, assign the accept header to
51
+ # application/json, and return the JSON-parsed output.
52
+ #
53
+ # Side effects:
54
+ # Raw textual output available in @response_raw
55
+ # Controller used available in @controller
56
+ def request_json(method, path, params, env, &block)
57
+ @controller = mock_request(path, params, env.merge({'HTTP_ACCEPT' => "application/json", :request_method => method})) do |controller|
58
+ stub_authentication(controller)
59
+ block.call(controller) if block
60
+ end
61
+
62
+ @response_raw = @controller.body
63
+ @response_json = Chef::JSONCompat.from_json(@response_raw)
64
+ end
65
+
66
+ def stub_authentication(controller)
67
+ username = "tester"
68
+
69
+ user = Chef::ApiClient.new
70
+ user.name(username)
71
+ user.admin(true)
72
+
73
+ # authenticate_every has a side-effect of setting @auth_user
74
+ controller.stub!(:authenticate_every).and_return(true)
75
+ controller.instance_variable_set(:@auth_user, user)
76
+ end
77
+
78
+ def root_url
79
+ # include organization name to run these tests in the platform
80
+ "http://localhost"
81
+ end
82
+
5
83
 
6
- require 'chef'
@@ -0,0 +1,67 @@
1
+ #
2
+ # Author:: Tim Hinderliter (<tim@opscode.com>)
3
+ # Copyright:: Copyright (c) 2011 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
+ # Set of methods to create model objects for spec tests.
20
+ # None of these methods save or otherwise commit the objects they
21
+ # create; they simply initialize the respective model object and
22
+ # set its name (and other important attributes, where appropriate).
23
+
24
+ def make_node(name)
25
+ res = Chef::Node.new
26
+ res.name(name)
27
+ res
28
+ end
29
+
30
+ def make_role(name)
31
+ res = Chef::Role.new
32
+ res.name(name)
33
+ res
34
+ end
35
+
36
+ def make_environment(name)
37
+ res = Chef::Environment.new
38
+ res.name(name)
39
+ res
40
+ end
41
+
42
+ def make_cookbook(name, version)
43
+ res = Chef::CookbookVersion.new(name)
44
+ res.version = version
45
+ res
46
+ end
47
+
48
+ def make_runlist(*items)
49
+ res = Chef::RunList.new
50
+ items.each do |item|
51
+ res << item
52
+ end
53
+ res
54
+ end
55
+
56
+ # Take an Array of cookbook_versions,
57
+ # And return a hash like:
58
+ # {
59
+ # "cookbook_name" => [CookbookVersion, CookbookVersion],
60
+ # }
61
+ def make_filtered_cookbook_hash(*array_cookbook_versions)
62
+ array_cookbook_versions.inject({}) do |res, cookbook_version|
63
+ res[cookbook_version.name] ||= Array.new
64
+ res[cookbook_version.name] << cookbook_version
65
+ res
66
+ end
67
+ end