pixiebox 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.
Files changed (74) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +4 -0
  4. data/DOCKER_INFO.md +3 -0
  5. data/Gemfile +4 -0
  6. data/Guardfile +47 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +146 -0
  9. data/Rakefile +6 -0
  10. data/bin/console +14 -0
  11. data/bin/pixiebox +5 -0
  12. data/bin/pixiebox_dev +10 -0
  13. data/bin/rake +17 -0
  14. data/bin/setup +8 -0
  15. data/lib/pixiebox.rb +88 -0
  16. data/lib/pixiebox/box.rb +31 -0
  17. data/lib/pixiebox/boxes/installer.rb +55 -0
  18. data/lib/pixiebox/boxes/manifest.rb +59 -0
  19. data/lib/pixiebox/cli.rb +214 -0
  20. data/lib/pixiebox/commands/add_box.rb +25 -0
  21. data/lib/pixiebox/commands/add_service.rb +27 -0
  22. data/lib/pixiebox/commands/build_service.rb +23 -0
  23. data/lib/pixiebox/commands/download_docker.rb +35 -0
  24. data/lib/pixiebox/commands/finish_install.rb +16 -0
  25. data/lib/pixiebox/commands/finish_uninstall.rb +14 -0
  26. data/lib/pixiebox/commands/get_root_permission.rb +14 -0
  27. data/lib/pixiebox/commands/initialize_project.rb +32 -0
  28. data/lib/pixiebox/commands/install_config.rb +17 -0
  29. data/lib/pixiebox/commands/install_docker.rb +55 -0
  30. data/lib/pixiebox/commands/list_boxes.rb +16 -0
  31. data/lib/pixiebox/commands/list_services.rb +16 -0
  32. data/lib/pixiebox/commands/reload_shell.rb +15 -0
  33. data/lib/pixiebox/commands/remove_service.rb +27 -0
  34. data/lib/pixiebox/commands/remove_setup_shell.rb +19 -0
  35. data/lib/pixiebox/commands/restart.rb +21 -0
  36. data/lib/pixiebox/commands/setup_shell.rb +18 -0
  37. data/lib/pixiebox/commands/ssh_instance.rb +27 -0
  38. data/lib/pixiebox/commands/start.rb +20 -0
  39. data/lib/pixiebox/commands/start_install.rb +14 -0
  40. data/lib/pixiebox/commands/start_uninstall.rb +16 -0
  41. data/lib/pixiebox/commands/stop.rb +20 -0
  42. data/lib/pixiebox/commands/update_packages.rb +46 -0
  43. data/lib/pixiebox/constants.rb +26 -0
  44. data/lib/pixiebox/dns.rb +8 -0
  45. data/lib/pixiebox/docker_compose/config.rb +59 -0
  46. data/lib/pixiebox/errors/pixiebox_error.rb +17 -0
  47. data/lib/pixiebox/handlers/stdout_handler.rb +179 -0
  48. data/lib/pixiebox/os/abstract.rb +40 -0
  49. data/lib/pixiebox/os/current_os.rb +15 -0
  50. data/lib/pixiebox/os/darwin.rb +20 -0
  51. data/lib/pixiebox/os/distro.rb +45 -0
  52. data/lib/pixiebox/os/linux.rb +21 -0
  53. data/lib/pixiebox/os/unsupported_os.rb +9 -0
  54. data/lib/pixiebox/project.rb +19 -0
  55. data/lib/pixiebox/service.rb +50 -0
  56. data/lib/pixiebox/services/installer.rb +41 -0
  57. data/lib/pixiebox/services/manifest.rb +50 -0
  58. data/lib/pixiebox/shell/bash.rb +18 -0
  59. data/lib/pixiebox/shell/ini_file.rb +38 -0
  60. data/lib/pixiebox/shell/startup_script.rb +53 -0
  61. data/lib/pixiebox/shell/zsh.rb +9 -0
  62. data/lib/pixiebox/system.rb +69 -0
  63. data/lib/pixiebox/utils/domain_event_publisher.rb +11 -0
  64. data/lib/pixiebox/utils/output.rb +105 -0
  65. data/lib/pixiebox/utils/packages.rb +35 -0
  66. data/lib/pixiebox/utils/progress_bar.rb +31 -0
  67. data/lib/pixiebox/utils/project.rb +55 -0
  68. data/lib/pixiebox/utils/shell.rb +18 -0
  69. data/lib/pixiebox/utils/spinner.rb +27 -0
  70. data/lib/pixiebox/utils/visitable.rb +9 -0
  71. data/lib/pixiebox/utils/visitor_by_os.rb +32 -0
  72. data/lib/runner.rb +51 -0
  73. data/pixiebox.gemspec +52 -0
  74. metadata +424 -0
