env.rb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.md +69 -0
- data/Rakefile +9 -0
- data/env.gemspec +20 -0
- data/lib/env.rb +87 -0
- data/lib/env/version.rb +3 -0
- data/spec/enforce_spec.rb +38 -0
- data/spec/load_spec.rb +33 -0
- data/spec/uri_spec.rb +52 -0
- metadata +62 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
# Env.rb
|
2
|
+
Managing your ENVironment
|
3
|
+
|
4
|
+
## Purpose
|
5
|
+
Many modern web applications consume and post to resources that reside at other urls, often requiring
|
6
|
+
more authentication tokens than a database password. These passwords need to be stored in some
|
7
|
+
location. A common, secure location that exists outside of the source directory is in the
|
8
|
+
application's runtime environment.
|
9
|
+
|
10
|
+
However, consuming a resource at a url can take up to three different variables to represent
|
11
|
+
the location, username, and password. If your app is consuming many endpoints the sheer
|
12
|
+
number of variables can become overwhelming. Remember, the average short-term memory holds
|
13
|
+
about 7 items. Certain production applications can have upwards of 50 to 100 ENV vars.
|
14
|
+
|
15
|
+
Env.rb allows you to declare environment variables like dependencies and configure multiple
|
16
|
+
environments with a simple ruby DSL. It provides tools for cleaning up existing apps, exporting
|
17
|
+
your Envfile to a shell-compatible format, and executing scripts within your environments.
|
18
|
+
|
19
|
+
## Examples
|
20
|
+
|
21
|
+
### Declaring Dependecies
|
22
|
+
|
23
|
+
export "PROVIDER_PASSWORD", '1234', :group => :development, :required => false
|
24
|
+
|
25
|
+
group :development do
|
26
|
+
export "SERVICE_URL", 'http://username:password@www.service.com/path"
|
27
|
+
end
|
28
|
+
|
29
|
+
group :test do
|
30
|
+
export "SERVICE_URL", 'http://username:password@example.com/"
|
31
|
+
end
|
32
|
+
|
33
|
+
### In your Ruby files
|
34
|
+
|
35
|
+
require 'env'
|
36
|
+
|
37
|
+
Env.load('../path_to_file')
|
38
|
+
Env.load! # look for Envfile
|
39
|
+
|
40
|
+
ENV['HELLO_WORLD'] # => nil
|
41
|
+
Env.enforce
|
42
|
+
ENV['HELLO_WORLD']
|
43
|
+
# => EnvironmentError: HELLO_WORLD is not a declared environment dependency
|
44
|
+
|
45
|
+
ENV['TEST'] = 'overriding'
|
46
|
+
# => EnvironmentError: TEST is not a declared environment dependency
|
47
|
+
|
48
|
+
Env.eval do
|
49
|
+
export 'TEXT', '15', :immutable => true
|
50
|
+
# same as export 'TEXT', '15', :mutable => false
|
51
|
+
end
|
52
|
+
|
53
|
+
ENV['TEST'] = 'overriding'
|
54
|
+
# => EnvironmentError: variable TEST cannot be changed
|
55
|
+
|
56
|
+
## Built-in support for URIs
|
57
|
+
|
58
|
+
### in Envfile
|
59
|
+
export "SERVICE", 'http://username:password@example.com/"
|
60
|
+
|
61
|
+
### in your Ruby Script
|
62
|
+
ENV['SERVICE'] #=> 'http://username:password@example.com/"
|
63
|
+
ENV['SERVICE'].base_uri #=> 'http://example.com/"
|
64
|
+
ENV['SERVICE'].url #=> 'http://example.com/"
|
65
|
+
ENV['SERVICE'].user #=> 'username'
|
66
|
+
ENV['SERVICE'].password #=> 'password'
|
67
|
+
ENV['SERVICE'].host #=> 'example.com'
|
68
|
+
ENV['SERVICE'].scheme #=> 'http'
|
69
|
+
|
data/Rakefile
ADDED
data/env.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "env/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "env.rb"
|
7
|
+
s.version = Env::VERSION
|
8
|
+
s.authors = ["Chris Continanza"]
|
9
|
+
s.email = ["christopher.continanza@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{Manage your ENV with ease}
|
12
|
+
s.description = %q{Allows your to manage many ENV vars by declaring them as dependencies on ENV vars and then enforcing those dependencies. Supports wrapping URIs with support methods.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "env.rb"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
end
|
data/lib/env.rb
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
require "env/version"
|
2
|
+
require 'uri'
|
3
|
+
require 'forwardable'
|
4
|
+
|
5
|
+
class EnvironmentError < StandardError
|
6
|
+
end
|
7
|
+
|
8
|
+
module Env
|
9
|
+
@@dependencies = []
|
10
|
+
@@env = {}
|
11
|
+
@@enforced = false
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def [](key)
|
15
|
+
_raise(key) unless dependencies.include? key
|
16
|
+
@@env[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def []=(key,value)
|
20
|
+
_raise(key) unless dependencies.include? key
|
21
|
+
@@env[key] = uri?(value) ? proxify(value) : value
|
22
|
+
end
|
23
|
+
|
24
|
+
def export(key, value = nil)
|
25
|
+
@@dependencies << key
|
26
|
+
@@env[key] = uri?(value) ? proxify(value) : value
|
27
|
+
end
|
28
|
+
|
29
|
+
def load!
|
30
|
+
@@enforced or Env.enforce
|
31
|
+
eval File.read("Envfile") if File.exist?("Envfile")
|
32
|
+
File.exist?("Envfile")
|
33
|
+
end
|
34
|
+
|
35
|
+
def enforce
|
36
|
+
class << ENV
|
37
|
+
alias_method :get, :[]
|
38
|
+
alias_method :set, :[]=
|
39
|
+
|
40
|
+
def [](key)
|
41
|
+
Env[key]
|
42
|
+
end
|
43
|
+
|
44
|
+
def []=(key, value)
|
45
|
+
Env[key] = value
|
46
|
+
end
|
47
|
+
end
|
48
|
+
@@enforced = true
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
def _raise(key)
|
53
|
+
raise EnvironmentError, "#{key} is not a declared depency, add it to your Envfile"
|
54
|
+
end
|
55
|
+
|
56
|
+
def uri?(value)
|
57
|
+
value.to_s.match(/^\w+:\/\//)
|
58
|
+
end
|
59
|
+
|
60
|
+
def proxify(value)
|
61
|
+
UriProxy.new(value)
|
62
|
+
end
|
63
|
+
|
64
|
+
def dependencies
|
65
|
+
@@dependencies
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class UriProxy < BasicObject
|
70
|
+
extend ::Forwardable
|
71
|
+
def_delegators :@uri, :scheme, :user, :password, :host
|
72
|
+
|
73
|
+
def initialize(uri)
|
74
|
+
@original = uri
|
75
|
+
@uri = ::URI.parse(uri)
|
76
|
+
end
|
77
|
+
|
78
|
+
def base_uri
|
79
|
+
"#{@uri.scheme}://#{@uri.host}"
|
80
|
+
end
|
81
|
+
alias url base_uri
|
82
|
+
|
83
|
+
def method_missing(method, *args, &block)
|
84
|
+
@original.send(method, *args, &block)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
data/lib/env/version.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require_relative '../lib/env'
|
2
|
+
|
3
|
+
describe Env, "::enforce" do
|
4
|
+
before { Env.enforce }
|
5
|
+
|
6
|
+
it "should not allow references to undeclared variables" do
|
7
|
+
lambda { ENV['UNDECLARED_VARIABLE'] }.should raise_error(EnvironmentError)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "with uninitialized dependency FOO" do
|
11
|
+
before do
|
12
|
+
Env.instance_eval do
|
13
|
+
export 'FOO'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should return nil for ENV['FOO']" do
|
18
|
+
ENV['FOO'].should eql(nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow you to set it" do
|
22
|
+
ENV['FOO'] = 'bar'
|
23
|
+
ENV['FOO'].should eql('bar')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
context "with initialized dependency FOO=bar" do
|
28
|
+
before do
|
29
|
+
Env.instance_eval do
|
30
|
+
export 'FOO', 'bar'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should return 'bar' for ENV['FOO']" do
|
35
|
+
ENV['FOO'].should eql('bar')
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/spec/load_spec.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative '../lib/env'
|
2
|
+
|
3
|
+
describe Env, '::load!' do
|
4
|
+
def envfile(string)
|
5
|
+
File.open("Envfile", 'w') do |f|
|
6
|
+
f << string
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return false" do
|
11
|
+
Env.load!.should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with a simple Envfile" do
|
15
|
+
before do
|
16
|
+
envfile(%{
|
17
|
+
export 'FOO', 'bar'
|
18
|
+
})
|
19
|
+
end
|
20
|
+
|
21
|
+
after { File.unlink('Envfile') }
|
22
|
+
|
23
|
+
it "should return true" do
|
24
|
+
Env.load!.should be_true
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should load Envfile in this directory" do
|
28
|
+
Env.load!
|
29
|
+
Env.enforce
|
30
|
+
ENV['FOO'].should == 'bar'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/spec/uri_spec.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require_relative '../lib/env'
|
2
|
+
|
3
|
+
describe Env, 'uri support' do
|
4
|
+
context "with a value FOO that is not a URI" do
|
5
|
+
before do
|
6
|
+
Env.instance_eval do
|
7
|
+
export 'FOO', 'bar'
|
8
|
+
end
|
9
|
+
Env.enforce
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should not wrap it" do
|
13
|
+
lambda { ENV['FOO'].scheme }.should raise_error(::NoMethodError)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
context "with a value FOO that is a URI" do
|
18
|
+
URL = 'http://username:password@this.domain.example.com/path?var=val'
|
19
|
+
|
20
|
+
before do
|
21
|
+
Env.instance_eval do
|
22
|
+
export 'FOO', URL
|
23
|
+
end
|
24
|
+
Env.enforce
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should leave the original value unchanged" do
|
28
|
+
ENV['FOO'].should == URL
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return scheme://host for #base_uri and #url" do
|
32
|
+
ENV['FOO'].base_uri.should == 'http://this.domain.example.com'
|
33
|
+
ENV['FOO'].url.should == 'http://this.domain.example.com'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should respond to #scheme with the scheme'" do
|
37
|
+
ENV['FOO'].scheme.should == 'http'
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should respond to #host with the host" do
|
41
|
+
ENV['FOO'].host.should == 'this.domain.example.com'
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should respond to #password with the password" do
|
45
|
+
ENV['FOO'].password.should == 'password'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should respond to #user with the user" do
|
49
|
+
ENV['FOO'].user.should == 'username'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
metadata
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: env.rb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Chris Continanza
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-08-04 00:00:00.000000000 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
description: Allows your to manage many ENV vars by declaring them as dependencies
|
16
|
+
on ENV vars and then enforcing those dependencies. Supports wrapping URIs with
|
17
|
+
support methods.
|
18
|
+
email:
|
19
|
+
- christopher.continanza@gmail.com
|
20
|
+
executables: []
|
21
|
+
extensions: []
|
22
|
+
extra_rdoc_files: []
|
23
|
+
files:
|
24
|
+
- .gitignore
|
25
|
+
- Gemfile
|
26
|
+
- README.md
|
27
|
+
- Rakefile
|
28
|
+
- env.gemspec
|
29
|
+
- lib/env.rb
|
30
|
+
- lib/env/version.rb
|
31
|
+
- spec/enforce_spec.rb
|
32
|
+
- spec/load_spec.rb
|
33
|
+
- spec/uri_spec.rb
|
34
|
+
has_rdoc: true
|
35
|
+
homepage: ''
|
36
|
+
licenses: []
|
37
|
+
post_install_message:
|
38
|
+
rdoc_options: []
|
39
|
+
require_paths:
|
40
|
+
- lib
|
41
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '0'
|
47
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ! '>='
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubyforge_project: env.rb
|
55
|
+
rubygems_version: 1.6.2
|
56
|
+
signing_key:
|
57
|
+
specification_version: 3
|
58
|
+
summary: Manage your ENV with ease
|
59
|
+
test_files:
|
60
|
+
- spec/enforce_spec.rb
|
61
|
+
- spec/load_spec.rb
|
62
|
+
- spec/uri_spec.rb
|