env.rb 0.0.1
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 +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
|