resat 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +321 -0
- data/Rakefile +33 -0
- data/bin/resat +223 -0
- data/examples/rightscale/README.rdoc +39 -0
- data/examples/rightscale/additional/run_server.yml +75 -0
- data/examples/rightscale/config/resat.yaml +34 -0
- data/examples/rightscale/scenarios/create_server.yml +48 -0
- data/examples/rightscale/scenarios/delete_server.yml +13 -0
- data/examples/rightscale/scenarios/list_servers.yml +9 -0
- data/examples/twitter/README.rdoc +50 -0
- data/examples/twitter/additional/follow.yml +15 -0
- data/examples/twitter/additional/send_message.yml +19 -0
- data/examples/twitter/config/resat.yaml +40 -0
- data/examples/twitter/output.yml +5 -0
- data/examples/twitter/scenarios/timelines.yml +31 -0
- data/examples/twitter/scenarios/tweet.yml +14 -0
- data/lib/api_request.rb +145 -0
- data/lib/config.rb +94 -0
- data/lib/engine.rb +98 -0
- data/lib/file_set.rb +33 -0
- data/lib/filter.rb +113 -0
- data/lib/guard.rb +36 -0
- data/lib/handler.rb +50 -0
- data/lib/kwalify_helper.rb +31 -0
- data/lib/log.rb +114 -0
- data/lib/net_patch.rb +15 -0
- data/lib/rdoc_patch.rb +37 -0
- data/lib/resat.rb +5 -0
- data/lib/scenario_runner.rb +203 -0
- data/lib/variables.rb +116 -0
- data/schemas/config.yaml +48 -0
- data/schemas/scenarios.yaml +169 -0
- data/schemas/variables.yaml +18 -0
- metadata +98 -0
data/schemas/config.yaml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
# == Synopsis
|
2
|
+
#
|
3
|
+
# This file contains the Kwalify YAML schema for the resat config file
|
4
|
+
#
|
5
|
+
# The resat config file is used to specify the API URI components as
|
6
|
+
# well as any required auxiliary information (such as username/password)
|
7
|
+
#
|
8
|
+
# The 'params' and 'headers' collections define request parameters and
|
9
|
+
# headers that will be sent with every API calls by default.
|
10
|
+
#
|
11
|
+
# The 'variables' collection define global variables and their values.
|
12
|
+
# The 'output' field defines the path to the file where extracted
|
13
|
+
# variables should be saved if the corresponding 'save' field in the
|
14
|
+
# scenario is true.
|
15
|
+
# The 'input' field defines the path to the file where variables are
|
16
|
+
# defined that should be loaded prior to executing any scenario.
|
17
|
+
# Both the output and input file use YAML to serialize variables so that
|
18
|
+
# a file produced as an output of resat can be later used as input.
|
19
|
+
#
|
20
|
+
# == Note
|
21
|
+
#
|
22
|
+
# All the URI components defined in the Config file may be overridden by
|
23
|
+
# each request in the scenario.
|
24
|
+
|
25
|
+
# Schema for resat configuration
|
26
|
+
type: map
|
27
|
+
class: Resat::Config
|
28
|
+
mapping:
|
29
|
+
"host": { type: str, required: yes } # Default host
|
30
|
+
"port": { type: int } # Default port (optional)
|
31
|
+
"base_url": { type: str } # Default base URL (optional)
|
32
|
+
"use_ssl": { type: bool, default: no } # http or https? (http by default)
|
33
|
+
"username": { type: str } # Basic auth username (optional)
|
34
|
+
"password": { type: str } # Basic auth password (optional)
|
35
|
+
"params": # Parameters used for all requests
|
36
|
+
&name_value_pairs
|
37
|
+
type: seq
|
38
|
+
sequence:
|
39
|
+
- type: map
|
40
|
+
mapping:
|
41
|
+
"name": { type: str, required: yes, unique: yes }
|
42
|
+
"value": { type: str, required: yes }
|
43
|
+
"headers": *name_value_pairs # Headers used for all requests
|
44
|
+
"delay": { type: str } # Delay in seconds before each request (integer or range)
|
45
|
+
"variables": *name_value_pairs # Global variables
|
46
|
+
"output": { type: str } # Path to variables save file
|
47
|
+
"input": { type: str } # Path to variables load file
|
48
|
+
|
@@ -0,0 +1,169 @@
|
|
1
|
+
# == Synopsis
|
2
|
+
# This file contains the Kwalify YAML schema for resat test scenarios.
|
3
|
+
# Scenarios consists of API requests and responses validation.
|
4
|
+
#
|
5
|
+
# A scenario may include other scenarios in which case all the included
|
6
|
+
# scenarios steps will be executed first even if the included scenario
|
7
|
+
# is marked as 'ignore' (that way it becomes possible to define
|
8
|
+
# include-only scenarios).
|
9
|
+
#
|
10
|
+
# Each step may define guards, that is conditions that must be validated
|
11
|
+
# before the flow can proceed. These conditions may apply to the response
|
12
|
+
# header or body and may define a pattern that a given field must validate
|
13
|
+
# for the guard to be enabled (and the flow to proceed). If no pattern is
|
14
|
+
# specified then all that is required is for the call to be successful.
|
15
|
+
# During execution a guard will re-send the same request until the condition
|
16
|
+
# gets fulfilled or it timeouts.
|
17
|
+
#
|
18
|
+
# API responses bodies and headers can optionally be run through filters.
|
19
|
+
# Filters can provide additional validation and can also initialize variables
|
20
|
+
# from the response. These variables can the be used in headers and parameters
|
21
|
+
# to later API requests as well as patterns used for validation and extraction.
|
22
|
+
#
|
23
|
+
# Variables are initialized via extractors defined in filters. Extractors
|
24
|
+
# may use a regular expression with a capturing group. The variable is
|
25
|
+
# initialized with the first capturing group match. If no regular expression
|
26
|
+
# is specified then the whole field is stored in the given variable.
|
27
|
+
#
|
28
|
+
# Fields in headers are identified by name while fields in response bodies
|
29
|
+
# are identified by their XPath e.g.:
|
30
|
+
#
|
31
|
+
# deployments/deployment/servers/server/state
|
32
|
+
#
|
33
|
+
# Filters validation is done through regular expressions validators and/or
|
34
|
+
# checking whether a field is empty. All validators regular expressions must
|
35
|
+
# match for the validation to pass. The validation will be applied to all
|
36
|
+
# elements matching the field XPath in the case of validators applied to a
|
37
|
+
# response body.
|
38
|
+
#
|
39
|
+
# To use a variable simply prefix its name with the '$' character e.g.:
|
40
|
+
#
|
41
|
+
# # Filter definition for extracting 'server_id' variable:
|
42
|
+
# target: header
|
43
|
+
# extractors:
|
44
|
+
# - field: location
|
45
|
+
# pattern: '.*\/servers\/(\d+)$'
|
46
|
+
# variable: server_id
|
47
|
+
#
|
48
|
+
# # API call definition using the 'server_id' variable:
|
49
|
+
# operation: show
|
50
|
+
# resource: server
|
51
|
+
# id: $server_id
|
52
|
+
#
|
53
|
+
# Finally, API responses can also be run through handlers. Handlers have
|
54
|
+
# access to the raw request and response for processing. The scenario
|
55
|
+
# specifies the name of the module that implements the handler. The module
|
56
|
+
# should expose a 'process' method taking two arguments: the underlying
|
57
|
+
# HTTP request and corresponding response.
|
58
|
+
|
59
|
+
# Schema for scenarios definitions
|
60
|
+
type: map
|
61
|
+
class: Resat::Scenario
|
62
|
+
mapping:
|
63
|
+
"name": { type: str, required: yes } # Scenario name
|
64
|
+
"config": { type: str } # Path to config file
|
65
|
+
"ignore": { type: bool, default: no } # Ignore scenario?
|
66
|
+
"includes": # Included scenarios if any
|
67
|
+
type: seq
|
68
|
+
sequence:
|
69
|
+
- type: str
|
70
|
+
"steps": # Scenario steps definition
|
71
|
+
type: seq
|
72
|
+
sequence:
|
73
|
+
- type: map
|
74
|
+
class: Resat::Step
|
75
|
+
mapping:
|
76
|
+
#------------------------------------------------------------------------------------------------------------------------
|
77
|
+
"request": # API REQUEST DEFINITION
|
78
|
+
type: map
|
79
|
+
class: Resat::ApiRequest
|
80
|
+
mapping:
|
81
|
+
"host": { type: str } # Request host (config override)
|
82
|
+
"port": { type: str } # Request port (config override)
|
83
|
+
"base_url": { type: str } # Request base URL (config override)
|
84
|
+
"use_ssl": { type: bool } # http or https (config override)
|
85
|
+
"username": { type: str } # Basic auth username (config override)
|
86
|
+
"password": { type: str } # Basic auth password (config override)
|
87
|
+
"operation": { enum: [create, index, show, update, destroy] } # Request operation
|
88
|
+
"custom": # Custom operation
|
89
|
+
type: map
|
90
|
+
class: Resat::CustomOperation
|
91
|
+
mapping:
|
92
|
+
"name": { type: str, required: yes } # Custom operation name
|
93
|
+
"type": { enum: [get, post, put, delete], required: yes } # Custom operation request type
|
94
|
+
"separator": { type: str, default: / } # Separator between base URI and operation name
|
95
|
+
"resource": { type: str, required: yes } # Request resource
|
96
|
+
"id": { type: str } # Request resource id
|
97
|
+
"format": { enum: [js, xml, html], default: xml } # Request format (only applies to GET requests)
|
98
|
+
"delay": { type: str} # Delay before request is made (integer or range)
|
99
|
+
"params": # Request body parameters
|
100
|
+
&name_value_pairs
|
101
|
+
type: seq
|
102
|
+
sequence:
|
103
|
+
- type: map
|
104
|
+
mapping:
|
105
|
+
"name": { type: str, required: yes, unique: yes }
|
106
|
+
"value": { type: str, required: yes }
|
107
|
+
"headers": *name_value_pairs # Request headers
|
108
|
+
"valid_codes": # List of valid response codes (all 2xx by default)
|
109
|
+
type: seq
|
110
|
+
sequence:
|
111
|
+
- type: int
|
112
|
+
#------------------------------------------------------------------------------------------------------------------------
|
113
|
+
"guards": # GUARDS DEFINITION
|
114
|
+
type: seq
|
115
|
+
sequence:
|
116
|
+
- type: map
|
117
|
+
class: Resat::Guard
|
118
|
+
mapping:
|
119
|
+
"name": { type: str, required: yes }
|
120
|
+
"target": { enum: [header, body] } # Guard target (response header or body)
|
121
|
+
"field": { type: str } # Field guard applies to
|
122
|
+
"status": { type: int }
|
123
|
+
"pattern": { type: str } # Pattern field should match if any
|
124
|
+
"period": { type: int, default: 5 } # Period between API requests
|
125
|
+
"timeout": { type: int, default: 120 } # Guard timeout
|
126
|
+
#------------------------------------------------------------------------------------------------------------------------
|
127
|
+
"filters": # FILTERS DEFINITION
|
128
|
+
type: seq
|
129
|
+
sequence:
|
130
|
+
- type: map
|
131
|
+
class: Resat::Filter
|
132
|
+
mapping:
|
133
|
+
"name": { type: str, required: yes } # Filter name (used for logging)
|
134
|
+
"target": { enum: [header, body], required: yes } # Filter target (response header or body)
|
135
|
+
"is_empty": { type: bool, default: no } # Check target is (not) empty
|
136
|
+
"required_fields": # List of target's required fields
|
137
|
+
type: seq
|
138
|
+
sequence:
|
139
|
+
- type: str
|
140
|
+
"validators": # List of validators
|
141
|
+
type: seq
|
142
|
+
sequence:
|
143
|
+
- type: map
|
144
|
+
class: Resat::Validator
|
145
|
+
mapping:
|
146
|
+
"field": { type: str, required: yes } # Field validator applies to
|
147
|
+
"is_empty": { type: bool, default: no } # Check field is (not) empty
|
148
|
+
"pattern": { type: str } # Regular expression field must match
|
149
|
+
"extractors": # List of extractors
|
150
|
+
type: seq
|
151
|
+
sequence:
|
152
|
+
- type: map
|
153
|
+
class: Resat::Extractor
|
154
|
+
mapping:
|
155
|
+
"field": { type: str, required: yes } # Field extractor applies to
|
156
|
+
"pattern": { type: str, pattern: /.*\(.*\).*/ } # Pattern used to extract data (if any)
|
157
|
+
"variable": { type: str, required: yes, unique: yes } # Variable extracted data should be stored in
|
158
|
+
"save": { type: bool, default: no } # Whether variable should be saved in output file
|
159
|
+
"export": { type: bool, default: no } # Whether variable should be exported so that other
|
160
|
+
# scenarios in same execution can use it
|
161
|
+
#------------------------------------------------------------------------------------------------------------------------
|
162
|
+
"handlers": # HANDLERS DEFINITION
|
163
|
+
type: seq
|
164
|
+
sequence:
|
165
|
+
- type: map
|
166
|
+
class: Resat::Handler
|
167
|
+
mapping:
|
168
|
+
"name": { type: str, required: yes } # Handler name (used for logging)
|
169
|
+
"module": { type: str, required: yes } # Handler moduler name
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# == Synopsis
|
2
|
+
#
|
3
|
+
# This file contains the Kwalify YAML schema for files containing serialized
|
4
|
+
# variables.
|
5
|
+
#
|
6
|
+
# resat scenarios may define filters with extractors that can save the
|
7
|
+
# extracted value to an output file specified in the config file.
|
8
|
+
#
|
9
|
+
# variables are serialized into a name value pairs YAML sequence.
|
10
|
+
#
|
11
|
+
|
12
|
+
# Schema for serialized variables
|
13
|
+
type: seq
|
14
|
+
sequence:
|
15
|
+
- type: map
|
16
|
+
mapping:
|
17
|
+
"name": { type: str, required: yes, unique: yes }
|
18
|
+
"value": { type: str, required: yes }
|
metadata
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: resat
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Raphael Simon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-12-03 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: kwalify
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.7.1
|
24
|
+
version:
|
25
|
+
description: Web scripting for the masses
|
26
|
+
email: raphael@rightscale.com
|
27
|
+
executables:
|
28
|
+
- resat
|
29
|
+
extensions: []
|
30
|
+
|
31
|
+
extra_rdoc_files:
|
32
|
+
- README.rdoc
|
33
|
+
- LICENSE
|
34
|
+
files:
|
35
|
+
- LICENSE
|
36
|
+
- README.rdoc
|
37
|
+
- Rakefile
|
38
|
+
- bin/resat
|
39
|
+
- lib/api_request.rb
|
40
|
+
- lib/config.rb
|
41
|
+
- lib/engine.rb
|
42
|
+
- lib/file_set.rb
|
43
|
+
- lib/filter.rb
|
44
|
+
- lib/guard.rb
|
45
|
+
- lib/handler.rb
|
46
|
+
- lib/kwalify_helper.rb
|
47
|
+
- lib/log.rb
|
48
|
+
- lib/net_patch.rb
|
49
|
+
- lib/rdoc_patch.rb
|
50
|
+
- lib/resat.rb
|
51
|
+
- lib/scenario_runner.rb
|
52
|
+
- lib/variables.rb
|
53
|
+
- schemas/config.yaml
|
54
|
+
- schemas/scenarios.yaml
|
55
|
+
- schemas/variables.yaml
|
56
|
+
- examples/rightscale/additional/run_server.yml
|
57
|
+
- examples/rightscale/config/resat.yaml
|
58
|
+
- examples/rightscale/README.rdoc
|
59
|
+
- examples/rightscale/scenarios/create_server.yml
|
60
|
+
- examples/rightscale/scenarios/delete_server.yml
|
61
|
+
- examples/rightscale/scenarios/list_servers.yml
|
62
|
+
- examples/twitter/additional/follow.yml
|
63
|
+
- examples/twitter/additional/send_message.yml
|
64
|
+
- examples/twitter/config/resat.yaml
|
65
|
+
- examples/twitter/output.yml
|
66
|
+
- examples/twitter/README.rdoc
|
67
|
+
- examples/twitter/scenarios/timelines.yml
|
68
|
+
- examples/twitter/scenarios/tweet.yml
|
69
|
+
has_rdoc: true
|
70
|
+
homepage: http://github.com/raphael/resat
|
71
|
+
licenses: []
|
72
|
+
|
73
|
+
post_install_message:
|
74
|
+
rdoc_options: []
|
75
|
+
|
76
|
+
require_paths:
|
77
|
+
- lib
|
78
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: "0"
|
83
|
+
version:
|
84
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - ">="
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: "0"
|
89
|
+
version:
|
90
|
+
requirements: []
|
91
|
+
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.3.5
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Web scripting for the masses
|
97
|
+
test_files: []
|
98
|
+
|