GitLab upgraded to 13.12.4-ee.0 - changelog: https://gitlab.com/gitlab-org/gitlab/blob/master/CHANGELOG-EE.md

Commit ebc1b392 authored by Adam Jacob's avatar Adam Jacob
Browse files

Moving chef-server into lib, reworking specs, adding stories

parent 14ca7fdc
#
# Example Chef Server Config
cookbook_path File.join(File.dirname(__FILE__), "..", "examples", "config", "cookbooks")
node_path File.join(File.dirname(__FILE__), "..", "examples", "config", "nodes")
file_store_path File.join(File.dirname(__FILE__), "..", "examples", "store")
log_level :debug
openid_providers [ "localhost:4001", "openid.hjksolutions.com" ]
Chef::Log::Formatter.show_time = false
......@@ -16,4 +16,5 @@ end
mode 0644
action :create
end
end
\ No newline at end of file
end
......@@ -19,7 +19,11 @@
require 'rubygems'
Dir[File.join(File.dirname(__FILE__), 'chef/**/*.rb')].sort.each { |lib| require lib unless lib =~ /server/ }
Dir[
File.join(
File.dirname(__FILE__),
'chef/**/*.rb'
)].sort.each { |lib| require lib unless lib =~ /server/ }
class Chef
VERSION = '0.0.1'
......
......@@ -26,7 +26,7 @@ require 'facter'
class Chef
class Client
attr_accessor :node, :registration
attr_accessor :node, :registration, :safe_name
def initialize()
@node = nil
......@@ -43,8 +43,8 @@ class Chef
converge
end
def build_node
node_name = Facter["fqdn"].value ? Facter["fqdn"].value : Facter["hostname"].value
def build_node(node_name=nil)
node_name ||= Facter["fqdn"].value ? Facter["fqdn"].value : Facter["hostname"].value
@safe_name = node_name.gsub(/\./, '_')
begin
@node = @rest.get_rest("nodes/#{@safe_name}")
......
......@@ -49,6 +49,7 @@ class Chef
:couchdb_url => "http://localhost:5984",
:registration_url => "http://localhost:4000",
:openid_url => "http://localhost:4001",
:couchdb_database => "chef",
}
class << self
......
......@@ -92,7 +92,7 @@ class Chef
def load_recipe(name, node, collection=nil, definitions=nil, cookbook_loader=nil)
cookbook_name = @name
recipe_name = nil
nmatch = name.match(/^(.+)::(.+)$/)
nmatch = name.match(/^(.+?)::(.+)$/)
recipe_name = nmatch ? nmatch[2] : name
unless @recipe_names.has_key?(recipe_name)
......
......@@ -13,16 +13,16 @@ class Chef
def create_db
@database_list = @rest.get_rest("_all_dbs")
unless @database_list.detect { |db| db == "chef" }
response = @rest.put_rest("chef", Hash.new)
unless @database_list.detect { |db| db == Chef::Config[:couchdb_database] }
response = @rest.put_rest(Chef::Config[:couchdb_database], Hash.new)
end
"chef"
Chef::Config[:couchdb_database]
end
def create_design_document(name, data)
to_update = true
begin
old_doc = @rest.get_rest("chef/_design%2F#{name}")
old_doc = @rest.get_rest("#{Chef::Config[:couchdb_database]}/_design%2F#{name}")
if data["version"] != old_doc["version"]
data["_rev"] = old_doc["_rev"]
Chef::Log.debug("Updating #{name} views")
......@@ -33,7 +33,7 @@ class Chef
Chef::Log.debug("Creating #{name} views for the first time")
end
if to_update
@rest.put_rest("chef/_design%2F#{name}", data)
@rest.put_rest("#{Chef::Config[:couchdb_database]}/_design%2F#{name}", data)
end
true
end
......@@ -49,7 +49,7 @@ class Chef
:object => { :respond_to => :to_json },
}
)
@rest.put_rest("chef/#{obj_type}_#{safe_name(name)}", object)
@rest.put_rest("#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}", object)
end
def load(obj_type, name)
......@@ -63,7 +63,7 @@ class Chef
:name => { :kind_of => String },
}
)
@rest.get_rest("chef/#{obj_type}_#{safe_name(name)}")
@rest.get_rest("#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}")
end
def delete(obj_type, name, rev=nil)
......@@ -78,14 +78,14 @@ class Chef
}
)
unless rev
last_obj = @rest.get_rest("chef/#{obj_type}_#{safe_name(name)}")
last_obj = @rest.get_rest("#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}")
if last_obj.respond_to?(:couchdb_rev)
rev = last_obj.couchdb_rev
else
rev = last_obj['_rev']
end
end
@rest.delete_rest("chef/#{obj_type}_#{safe_name(name)}?rev=#{rev}")
@rest.delete_rest("#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}?rev=#{rev}")
end
def list(view, inflate=false)
......@@ -98,9 +98,9 @@ class Chef
}
)
if inflate
@rest.get_rest("chef/_view/#{view}/all")
@rest.get_rest("#{Chef::Config[:couchdb_database]}/_view/#{view}/all")
else
@rest.get_rest("chef/_view/#{view}/all_id")
@rest.get_rest("#{Chef::Config[:couchdb_database]}/_view/#{view}/all_id")
end
end
......@@ -116,7 +116,7 @@ class Chef
}
)
begin
@rest.get_rest("chef/#{obj_type}_#{safe_name(name)}")
@rest.get_rest("#{Chef::Config[:couchdb_database]}/#{obj_type}_#{safe_name(name)}")
true
rescue
false
......
class Application < Merb::Controller
def fix_up_node_id
if params.has_key?(:id)
params[:id].gsub!(/_/, '.')
end
end
def escape_node_id
if params.has_key?(:id)
params[:id].gsub(/_/, '.')
end
end
def login_required
if session[:openid]
return session[:openid]
else
self.store_location
throw(:halt, :access_denied)
end
end
def authorized_node
if session[:level] == :admin
Chef::Log.debug("Authorized as Administrator")
true
elsif session[:level] == :node
Chef::Log.debug("Authorized as node")
if session[:node_name] == params[:id].gsub(/\./, '_')
true
else
raise(
Unauthorized,
"You are not the correct node for this action: #{session[:node_name]} instead of #{params[:id]}"
)
end
else
Chef::Log.debug("Unauthorized")
raise Unauthorized, "You are not allowed to take this action."
end
end
# Store the URI of the current request in the session.
#
# We can return to this location by calling #redirect_back_or_default.
def store_location
session[:return_to] = request.uri
end
# Redirect to the URI stored by the most recent store_location call or
# to the passed default.
def redirect_back_or_default(default)
loc = session[:return_to] || default
session[:return_to] = nil
redirect loc
end
def access_denied
case content_type
when :html
store_location
redirect url(:openid_consumer)
else
raise Unauthorized, "You must authenticate first!"
end
end
end
\ No newline at end of file
class Exceptions < Application
provides :html, :json
# handle NotFound exceptions (404)
def not_found
display params
end
# handle NotAcceptable exceptions (406)
def not_acceptable
display params
end
# handle BadRequest exceptions (400)
def bad_request
display params
end
end
\ No newline at end of file
class Nodes < Application
provides :html, :json
before :fix_up_node_id
before :login_required, :only => [ :create, :update, :destroy ]
before :authorized_node, :only => [ :update, :destroy ]
def index
@node_list = Chef::Node.list
display @node_list
end
def show
begin
@node = Chef::Node.load(params[:id])
rescue Net::HTTPServerException => e
raise NotFound, "Cannot load node #{params[:id]}"
end
display @node
end
def create
@node = params.has_key?("inflated_object") ? params["inflated_object"] : nil
if @node
@status = 202
@node.save
display @node
else
raise BadRequest, "You must provide a Node to create"
end
end
def update
@node = params.has_key?("inflated_object") ? params["inflated_object"] : nil
if @node
@status = 202
@node.save
display @node
else
raise NotFound, "You must provide a Node to update"
end
end
def destroy
begin
@node = Chef::Node.load(params[:id])
rescue RuntimeError => e
raise BadRequest, "Node #{params[:id]} does not exist to destroy!"
end
@status = 202
@node.destroy
if content_type == :html
redirect url(:nodes)
else
display @node
end
end
def compile
# Grab a Chef::Compile object
compile = Chef::Compile.new()
compile.load_node(params[:id])
compile.node.save
compile.load_definitions
compile.load_recipes
@output = {
:node => compile.node,
:collection => compile.collection,
}
display @output
end
end
require 'pathname'
require "openid"
require 'openid/store/filesystem'
class OpenidConsumer < Application
provides :html, :json
def index
render
end
def start
check_valid_openid_provider(params[:openid_identifier])
begin
oidreq = consumer.begin(params[:openid_identifier])
rescue OpenID::OpenIDError => e
raise BadRequest, "Discovery failed for #{params[:openid_identifier]}: #{e}"
end
return_to = absolute_url(:openid_consumer_complete)
realm = absolute_url(:openid_consumer)
if oidreq.send_redirect?(realm, return_to, params[:immediate])
return redirect(oidreq.redirect_url(realm, return_to, params[:immediate]))
else
@form_text = oidreq.form_markup(realm, return_to, params[:immediate], {'id' => 'openid_form'})
render
end
end
def complete
# FIXME - url_for some action is not necessarily the current URL.
current_url = absolute_url(:openid_consumer_complete)
parameters = params.reject{|k,v| k == "controller" || k == "action"}
oidresp = consumer.complete(parameters, current_url)
case oidresp.status
when OpenID::Consumer::FAILURE
if oidresp.display_identifier
raise BadRequest, "Verification of #{oidresp.display_identifier} failed: #{oidresp.message}"
else
raise BadRequest, "Verification failed: #{oidresp.message}"
end
when OpenID::Consumer::SUCCESS
session[:openid] = oidresp.identity_url
if oidresp.display_identifier =~ /openid\/server\/node\/(.+)$/
session[:level] = :node
session[:node_name] = $1
else
session[:level] = :admin
end
redirect_back_or_default(absolute_url(:nodes))
return "Verification of #{oidresp.display_identifier} succeeded."
when OpenID::Consumer::SETUP_NEEDED
return "Immediate request failed - Setup Needed"
when OpenID::Consumer::CANCEL
return "OpenID transaction cancelled."
else
end
redirect absolute_url(:openid_consumer)
end
def logout
session[:openid] = nil if session.has_key?(:openid)
session[:level] = nil if session.has_key?(:level)
session[:node_name] = nil if session.has_key?(:node_name)
redirect url(:top)
end
private
# Returns true if the openid is at a valid provider, based on whether :openid_providers is
# defined. Raises an exception if it is not an allowed provider.
def check_valid_openid_provider(openid)
if Chef::Config[:openid_providers]
fp = Chef::Config[:openid_providers].detect do |p|
case openid
when /^http:\/\/#{p}/, /^#{p}/
true
else
false
end
end
unless fp
raise Unauthorized, "Sorry, #{openid} is not an allowed OpenID Provider."
end
end
true
end
def consumer
if @consumer.nil?
dir = Pathname.new(Merb.root).join('db').join('cstore')
store = OpenID::Store::Filesystem.new(dir)
@consumer = OpenID::Consumer.new(session, store)
end
return @consumer
end
end
# Controller for handling the login, logout process for "users" of our
# little server. Users have no password. This is just an example.
require 'openid'
class OpenidRegister < Application
provides :html, :json
before :fix_up_node_id
def index
@headers['X-XRDS-Location'] = absolute_url(:controller => "openid_server", :action => "idp_xrds")
@registered_nodes = Chef::OpenIDRegistration.list(true)
Chef::Log.debug(@registered_nodes.inspect)
display @registered_nodes
end
def show
begin
@registered_node = Chef::OpenIDRegistration.load(params[:id])
rescue Net::HTTPServerException => e
if e.message =~ /^404/
raise NotFound, "Cannot load node registration for #{params[:id]}"
else
raise e
end
end
Merb.logger.debug(@registered_node.inspect)
display @registered_node
end
def create
params.has_key?(:id) or raise BadRequest, "You must provide an id to register"
params.has_key?(:password) or raise BadRequest, "You must provide a password to register"
if Chef::OpenIDRegistration.has_key?(params[:id])
raise BadRequest, "You cannot re-register #{params[:id]}!"
end
@registered_node = Chef::OpenIDRegistration.new
@registered_node.name = params[:id]
@registered_node.set_password(params[:password])
@registered_node.save
display @registered_node
end
def update
raise BadRequest, "You cannot update your registration -- delete #{params[:id]} and re-register"
end
def destroy
begin
r = Chef::OpenIDRegistration.load(params[:id])
rescue Exception => e
raise BadRequest, "Cannot find the registration for #{params[:id]}"
end
r.destroy
if content_type == :html
redirect url(:registrations)
else
display({ :message => "Deleted registration for #{params[:id]}"})
end
end
def validate
begin
r = Chef::OpenIDRegistration.load(params[:id])
rescue Exception => e
raise BadRequest, "Cannot find the registration for #{params[:id]}"
end
r.validated = r.validated ? false : true
r.save
redirect url(:registrations)
end
end
require 'pathname'
# load the openid library, first trying rubygems
#begin
# require "rubygems"
# require_gem "ruby-openid", ">= 1.0"
#rescue LoadError
require "openid"
require "openid/consumer/discovery"
require 'openid/store/filesystem'
require 'json'
#end
class OpenidServer < Application
provides :html, :json
include Merb::OpenidServerHelper
include OpenID::Server
layout nil
before :fix_up_node_id
def index
oidreq = server.decode_request(params.reject{|k,v| k == "controller" || k == "action"})
# no openid.mode was given
unless oidreq
return "This is the Chef OpenID server endpoint."
end
oidresp = nil
if oidreq.kind_of?(CheckIDRequest)
identity = oidreq.identity
if oidresp
nil
elsif self.is_authorized(identity, oidreq.trust_root)
oidresp = oidreq.answer(true, nil, identity)
elsif oidreq.immediate
server_url = url :openid_server
oidresp = oidreq.answer(false, server_url)
else
if content_type != 'application/json'
session[:last_oidreq] = oidreq
response = { :action => url(:openid_server_decision) }
return response.to_json
else
return show_decision_page(oidreq)
end
end
else
oidresp = server.handle_request(oidreq)
end
self.render_response(oidresp)
end
def show_decision_page(oidreq, message="Do you trust this site with your identity?")
session[:last_oidreq] = oidreq
@oidreq = oidreq
if message
session[:notice] = message
end
render :template => 'openid_server/decide'
end
def node_page
unless Chef::OpenIDRegistration.has_key?(params[:id])
raise NotFound, "Cannot find registration for #{params[:id]}"
end
# Yadis content-negotiation: we want to return the xrds if asked for.
accept = request.env['HTTP_ACCEPT']
# This is not technically correct, and should eventually be updated
# to do real Accept header parsing and logic. Though I expect it will work
# 99% of the time.
if accept and accept.include?('application/xrds+xml')
return node_xrds
end
# content negotiation failed, so just render the user page
xrds_url = absolute_url(:openid_node_xrds, :id => params[:id])
identity_page = <<EOS
<html><head>
<meta http-equiv="X-XRDS-Location" content="#{xrds_url}" />
<link rel="openid.server" href="#{absolute_url(:openid_node, :id => params[:id])}" />
</head><body><p>OpenID identity page for registration #{params[:id]}</p>
</body></html>
EOS
# Also add the Yadis location header, so that they don't have
# to parse the html unless absolutely necessary.
@headers['X-XRDS-Location'] = xrds_url
render identity_page
end