islo 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b73d49fca1c9bbc70e94c8127f312cfa7710d435
4
+ data.tar.gz: 61ab656bc1d910a4d59036e0dd13add441a2da3b
5
+ SHA512:
6
+ metadata.gz: 016bb45985d99b0814010a4719aa124701d4675c4c2ef74098150a32ae13ff4c628eb677cdb9908a1b5577d9c86c38116a77a02b73079e05fb8f81cb99f07fcf
7
+ data.tar.gz: d60f682ee982622d098294b0052efec9554f398b12ab136ab4237c7f2d8617eff6d907da1d023eb48a23e4229e445434761a5ec3801f003920c8de3fb9ecf61b
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2014 Loic Nageleisen
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,74 @@
1
+ # Islo - Self-contained apps
2
+
3
+ Make apps completely self-contained by abstracting service process settings and execution.
4
+
5
+ ## Quick, show me how to use my favorite daemon!
6
+
7
+ First, install Islo:
8
+
9
+ ```
10
+ $ gem install islo
11
+ ```
12
+
13
+ Then, a nice example might be worth a thousand words, so here goes:
14
+
15
+ ### MySQL or MariaDB
16
+
17
+ ```
18
+ $ islo mysql_install_db # creates database in db/mysql
19
+ $ islo mysqld # starts server without daemonizing[^1]
20
+ $ islo mysql # connects to running server via unix socket in tmp/sockets
21
+ ```
22
+
23
+ ### Redis
24
+
25
+ ```
26
+ $ islo redis-init # creates directory in db/redis
27
+ $ islo redis-server # starts server without daemonizing[^1]
28
+ $ islo redis-cli # connects to server via unix socket in tmp/sockets
29
+ ```
30
+
31
+ ### PostgreSQL
32
+
33
+ ```
34
+ $ islo initdb # creates directory in db/postgres
35
+ $ islo postgres # starts server without daemonizing[^1]
36
+ $ islo psql # connects to server via unix socket in tmp/sockets
37
+ ```
38
+
39
+ [^1]: Best used in a [Procfile](https://github.com/ddollar/foreman)
40
+
41
+ ## What's more to know?
42
+
43
+ - Additional arguments are passed to the command.
44
+
45
+ Run `islo --help` for details.
46
+
47
+ - Servers will listen only on unix sockets, TCP will be disabled.
48
+
49
+ This saves headaches when you have to handle multiple projects, and thus
50
+ conflicting ports. Also, it's too easy to forget not to listen for the world.
51
+
52
+ ## My service is installed in a non-standard location/I want to use different versions in different projects
53
+
54
+ Configuration is a pending item, which will make locations selectable.
55
+
56
+ ## I don't like how it assumes a Rails project layout
57
+
58
+ Configuration is a pending item, which will help set relevant paths.
59
+
60
+ ## I've got a super service you don't seem to know about
61
+
62
+ Some configuration may help you soon. Also, contributions are welcome.
63
+
64
+ ## I can't be bothered/always forget to type *islo* before my commands every single time!
65
+
66
+ Look soon enough under `support` for a few optional helpers for your favorite shell.
67
+
68
+ ## I want to contribute. How?
69
+
70
+ Great! Write specs, have them all pass, respect rubocop, rebase on master and make your PR.
71
+
72
+ ## License
73
+
74
+ MIT, see [LICENSE](LICENSE).
data/Rakefile ADDED
File without changes
data/bin/islo ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'islo/cli'
4
+
5
+ Islo::CLI.start
data/islo.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
+ require 'islo/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'islo'
7
+ s.version = Islo::VERSION
8
+ s.authors = ['Loic Nageleisen']
9
+ s.email = ['loic.nageleisen@gmail.com']
10
+ s.homepage = 'http://github.com/lloeki/islo'
11
+ s.summary = %q(Self-contained apps)
12
+ s.description = <<-EOT
13
+ Makes app completely self-contained by abstracting
14
+ service process settings and execution
15
+ EOT
16
+ s.license = 'MIT'
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n")
20
+ .map { |f| File.basename(f) }
21
+ s.require_paths = ['lib']
22
+
23
+ s.add_dependency 'rainbow', '~> 2.0'
24
+ s.add_dependency 'slop'
25
+
26
+ s.add_development_dependency 'rspec', '~> 2.14'
27
+ s.add_development_dependency 'rake', '~> 10.3'
28
+ s.add_development_dependency 'pry'
29
+ end
data/lib/islo.rb ADDED
@@ -0,0 +1,21 @@
1
+ # Islo - application isolator
2
+ module Islo
3
+ class << self
4
+ def commands
5
+ @commands ||= {}
6
+ end
7
+
8
+ def register(command)
9
+ commands[command.name.to_sym] = command
10
+ end
11
+
12
+ def command(args, options = {})
13
+ name = File.basename(args[0]).to_sym
14
+ (commands[name] || Command).new(args, options)
15
+ end
16
+ end
17
+ end
18
+
19
+ [:mysql, :postgres, :redis].each do |c|
20
+ require "islo/commands/#{c}"
21
+ end
data/lib/islo/cli.rb ADDED
@@ -0,0 +1,91 @@
1
+ require 'slop'
2
+ require 'islo'
3
+ require 'rainbow/ext/string'
4
+
5
+ module Islo
6
+ # Handle and run the command line interface
7
+ class CLI
8
+ NAME = File.basename($PROGRAM_NAME)
9
+
10
+ # See sysexits(3)
11
+ RC = { ok: 0,
12
+ error: 1,
13
+ usage: 64,
14
+ data: 65,
15
+ noinput: 66,
16
+ nouser: 67,
17
+ nohost: 68,
18
+ unavailable: 69,
19
+ software: 70,
20
+ oserr: 71,
21
+ osfile: 72,
22
+ cantcreat: 73,
23
+ ioerr: 74,
24
+ tempfail: 75,
25
+ protocol: 76,
26
+ noperm: 77,
27
+ config: 78 }
28
+
29
+ # Shortcut for Islo::CLI.new.start
30
+ def self.start
31
+ new.start
32
+ end
33
+
34
+ attr_reader :args
35
+
36
+ def opts
37
+ @opts.to_hash
38
+ end
39
+
40
+ def initialize(args = ARGV)
41
+ @args, @opts = parse(args)
42
+ rescue Slop::InvalidOptionError => e
43
+ die(:usage, e.message)
44
+ rescue Slop::MissingArgumentError => e
45
+ die(:usage, e.message)
46
+ end
47
+
48
+ # Start execution based on options
49
+ def start
50
+ Islo.command(args, title: opts[:title]).exec
51
+ rescue Islo::Command::Error => e
52
+ die(:oserr, e.message)
53
+ end
54
+
55
+ private
56
+
57
+ # Stop with a popping message and exit with a return code
58
+ def die(rc, message)
59
+ $stderr.puts('Error: '.color(:red) << message)
60
+ exit(rc.is_a?(Symbol) ? RC[rc] : rc)
61
+ end
62
+
63
+ # Stop with a nice message
64
+ def bye(message)
65
+ $stdout.puts message
66
+ exit
67
+ end
68
+
69
+ def version_string
70
+ "#{NAME} v#{Islo::VERSION}"
71
+ end
72
+
73
+ # Parse arguments and set options
74
+ # rubocop:disable MethodLength
75
+ def parse(args)
76
+ args = args.dup
77
+
78
+ opts = Slop.parse!(args, strict: true, help: true) do
79
+ banner "Usage: #{NAME} [options] [--] command arguments"
80
+
81
+ on 't', 'title=', 'String displayed in process list', argument: true
82
+ on 'd', 'directory=', 'Change working directory', argument: true
83
+ on 'v', 'version', 'Print the version', -> { bye(version_string) }
84
+ end
85
+
86
+ fail Slop::MissingArgumentError, 'missing an argument' if args.empty?
87
+
88
+ [args, opts]
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,36 @@
1
+ module Islo
2
+ # Generic command execution
3
+ class Command
4
+ class Error < StandardError; end
5
+
6
+ attr_reader :title, :wd
7
+ attr_reader :command, :args
8
+
9
+ def initialize(args, title: nil, wd: nil)
10
+ @command = args.shift
11
+ @args = args
12
+ @title = title unless title.nil? || title.empty?
13
+ @wd = Pathname.new(wd || Dir.pwd)
14
+ end
15
+
16
+ def title?
17
+ !title.nil?
18
+ end
19
+
20
+ def exec
21
+ Dir.chdir(wd.to_s)
22
+ Kernel.exec(*args_for_exec)
23
+ rescue SystemCallError => e
24
+ raise Command::Error, e.message
25
+ end
26
+
27
+ private
28
+
29
+ def args_for_exec
30
+ command = (title? ? [@command, title] : @command)
31
+ args = self.args
32
+
33
+ [command] + args
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,70 @@
1
+ require 'islo/command'
2
+
3
+ module Islo
4
+ # MySQL support
5
+ module Mysql
6
+ # MySQL client
7
+ class Client < Command
8
+ def self.name
9
+ :mysql
10
+ end
11
+
12
+ def args
13
+ %W(
14
+ --socket=#{wd}/tmp/sockets/mysql.sock
15
+ -uroot
16
+ ) + super
17
+ end
18
+
19
+ Islo.register(self)
20
+ end
21
+
22
+ # MySQL server
23
+ class Server < Command
24
+ def self.name
25
+ :mysqld
26
+ end
27
+
28
+ def args
29
+ %W(
30
+ --no-defaults
31
+ --datadir=#{wd}/db/mysql
32
+ --pid-file=#{wd}/tmp/pids/mysqld.pid
33
+ --socket=#{wd}/tmp/sockets/mysql.sock
34
+ --skip-networking
35
+ ) + super
36
+ end
37
+
38
+ Islo.register(self)
39
+ end
40
+
41
+ # MySQL initializer
42
+ class Init < Command
43
+ def self.name
44
+ :mysql_install_db
45
+ end
46
+
47
+ def args
48
+ %W(
49
+ --no-defaults
50
+ --basedir=#{Mysql.basedir}
51
+ --datadir=#{wd}/db/mysql
52
+ --pid-file=#{wd}/tmp/pids/mysqld.pid
53
+ ) + super
54
+ end
55
+
56
+ Islo.register(self)
57
+ end
58
+
59
+ def self.basedir
60
+ path = %x(which mysql)
61
+
62
+ fail Command::Error, 'could not find mysql' if path.empty?
63
+
64
+ path = File.dirname(path)
65
+ path = File.dirname(path)
66
+
67
+ path
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,50 @@
1
+ require 'islo/command'
2
+
3
+ module Islo
4
+ # PostgreSQL support
5
+ module Postgres
6
+ # PostgreSQL client
7
+ class Client < Command
8
+ def self.name
9
+ :psql
10
+ end
11
+
12
+ def args
13
+ %W(--host=#{wd}/tmp/sockets) + super
14
+ end
15
+
16
+ Islo.register(self)
17
+ end
18
+
19
+ # PostgreSQL server
20
+ class Server < Command
21
+ def self.name
22
+ :postgres
23
+ end
24
+
25
+ def args
26
+ %W(
27
+ -D #{wd}/db/postgres
28
+ -k #{wd}/tmp/sockets
29
+ ) + ['-h', ''] + super
30
+ end
31
+
32
+ Islo.register(self)
33
+ end
34
+
35
+ # PostgreSQL initializer
36
+ class Init < Command
37
+ def self.name
38
+ :initdb
39
+ end
40
+
41
+ def args
42
+ %W(
43
+ -D #{wd}/db/postgres
44
+ ) + super
45
+ end
46
+
47
+ Islo.register(self)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,108 @@
1
+ require 'islo/command'
2
+
3
+ module Islo
4
+ # Redis support
5
+ module Redis
6
+ # Redis client
7
+ class Client < Command
8
+ def self.name
9
+ :'redis-cli'
10
+ end
11
+
12
+ def args
13
+ %w(-s redis.sock)
14
+ end
15
+
16
+ # Change working directory (makes for a nicer prompt)
17
+ def wd
18
+ super + 'tmp/sockets'
19
+ end
20
+
21
+ Islo.register(self)
22
+ end
23
+
24
+ # Redis server
25
+ class Server < Command
26
+ def self.name
27
+ :'redis-server'
28
+ end
29
+
30
+ def args
31
+ %W(#{wd}/db/redis/redis.conf)
32
+ end
33
+
34
+ Islo.register(self)
35
+ end
36
+
37
+ # Redis initializer
38
+ #
39
+ # Creates a minimal configuration because redis-server doesn't accept
40
+ # arguments allowing for paths to be set.
41
+ class Init < Command
42
+ def self.name
43
+ :'redis-init'
44
+ end
45
+
46
+ def exec
47
+ FileUtils.mkdir_p(wd + 'db/redis')
48
+
49
+ File.open(wd + 'db/redis/redis.conf', 'w') do |f|
50
+ f << template.gsub('${WORKING_DIR}', wd.to_s)
51
+ end
52
+ rescue SystemCallError => e
53
+ raise Command::Error, e.message
54
+ end
55
+
56
+ private
57
+
58
+ # rubocop:disable MethodLength,LineLength
59
+ def template
60
+ <<-EOT.gsub(/^ +/, '')
61
+ daemonize no
62
+ pidfile ${WORKING_DIR}/pids/redis.pid
63
+ port 0
64
+ bind 127.0.0.1
65
+ unixsocket ${WORKING_DIR}/tmp/sockets/redis.sock
66
+ unixsocketperm 700
67
+ timeout 0
68
+ tcp-keepalive 0
69
+ loglevel notice
70
+ databases 1
71
+ save 900 1
72
+ save 300 10
73
+ save 60 10000
74
+ stop-writes-on-bgsave-error yes
75
+ rdbcompression yes
76
+ rdbchecksum yes
77
+ dbfilename dump.rdb
78
+ dir ${WORKING_DIR}/db/redis
79
+ slave-serve-stale-data yes
80
+ slave-read-only yes
81
+ repl-disable-tcp-nodelay no
82
+ slave-priority 100
83
+ appendonly yes
84
+ appendfsync everysec
85
+ no-appendfsync-on-rewrite no
86
+ auto-aof-rewrite-percentage 100
87
+ auto-aof-rewrite-min-size 64mb
88
+ lua-time-limit 5000
89
+ slowlog-log-slower-than 10000
90
+ slowlog-max-len 128
91
+ hash-max-ziplist-entries 512
92
+ hash-max-ziplist-value 64
93
+ list-max-ziplist-entries 512
94
+ list-max-ziplist-value 64
95
+ set-max-intset-entries 512
96
+ zset-max-ziplist-entries 128
97
+ zset-max-ziplist-value 64
98
+ activerehashing yes
99
+ client-output-buffer-limit normal 0 0 0
100
+ client-output-buffer-limit slave 256mb 64mb 60
101
+ client-output-buffer-limit pubsub 32mb 8mb 60
102
+ EOT
103
+ end
104
+
105
+ Islo.register(self)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,3 @@
1
+ module Islo
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: islo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Loic Nageleisen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-05-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rainbow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: slop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: |2
84
+ Makes app completely self-contained by abstracting
85
+ service process settings and execution
86
+ email:
87
+ - loic.nageleisen@gmail.com
88
+ executables:
89
+ - islo
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - Gemfile
95
+ - LICENSE
96
+ - README.md
97
+ - Rakefile
98
+ - bin/islo
99
+ - islo.gemspec
100
+ - lib/islo.rb
101
+ - lib/islo/cli.rb
102
+ - lib/islo/command.rb
103
+ - lib/islo/commands/mysql.rb
104
+ - lib/islo/commands/postgres.rb
105
+ - lib/islo/commands/redis.rb
106
+ - lib/islo/version.rb
107
+ homepage: http://github.com/lloeki/islo
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.2.2
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Self-contained apps
131
+ test_files: []