uberinstaller 1.0.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.
- data/.gitignore +20 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +66 -0
- data/Rakefile +7 -0
- data/TODO +14 -0
- data/bin/uberinstaller +6 -0
- data/lib/uberinstaller.rb +24 -0
- data/lib/uberinstaller/cli.rb +51 -0
- data/lib/uberinstaller/commander.rb +112 -0
- data/lib/uberinstaller/config.rb +55 -0
- data/lib/uberinstaller/exception.rb +40 -0
- data/lib/uberinstaller/exceptions/command_not_processable.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_folder.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_json.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_local_package.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_package.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_ppa.rb +13 -0
- data/lib/uberinstaller/exceptions/invalid_url.rb +13 -0
- data/lib/uberinstaller/exceptions/json_file_not_found.rb +13 -0
- data/lib/uberinstaller/exceptions/json_parse_error.rb +13 -0
- data/lib/uberinstaller/exceptions/missing_local_package.rb +13 -0
- data/lib/uberinstaller/exceptions/missing_url.rb +13 -0
- data/lib/uberinstaller/exceptions/multiple_local_files_not_supported.rb +13 -0
- data/lib/uberinstaller/exceptions/multiple_repositories_not_supported.rb +13 -0
- data/lib/uberinstaller/exceptions/no_preprocessor_exception.rb +13 -0
- data/lib/uberinstaller/exceptions/parser_argument_error.rb +13 -0
- data/lib/uberinstaller/exceptions/wrong_architecture.rb +13 -0
- data/lib/uberinstaller/exceptions/wrong_version.rb +13 -0
- data/lib/uberinstaller/installer.rb +284 -0
- data/lib/uberinstaller/logger.rb +113 -0
- data/lib/uberinstaller/package_manager.rb +27 -0
- data/lib/uberinstaller/package_managers/apt.rb +18 -0
- data/lib/uberinstaller/package_managers/base.rb +87 -0
- data/lib/uberinstaller/package_managers/dpkg.rb +15 -0
- data/lib/uberinstaller/package_managers/git.rb +15 -0
- data/lib/uberinstaller/parser.rb +51 -0
- data/lib/uberinstaller/platform.rb +103 -0
- data/lib/uberinstaller/runner.rb +218 -0
- data/lib/uberinstaller/utils.rb +13 -0
- data/lib/uberinstaller/version.rb +3 -0
- data/uberinstaller.gemspec +35 -0
- metadata +243 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Edoardo Tenani
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
# Uberinstaller
|
2
|
+
|
3
|
+
Uberinstaller is a ruby gem that make easy to install system packages from a JSON configuration file.
|
4
|
+
Thinked for Ubuntu, can handle pre and post installation commands, repositories and PPA, package installation from system repositories, git repositories or local files.
|
5
|
+
|
6
|
+
Has support for different Package Managers as the one in use now can be modified and extended as needed.
|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Add this line to your application's Gemfile:
|
11
|
+
|
12
|
+
gem 'uberinstaller'
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install uberinstaller
|
21
|
+
|
22
|
+
Also, you need to have `sudo` installed and working on your machine to execute the uberinstaller executable and for every command launched from uberinstaller.
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
duplicates are overridden!
|
27
|
+
order is respected!
|
28
|
+
|
29
|
+
Architecture verification:
|
30
|
+
- system => leave to the system to handle architecture package version resolution
|
31
|
+
- i386 => can be run only on 32 bit systems
|
32
|
+
- x86_64 => can be run only on 64 bit systems
|
33
|
+
|
34
|
+
Version verification:
|
35
|
+
- codename of OS ( precise on ubuntu )
|
36
|
+
|
37
|
+
Installation type:
|
38
|
+
- system
|
39
|
+
- git
|
40
|
+
- local
|
41
|
+
- json ( no extension )
|
42
|
+
|
43
|
+
Command before/after:
|
44
|
+
- in the right folder: cmds/after/ cmds/before/, so specify only the filename, with extension
|
45
|
+
- array of commands
|
46
|
+
- a single command in a string
|
47
|
+
|
48
|
+
before all => cmds/before/all.sh
|
49
|
+
after all => cmds/after/all.sh
|
50
|
+
|
51
|
+
Blocking package configuration as Debconf in Debian system must be properly avoided ( APT Package Manager use gnome DEBIAN_FRONTEND to avoid apt-get hangs)
|
52
|
+
|
53
|
+
## Docs
|
54
|
+
|
55
|
+
http://rubydoc.info/docs/yard/file/docs/GettingStarted.md
|
56
|
+
http://rubydoc.info/docs/yard/file/docs/Tags.md
|
57
|
+
|
58
|
+
http://gorails.com/setup/ubuntu
|
59
|
+
|
60
|
+
## Contributing
|
61
|
+
|
62
|
+
1. Fork it
|
63
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
64
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
65
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
66
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/TODO
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
☐ add JSON schema validation https://github.com/hoxworth/json-schema
|
2
|
+
☐ installation advanced option ( install with dpkg for local install, --force-architecture )
|
3
|
+
☐ README need refactoring
|
4
|
+
☐ support {version} and {arch} in ppa/pkg strings
|
5
|
+
☐ add repository support, not only ppa
|
6
|
+
☐ check for superuser!
|
7
|
+
☐ add progress bar for multiple packages installation
|
8
|
+
|
9
|
+
|
10
|
+
___________________
|
11
|
+
Archive:
|
12
|
+
✔ multiple "recipe" inclusion in recipe @done (13-07-17 02:44)
|
13
|
+
✘ preseeding @cancelled (13-07-17 01:43)
|
14
|
+
✔ use proper debian frontend to avoid hangs @done (13-07-17 01:43)
|
data/bin/uberinstaller
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uberinstaller/version'
|
4
|
+
require 'uberinstaller/config'
|
5
|
+
|
6
|
+
require 'uberinstaller/commander'
|
7
|
+
require 'uberinstaller/exception'
|
8
|
+
require 'uberinstaller/installer'
|
9
|
+
require 'uberinstaller/platform'
|
10
|
+
require 'uberinstaller/package_manager'
|
11
|
+
require 'uberinstaller/parser'
|
12
|
+
require 'uberinstaller/runner'
|
13
|
+
|
14
|
+
|
15
|
+
module Uberinstaller
|
16
|
+
# Create a new instance of the Runner class in an easy way
|
17
|
+
#
|
18
|
+
# @param [String] file
|
19
|
+
# the path of the JSON configuration file
|
20
|
+
def self.new(file)
|
21
|
+
puts "#{Config.app_name} - v#{Config.app_version}"
|
22
|
+
Uberinstaller::Runner.new file
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'logger'
|
4
|
+
require 'thor'
|
5
|
+
|
6
|
+
module Uberinstaller
|
7
|
+
class Cli < Thor
|
8
|
+
default_task :help
|
9
|
+
|
10
|
+
# Main Uberinstaller installation command.
|
11
|
+
#
|
12
|
+
# @param file [String] the JSON file with package informations
|
13
|
+
#
|
14
|
+
# Exit status:
|
15
|
+
# - 0 => Execution has been done as expected
|
16
|
+
# - 127 => An error stopped execution
|
17
|
+
desc "install FILE", "Install packages from the specified JSON FILE"
|
18
|
+
method_option :verbose,
|
19
|
+
:type => :boolean,
|
20
|
+
:default => false,
|
21
|
+
:aliases => "-v",
|
22
|
+
:desc => "Enable verbose output"
|
23
|
+
method_option :debug,
|
24
|
+
:type => :boolean,
|
25
|
+
:default => false,
|
26
|
+
:aliases => "-d",
|
27
|
+
:desc => "Enable debug output, include verbose option"
|
28
|
+
method_option :dry_run,
|
29
|
+
:type => :boolean,
|
30
|
+
:default => false,
|
31
|
+
:desc => "Enable dry run, no modification to the system will be made during this execution"
|
32
|
+
def install(file)
|
33
|
+
Uberinstaller::Loggable.level = Logger::WARN
|
34
|
+
Uberinstaller::Loggable.level = Logger::INFO if options[:verbose]
|
35
|
+
Uberinstaller::Loggable.level = Logger::DEBUG if options[:debug]
|
36
|
+
|
37
|
+
Uberinstaller::Loggable.log_path = File.join(File.dirname(file), 'log', "#{Time.now}.log") unless options[:debug]
|
38
|
+
|
39
|
+
Uberinstaller::Config.uberdirectory = File.dirname file
|
40
|
+
Uberinstaller::Config.dry_run = options[:dry_run]
|
41
|
+
|
42
|
+
begin
|
43
|
+
runner = Uberinstaller.new file
|
44
|
+
runner.preprocess
|
45
|
+
runner.install
|
46
|
+
rescue Uberinstaller::Exception::WrongVersion, Uberinstaller::Exception::WrongArchitecture => e
|
47
|
+
exit(127)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uberinstaller/config'
|
4
|
+
require 'uberinstaller/exception'
|
5
|
+
require 'uberinstaller/logger'
|
6
|
+
|
7
|
+
module Uberinstaller
|
8
|
+
|
9
|
+
# Execute user defined command before and after installation
|
10
|
+
class Commander
|
11
|
+
include Loggable
|
12
|
+
|
13
|
+
# @!attribute [String] pkg_name
|
14
|
+
# The name of the package being processed
|
15
|
+
# @!attribute [Hash] pkg
|
16
|
+
# an Hash rapresenting a package to be installed
|
17
|
+
attr_reader :pkg_name, :pkg
|
18
|
+
|
19
|
+
# Initialize the Commander class with the package information
|
20
|
+
#
|
21
|
+
# @param pkg_name [String] the name of the package
|
22
|
+
# @param pkg [Hash] the content of the package
|
23
|
+
def initialize(pkg_name, pkg)
|
24
|
+
@pkg_name = pkg_name
|
25
|
+
@pkg = pkg
|
26
|
+
|
27
|
+
@after_cmd_path = File.join Config.command_path, 'after'
|
28
|
+
@before_cmd_path = File.join Config.command_path, 'before'
|
29
|
+
end
|
30
|
+
|
31
|
+
# Execute after installation command
|
32
|
+
def after
|
33
|
+
if @pkg.has_key? :cmd and @pkg[:cmd].has_key? :after
|
34
|
+
logger.info "Executing after commands..."
|
35
|
+
run :after
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Execute after installation command
|
40
|
+
def before
|
41
|
+
if @pkg.has_key? :cmd and @pkg[:cmd].has_key? :before
|
42
|
+
logger.info "Executing before commands..."
|
43
|
+
run :before
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Execute a command in a subprocess
|
50
|
+
#
|
51
|
+
# All commands will be executed using `sudo`
|
52
|
+
#
|
53
|
+
# @param command [String] the command to be executed
|
54
|
+
def exec(command)
|
55
|
+
command = "sudo #{command}"
|
56
|
+
logger.debug "Executing command: #{command}"
|
57
|
+
|
58
|
+
unless Config.dry_run
|
59
|
+
Open3.popen3(command) { |stdin, stdout, stderr, wait_thr|
|
60
|
+
pid = wait_thr.pid # pid of the started process.
|
61
|
+
logger.debug "Running pid: #{pid}"
|
62
|
+
|
63
|
+
logger.debug stdout.readlines
|
64
|
+
|
65
|
+
exit_status = wait_thr.value.to_i # Process::Status object returned.
|
66
|
+
logger.debug "Exit status: #{exit_status}"
|
67
|
+
unless exit_status == 0
|
68
|
+
logger.error 'Some error happended during execution:'
|
69
|
+
logger.error stderr.readlines
|
70
|
+
end
|
71
|
+
}
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Execute the specified file
|
76
|
+
#
|
77
|
+
# Passes the file to the `exec` function
|
78
|
+
#
|
79
|
+
# @param file [String] the path to the file to be executed
|
80
|
+
def exec_file(file)
|
81
|
+
exec "#{file}"
|
82
|
+
end
|
83
|
+
|
84
|
+
# Execute the specified action
|
85
|
+
#
|
86
|
+
# Currently available actions are: :after, :before
|
87
|
+
#
|
88
|
+
# @param type [Symbol] a symbol rapresenting an action to be performed
|
89
|
+
def run(type)
|
90
|
+
file = (type == :after) ? File.join(@after_cmd_path, @pkg[:cmd][type]) : File.join(@before_cmd_path, @pkg[:cmd][type])
|
91
|
+
|
92
|
+
logger.debug @pkg[:cmd][type]
|
93
|
+
logger.debug 'is array : ' + (@pkg[:cmd][type].kind_of? Array).to_s
|
94
|
+
logger.debug 'is string : ' + (@pkg[:cmd][type].kind_of? String).to_s
|
95
|
+
logger.debug 'file exists : ' + (File.exists? file).to_s if @pkg[:cmd][type].kind_of? String
|
96
|
+
|
97
|
+
if @pkg[:cmd][type].kind_of? Array
|
98
|
+
@pkg[:cmd][type].each do |cmd|
|
99
|
+
exec cmd
|
100
|
+
end
|
101
|
+
elsif @pkg[:cmd][type].kind_of? String
|
102
|
+
if File.exists? file
|
103
|
+
exec_file file
|
104
|
+
else
|
105
|
+
exec @pkg[:cmd][type]
|
106
|
+
end
|
107
|
+
else
|
108
|
+
raise Exception::CommandNotProcessable, @pkg_name, type
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uberinstaller/version'
|
4
|
+
|
5
|
+
module Uberinstaller
|
6
|
+
|
7
|
+
# Shared configuration for Uberinstaller
|
8
|
+
module Config
|
9
|
+
class << self
|
10
|
+
attr_accessor :dry_run, :local_package_manager, :remote_package_manager, :uberdirectory
|
11
|
+
|
12
|
+
attr_reader :app_name, :app_version
|
13
|
+
|
14
|
+
def command_path
|
15
|
+
@command_path ||= File.join @uberdirectory, 'cmds'
|
16
|
+
end
|
17
|
+
def local_pkg_path
|
18
|
+
@local_pkg_path ||= File.join @uberdirectory, 'pkgs'
|
19
|
+
end
|
20
|
+
def json_path
|
21
|
+
@json_path ||= File.join @uberdirectory, 'json'
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# @!attribute [rw] uberdirectory
|
26
|
+
# absolute path to the folder in which the JSON file is located and in which every other installation script must be located
|
27
|
+
@uberdirectory = nil
|
28
|
+
# @!attribute [r] command_path
|
29
|
+
@command_path = nil
|
30
|
+
# @!attribute [r] local_pkg_path
|
31
|
+
# absolute path in which local package for the configuration file are found
|
32
|
+
@local_pkg_path = nil
|
33
|
+
# @!attribute [r] json_path
|
34
|
+
# absolute path in which locate json file to be imported in configuration
|
35
|
+
@local_pkg_path = nil
|
36
|
+
|
37
|
+
# @!attribute [rw] remote_package_manager
|
38
|
+
# the package manager used to install system type packages
|
39
|
+
@remote_package_manager = 'Apt'
|
40
|
+
# @!attribute [rw] local_package_manager
|
41
|
+
# the package manager used to install local type packages
|
42
|
+
@local_package_manager = 'Dpkg'
|
43
|
+
|
44
|
+
# @!attribute [rw] dry_run
|
45
|
+
# prevent real execution of commands enabling a dummy execution for test and debug purposes
|
46
|
+
@dry_run = false
|
47
|
+
|
48
|
+
# @!attribute [r] app_name
|
49
|
+
# Application name
|
50
|
+
@app_name = "UberInstaller"
|
51
|
+
# @!attribute [r] app_version
|
52
|
+
# Application version
|
53
|
+
@app_version = VERSION
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require 'uberinstaller/logger'
|
4
|
+
|
5
|
+
module Uberinstaller
|
6
|
+
module Exception
|
7
|
+
class Exception < StandardError
|
8
|
+
include Loggable
|
9
|
+
|
10
|
+
attr :parent
|
11
|
+
|
12
|
+
def initialize(parent, print = true)
|
13
|
+
@parent = parent
|
14
|
+
logger.fatal parent if print
|
15
|
+
super parent
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# When :pkg for a :type => :local package is not a String
|
20
|
+
class MultipleLocalFileNotSupported < Exception; end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'uberinstaller/exceptions/command_not_processable'
|
25
|
+
require 'uberinstaller/exceptions/invalid_folder'
|
26
|
+
require 'uberinstaller/exceptions/invalid_json'
|
27
|
+
require 'uberinstaller/exceptions/invalid_local_package'
|
28
|
+
require 'uberinstaller/exceptions/invalid_package'
|
29
|
+
require 'uberinstaller/exceptions/invalid_ppa'
|
30
|
+
require 'uberinstaller/exceptions/invalid_url'
|
31
|
+
require 'uberinstaller/exceptions/json_file_not_found'
|
32
|
+
require 'uberinstaller/exceptions/json_parse_error'
|
33
|
+
require 'uberinstaller/exceptions/missing_local_package'
|
34
|
+
require 'uberinstaller/exceptions/multiple_local_files_not_supported'
|
35
|
+
require 'uberinstaller/exceptions/multiple_repositories_not_supported'
|
36
|
+
require 'uberinstaller/exceptions/missing_url'
|
37
|
+
require 'uberinstaller/exceptions/no_preprocessor_exception'
|
38
|
+
require 'uberinstaller/exceptions/parser_argument_error'
|
39
|
+
require 'uberinstaller/exceptions/wrong_architecture'
|
40
|
+
require 'uberinstaller/exceptions/wrong_version'
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
module Uberinstaller
|
4
|
+
module Exception
|
5
|
+
|
6
|
+
# When a package as an unknown command ( is not a string nor an array )
|
7
|
+
class CommandNotProcessable < Exception
|
8
|
+
def initialize(name, type)
|
9
|
+
super "#{name}'s #{type} command is not proccessable, as it is of unknown type"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|