Skip to content

Commit

Permalink
Merge pull request #7 from instana/fix-n-a
Browse files Browse the repository at this point in the history
support zip file for bundle test
  • Loading branch information
rongzhus authored Jun 16, 2023
2 parents aae0094 + a886a18 commit 376c9c2
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 64 deletions.
95 changes: 55 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,45 +110,36 @@ synctl get test <id> --show-json
## Create a synthetic test

```
synctl create test -t <type> --label <label> ...
synctl create test [options]
options:
-t <type>: synthetic type
0 HTTPAction
1 HTTPScript
2 BrowserScript
3 WebpageScript
--label <label> test name
--location [LOCATION ...] location id, support multiple locations id
--description DESCRIPTION, -d DESCRIPTION
description of synthetic test
--frequency FREQUENCY The range is from 1 to 120min, default is 15
--app-id, --application-id APP_ID
set application id
--url URL HTTP Request URL
--operation OPERATION HTTP Request Method, GET, POST, HEAD, PUT, etc.
--headers HEADERS HTTP Headers
--body BODY HTTP Body
--from-file FROM_FILE synthetic script, specify a file name
--bundle BUNDLE synthetic script encoded with base64
--script-file SCRIPT_FILE bundle script entry file, e.g, myscript.js
--retries {0,1,2} retry times, value is from [0, 2]
--retry-interval {1,2,3,4,5,6,7,8,9,10} retryInvertal
--follow-redirect {true,false,True,False}
followRedirect default True
--expect-status EXPECT_STATUS
expectStatus default 200
--expect-json EXPECT_JSON
expectJson
--expect-match EXPECT_MATCH expectMatch
--expect-exists EXPECT_EXISTS
expectExists
--expect-not-empty EXPECT_NOT_EMPTY
expectNotEmpty
--allow-insecure {false,true}
allowInsecure
--browser {chrome,firefox}
set browser type
-t int synthetic type
0 HTTPAction
1 HTTPScript
2 BrowserScript
3 WebpageScript
--label <label> test name
--location [id,...] location id, support multiple locations id
--description string, -d string description of synthetic test
--frequency int The range is [1, 120], unit is min, default is 15
--app-id, --application-id <app-id> set application id
--url URL HTTP Request URL
--operation OPERATION HTTP Request Method, GET, POST, HEAD, PUT, etc.
--headers HEADERS HTTP Headers
--body BODY HTTP Body
--from-file, -f <file> specify synthetic script file name
--bundle <BASE64>, zip file synthetic script encoded with base64, or use a zip file instead
--script-file <entry-name> bundle script entry file, e.g, myscript.js
--retries {0,1,2} retry times, value is from [0, 2]
--retry-interval [1, 10] retryInvertal
--follow-redirect {true,false} followRedirect, default true
--expect-status int expectStatus, expected status code, default 200
--expect-json <json> expectJson
--expect-match string expectMatch
--expect-exists string expectExists
--expect-not-empty string expectNotEmpty
--allow-insecure {false,true} allowInsecure
--browser {chrome,firefox} set browser type
```

Examples:
Expand All @@ -171,6 +162,13 @@ synctl create test -t 0 --label "simple-ping" --url "https://httpbin.org/get" --
# a simple API script
synctl create test -t 1 --label "simple-api-script" --from-file http-scripts/http-get.js --location "$LOCATION" --frequency 5
# create bundle test with a zip file
synctl create test -t 1 --label syn-bundle-zip-test \
--bundle synthetic.zip \
--script-file index.js \
--location "$LOCATION" \
--frequency 5
# create bundle test
synctl create test -t 1 --label "syn-bundle-test" \
--bundle "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" \
Expand All @@ -183,6 +181,23 @@ synctl create test -t 1 --label "syn-bundle-test" \


```
# create a browser script test
synctl create test -t 2 \
--label browser-script-test \
--from-file browser.side \
--location "$LOCATION" \
--frequency 15
# create browser bundle test using a zip file
synctl create test -t 2 \
--label browser-script-zip-test \
--bundle browserscript.zip \
--script-file mytest.js \
--location "$LOCATION" \
--frequency 15
# create browser bundle test using base64 string
synctl create test -t 2 \
--label "browserscript-test" \
--location "$LOCATION" --frequency 15 \
Expand All @@ -209,7 +224,7 @@ synctl create test -t <type> --from-json payload-examples/api-script.json
```


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



