Class: Sandboxes

Inherits:
Application show all
Includes:
Chef::Mixin::Checksum, Merb::TarballHelper
Defined in:
app/controllers/sandboxes.rb

Overview

Sandboxes are used to upload files to the server (e.g., cookbook upload).

Instance Method Summary collapse

Methods included from Merb::TarballHelper

#cookbook_base, #cookbook_location, #expand_tarball_and_put_in_repository, #get_or_create_cookbook_tarball_location, #sandbox_base, #sandbox_checksum_location, #sandbox_location, #validate_file_parameter

Methods inherited from Application

#access_denied, #admin_or_requesting_node, #authenticate_every, #display, #get_available_recipes, #is_admin, #is_admin_or_validator, #redirect_back_or_default, #store_location

Instance Method Details

#createObject

Raises:

  • (BadRequest)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/controllers/sandboxes.rb', line 52

def create
  checksums = params[:checksums]
  
  raise BadRequest, "missing required parameter: checksums" unless checksums
  raise BadRequest, "required parameter checksums is not a hash: #{checksums.class.name}" unless checksums.is_a?(Hash)

  new_sandbox = Chef::Sandbox.new
  result_checksums = Hash.new
  
  all_existing_checksums = Chef::Checksum.cdb_all_checksums
  checksums.keys.each do |checksum|
    if all_existing_checksums[checksum]
      result_checksums[checksum] = {
        :needs_upload => false
      }
    else
      result_checksums[checksum] = {
        :url => absolute_url(:sandbox_checksum, :sandbox_id => new_sandbox.guid, :checksum => checksum),
        :needs_upload => true
      }
      new_sandbox.checksums << checksum
    end
  end
  
  FileUtils.mkdir_p(sandbox_location(new_sandbox.guid))
  
  new_sandbox.cdb_save
  
  # construct successful response
  self.status = 201
  location = absolute_url(:sandbox, :sandbox_id => new_sandbox.guid)
  headers['Location'] = location
  result = { 'uri' => location, 'checksums' => result_checksums, 'sandbox_id' => new_sandbox.guid }
  #result = { 'uri' => location }
  
  display result
end

#destroyObject

Raises:

  • (NotFound)


156
157
158
# File 'app/controllers/sandboxes.rb', line 156

def destroy
  raise NotFound, "Destroy not implemented"
end

#indexObject



32
33
34
35
36
37
38
39
40
# File 'app/controllers/sandboxes.rb', line 32

def index
  couch_sandbox_list = Chef::Sandbox::cdb_list(true)
  
  sandbox_list = Hash.new
  couch_sandbox_list.each do |sandbox|
    sandbox_list[sandbox.guid] = absolute_url(:sandbox, :sandbox_id => sandbox.guid)
  end
  display sandbox_list
end

#showObject



42
43
44
45
46
47
48
49
50
# File 'app/controllers/sandboxes.rb', line 42

def show
  begin
    sandbox = Chef::Sandbox.cdb_load(params[:sandbox_id])
  rescue Chef::Exceptions::CouchDBNotFound => e
    raise NotFound, "Cannot find a sandbox named #{params[:sandbox_id]}"
  end

  display sandbox
end

#updateObject

Raises:

  • (NotFound)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'app/controllers/sandboxes.rb', line 103

def update
  # look up the sandbox by its guid
  existing_sandbox = Chef::Sandbox.cdb_load(params[:sandbox_id])
  raise NotFound, "cannot find sandbox with guid #{params[:sandbox_id]}" unless existing_sandbox
  
  if existing_sandbox.is_completed
    Chef::Log.warn("Sandbox finalization: #{params[:sandbox_id]} is already complete, ignoring")
    return display(existing_sandbox)
  end

  if params[:is_completed]
    existing_sandbox.is_completed = (params[:is_completed] == true)

    if existing_sandbox.is_completed
      # Check if files were uploaded to sandbox directory before we 
      # commit the sandbox. Fail if any weren't.
      existing_sandbox.checksums.each do |checksum|
        checksum_filename = sandbox_checksum_location(existing_sandbox.guid, checksum)
        if !File.exists?(checksum_filename)
          raise BadRequest, "cannot update sandbox #{params[:sandbox_id]}: checksum #{checksum} was not uploaded"
        end
      end
      
      # If we've gotten here all the files have been uploaded.
      # Track the steps to undo everything we've done. If any steps fail,
      # we will undo the successful steps that came before it
      begin
        undo_steps = Array.new
        existing_sandbox.checksums.each do |file_checksum|
          checksum_filename_in_sandbox = sandbox_checksum_location(existing_sandbox.guid, file_checksum)
          checksum = Chef::Checksum.new(file_checksum)

          checksum.commit_sandbox_file(checksum_filename_in_sandbox)
          
          undo_steps << proc { checksum.revert_sandbox_file_commit }
        end
      rescue
        # undo the successful moves we did before
        Chef::Log.error("Sandbox finalization: got exception moving files, undoing previous changes: #{$!} -- #{$!.backtrace.join("\n")}")
        undo_steps.each do |undo_step|
          undo_step.call
        end
        raise
      end
      
    end
  end
  
  existing_sandbox.cdb_save

  display existing_sandbox
end

#upload_checksumObject

Raises:

  • (BadRequest)


90
91
92
93
94
95
96
97
98
99
100
101
# File 'app/controllers/sandboxes.rb', line 90

def upload_checksum
  sandbox_file = ChefServerApi::SandboxFile.new(self.request.env["rack.input"], params)
  raise BadRequest, sandbox_file.error  if sandbox_file.invalid_params?
  raise NotFound, sandbox_file.error    if sandbox_file.invalid_sandbox?
  raise BadRequest, sandbox_file.error  if sandbox_file.invalid_file?
  
  sandbox_file.commit_to(sandbox_checksum_location(sandbox_file.sandbox_id, sandbox_file.expected_checksum))
  
  url = absolute_url(:sandbox_checksum, sandbox_file.resource_params)
  result = { 'uri' => url }
  display result
end