Skip to content

Commit 376c9c2

Browse files
author
rongzhus
authored
Merge pull request #7 from instana/fix-n-a
support zip file for bundle test
2 parents aae0094 + a886a18 commit 376c9c2

2 files changed

Lines changed: 102 additions & 64 deletions

File tree

README.md

Lines changed: 55 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -110,45 +110,36 @@ synctl get test <id> --show-json
110110
## Create a synthetic test
111111

112112
```
113-
synctl create test -t <type> --label <label> ...
113+
synctl create test [options]
114114
115115
options:
116-
-t <type>: synthetic type
117-
0 HTTPAction
118-
1 HTTPScript
119-
2 BrowserScript
120-
3 WebpageScript
121-
--label <label> test name
122-
--location [LOCATION ...] location id, support multiple locations id
123-
--description DESCRIPTION, -d DESCRIPTION
124-
description of synthetic test
125-
--frequency FREQUENCY The range is from 1 to 120min, default is 15
126-
--app-id, --application-id APP_ID
127-
set application id
128-
--url URL HTTP Request URL
129-
--operation OPERATION HTTP Request Method, GET, POST, HEAD, PUT, etc.
130-
--headers HEADERS HTTP Headers
131-
--body BODY HTTP Body
132-
--from-file FROM_FILE synthetic script, specify a file name
133-
--bundle BUNDLE synthetic script encoded with base64
134-
--script-file SCRIPT_FILE bundle script entry file, e.g, myscript.js
135-
--retries {0,1,2} retry times, value is from [0, 2]
136-
--retry-interval {1,2,3,4,5,6,7,8,9,10} retryInvertal
137-
--follow-redirect {true,false,True,False}
138-
followRedirect default True
139-
--expect-status EXPECT_STATUS
140-
expectStatus default 200
141-
--expect-json EXPECT_JSON
142-
expectJson
143-
--expect-match EXPECT_MATCH expectMatch
144-
--expect-exists EXPECT_EXISTS
145-
expectExists
146-
--expect-not-empty EXPECT_NOT_EMPTY
147-
expectNotEmpty
148-
--allow-insecure {false,true}
149-
allowInsecure
150-
--browser {chrome,firefox}
151-
set browser type
116+
-t int synthetic type
117+
0 HTTPAction
118+
1 HTTPScript
119+
2 BrowserScript
120+
3 WebpageScript
121+
--label <label> test name
122+
--location [id,...] location id, support multiple locations id
123+
--description string, -d string description of synthetic test
124+
--frequency int The range is [1, 120], unit is min, default is 15
125+
--app-id, --application-id <app-id> set application id
126+
--url URL HTTP Request URL
127+
--operation OPERATION HTTP Request Method, GET, POST, HEAD, PUT, etc.
128+
--headers HEADERS HTTP Headers
129+
--body BODY HTTP Body
130+
--from-file, -f <file> specify synthetic script file name
131+
--bundle <BASE64>, zip file synthetic script encoded with base64, or use a zip file instead
132+
--script-file <entry-name> bundle script entry file, e.g, myscript.js
133+
--retries {0,1,2} retry times, value is from [0, 2]
134+
--retry-interval [1, 10] retryInvertal
135+
--follow-redirect {true,false} followRedirect, default true
136+
--expect-status int expectStatus, expected status code, default 200
137+
--expect-json <json> expectJson
138+
--expect-match string expectMatch
139+
--expect-exists string expectExists
140+
--expect-not-empty string expectNotEmpty
141+
--allow-insecure {false,true} allowInsecure
142+
--browser {chrome,firefox} set browser type
152143
```
153144

154145
Examples:
@@ -171,6 +162,13 @@ synctl create test -t 0 --label "simple-ping" --url "https://httpbin.org/get" --
171162
# a simple API script
172163
synctl create test -t 1 --label "simple-api-script" --from-file http-scripts/http-get.js --location "$LOCATION" --frequency 5
173164
165+
# create bundle test with a zip file
166+
synctl create test -t 1 --label syn-bundle-zip-test \
167+
--bundle synthetic.zip \
168+
--script-file index.js \
169+
--location "$LOCATION" \
170+
--frequency 5
171+
174172
# create bundle test
175173
synctl create test -t 1 --label "syn-bundle-test" \
176174
--bundle "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" \
@@ -183,6 +181,23 @@ synctl create test -t 1 --label "syn-bundle-test" \
183181

