shaddox 0.0.30 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 46fa597ccc0b93dcbbdf658a5d0e25b6e70e877a
4
- data.tar.gz: 8f4864ce6dc4971389e1eba700ce177a466cb133
3
+ metadata.gz: 10d9d20d568a9f429430855db8652655b78908c9
4
+ data.tar.gz: 7aa5c9f137fb1fa95201e7825a0e9bf3d8f4cd78
5
5
  SHA512:
6
- metadata.gz: 49fab60501a5f1c8d838a78c6632ee709ff92ef385bef45a1a39021991065ae3ba8fd19f327b6457f797a87d059eaad65f3f31e67dde40e79c399572d5d00721
7
- data.tar.gz: 7899e6f5689f2a0ccd2280783d4ad08a2709da58a9055031ac807f63533409f58e812d77419425dcfe1a1ab5a127a0fa1ff184a06fbb35b801d0deb0bcb52a10
6
+ metadata.gz: 48760f0b6cdbd5e4b9f539116499c32bd270da4f22127853bc2b4dffc5a8a898e09341da25e758764c91936ced54a01ddb46fc3502c529948c5a19ea5eefe257
7
+ data.tar.gz: 858f39652d4be97f7a856180030ec98820aaf95a50dfa794bb9988ac144c7cbab5c433435a6b43572c80750c0485f904259a4d848132b268bae1a06c381813ea
data/Doxfile CHANGED
@@ -1,36 +1,19 @@
1
- server :vagrant, {
2
- :host => "localhost",
3
- :user => 'vagrant',
4
- :ssh => {
5
- :port => 2222,
6
- :password => 'vagrant'
7
- },
8
- :installer => :apt
9
- }
10
-
11
- repo :profile, {
12
- :url => "https://github.com/joshglendenning/profile.git",
13
- :shared => 'tmp'
14
- }
15
-
16
1
  task :foo do
17
- sh "echo 'foo'"
2
+ exec "echo 'foo'"
18
3
  end
19
4
 
20
5
  task :foobar => :foo do
21
- sh "echo 'bar'"
22
- end
23
-
24
- task :install do
25
- repo_deploy :profile, "~/repo_test/profile" do
26
- ln_s './current', '/var/www/profile'
27
- end
6
+ exec "echo 'bar'"
28
7
  end
29
8
 
30
9
  task :broken => :foo do
31
- sh "notacommand"
10
+ exec "notacommand"
32
11
  end
33
12
 
34
13
  task :sudo do
35
- sh "sudo echo 'this is a sudo echo'"
14
+ exec "sudo echo 'this is a sudo echo'"
15
+ end
16
+
17
+ task :install do
18
+ install "git"
36
19
  end
