req-cli 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9ce6c0c76b2d31aa7e45b63fd8d8af40c40ec826
4
+ data.tar.gz: d742a1985e3bf964678a5475a1fd0529bc1ee423
5
+ SHA512:
6
+ metadata.gz: a019e10f8e119d44d24c816ce7b1dcdc4614f54806744a099eaf1c39c24ef12eabd54874f3312c2d13e9f87a6e2b7cc669887e29bb52bf0723cfd0f54351d6c4
7
+ data.tar.gz: ccac9284dceeb3c273cfedb42d614c7413dce65e6c126d6fd0646d67268ef0925a0762288143e5d10312a9746dabcc889056c12d592dc36822ff6768da194ea7
data/bin/req ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'req-cli'
4
+
5
+ Req.start(ARGV)
@@ -0,0 +1,44 @@
1
+
2
+ class Config
3
+ attr_accessor :contexts, :environments, :requests
4
+
5
+ def initialize(hash)
6
+ @contexts = hash[:contexts] || hash['contexts'] || {}
7
+ @contexts = @contexts.map {|ctx| Context.new(ctx) }
8
+
9
+ @environments = hash[:environments] || hash['environments'] || {}
10
+ @environments = @environments.map { |env| Environment.new(env) }
11
+
12
+ @requests = hash[:requests] || hash['requests'] || {}
13
+ @requests = @requests.map { |req| Request.new(req) }
14
+ end
15
+
16
+ def self.create_from_yaml(yaml_string)
17
+ return Config.new YAML.load(yaml_string)
18
+ end
19
+
20
+ def has_context?(ctx_name)
21
+ @contexts.any? {|ctx| ctx.name == ctx_name }
22
+ end
23
+
24
+ def get_context(ctx_name)
25
+ @contexts.find {|ctx| ctx.name == ctx_name }
26
+ end
27
+
28
+ def has_environment?(env_name)
29
+ @environments.any? {|env| env.name == env_name }
30
+ end
31
+
32
+ def get_environment(env_name)
33
+ @environments.find {|env| env.name == env_name }
34
+ end
35
+
36
+ def has_request?(env_name)
37
+ @requests.any? {|env| env.name == env_name }
38
+ end
39
+
40
+ def get_request(env_name)
41
+ @requests.find {|env| env.name == env_name }
42
+ end
43
+
44
+ end
@@ -0,0 +1,10 @@
1
+ class Context
2
+ attr_accessor :name, :variables, :headers
3
+
4
+ def initialize(hash)
5
+ @name = hash[:name] || hash['name'] || 'default_context'
6
+ @variables = hash[:vars] || hash['vars'] || {}
7
+ @headers = hash[:headers] || hash['headers'] || {}
8
+ end
9
+
10
+ end
@@ -0,0 +1,30 @@
1
+ class CurlBackend
2
+
3
+ def initialize(prepared_request, options={})
4
+ @request = prepared_request
5
+ @curl_options = parse_curl_options(options)
6
+ end
7
+
8
+ def execute
9
+ header_string = @request.headers.map {|key, val| "-H '#{key}: #{val}'"}.join ' '
10
+ data_string = @request.data ? "-d '#{@request.data}'" : ""
11
+
12
+ curl_command = "curl -X #{@request.method.upcase} #{header_string} #{data_string} #{@curl_options} #{@request.uri}"
13
+ system curl_command
14
+ end
15
+
16
+ def parse_curl_options(options)
17
+ opts = ''
18
+
19
+ if options.has_key? 'verbose'
20
+ opts += '--verbose '
21
+ end
22
+
23
+ if options.has_key? 'head'
24
+ opts += ' --head '
25
+ end
26
+
27
+ opts
28
+ end
29
+
30
+ end
@@ -0,0 +1,12 @@
1
+ class Environment
2
+ attr_accessor :name, :variables, :endpoint, :headers
3
+
4
+ def initialize(hash)
5
+ @name = hash[:name] || hash['name'] || ''
6
+ @endpoint = hash[:endpoint] || hash['endpoint'] || ''
7
+ @variables = hash[:vars] || hash['vars'] || {}
8
+ @headers = hash[:headers] || hash['headers'] || {}
9
+
10
+ # TODO raise exceptions when @name or @endpoint is nil or empty
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ class PreparedRequest
2
+
3
+ attr_accessor :headers, :uri, :method, :data
4
+
5
+ def initialize(options={})
6
+ @headers = options[:headers] || {}
7
+ @uri = options[:uri] || ''
8
+ @method = options[:method] || :get
9
+ @data = options[:data] || nil
10
+ end
11
+
12
+ # Hash of HTTP headers
13
+
14
+ # string with full request URI
15
+
16
+ # symbol :get, :post, :put, :delete
17
+
18
+ end
@@ -0,0 +1,139 @@
1
+ require 'thor'
2
+ require 'yaml'
3
+
4
+ require 'context'
5
+ require 'environment'
6
+ require 'request'
7
+ require 'state'
8
+ require 'config'
9
+ require 'prepared_request'
10
+ require 'request_factory'
11
+ require 'variable_interpolator'
12
+ require 'curl_backend'
13
+
14
+ STATEFILE = '.reqstate'
15
+ REQFILE = 'Reqfile'
16
+
17
+
18
+ class Req < Thor
19
+
20
+ attr_accessor :config, :state
21
+ @config = nil
22
+ @state = nil
23
+
24
+ def self.create_with_config(config)
25
+ req = Req.new
26
+ req.config = config
27
+ req.state = State.new
28
+ req
29
+ end
30
+
31
+ desc "contexts", "list all contexts"
32
+ def contexts
33
+ init # TODO avoid this
34
+ @config.contexts.each {|ctx| puts ctx.name }
35
+ end
36
+
37
+ desc "context NAME", "switch to context NAME"
38
+ def context(name)
39
+ init
40
+ if @config.contexts.any? { |ctx| ctx.name == name }
41
+ puts "switching to context #{name}"
42
+ @state.context = name
43
+ save_state
44
+ else
45
+ puts "context not found"
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ desc "environments", "list all environments"
51
+ def environments
52
+ init
53
+ @config.environments.each {|env| puts env.name }
54
+ end
55
+
56
+ desc "environment", "switch to environment"
57
+ def environment(name)
58
+ init
59
+ if @config.has_environment? name
60
+ puts "switching to environment #{name}"
61
+ @state.environment = name
62
+ save_state
63
+ else
64
+ puts "environment not found"
65
+ exit 1
66
+ end
67
+ end
68
+
69
+ desc "variable NAME VALUE", "add variable with key NAME and value VALUE"
70
+ def variable(name, value)
71
+ init
72
+ @state.variables[name] = value
73
+ save_state
74
+ end
75
+
76
+ desc "variables", "list all custom variables"
77
+ def variables
78
+ init
79
+ @state.variables.each {|key, val| put "#{key}: #{val}" }
80
+ end
81
+
82
+ desc "status", "print current environment and context info"
83
+ def status
84
+ init
85
+ puts "context: #{@state.context}"
86
+ puts "environment: #{@state.environment}"
87
+ puts "variables: "
88
+ @state.variables.each { |key,val| puts " #{key}: #{val}" }
89
+ end
90
+
91
+ desc "clear", "clear current context, environment and vars"
92
+ def clear
93
+ @state = State.new
94
+ save_state
95
+ end
96
+
97
+ desc "exec REQUESTNAME", "execute request with name REQUESTNAME"
98
+ option :verbose, aliases: '-v'
99
+ option :head, aliases: '-I'
100
+ def exec(requestname)
101
+ init
102
+ valid_for_execution?
103
+ request = @config.get_request(requestname)
104
+ prepared_request = RequestFactory.create(@config, @state, request)
105
+ backend = CurlBackend.new prepared_request, options
106
+ backend.execute
107
+ end
108
+
109
+ desc "requests", "list all requests"
110
+ def requests
111
+ init
112
+ @config.requests.each {|req| puts "#{req.name} \t#{req.method} \t#{req.path}"}
113
+ end
114
+
115
+ no_commands do
116
+ def init
117
+ return if @config
118
+ @state = State.new
119
+ @config = Config.create_from_yaml(File.read(REQFILE))
120
+ if File.exist? '.reqstate'
121
+ @state = YAML.load(File.read(STATEFILE))
122
+ end
123
+ end
124
+
125
+ def valid_for_execution?
126
+ env = @config.get_environment(@state.environment)
127
+ puts "No valid environment specified, use req environment NAME to choose an environment" if env.nil?
128
+ exit 1 if env.nil?
129
+
130
+ ctx = @config.get_context(@state.context)
131
+ puts "No valid context specified, use req context NAME to choose a context" if ctx.nil?
132
+ exit 1 if ctx.nil?
133
+ end
134
+
135
+ def save_state
136
+ File.write(STATEFILE, @state.to_yaml)
137
+ end
138
+ end
139
+ end
@@ -0,0 +1,15 @@
1
+ class Request
2
+ attr_accessor :name, :path, :method, :headers, :variables, :data
3
+
4
+ def initialize(hash)
5
+ @name = hash[:name] || hash['name'] || ''
6
+ @path = hash[:path] || hash['path'] || ''
7
+ @method = hash[:method] || hash['method'] || ''
8
+
9
+ @headers = hash[:headers] || hash['headers'] || {}
10
+ @variables = hash[:vars] || hash['vars'] || {}
11
+ @data = hash[:data] || hash['data'] || nil
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,42 @@
1
+ class RequestFactory
2
+ def self.create(config, state, request)
3
+ environment = config.get_environment(state.environment) || Environment.new
4
+ context = config.get_context(state.context) || Context.new
5
+
6
+ variables = merge_variables(environment, context, request, state.variables)
7
+ interpolator = VariableInterpolator.new(variables)
8
+
9
+ PreparedRequest.new({
10
+ headers: build_headers(environment, context, request, interpolator),
11
+ method: request.method.downcase.to_sym,
12
+ uri: build_uri(environment, context, request, interpolator),
13
+ data: build_data(request, interpolator)
14
+ })
15
+ end
16
+
17
+ def self.merge_variables(environment, context, request, custom_variables)
18
+ (environment.variables || {})
19
+ .merge(context.variables || {})
20
+ .merge(request.variables || {})
21
+ .merge(custom_variables || {})
22
+ end
23
+
24
+ def self.build_headers(environment, context, request, interpolator)
25
+ environment.headers
26
+ .merge(context.headers)
27
+ .merge(request.headers)
28
+ .map {|key, value| [key, interpolator.interpolate(value)]}.to_h
29
+ end
30
+
31
+ def self.build_uri(environment, context, request, interpolator)
32
+ uri = environment.endpoint + request.path
33
+ interpolator.interpolate(uri)
34
+ end
35
+
36
+ def self.build_data(request, interpolator)
37
+ return nil if request.data.nil?
38
+
39
+ interpolator.interpolate(request.data)
40
+ end
41
+
42
+ end
@@ -0,0 +1,8 @@
1
+ class State
2
+ attr_accessor :context, :environment, :variables
3
+
4
+ def initialize
5
+ @variables = {}
6
+ end
7
+
8
+ end
@@ -0,0 +1,16 @@
1
+ class VariableInterpolator
2
+
3
+ attr_accessor :variables
4
+
5
+ def initialize(variables = {})
6
+ @variables = variables.map { |key, value| [key.to_sym, value] }.to_h
7
+ end
8
+
9
+ def interpolate(input)
10
+ input.gsub(/\${[a-zA-Z0-9\-_]*}/) do |m|
11
+ var = m.scan(/[a-zA-Z0-9\-_]+/).first.to_sym
12
+ variables[var]
13
+ end
14
+ end
15
+
16
+ end
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: req-cli
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Steven Van Bael
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-08-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.19'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.19'
27
+ - !ruby/object:Gem::Dependency
28
+ name: httparty
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ description: ''
42
+ email: steven@quantus.io
43
+ executables:
44
+ - req
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - bin/req
49
+ - lib/config.rb
50
+ - lib/context.rb
51
+ - lib/curl_backend.rb
52
+ - lib/environment.rb
53
+ - lib/prepared_request.rb
54
+ - lib/req-cli.rb
55
+ - lib/request.rb
56
+ - lib/request_factory.rb
57
+ - lib/state.rb
58
+ - lib/variable_interpolator.rb
59
+ homepage: http://github.com/vbsteven/req
60
+ licenses:
61
+ - MIT
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.5.1
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: CLI tool for templating HTTP requests from a config file and execute them
83
+ with curl.
84
+ test_files: []