184182

185183
```
184+
# create a browser script test
185+
synctl create test -t 2 \
186+
--label browser-script-test \
187+
--from-file browser.side \
188+
--location "$LOCATION" \
189+
--frequency 15
190+
191+
192+
# create browser bundle test using a zip file
193+
synctl create test -t 2 \
194+
--label browser-script-zip-test \
195+
--bundle browserscript.zip \
196+
--script-file mytest.js \
197+
--location "$LOCATION" \
198+
--frequency 15
199+
200+
# create browser bundle test using base64 string
186201
synctl create test -t 2 \
187202
--label "browserscript-test" \
188203
--location "$LOCATION" --frequency 15 \
@@ -209,7 +224,7 @@ synctl create test -t <type> --from-json payload-examples/api-script.json
209224
```
210225

211226

212-
**Note:** Support specify appliation id when create synthetic test, get an application id through command `synctl get app`.
227+
**Note:** Support specify application id when create synthetic test, get an application id through command `synctl get app`.
213228

214229

215230

@@ -288,9 +303,9 @@ synctl get app --name-filter <application-name>
288303
synctl create test -t 0 --app-id <application-id> ...
289304
```
290305

291-
## Query and Delete Synthetic Location
306+
## Manage Synthetic Locations
292307

293-
### Query synthetic location
308+
### Display synthetic location
294309

295310
```
296311
synctl get location

synctl

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@ SYN_APP = "app" # short for application
5454
POSITION_PARAMS = "commands"
5555
OPTIONS_PARAMS = "options"
5656

57+
NOT_APPLICABLE = "N/A"
58+
5759

