Skip to content
This repository has been archived by the owner on Oct 16, 2018. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
Add some initial buildpack and application commands
  • Loading branch information
peterkeen committed Aug 18, 2012
1 parent d7d1924 commit 6180fa2
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 22 deletions.
1 change: 1 addition & 0 deletions lib/dokuen.rb
Expand Up @@ -15,5 +15,6 @@ def self.template(name, bind)

require "dokuen/config"
require "dokuen/remote"
require "dokuen/application"
require "dokuen/cli"

41 changes: 41 additions & 0 deletions lib/dokuen/application.rb
@@ -0,0 +1,41 @@
class Dokuen::Application

attr_reader :name, :remote

def initialize(remote, name)
@remote = remote
@name = name
end

def run(*args)
remote.run(*args)
end

def sudo(*args)
remote.sudo(*args)
end

def create!
return if remote.application_exists?(name)

remote.create_user(name)
dirs = [
'releases',
'env',
'logs',
'build'
]
dirs.each do |dir|
sudo("mkdir -p #{remote.path}/apps/#{name}/#{dir}")
end
sudo("chown -R #{name}.#{name} #{remote.path}/apps/#{name}")
end

def destroy!
return unless remote.application_exists?(name)

sudo("rm -rf #{remote.path}/apps/#{name}")
sudo("userdel #{name}")
end

end
107 changes: 88 additions & 19 deletions lib/dokuen/cli.rb
Expand Up @@ -8,15 +8,33 @@ class Dokuen::CLI < Thor

class_option :config, :type => :string, :desc => "Config file"

class Remote < Thor
class SubCommand < Thor

namespace :remote
no_tasks do

def initialize(*args)
super(*args)
@config = Dokuen::Config.new(options[:config] || "~/.dokuen")
end

def verify_remote(remote, create_remote=true)
if @config[:remotes][remote].nil?
raise Thor::Error.new("#{remote} is not a known remote")
end
@remote = Dokuen::Remote.new(@config[:remotes][remote]) if create_remote
end

def initialize(*args)
super(*args)
@config = Dokuen::Config.new(options[:config] || "~/.dokuen")
def self.banner(task, namespace = true, subcommand = false)
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
end
end

end

class Remote < SubCommand

namespace :remote

desc "add NAME SPEC", "Add a remote named NAME with spec SPEC (ex: user@hostname:/path/to/dokuen)"
def add(name, spec)
@config[:remotes][name] = spec
Expand All @@ -26,34 +44,85 @@ def add(name, spec)

desc "remove NAME", "Remote the named remote from dokuen config"
def remove(name)
if @config[:remotes][name].nil?
raise Thor::Error.new("#{name} is not a known remote")
end
verify_remote(name, false)

@config[:remotes].delete(name)
@config.write_file
say "Removed #{name} from #{@config.filename}"
end

desc "setup NAME", "Setup Dokuen on the named remote"
def setup(name)
if @config[:remotes][name].nil?
raise Thor::Error.new("#{name} is not a known remote")
end
desc "prepare NAME", "Setup Dokuen on the named remote"
def prepare(name)
verify_remote(name)

say "Setting up dokuen on #{name}"
say "Preparing #{name} for dokuen"

remote = Dokuen::Remote.new(@config[:remotes][name])
remote.setup!
@remote.prepare!
end

def self.banner(task, namespace = true, subcommand = false)
"#{basename} #{task.formatted_usage(self, true, subcommand)}"
end
end

class Buildpack < SubCommand
namespace :buildpack

desc "add REMOTE URL", "Add a buildpack to the standard set"
def add(remote, url)
verify_remote(remote)

say "Cloning buildpack from #{url} onto #{remote}"

@remote.clone_buildpack(url)
end

desc "remove REMOTE NAME", "Remove buildpack from remote"
def remove(remote, name)
verify_remote(remote)

say "Removing buildpack #{name} from remote #{remote}"

@remote.remove_buildpack(name)
end

end

class Application < SubCommand

namespace :app

desc "create REMOTE NAME", "Create an application"
def create(remote, name)
verify_remote(remote)

say "Creating application #{name} on #{remote}"

if @remote.application_exists? name
raise "Application #{name} already exists on remote #{remote}"
end
app = Dokuen::Application.new(@remote, name)
app.create!
end

desc "destroy REMOTE NAME", "Destroy an application"
def destroy(remote, name)
verify_remote(remote)
say "Destroying application #{name} on #{remote}"

raise "Application does not exist" unless @remote.application_exists?(name)

say "THIS IS PERMANENT"
say "Type '#{name}' at the prompt below to confirm"

confirm = ask "Confirm: "
raise "Confirmation invalid!" unless confirm == name

app = Dokuen::Application.new(@remote, name)
app.destroy!
end
end

register(Remote, 'remote', 'remote <command>', 'Manipulate Dokuen remotes')
register(Buildpack, 'buildpack', 'buildpack <command>', 'Manipulate Dokuen buildpacks')
register(Application, 'app', 'app <command>', 'Manipulate Dokuen applications')

end

57 changes: 54 additions & 3 deletions lib/dokuen/remote.rb
@@ -1,17 +1,68 @@
require 'capistrano'
require 'fileutils'

class Dokuen::Remote

attr_reader :user, :server_name, :path

def initialize(spec)
@remote_spec = spec

@server_name, @path = spec.split(/:/, 2)

@user, rest = @server_name.split(/@/, 2)

@cap = Capistrano::Configuration.new
@cap.logger.level = Capistrano::Logger::TRACE
@cap.server(@server_name, :dokuen)
end

def setup!
@cap.run("hostname")
def prepare!
mkdirs
install_foreman
end

def run(*args)
@cap.run(*args)
end

def sudo(*args)
@cap.sudo(*args)
end

def mkdirs
dirs = [
'apps',
'env',
'nginx',
'buildpacks',
]

dirs.each do |dir|
full_path = File.join(path, dir)
sudo("mkdir -p #{full_path}")
sudo("chown #{user} #{full_path}")
end
end

def install_foreman
sudo("apt-get -y install ruby1.9.1")
sudo("gem install foreman -v 0.55.0")
end

def clone_buildpack(url)
run("cd #{path}/buildpacks && git clone #{url}")
end

def remove_buildpack(name)
run("rm -rf #{path}/buildpacks/#{name}")
end

def application_exists?(name)
@cap.capture("([ -d #{path}/apps/#{name} ] && echo #{name}) || echo '' ") != ""
end

def create_user(name)
sudo("useradd --home #{path}/apps/#{name} --shell /usr/bin/false #{name}")
end

end

0 comments on commit 6180fa2

Please sign in to comment.