data/bin/shaddox CHANGED
@@ -10,25 +10,13 @@ options = {
10
10
 
11
11
  OptionParser.new do |opts|
12
12
 
13
- opts.banner = "Usage: shaddox [task] [target] [options]"
13
+ opts.banner = "Usage: shaddox [task] [options]"
14
14
 
15
- opts.on("--debug", "Run verbosely") do |v|
16
- options[:debug] = v
15
+ opts.on('-v', '--verboase', "Run verbosely") do
16
+ options[:verbose] = true
17
17
  end
18
18
 
19
- opts.on("--force", "Override lock on target") do |b|
20
- options[:force] = b
21
- end
22
-
23
- opts.on("--keep-tmp-dir", "Don't remove the tmpdir after deployment") do |b|
24
- options[:keep_tmp_dir] = b
25
- end
26
-
27
- opts.on("--tmpdir PATH", "Specify the tmp directory to use (default '/tmp/shaddox')") do |dir|
28
- options[:tmpdir] = dir
29
- end
30
-
31
- opts.on('-f PATH', '--doxfile', "Specify doxfile") do |f|
19
+ opts.on('--doxfile', "Specify doxfile") do |f|
32
20
  @doxfile = f
33
21
  end
34
22
 
@@ -39,8 +27,7 @@ OptionParser.new do |opts|
39
27
 
40
28
  end.parse!
41
29
 
42
- task = ARGV[0]
43
- target = ARGV[1] || 'localhost'
30
+ task = ARGV[0] || :default
44
31
 
45
32
  config = Shaddox::Config.new(@doxfile)
46
- config.invoke(task.to_sym, target.to_sym, options)
33
+ config.invoke(task, options)
@@ -1,6 +1,10 @@
1
1
  module Shaddox
2
2
  class Config
3
- attr_accessor :servers, :targets, :repos, :tasks
3
+
4
+ # Init ==============================================
5
+
6
+ attr_accessor :tasks
7
+
4
8
  def initialize(doxfile)
5
9
  doxfile = './Doxfile' unless doxfile
6
10
  if !File.exists?(doxfile)
@@ -8,83 +12,32 @@ module Shaddox
8
12
  exit(1)
9
13
  end
10
14
 
11
- @servers = Hash.new
12
- @targets = Hash.new {|hsh, key| @servers[key]} # Fall back on @servers hash for missing targets
13
15
  @tasks = Hash.new
14
- @repos = Hash.new
15
-
16
- # :local and :localhost point to local by default
17
- @targets[:localhost] = Localhost.new
18
- @targets[:local] = :localhost
19
16
 
20
17
  instance_eval(File.read(doxfile), doxfile)
21
18
  end
22
19
 
23
- def explode_target(target_key)
24
- exploded = []
25
- [@targets[target_key]].flatten.each do |target|
26
- if target.is_a? Symbol
27
- exploded += explode_target(target)
28
- else
29
- exploded.push(target)
30
- end
31
- end
32
- exploded
33
- end
34
-
35
- def invoke(task_key, target_key, opts = {})
36
- explode_target(target_key).each do |target|
37
- raise "The target :#{target_key} could not be found. Please check your Doxfile.".red unless target
38
- info "Deploying to #{target_key}..."
39
- begin
40
- script_opts = {}
41
- script_opts[:installer] = target.installer if target.respond_to? :installer
42
- script_opts[:debug] = opts[:debug] if opts[:debug]
43
- script = ShadowScript.new(self, task_key, script_opts)
44
- target.deploy(script, opts)
45
- info "Provisioning on :#{target_key} complete.".green
46
- rescue TargetError => e
47
- err "Provisioning on :#{target_key} failed:".red
48
- puts e.message.red
49
- rescue => e
50
- err "Provisioning on :#{target_key} failed:".red
51
- puts e.message.red
52
- e.backtrace.each { |line| puts line }
53
- end
20
+ # Methods ============================================
21
+
22
+ def invoke(task_key, opts)
23
+ begin
24
+ task = @tasks[task_key.to_sym]
25
+ return if task.done
26
+ task.deps.each { |dep| invoke(dep, opts) }
27
+ info "[#{task_key}] Starting..."
28
+ Provisioner.new(task.block, opts)
29
+ task.done = true
30
+ info "[#{task_key}] Done".green
31
+ rescue => e
32
+ err "[#{task_key}] Failed".red
33
+ puts e.message.red
34
+ e.backtrace.each { |line| puts line }
54
35
  end
55
36
  end
56
37
 
57
38
  ## DSL Methods ##
58
39
 
59
- # ### Add a server
60
- # info: A hash containing the server's info. Allowed keys:
61
- # :address (required)
62
- # :user
63
- # :port
64
- # :identity_file
65
- # :ssh_options
66
- def server(key, info)
67
- @servers[key] = Server.new(info)
68
- end
69
-
70
- # ### Add a target
71
- # linked_target: A symbol or Array of symbols representing
72
- # the other targets/servers that this target invokes
73
- def target(key, linked_target)
74
- @targets[key] = linked_target
75
- end
76
-
77
- # ### Add a repo
78
- # info: A hash containing the repo's info. Allowed keys:
79
- # :repository (required)
80
- # :branch
81
- def repo(key, info)
82
- @repos[key] = Repo.new(info)
83
- end
84
-
85
- # ### Add a package
86
- # blk: A block of code to be executed in the context of the target[s]
87
- # specified when running Shaddox
40
+ # ### Add a task
88
41
  # key can be bound to a list to define dependencies, like with Rake
89
42
  # task :example => :some_dep do ...
90
43
  # task :example => [:dep1, :dep2] do ...
@@ -0,0 +1,74 @@
1
+ module Shaddox
2
+
3
+ class Installer
4
+ def self.autodetect(pvr)
5
+ return AptInstaller.new(pvr) if pvr.availiable? "apt-get"
6
+ return BrewInstaller.new(pvr) if pvr.availiable? "brew"
7
+ return PacmanInstaller.new(pvr) if pvr.availiable? "pacman"
8
+ warn "Installer could not be automatically identified.", 1
9
+ require 'highline/import'
10
+ choose do |menu|
11
+ menu.prompt = "Please select a package manager to use:"
12
+
13
+ menu.choice(:manual) { return ManualInstaller.new(pvr) }
14
+ menu.choice(:apt) { return AptInstaller.new(pvr) }
15
+ menu.choice(:brew) { return BrewInstaller.new(pvr) }
16
+ end
17
+ end
18
+ def initialize(pvr)
19
+ @pvr = pvr
20
+ end
21
+ def install(package)
22
+ raise "This should be implemented by subclass."
23
+ end
24
+ def installed?(cmd)
25
+ @pvr.availiable?(cmd)
26
+ end
27
+ end
28
+
29
+ class ManualInstaller < Installer
30
+ def install(package)
31
+ return if installed?(package)
32
+ puts "Please install '#{package}' manually."
33
+ gets
34
+ raise "Could not install #{package}" unless installed?(package)
35
+ end
36
+ end
37
+
38
+ class AptInstaller < Installer
39
+ # def initialize(pvr)
40
+ # super(pvr)
41
+ # @pvr.exec("sudo apt-get update")
42
+ # end
43
+ def install(package)
44
+ return if installed?(package)
45
+ @pvr.exec("sudo apt-get install #{package}")
46
+ raise "Could not install #{package}" unless installed?(package)
47
+ end
48
+ end
49
+
50
+ class BrewInstaller < Installer
51
+ # def initialize(pvr)
52
+ # super(pvr)
53
+ # @pvr.exec("brew update")
54
+ # end
55
+ def install(package)
56
+ return if installed?(package)
57
+ @pvr.exec("brew install #{package}")
58
+ raise "Could not install #{package}" unless installed?(package)
59
+ end
60
+ end
61
+
62
+ class PacmanInstaller < Installer
63
+ # def initialize(pvr)
64
+ # super(pvr)
65
+ # @pvr.exec("pacman -Sy")
66
+ # end
67
+ def install(package)
68
+ return if installed?(package)
69
+ @pvr.exec("pacman -S #{package}")
70
+ raise "Could not install #{package}" unless installed?(package)
71
+ end
72
+ end
73
+
74
+ end
@@ -0,0 +1,89 @@
1
+ class String
2
+ def exp_path
3
+ File.expand_path(self)
4
+ end
5
+ def parent
6
+ File.split(self)[0]
7
+ end
8
+ end
9
+
10
+ module Shaddox
11
+
12
+ class Provisioner
13
+
14
+ require 'fileutils'
15
+
16
+ # Init ====================================================
17
+
18
+ def initialize(block, opts = {:verbose => false})
19
+ @verbose = opts[:verbose]
20
+ @required = true
21
+ instance_eval(&block) unless !block
22
+ end
23
+
24
+ # Methods =================================================
25
+
26
+ def optional(&block)
27
+ @required = false
28
+ instance_eval(&block)
29
+ @required = true
30
+ end
31
+
32
+ def exists(path)
33
+ system("test -e #{path.exp_path}")
34
+ end
35
+
36
+ def exists_d(path)
37
+ system("test -d #{path.exp_path}")
38
+ end
39
+
40
+ def exists_f(path)
41
+ system("test -f #{path.exp_path}")
42
+ end
43
+
44
+ def exec(command, args = nil)
45
+ cmd = "#{command}"
46
+ cmd += " #{args.join(" ")}" if args
47
+ info "Running '#{cmd}' in '#{Dir.pwd}'", 1 if @verbose
48
+ system(cmd)
49
+ raise "'#{cmd}' failed" unless $? == 0 or !@required
50
+ end
51
+
52
+ def cd(path, &block)
53
+ mkdir(path)
54
+ FileUtils.cd(path.exp_path) do
55
+ instance_eval(&block)
56
+ end
57
+ end
58
+
59
+ def ln_s(source, dest, opts = {})
60
+ mkdir(dest.exp_path.parent)
61
+ Dir.glob(source.exp_path).each { |src|
62
+ info "Linking '#{source.exp_path}' to '#{dest.exp_path}'", 1 if @verbose
63
+ FileUtils::ln_s(src, dest.exp_path, opts)
64
+ }
65
+ end
66
+
67
+ def mkdir(path)
68
+ info "Ensuring directory '#{path}' exists", 1 if @verbose
69
+ FileUtils::mkdir_p(path.exp_path)
70
+ end
71
+
72
+ def availiable?(cmd)
73
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
74
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
75
+ exts.each { |ext|
76
+ exe = File.join(path, "#{cmd}#{ext}")
77
+ return true if File.executable?(exe) && !File.directory?(exe)
78
+ }
79
+ end
80
+ return false
81
+ end
82
+
83
+ def install(package)
84
+ @installer ||= Installer.autodetect(self);
85
+ info "Ensuring #{package} is installed", 1 if @verbose
86
+ @installer.install(package)
87
+ end
88
+ end
89
+ end
data/lib/shaddox/task.rb CHANGED
@@ -1,18 +1,10 @@
1
1
  module Shaddox
2
2
  class Task
3
- attr_accessor :block, :deps
3
+ attr_accessor :block, :deps, :done
4
4
  def initialize(block, deps)
5
5
  @block = block
6
6
  @deps = [deps].flatten
7
- end
8
-
9
- def to_source
10
- require 'sourcify'
11
- if @block
12
- @block.to_source(:strip_enclosure => true)
13
- else
14
- "# Empty block #"
15
- end
7
+ @done = false
16
8
  end
17
9
  end
18
10
  end
@@ -1,3 +1,3 @@
1
1
  module Shaddox
2
- VERSION = "0.0.30"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/shaddox.rb CHANGED
@@ -1,9 +1,6 @@
1
1
  require "shaddox/version"
2
2
  require "shaddox/ui"
3
- require "shaddox/settings"
4
- require "shaddox/target"
3
+ require "shaddox/installer"
4
+ require "shaddox/provisioner"
5
5
  require "shaddox/task"
6
- require "shaddox/repo"
7
- require "shaddox/shadow"
8
- require "shaddox/shadow_script"
9
6
  require "shaddox/config"
data/shaddox.gemspec CHANGED
@@ -18,9 +18,5 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "sourcify", "~> 0.6.0.rc4"
22
- spec.add_dependency "net-ssh", "~> 2.9"
23
- spec.add_dependency "highline", "~> 1.6"
24
- spec.add_development_dependency "bundler", "~> 1.6"
25
- spec.add_development_dependency "rake", "~> 10.0"
21
+ spec.add_dependency 'highline', '~> 1.7'
26
22
  end
metadata CHANGED
@@ -1,85 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shaddox
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.30
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - joshglendenning
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-17 00:00:00.000000000 Z
11
+ date: 2015-06-23 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: sourcify
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: 0.6.0.rc4
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: 0.6.0.rc4
27
- - !ruby/object:Gem::Dependency
28
- name: net-ssh
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.9'
34
- type: :runtime
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.9'
41
13
  - !ruby/object:Gem::Dependency
42
14
  name: highline
43
15
  requirement: !ruby/object:Gem::Requirement
44
16
  requirements:
45
17
  - - "~>"
46
18
  - !ruby/object:Gem::Version
47
- version: '1.6'
19
+ version: '1.7'
48
20
  type: :runtime
49
21
  prerelease: false
50
22
  version_requirements: !ruby/object:Gem::Requirement
51
23
  requirements:
52
24
  - - "~>"
53
25
  - !ruby/object:Gem::Version
54
- version: '1.6'
55
- - !ruby/object:Gem::Dependency
56
- name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.6'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.6'
69
- - !ruby/object:Gem::Dependency
70
- name: rake
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '10.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '10.0'
26
+ version: '1.7'
83
27
  description: Ruby-based system provisioning tool.
84
28
  email:
85
29
  - joshglendenning@gmail.com
@@ -93,20 +37,14 @@ files:
93
37
  - Gemfile
94
38
  - LICENSE.txt
95
39
  - README.md
96
- - Vagrantfile
97
40
  - bin/shaddox
98
41
  - lib/shaddox.rb
99
42
  - lib/shaddox/config.rb
100
- - lib/shaddox/repo.rb
101
- - lib/shaddox/settings.rb
102
- - lib/shaddox/shadow.rb
103
- - lib/shaddox/shadow_script.rb
104
- - lib/shaddox/target.rb
43
+ - lib/shaddox/installer.rb
44
+ - lib/shaddox/provisioner.rb
105
45
  - lib/shaddox/task.rb
106
46
  - lib/shaddox/ui.rb
107
47
  - lib/shaddox/version.rb
108
- - push.sh
109
- - scripts/bootstrap.sh
110
48
  - shaddox.gemspec
111
49
  homepage: http://nominaltech.com
112
50
  licenses:
data/Vagrantfile DELETED
@@ -1,122 +0,0 @@
1
- # -*- mode: ruby -*-
2
- # vi: set ft=ruby :
3
-
4
- # Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
5
- VAGRANTFILE_API_VERSION = "2"
6
-
7
- Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8
- # All Vagrant configuration is done here. The most common configuration
9
- # options are documented and commented below. For a complete reference,
10
- # please see the online documentation at vagrantup.com.
11
-
12
- # Every Vagrant virtual environment requires a box to build off of.
13
- config.vm.box = "chef/debian-7.4"
14
-
15
- # Disable automatic box update checking. If you disable this, then
16
- # boxes will only be checked for updates when the user runs
17
- # `vagrant box outdated`. This is not recommended.
18
- # config.vm.box_check_update = false
19
-
20
- # Create a forwarded port mapping which allows access to a specific port
21
- # within the machine from a port on the host machine. In the example below,
22
- # accessing "localhost:8080" will access port 80 on the guest machine.
23
- # config.vm.network "forwarded_port", guest: 80, host: 8080
24
-
25
- # Create a private network, which allows host-only access to the machine
26
- # using a specific IP.
27
- # config.vm.network "private_network", ip: "192.168.33.10"
28
-
29
- # Create a public network, which generally matched to bridged network.
30
- # Bridged networks make the machine appear as another physical device on
31
- # your network.
32
- # config.vm.network "public_network"
33
-
34
- # If true, then any SSH connections made will enable agent forwarding.
35
- # Default value: false
36
- # config.ssh.forward_agent = true
37
-
38
- # Share an additional folder to the guest VM. The first argument is
39
- # the path on the host to the actual folder. The second argument is
40
- # the path on the guest to mount the folder. And the optional third
41
- # argument is a set of non-required options.
42
- # config.vm.synced_folder "../data", "/vagrant_data"
43
-
44
- # Provider-specific configuration so you can fine-tune various
45
- # backing providers for Vagrant. These expose provider-specific options.
46
- # Example for VirtualBox:
47
- #
48
- # config.vm.provider "virtualbox" do |vb|
49
- # # Don't boot with headless mode
50
- # vb.gui = true
51
- #
52
- # # Use VBoxManage to customize the VM. For example to change memory:
53
- # vb.customize ["modifyvm", :id, "--memory", "1024"]
54
- # end
55
- #
56
- # View the documentation for the provider you're using for more
57
- # information on available options.
58
-
59
- # Enable provisioning with CFEngine. CFEngine Community packages are
60
- # automatically installed. For example, configure the host as a
61
- # policy server and optionally a policy file to run:
62
- #
63
- # config.vm.provision "cfengine" do |cf|
64
- # cf.am_policy_hub = true
65
- # # cf.run_file = "motd.cf"
66
- # end
67
- #
68
- # You can also configure and bootstrap a client to an existing
69
- # policy server:
70
- #
71
- # config.vm.provision "cfengine" do |cf|
72
- # cf.policy_server_address = "10.0.2.15"
73
- # end
74
-
75
- # Enable provisioning with Puppet stand alone. Puppet manifests
76
- # are contained in a directory path relative to this Vagrantfile.
77
- # You will need to create the manifests directory and a manifest in
78
- # the file default.pp in the manifests_path directory.
79
- #
80
- # config.vm.provision "puppet" do |puppet|
81
- # puppet.manifests_path = "manifests"
82
- # puppet.manifest_file = "site.pp"
83
- # end
84
-
85
- # Enable provisioning with chef solo, specifying a cookbooks path, roles
86
- # path, and data_bags path (all relative to this Vagrantfile), and adding
87
- # some recipes and/or roles.
88
- #
89
- # config.vm.provision "chef_solo" do |chef|
90
- # chef.cookbooks_path = "../my-recipes/cookbooks"
91
- # chef.roles_path = "../my-recipes/roles"
92
- # chef.data_bags_path = "../my-recipes/data_bags"
93
- # chef.add_recipe "mysql"
94
- # chef.add_role "web"
95
- #
96
- # # You may also specify custom JSON attributes:
97
- # chef.json = { mysql_password: "foo" }
98
- # end
99
-
100
- # Enable provisioning with chef server, specifying the chef server URL,
101
- # and the path to the validation key (relative to this Vagrantfile).
102
- #
103
- # The Opscode Platform uses HTTPS. Substitute your organization for
104
- # ORGNAME in the URL and validation key.
105
- #
106
- # If you have your own Chef Server, use the appropriate URL, which may be
107
- # HTTP instead of HTTPS depending on your configuration. Also change the
108
- # validation key to validation.pem.
109
- #
110
- # config.vm.provision "chef_client" do |chef|
111
- # chef.chef_server_url = "https://api.opscode.com/organizations/ORGNAME"
112
- # chef.validation_key_path = "ORGNAME-validator.pem"
113
- # end
114
- #
115
- # If you're using the Opscode platform, your validator client is
116
- # ORGNAME-validator, replacing ORGNAME with your organization name.
117
- #
118
- # If you have your own Chef Server, the default validation client name is
119
- # chef-validator, unless you changed the configuration.
120
- #
121
- # chef.validation_client_name = "ORGNAME-validator"
122
- end
data/lib/shaddox/repo.rb DELETED
@@ -1,16 +0,0 @@
1
- module Shaddox
2
- class Repo
3
- attr_reader :url, :branch, :vcs, :shared
4
- def initialize(info)
5
- @info = info
6
- @url = info[:url]
7
- @branch = info[:branch] || 'master'
8
- @vcs = info[:vcs] || :git
9
- @shared = [info[:shared]].flatten || []
10
- end
11
-
12
- def to_source
13
- "Shaddox::Repo.new(#{@info.inspect})"
14
- end
15
- end
16
- end
@@ -1,42 +0,0 @@
1
- module Shaddox
2
- class Settings < Hash
3
- def method_missing(meth, *args, &blk)
4
- name = meth.to_s
5
-
6
- return evaluate(self[meth]) if name.size == 1
7
-
8
- # Ruby 1.8.7 doesn't let you do string[-1]
9
- key, suffix = name[0..-2].to_sym, name[-1..-1]
10
-
11
- case suffix
12
- when '='
13
- self[key] = args.first
14
- when '?'
15
- include? key
16
- when '!'
17
- raise Error, "Setting :#{key} is not set" unless include?(key)
18
- evaluate self[key]
19
- else
20
- evaluate self[meth]
21
- end
22
- end
23
-
24
- def evaluate(value)
25
- if value.is_a?(Proc)
26
- value.call
27
- else
28
- value
29
- end
30
- end
31
- end
32
- module SettingContainer
33
- def init_settings(default_settings = {})
34
- @settings = Settings.new.update(default_settings)
35
- end
36
-
37
- # Hook to loop up values in @info
38
- def method_missing(meth, *args, &blk)
39
- @settings.send meth, *args
40
- end
41
- end
42
- end
@@ -1,160 +0,0 @@
1
- class String
2
- def exp_path
3
- File.expand_path(self)
4
- end
5
- end
6
-
7
- module Shaddox
8
-
9
- class Shadow
10
- require 'fileutils'
11
- #include FileUtils
12
- def initialize(options, &block)
13
- @debug = options[:debug] || true # TODO: change to false for actual release
14
- @installer = options[:installer]
15
- @tmppath = options[:tmppath] || '/tmp/shaddox/'
16
- @required = true
17
- instance_eval(&block)
18
- end
19
-
20
- def optional(&block)
21
- @required = false
22
- instance_eval(&block)
23
- @required = true
24
- end
25
-
26
- def sh(command, args = nil)
27
- line = "#{command}"
28
- line += " #{args.join(" ")}" if args
29
- exec(line, :verbose => true)
30
- end
31
-
32
- def exec(command, opts = {:verbose => false})
33
- info "Running '#{command}' in '#{Dir.pwd}'", 1 if opts[:verbose] or @debug
34
- system(command)
35
- raise "#{line} failed" unless $? == 0 or !@required
36
- end
37
-
38
- def cd(path, &block)
39
- mkdir(path)
40
- FileUtils.cd(path.exp_path) do
41
- instance_eval(&block)
42
- end
43
- end
44
-
45
- def exists(path)
46
- system("test -e #{path.exp_path}")
47
- end
48
-
49
- def exists_d(path)
50
- system("test -d #{path.exp_path}")
51
- end
52
-
53
- def exists_f(path)
54
- system("test -f #{path.exp_path}")
55
- end
56
-
57
- def ln_s(source, dest, opts = {})
58
- ensure_parent_dir(source)
59
- ensure_parent_dir(dest)
60
- info "Linking '#{source.exp_path}' to '#{dest.exp_path}'", 1 if @debug
61
- FileUtils::ln_s(source.exp_path, dest.exp_path, opts)
62
- end
63
-
64
- def mkdir(path)
65
- info "Ensuring directory '#{path}' exists", 1 if @debug
66
- FileUtils::mkdir_p(path.exp_path)
67
- end
68
-
69
- def ensure_parent_dir(path)
70
- dir, base = File.split(path.exp_path)
71
- mkdir(dir)
72
- end
73
-
74
- def ensure_git()
75
- unless @git_installed
76
- install 'git'
77
- @git_installed = true
78
- end
79
- end
80
-
81
- def repo_deploy(repo_key, deploy_path, opts ={}, &in_deploy_path_block)
82
- keep_releases = opts[:keep_releases] || 5
83
- repo = @repos[repo_key]
84
-
85
- ensure_git()
86
- ensure_parent_dir(deploy_path)
87
- deploy_path = deploy_path.exp_path
88
-
89
- cd deploy_path do
90
-
91
- # Get the current release number
92
- release = 0
93
- cd 'releases' do
94
- current_max = Dir.entries('.').select { |e| e =~ /\d+/ }.max
95
- release = current_max.to_i + 1 if current_max
96
- end
97
-
98
- # Make a new release dir
99
- release_path = "./releases/#{release}"
100
-
101
- case repo.vcs
102
- when :git
103
- # Clone/update repo in vcs:
104
- info 'Updating the repository', 1 if @debug
105
- if exists_d('vcs')
106
- cd 'vcs' do
107
- exec "git fetch #{repo.url} #{repo.branch}:#{repo.branch} --force"
108
- end
109
- else
110
- exec "git clone #{repo.url} vcs --bare"
111
- end
112
- exec "git clone ./vcs #{release_path} --recursive --branch #{repo.branch}"
113
- end
114
-
115
- # Link shared paths
116
- info 'Linking shared paths', 1 if @debug
117
- repo.shared.each do |shared_path|
118
- ln_s "./shared/#{shared_path}", "#{release_path}/#{shared_path}"
119
- end
120
-
121
- # Link ./current to the latest release
122
- info 'Linking current to latest release', 1 if @debug
123
- ln_s release_path, './current'
124
- end
125
-
126
- cd deploy_path, &in_deploy_path_block if block_given?
127
- end
128
-
129
- def install(package)
130
- unless @installer
131
- # TODO: Try to autodetect package manager
132
- warn "No installer is specified for this target.", 1
133
- puts "-------------------"
134
- require 'highline/import'
135
- choose do |menu|
136
- menu.prompt = "Please select a package manager to use:"
137
-
138
- menu.choice(:apt) { @installer = :apt }
139
- menu.choice(:brew) { @installer = :brew }
140
- menu.choice(:pacman) { @installer = :pacman }
141
- end
142
- puts "-------------------"
143
- end
144
- raise "No installer specified for this target!" unless @installer
145
- info "Ensuring #{package} is installed with #{@installer}", 1 if @debug
146
- package_installed = lambda { system("type #{package} >/dev/null 2>&1") }
147
- unless package_installed.call()
148
- case @installer
149
- when :apt
150
- exec "sudo apt-get install -y #{package}"
151
- when :brew
152
- exec "brew install #{package}"
153
- when :pacman
154
- exec "pacman -S --noconfirm #{package}"
155
- end
156
- end
157
- raise "#{package} could not be installed." unless package_installed.call()
158
- end
159
- end
160
- end
@@ -1,61 +0,0 @@
1
- module Shaddox
2
- class ShadowScript
3
- attr_reader :script
4
- def initialize(config, task_key, opts = {})
5
- # Initialize properties
6
- @installer = opts[:installer]
7
- @debug = opts[:debug]
8
-
9
- @config = config
10
- @cast_tasks = []
11
-
12
- # Generate script
13
- params = []
14
- params.push(":installer => :#{@installer}") if @installer
15
- params.push(":debug => #{@debug}") if @debug
16
-
17
- @script = %Q{
18
- require 'shaddox'
19
- Shaddox::Shadow.new({#{params.join(',')}}) do
20
- ## begin generated shadow ##
21
- }
22
- add_repos
23
- cast(task_key)
24
- @script += %Q{
25
- ## end generated shadow ##
26
- end
27
- }
28
- end
29
-
30
- ## cast
31
- # Retrieves a task from the @config and ensures all of its dependencies
32
- # have been added to the script before adding itself. Tasks are only cast
33
- # once to elimate redundency.
34
- def cast(task_key)
35
- task = @config.tasks[task_key]
36
- if !task
37
- raise "The task :#{task_key} could not be found. Please check your Doxfile and try again.".red
38
- end
39
- task.deps.each do |dep_key|
40
- cast(dep_key) if !@cast_tasks.include? dep_key
41
- end
42
- @script += %Q{
43
- ## #{task_key} ##
44
- #{task.to_source}
45
- }
46
- @cast_tasks.push(task_key)
47
- end
48
-
49
- ## add_repos
50
- # Retrieves all repos from the @config and ensures their data is copied
51
- # to the script for use by tasks.
52
- def add_repos
53
- @script += %Q(
54
- @repos = {)
55
- @config.repos.each do |key, repo|
56
- @script += ":#{key} => #{repo.to_source}"
57
- end
58
- @script += %Q(})
59
- end
60
- end
61
- end
@@ -1,154 +0,0 @@
1
- module Shaddox
2
- class TargetError < StandardError ; end
3
- class Target
4
- def new_actor
5
- raise "new_actor method must be implemented by Target subclass"
6
- end
7
- def deploy(shadow_script, opts)
8
- tmpdir = opts[:tmpdir] || '/tmp/shaddox'
9
- shadow_script_path = "#{tmpdir}/shadow_script.rb"
10
- # Everything inside this block is handled by the target's actor (typically an SSH session)
11
- new_actor do
12
-
13
- rm_tmpdir = lambda {
14
- unless !exec("test -e #{tmpdir} >/dev/null")
15
- info "Removing #{tmpdir}", 1
16
- exec("rm -r #{tmpdir}")
17
- end
18
- }
19
-
20
- rm_tmpdir.call() if opts[:force]
21
-
22
- # Try to create tmpdir:
23
- info "Creating #{tmpdir}", 1
24
- unlocked = exec "mkdir #{tmpdir}"
25
-
26
- # Abort if the tmpdir already exists
27
- raise TargetError, "A shadow script is already running on this machine. Try again later." unless unlocked
28
-
29
- begin
30
- # Initial provisioning to ensure that we have everyting we need to execute a shadow script:
31
- ruby_installed = exec 'type ruby >/dev/null'
32
- raise TargetError, "Ruby is required to use shaddox. Please install it manually." unless ruby_installed
33
- gem_installed = exec 'type gem >/dev/null'
34
- raise TargetError, "Gem is required to use shaddox. Please install it manually." unless gem_installed
35
- shaddox_installed = lambda { exec 'gem list shaddox -i >/dev/null' }
36
- if shaddox_installed.call()
37
- info "Updating shaddox...", 1
38
- updated = exec "gem update shaddox", :verbose => false
39
- updated = exec "sudo gem update shaddox" unless updated
40
- warn "Shaddox could not be automatically updated. Please update it manually with 'gem update shaddox'.", 1 unless updated
41
- else
42
- info "Installing shaddox...", 1
43
- installed = exec "gem install shaddox", :verbose => false
44
- installed = exec "sudo gem install shaddox" unless installed
45
- warn "Shaddox could not be automatically installed. Please update it manually with 'gem update shaddox'.", 1 unless installed
46
- end
47
- unless shaddox_installed.call()
48
- raise TargetError, "Shaddox was not found on this target."
49
- end
50
-
51
- # Push the shadow script to tmpdir:
52
- info "Writing shadow script", 1
53
- write_file(shadow_script.script, shadow_script_path)
54
-
55
- # Execute the shadow script:
56
- info "Executing shadow script", 1
57
- raise TargetError, "Shadow script was not executed successfully." unless exec "ruby #{shadow_script_path}"
58
-
59
- rm_tmpdir.call() unless opts[:keep_tmp_dir]
60
- rescue Exception => e
61
- # Make sure the tmpdir is removed even if the provisioning fails:
62
- rm_tmpdir.call() unless opts[:keep_tmp_dir]
63
- raise e
64
- end
65
- end
66
- end
67
- end
68
-
69
- class Actor
70
- def initialize(&block)
71
- instance_eval(&block)
72
- end
73
- def exec(command, opts = {})
74
- raise "exec method must be implemented by Actor subclass"
75
- end
76
- def write_file(content, dest_path)
77
- raise "write_file method must be implemented by Actor subclass"
78
- end
79
- end
80
-
81
- class Localhost < Target
82
- def new_actor(&block)
83
- LocalActor.new(&block)
84
- end
85
- class LocalActor < Actor
86
- def exec(command, opts = {})
87
- system(command)
88
- end
89
- def write_file(content, dest_path)
90
- File.open(dest_path, 'w') { |f| f.write(content) }
91
- end
92
- end
93
- end
94
-
95
- class Server < Target
96
- include SettingContainer
97
- require 'net/ssh'
98
- # ###
99
- # Constructor for Server
100
- # @info param A hash containing the server's info. Allowed keys:
101
- # :host (required)
102
- # :user (required)
103
- # :ssh (required for authentication)
104
- # :installer
105
- #
106
- attr_reader :host, :user, :ssh, :installer
107
- def initialize(info)
108
- @host = info[:host]
109
- @user = info[:user]
110
- @ssh = info[:ssh]
111
- @installer = info[:installer]
112
- end
113
- def new_actor(&block)
114
- SSHActor.new(host, user, ssh, &block)
115
- end
116
- class SSHActor < Actor
117
- def initialize(host, user, ssh_opts, &block)
118
- Net::SSH.start(host, user, ssh_opts) do |ssh|
119
- @ssh = ssh
120
- super(&block)
121
- end
122
- end
123
- def exec(command, opts = {:verbose => true})
124
- require 'highline/import'
125
- exit_code = nil
126
- @ssh.open_channel do |channel|
127
- channel.request_pty do |c, success|
128
- raise "SSH could not obtain a pty." unless success
129
- channel.exec(command)
130
- channel.on_data do |c_, data|
131
- if data =~ /\[sudo\]/ || data =~ /Password/i
132
- warn "Target is asking for password: ", 1
133
- $stdout.print data
134
- pass = ask("") { |q| q.echo = false }
135
- channel.send_data "#{pass}\n"
136
- else
137
- $stdout.print data if opts[:verbose]
138
- end
139
- end
140
- channel.on_request('exit-status') do |ch, data|
141
- exit_code = data.read_long
142
- end
143
- end
144
- end
145
- @ssh.loop
146
- exit_code == 0 ? true : false
147
- end
148
- def write_file(content, dest_path)
149
- require 'shellwords'
150
- exec "echo #{Shellwords.shellescape(content)} > #{dest_path}"
151
- end
152
- end
153
- end
154
- end
data/push.sh DELETED
@@ -1,13 +0,0 @@
1
- #! /bin/sh
2
- #
3
- # install.sh
4
- # Copyright (C) 2014 joshglendenning <joshglendenning@Q.local>
5
- #
6
- # Distributed under terms of the MIT license.
7
- #
8
-
9
-
10
- gem build shaddox.gemspec
11
- gem push shaddox-*
12
- sudo gem install shaddox-*
13
- rm shaddox-*
data/scripts/bootstrap.sh DELETED
@@ -1,18 +0,0 @@
1
- #! /bin/bash
2
- #
3
- # bootstrap.sh
4
- # Copyright (C) 2014 josh <josh@ubuntu>
5
- #
6
- # Distributed under terms of the MIT license.
7
- #
8
-
9
- ensure_installed() {
10
- type $1 >/dev/null 2>&1 || { echo >&2 "$1 is required to use shaddox. Please install it manually."; exit 1; }
11
- }
12
-
13
- ensure_installed(ruby)
14
- ensure_installed(gem)
15
-
16
- if ! gem list shaddox -i; then
17
- gem install shaddox
18
- fi