@@ -0,0 +1,9 @@
1
+ module Pixiebox
2
+ module Os
3
+ class UnsupportedOs < Abstract
4
+ class << self
5
+ def to_s() :unsupported end
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,19 @@
1
+ module Pixiebox
2
+ class Project
3
+ include Utils::Visitable
4
+ include Utils::Output
5
+
6
+ attr_reader :os
7
+
8
+ def initialize(os)
9
+ @os = os
10
+ end
11
+
12
+ def init
13
+ accept(Commands::InitializeProject.new)
14
+ rescue StandardError => e
15
+ display_error e
16
+ exit 1
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,50 @@
1
+ module Pixiebox
2
+ class Service
3
+ include Utils::Visitable
4
+ include Utils::Output
5
+
6
+ attr_reader :os
7
+
8
+ def initialize(os)
9
+ @os = os
10
+ end
11
+
12
+ def build(service=nil)
13
+ accept(Commands::BuildService.new(service))
14
+ rescue StandardError => e
15
+ display_error e
16
+ exit 1
17
+ end
18
+
19
+ def add(services)
20
+ services.each { |service| accept(Commands::AddService.new(service)) }
21
+ accept(Commands::Restart.new)
22
+ rescue StandardError => e
23
+ display_error e
24
+ exit 1
25
+ end
26
+
27
+
28
+ def remove(type = nil)
29
+ return if type.nil?
30
+ accept(Commands::RemoveService.new(type))
31
+ accept(Commands::Restart.new)
32
+ rescue Errors::ServiceNotInstalled
33
+ display_service_not_installed type
34
+ rescue Errors::ServiceNotImplemented
35
+ display_service_not_available type
36
+ rescue StandardError => e
37
+ display_error e
38
+ exit 1
39
+ end
40
+
41
+
42
+ def list()
43
+ accept(Commands::UpdatePackages.new)
44
+ accept(Commands::ListServices.new)
45
+ rescue StandardError => e
46
+ display_error e
47
+ exit 1
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,41 @@
1
+ module Pixiebox
2
+ module Services
3
+ class Installer
4
+ include Utils::Output
5
+
6
+ def initialize(os)
7
+ @os = os
8
+ end
9
+
10
+
11
+ def install(type)
12
+ @manifest = Manifest.new(os, type)
13
+ @manifest.check! # raises an exception if we can't find the type in the manifest
14
+
15
+ config = DockerCompose::Config.new manifest.docker_compose_file
16
+ config.add_service manifest.service, manifest.service_links
17
+
18
+ config.save
19
+ display_status 'modify', manifest.docker_compose_file
20
+ display_status 'info', "hostname '#{manifest.service_name}' is visible to other services", :yellow
21
+ display_status 'info', manifest.post_install_instructions, :yellow
22
+ end
23
+
24
+
25
+ def uninstall(type)
26
+ @manifest = Manifest.new(os, type)
27
+
28
+ config = DockerCompose::Config.new manifest.docker_compose_file
29
+ config.check!(type) # raises an exception if we can't find the type currently installed
30
+
31
+ config.remove_service manifest.service
32
+
33
+ config.save
34
+ display_status 'modify', manifest.docker_compose_file
35
+ end
36
+
37
+ private
38
+ attr_reader :os, :manifest
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ module Pixiebox
2
+ module Services
3
+ class Manifest
4
+ def initialize(os, type = nil)
5
+ @os, @type = os, type
6
+ end
7
+
8
+ def list
9
+ result = Dir.glob("#{os.service_packages_dir}/*").select {|f| File.directory? f}
10
+ result.map {|r| strip_path(r) }.sort!
11
+ end
12
+
13
+
14
+ def package_contents
15
+ @package_contents ||= Dir.glob(File.join(service, "*"))
16
+ end
17
+
18
+
19
+ def check!
20
+ (raise Errors::ServiceNotImplemented, type) unless list.include?(type)
21
+ end
22
+
23
+ def docker_compose_file () "#{os.project_root}/docker-compose.yml" end
24
+ def service_name() (package.keys - ['links', 'instructions']).first end
25
+
26
+ def service () slice(package, service_name) end
27
+ def service_links() slice(package, 'links')['links'] end
28
+ def post_install_instructions() slice(package, 'instructions')['instructions'] end
29
+
30
+ private
31
+ attr_reader :os, :type
32
+
33
+ def package
34
+ @package ||= YAML.load_file("#{package_dir}/config.yml")
35
+ end
36
+
37
+ def package_dir
38
+ "#{os.service_packages_dir}/#{type}"
39
+ end
40
+
41
+ def strip_path(file)
42
+ file.split('/').last
43
+ end
44
+
45
+ def slice(hash, *keys)
46
+ Hash[ [keys, hash.values_at(*keys)].transpose]
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,18 @@
1
+ module Pixiebox
2
+ module Shell
3
+ class Bash < StartupScript
4
+ def filename
5
+ [
6
+ '.bashrc',
7
+ '.bash_profile',
8
+ '.bash_login',
9
+ '.profile'
10
+ ].map do |script|
11
+ Pathname.new("#{os.home_dir}/#{script}")
12
+ end.select do |file|
13
+ file.exist?
14
+ end.first.to_path
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,38 @@
1
+ module Pixiebox
2
+ module Shell
3
+ class IniFile
4
+ class << self
5
+ def get(os)
6
+ self.new(os)
7
+ end
8
+ end
9
+
10
+ def initialize(os)
11
+ @os = os
12
+ end
13
+
14
+ def install
15
+ TTY::File.create_file filename do |content|
16
+ "[packages]\nversion=v0.0\nlast_update=#{Time.now.to_i}\n"
17
+ end unless File.exist? filename
18
+ end
19
+
20
+
21
+ def [](key)
22
+ ini_file[key]
23
+ end
24
+
25
+
26
+ def []=(section, value)
27
+ ini_file[section.to_s] = value
28
+ ini_file.save
29
+ end
30
+
31
+ private
32
+ attr_reader :os
33
+
34
+ def filename() "#{os.config_dir}/#{Pixiebox::PIXIEBOX_INI}" end
35
+ def ini_file() @ini_file ||= ::IniFile.load(filename) end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,53 @@
1
+ module Pixiebox
2
+ module Shell
3
+ class StartupScript
4
+ class << self
5
+ def get(os)
6
+ case "#{os.user_shell}:#{os.to_s}"
7
+ when /\/bin\/bash:darwin/, /\/bin\/bash:linux/
8
+ Shell::Bash.new(os)
9
+ when /\/bin\/zsh:darwin/, /\/bin\/zsh:linux/
10
+ Shell::Zsh.new(os)
11
+ else
12
+ raise Errors::ShellNotSupported, "#{os.user_shell}:#{os.to_s}"
13
+ end
14
+ end
15
+ end
16
+
17
+ attr_reader :os
18
+
19
+ def initialize(os)
20
+ @os = os
21
+ end
22
+
23
+ def install_extensions
24
+ source = "#{os.extensions_dir}/extensions.bash"
25
+ dest = os.shell_extensions
26
+
27
+ TTY::File.copy_file source, dest
28
+
29
+ TTY::File.append_to_file(
30
+ filename,
31
+ "\n#{extension}\n"
32
+ )
33
+ end
34
+
35
+
36
+ def uninstall_extensions
37
+ TTY::File.gsub_file filename, /#{Regexp.escape(extension)}/ do
38
+ "# pixiebox removed #{Time.now}"
39
+ end
40
+ end
41
+
42
+
43
+ def filename
44
+ raise ::NotImplementedError, 'must have filename'
45
+ end
46
+
47
+ private
48
+ def extension
49
+ "# added by pixiebox\nsource #{os.shell_extensions}"
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,9 @@
1
+ module Pixiebox
2
+ module Shell
3
+ class Zsh < StartupScript
4
+ def filename
5
+ "#{os.home_dir}/.zshrc"
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,69 @@
1
+ module Pixiebox
2
+ class System
3
+ include Utils::Visitable
4
+ include Utils::Output
5
+
6
+ attr_reader :os
7
+
8
+ def initialize(os)
9
+ @os = os
10
+ end
11
+
12
+ def install
13
+ accept(Commands::StartInstall.new)
14
+ accept(Commands::GetRootPermission.new)
15
+ accept(Commands::DownloadDocker.new)
16
+ accept(Commands::InstallDocker.new)
17
+ accept(Commands::InstallConfig.new)
18
+ accept(Commands::UpdatePackages.new)
19
+ accept(Commands::SetupShell.new)
20
+ accept(Commands::FinishInstall.new)
21
+ accept(Commands::ReloadShell.new)
22
+ rescue StandardError => e
23
+ display_error e
24
+ exit 1
25
+ end
26
+
27
+
28
+ def uninstall
29
+ accept(Commands::StartUninstall.new)
30
+ accept(Commands::RemoveSetupShell.new)
31
+ accept(Commands::FinishUninstall.new)
32
+ rescue StandardError => e
33
+ display_error e
34
+ exit 1
35
+ end
36
+
37
+
38
+ def start
39
+ accept(Commands::Start.new)
40
+ rescue StandardError => e
41
+ display_error e
42
+ exit 1
43
+ end
44
+
45
+
46
+ def stop
47
+ accept(Commands::Stop.new)
48
+ rescue StandardError => e
49
+ display_error e
50
+ exit 1
51
+ end
52
+
53
+
54
+ def restart
55
+ accept(Commands::Restart.new)
56
+ rescue StandardError => e
57
+ display_error e
58
+ exit 1
59
+ end
60
+
61
+
62
+ def ssh(service)
63
+ accept(Commands::SshInstance.new(service))
64
+ rescue StandardError => e
65
+ display_error e
66
+ exit 1
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,11 @@
1
+ module Pixiebox
2
+ module Utils
3
+ module DomainEventPublisher
4
+ include Wisper::Publisher
5
+
6
+ def publish_event(event_name, *event_params)
7
+ broadcast(event_name, *event_params)
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,105 @@
1
+ module Pixiebox
2
+ module Utils
3
+ module Output
4
+ def display_line(line)
5
+ thor.say line
6
+ end
7
+
8
+
9
+ def display_info(info, color=nil)
10
+ thor.say " #{info}", color
11
+ end
12
+
13
+
14
+ def display_status(status, line, log_status=true)
15
+ return if line.nil? || line.strip == ""
16
+ thor.say_status status, line, log_status
17
+ end
18
+
19
+
20
+ def display_error(e)
21
+ case e
22
+ when Errors::ProjectNotInitialized
23
+ display_project_not_initialized
24
+ when Errors::DockerError
25
+ display_docker_error
26
+ when Errors::SystemDownError
27
+ display_system_down
28
+ when Errors::ShellNotSupported
29
+ display_shell_not_supported e.message
30
+ when Errors::DistroNotSupported
31
+ display_distro_not_supported
32
+ when Errors::PixieboxNotInstalled
33
+ display_pixiebox_not_installed
34
+ when Errors::ServiceNotImplemented
35
+ display_service_not_available e.message
36
+ when Pixiebox::Errors::FileNotFoundError
37
+ display_file_not_found e.message
38
+ else
39
+ display_info(e, :red)
40
+ end
41
+ end
42
+
43
+ private
44
+ def display_project_not_initialized
45
+ display_status('error', 'no project found', :red)
46
+ display_info("Run 'pixiebox init [BOX]'", :yellow)
47
+ end
48
+
49
+
50
+ def display_box_not_available(type)
51
+ display_status('error', "#{type.capitalize} boxes are not available...yet", :red)
52
+ end
53
+
54
+
55
+ def display_service_not_available(type)
56
+ display_status('error', "#{type} service is not available...yet", :red)
57
+ end
58
+
59
+
60
+ def display_file_not_found(message)
61
+ display_status('error', message, :red)
62
+ end
63
+
64
+
65
+ def display_system_down
66
+ display_info("Pixiebox is not running!", :red)
67
+ end
68
+
69
+
70
+ def display_service_not_installed(type)
71
+ display_status('info', "#{type} not installed", :yellow)
72
+ end
73
+
74
+ def display_shell_not_supported(type)
75
+ display_status('error', "shell not supported #{type}", :red)
76
+ display_line ''
77
+
78
+ display_line "You can file a request at: #{Pixiebox::HOMEPAGE}"
79
+ display_line "and we'll get right on it!"
80
+ display_line ''
81
+ end
82
+
83
+ def display_pixiebox_not_installed
84
+ display_info "Pixiebox not installed!", :red
85
+ display_info "Run: pixiebox install", :yellow
86
+ end
87
+
88
+
89
+ def display_distro_not_supported
90
+ display_info('distro is not yet supported :(', :red)
91
+ end
92
+
93
+ def display_docker_error
94
+ display_info "Docker gave an error", :red
95
+ display_info "Check to see if docker is running", :red
96
+ display_info("Try running 'docker ps'", :yellow)
97
+ end
98
+
99
+ private
100
+ def thor
101
+ @thor ||= Thor::Shell::Color.new
102
+ end
103
+ end
104
+ end
105
+ end