uberinstaller 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|