5860
def show_version():
5961
"""show synctl version"""
@@ -104,13 +106,15 @@ synctl create test -t 0 --label simple-ping-test --url <url> --location <id> --f
104106
synctl create test -t 1 --label script-test --from-file script-name.js --location <id>
105107
106108
# create an API script bundle type
109+
synctl create test -t 1 --label script-bundle-test --bundle file.zip --script-file index.js --location <id>
107110
synctl create test -t 1 --label script-bundle-test --bundle <base64> --script-file index.js --location <id>
108111
109112
# create browserscript
110113
synctl create test -t 2 --label browserscript-test --from-file api-sample.js --browser firefox --location <id>
111114
112115
# create browserscript bundle
113-
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "base64" --script-file mytest.js --browser chrome --location <id>
116+
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "file.zip" --script-file mytest.js --browser chrome --location <id>
117+
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "<base64>" --script-file mytest.js --browser chrome --location <id>
114118
115119
# create webpagescript
116120
synctl create test -t 3 --label "webpagescript-test" --from-file side/browser.side --browser chrome --location <id>"""
@@ -181,7 +185,7 @@ class Base:
181185

182186
def set_host_token(self, new_host=None, new_token=None):
183187
if new_host is not None and new_token is not None:
184-
self.auth["host"] = new_host
188+
self.auth["host"] = new_host.rstrip('/')
185189
self.auth["token"] = new_token
186190
else:
187191
print("both --host and --token are required")
@@ -306,6 +310,10 @@ class ConfigurationFile(Base):
306310

307311
return False
308312

313+
def __remove_right_slash(self, host_name):
314+
"""remove right slash of a host"""
315+
return host_name.rstrip('/')
316+
309317
def add_an_item_to_config(self, name, host, token, set_default=False):
310318
"""add a new config"""
311319
if name is None or host is None or token is None:
@@ -314,11 +322,12 @@ class ConfigurationFile(Base):
314322
print("name, host, and token must not be none")
315323
elif self.__check_if_already_in_config(name):
316324
# update it
317-
self.update_an_item(name, host, token, set_default=set_default)
325+
self.update_an_item(name, self.__remove_right_slash(
326+
host), token, set_default=set_default)
318327
else:
319328
self.config_json.append({
320329
"name": name,
321-
"host": host,
330+
"host": self.__remove_right_slash(host),
322331
"token": token,
323332
"default": False
324333
})
@@ -376,12 +385,12 @@ class ConfigurationFile(Base):
376385
for item in self.config_json:
377386
if item["default"] is True:
378387
return {
379-
"host": item["host"],
388+
"host": self.__remove_right_slash(item["host"]),
380389
"token": item["token"]
381390
}
382391
if len(self.config_json) > 0:
383392
return {
384-
"host": self.config_json[0]["host"],
393+
"host": self.__remove_right_slash(self.config_json[0]["host"]),
385394
"token": self.config_json[0]["token"]
386395
}
387396
else:
@@ -393,7 +402,7 @@ class ConfigurationFile(Base):
393402
for item in self.config_json:
394403
if item["name"] == name:
395404
return {
396-
"host": item["host"],
405+
"host": self.__remove_right_slash(item["host"]),
397406
"token": item["token"]
398407
}
399408
raise ValueError(f"no config named {name}")
@@ -802,12 +811,19 @@ class SyntheticConfiguration(Base):
802811
print(not_found_e)
803812
sys.exit(-1)
804813

805-
def read_zip_file(self, file_name):
814+
def is_zip_file(self, file_name):
815+
"""check zip file name"""
816+
if file_name is not None and isinstance(file_name, str):
817+
return file_name.endswith('.zip')
818+
819+
def read_zip_file_to_base64(self, file_name):
820+
"""read zip file and encode with base64"""
806821
with open(file_name, 'rb') as file1:
807822
zip_content_byte = file1.read()
808823
zip_content_byte_base64 = b64encode(zip_content_byte)
809-
self.set_api_bundle_script(zip_content_byte_base64)
810-
return zip_content_byte_base64
824+
zip_content_base64_str = zip_content_byte_base64.decode('utf-8')
825+
# self.set_api_bundle_script(zip_content_base64_str)
826+
return zip_content_base64_str
811827

812828
def get_json(self):
813829
"""return payload as json"""
@@ -1361,7 +1377,7 @@ class SyntheticTest(Base):
13611377
active_length = 6
13621378
success_rate_length = 12
13631379
response_time_length = 12
1364-
location_str = "no locations"
1380+
location_str = NOT_APPLICABLE
13651381

13661382
test_type = "" if test_type is None else test_type
13671383
# show title
@@ -1393,7 +1409,7 @@ class SyntheticTest(Base):
13931409
# locations,
13941410
location_str = ','.join(t['locationDisplayLabels'])
13951411
else:
1396-
location_str = "no locations"
1412+
location_str = NOT_APPLICABLE
13971413
if test_type == "" or (test_type != "" and current_type == test_type):
13981414
print(self.fill_space(t["id"], id_length),
13991415
self.fill_space(t['label'], max_label_length),
@@ -1413,7 +1429,7 @@ class SyntheticTest(Base):
14131429
if len(t['locations']) > 0:
14141430
location_str = ','.join(t['locationDisplayLabels'])
14151431
else:
1416-
location_str = "no locations"
1432+
location_str = NOT_APPLICABLE
14171433
if test_type == "" or (test_type != "" and current_type == test_type):
14181434
print(self.fill_space(t["id"], id_length),
14191435
self.fill_space(t['label'], max_label_length),
@@ -1810,7 +1826,6 @@ class SyntheticResult(Base):
18101826
if summary_res.status_code == 200:
18111827
# extracting data in json format
18121828
data = summary_res.json()
1813-
# print("summary data:", data)
18141829
return data
18151830
elif summary_res.status_code == 400:
18161831
print(f'Bad Request: status code: {summary_res.status_code}')
@@ -2147,7 +2162,7 @@ class ParseParameter:
21472162

21482163
# options for bundle script
21492164
self.parser_create.add_argument(
2150-
'--bundle', type=str, help='synthetic script encoded with base64')
2165+
'--bundle', type=str, help='specify a zip file or use synthetic script encoded with base64')
21512166
self.parser_create.add_argument(
21522167
'--script-file', type=str, help='bundle script entry file, e.g, myscript.js')
21532168
# [0, 2]
@@ -2188,7 +2203,7 @@ class ParseParameter:
21882203

21892204
# set auth
21902205
self.parser_create.add_argument(
2191-
'--use-env', type=str, default=None, help='use a specified configuration')
2206+
'--use-env', '-e', type=str, default=None, help='use a specified configuration')
21922207
self.parser_create.add_argument(
21932208
'--host', type=str, help='set hostname')
21942209
self.parser_create.add_argument(
@@ -2201,7 +2216,7 @@ class ParseParameter:
22012216
# parser_get.add_argument('type_id', type=str,
22022217
# required=False, help='test id or location id')
22032218
self.parser_get.add_argument(
2204-
'--type', '-t', type=int, metavar='synthetic type', help='specify synthetic type')
2219+
'--type', '-t', type=int, choices=[0, 1, 2, 3], metavar='synthetic type', help='specify synthetic type')
22052220
self.parser_get.add_argument(
22062221
'id', type=str, nargs="?", help='synthetic id')
22072222
self.parser_get.add_argument(
@@ -2235,7 +2250,7 @@ class ParseParameter:
22352250
# self.parser_get.add_argument(
22362251
# '--token', type=str, help='set token')
22372252
host_token_group.add_argument(
2238-
'--use-env', type=str, default=None, help='use a specified config')
2253+
'--use-env', '-e', type=str, default=None, help='use a specified config')
22392254
host_token_group.add_argument(
22402255
'--host', type=str, help='set hostname')
22412256
host_token_group.add_argument(
@@ -2274,7 +2289,7 @@ class ParseParameter:
22742289

22752290
# parser_patch.add_mutually_exclusive_group
22762291
self.parser_patch.add_argument(
2277-
'--use-env', type=str, default=None, help='use a config hostname')
2292+
'--use-env', '-e', type=str, default=None, help='use a config hostname')
22782293
self.parser_patch.add_argument(
22792294
'--host', type=str, help='set hostname')
22802295
self.parser_patch.add_argument(
@@ -2292,7 +2307,7 @@ class ParseParameter:
22922307
'--from-data', type=str, help='new json payload')
22932308

22942309
self.parser_update.add_argument(
2295-
'--use-env', type=str, default=None, help='use a config hostname')
2310+
'--use-env', '-e', type=str, default=None, help='use a config hostname')
22962311
self.parser_update.add_argument(
22972312
'--host', type=str, help='set hostname')
22982313
self.parser_update.add_argument(
@@ -2315,7 +2330,7 @@ class ParseParameter:
23152330
'--no-locations', action="store_true", help="delete test with no locations")
23162331

23172332
self.parser_delete.add_argument(
2318-
'--use-env', type=str, default=None, help='use a config hostname')
2333+
'--use-env', '-e', type=str, default=None, help='use a config hostname')
23192334
self.parser_delete.add_argument(
23202335
'--host', type=str, help='set hostname')
23212336
self.parser_delete.add_argument(
@@ -2427,7 +2442,10 @@ def main():
24272442
syn_type_t = None
24282443
syn_window_size = get_args.window_size
24292444
if get_args.type is not None:
2430-
syn_type_t = synthetic_type[get_args.type]
2445+
try:
2446+
syn_type_t = synthetic_type[get_args.type]
2447+
except IndexError:
2448+
print("synthetic type only support 0 1 2 3", syn_type_t)
24312449

24322450
if get_args.id is None:
24332451
out_list = syn_instance.retrieve_all_synthetic_tests(
@@ -2552,13 +2570,18 @@ def main():
25522570
syn_type_t = synthetic_type[get_args.type]
25532571
payload = SyntheticConfiguration(syn_type_t, bundle_type=True)
25542572

2573+
if payload.is_zip_file(get_args.bundle):
2574+
bundle_base64_str = payload.read_zip_file_to_base64(
2575+
get_args.bundle)
2576+
else:
2577+
bundle_base64_str = get_args.bundle
25552578
# entry file
25562579
if get_args.script_file is not None:
25572580
payload.set_api_bundle_script(
2558-
get_args.bundle, script_file=get_args.script_file)
2581+
bundle_base64_str, script_file=get_args.script_file)
25592582
else:
25602583
# script file use index.js
2561-
payload.set_api_bundle_script(get_args.bundle)
2584+
payload.set_api_bundle_script(bundle_base64_str)
25622585
# BrowserScript 2, WebpageScript 3
25632586
if get_args.type in (2, 3):
25642587
payload.set_browser_type(get_args.browser)

0 commit comments

Comments
 (0)