Expand Down Expand Up @@ -288,9 +303,9 @@ synctl get app --name-filter <application-name>
synctl create test -t 0 --app-id <application-id> ...
```

## Query and Delete Synthetic Location
## Manage Synthetic Locations

### Query synthetic location
### Display synthetic location

```
synctl get location
Expand Down
71 changes: 47 additions & 24 deletions synctl
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ SYN_APP = "app" # short for application
POSITION_PARAMS = "commands"
OPTIONS_PARAMS = "options"

NOT_APPLICABLE = "N/A"


def show_version():
"""show synctl version"""
Expand Down Expand Up @@ -104,13 +106,15 @@ synctl create test -t 0 --label simple-ping-test --url <url> --location <id> --f
synctl create test -t 1 --label script-test --from-file script-name.js --location <id>
# create an API script bundle type
synctl create test -t 1 --label script-bundle-test --bundle file.zip --script-file index.js --location <id>
synctl create test -t 1 --label script-bundle-test --bundle <base64> --script-file index.js --location <id>
# create browserscript
synctl create test -t 2 --label browserscript-test --from-file api-sample.js --browser firefox --location <id>
# create browserscript bundle
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "base64" --script-file mytest.js --browser chrome --location <id>
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "file.zip" --script-file mytest.js --browser chrome --location <id>
synctl create test -t 2 --label "browserscript-bundle-test" --bundle "<base64>" --script-file mytest.js --browser chrome --location <id>
# create webpagescript
synctl create test -t 3 --label "webpagescript-test" --from-file side/browser.side --browser chrome --location <id>"""
Expand Down Expand Up @@ -181,7 +185,7 @@ class Base:

def set_host_token(self, new_host=None, new_token=None):
if new_host is not None and new_token is not None:
self.auth["host"] = new_host
self.auth["host"] = new_host.rstrip('/')
self.auth["token"] = new_token
else:
print("both --host and --token are required")
Expand Down Expand Up @@ -306,6 +310,10 @@ class ConfigurationFile(Base):

return False

def __remove_right_slash(self, host_name):
"""remove right slash of a host"""
return host_name.rstrip('/')

def add_an_item_to_config(self, name, host, token, set_default=False):
"""add a new config"""
if name is None or host is None or token is None:
Expand All @@ -314,11 +322,12 @@ class ConfigurationFile(Base):
print("name, host, and token must not be none")
elif self.__check_if_already_in_config(name):
# update it
self.update_an_item(name, host, token, set_default=set_default)
self.update_an_item(name, self.__remove_right_slash(
host), token, set_default=set_default)
else:
self.config_json.append({
"name": name,
"host": host,
"host": self.__remove_right_slash(host),
"token": token,
"default": False
})
Expand Down Expand Up @@ -376,12 +385,12 @@ class ConfigurationFile(Base):
for item in self.config_json:
if item["default"] is True:
return {
"host": item["host"],
"host": self.__remove_right_slash(item["host"]),
"token": item["token"]
}
if len(self.config_json) > 0:
return {
"host": self.config_json[0]["host"],
"host": self.__remove_right_slash(self.config_json[0]["host"]),
"token": self.config_json[0]["token"]
}
else:
Expand All @@ -393,7 +402,7 @@ class ConfigurationFile(Base):
for item in self.config_json:
if item["name"] == name:
return {
"host": item["host"],
"host": self.__remove_right_slash(item["host"]),
"token": item["token"]
}
raise ValueError(f"no config named {name}")
Expand Down Expand Up @@ -802,12 +811,19 @@ class SyntheticConfiguration(Base):
print(not_found_e)
sys.exit(-1)

def read_zip_file(self, file_name):
def is_zip_file(self, file_name):
"""check zip file name"""
if file_name is not None and isinstance(file_name, str):
return file_name.endswith('.zip')

def read_zip_file_to_base64(self, file_name):
"""read zip file and encode with base64"""
with open(file_name, 'rb') as file1:
zip_content_byte = file1.read()
zip_content_byte_base64 = b64encode(zip_content_byte)
self.set_api_bundle_script(zip_content_byte_base64)
return zip_content_byte_base64
zip_content_base64_str = zip_content_byte_base64.decode('utf-8')
# self.set_api_bundle_script(zip_content_base64_str)
return zip_content_base64_str

def get_json(self):
"""return payload as json"""
Expand Down Expand Up @@ -1361,7 +1377,7 @@ class SyntheticTest(Base):
active_length = 6
success_rate_length = 12
response_time_length = 12
location_str = "no locations"
location_str = NOT_APPLICABLE

test_type = "" if test_type is None else test_type
# show title
Expand Down Expand Up @@ -1393,7 +1409,7 @@ class SyntheticTest(Base):
# locations,
location_str = ','.join(t['locationDisplayLabels'])
else:
location_str = "no locations"
location_str = NOT_APPLICABLE
if test_type == "" or (test_type != "" and current_type == test_type):
print(self.fill_space(t["id"], id_length),
self.fill_space(t['label'], max_label_length),
Expand All @@ -1413,7 +1429,7 @@ class SyntheticTest(Base):
if len(t['locations']) > 0:
location_str = ','.join(t['locationDisplayLabels'])
else:
location_str = "no locations"
location_str = NOT_APPLICABLE
if test_type == "" or (test_type != "" and current_type == test_type):
print(self.fill_space(t["id"], id_length),
self.fill_space(t['label'], max_label_length),
Expand Down Expand Up @@ -1810,7 +1826,6 @@ class SyntheticResult(Base):
if summary_res.status_code == 200:
# extracting data in json format
data = summary_res.json()
# print("summary data:", data)
return data
elif summary_res.status_code == 400:
print(f'Bad Request: status code: {summary_res.status_code}')
Expand Down Expand Up @@ -2147,7 +2162,7 @@ class ParseParameter:

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

# set auth
self.parser_create.add_argument(
'--use-env', type=str, default=None, help='use a specified configuration')
'--use-env', '-e', type=str, default=None, help='use a specified configuration')
self.parser_create.add_argument(
'--host', type=str, help='set hostname')
self.parser_create.add_argument(
Expand All @@ -2201,7 +2216,7 @@ class ParseParameter:
# parser_get.add_argument('type_id', type=str,
# required=False, help='test id or location id')
self.parser_get.add_argument(
'--type', '-t', type=int, metavar='synthetic type', help='specify synthetic type')
'--type', '-t', type=int, choices=[0, 1, 2, 3], metavar='synthetic type', help='specify synthetic type')
self.parser_get.add_argument(
'id', type=str, nargs="?", help='synthetic id')
self.parser_get.add_argument(
Expand Down Expand Up @@ -2235,7 +2250,7 @@ class ParseParameter:
# self.parser_get.add_argument(
# '--token', type=str, help='set token')
host_token_group.add_argument(
'--use-env', type=str, default=None, help='use a specified config')
'--use-env', '-e', type=str, default=None, help='use a specified config')
host_token_group.add_argument(
'--host', type=str, help='set hostname')
host_token_group.add_argument(
Expand Down Expand Up @@ -2274,7 +2289,7 @@ class ParseParameter:

# parser_patch.add_mutually_exclusive_group
self.parser_patch.add_argument(
'--use-env', type=str, default=None, help='use a config hostname')
'--use-env', '-e', type=str, default=None, help='use a config hostname')
self.parser_patch.add_argument(
'--host', type=str, help='set hostname')
self.parser_patch.add_argument(
Expand All @@ -2292,7 +2307,7 @@ class ParseParameter:
'--from-data', type=str, help='new json payload')

self.parser_update.add_argument(
'--use-env', type=str, default=None, help='use a config hostname')
'--use-env', '-e', type=str, default=None, help='use a config hostname')
self.parser_update.add_argument(
'--host', type=str, help='set hostname')
self.parser_update.add_argument(
Expand All @@ -2315,7 +2330,7 @@ class ParseParameter:
'--no-locations', action="store_true", help="delete test with no locations")

self.parser_delete.add_argument(
'--use-env', type=str, default=None, help='use a config hostname')
'--use-env', '-e', type=str, default=None, help='use a config hostname')
self.parser_delete.add_argument(
'--host', type=str, help='set hostname')
self.parser_delete.add_argument(
Expand Down Expand Up @@ -2427,7 +2442,10 @@ def main():
syn_type_t = None
syn_window_size = get_args.window_size
if get_args.type is not None:
syn_type_t = synthetic_type[get_args.type]
try:
syn_type_t = synthetic_type[get_args.type]
except IndexError:
print("synthetic type only support 0 1 2 3", syn_type_t)

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

if payload.is_zip_file(get_args.bundle):
bundle_base64_str = payload.read_zip_file_to_base64(
get_args.bundle)
else:
bundle_base64_str = get_args.bundle
# entry file
if get_args.script_file is not None:
payload.set_api_bundle_script(
get_args.bundle, script_file=get_args.script_file)
bundle_base64_str, script_file=get_args.script_file)
else:
# script file use index.js
payload.set_api_bundle_script(get_args.bundle)
payload.set_api_bundle_script(bundle_base64_str)
# BrowserScript 2, WebpageScript 3
if get_args.type in (2, 3):
payload.set_browser_type(get_args.browser)
Expand Down

0 comments on commit 376c9c2

Please sign in to comment.