2020-02-09 00:34:13 +03:00
|
|
|
import datetime
|
2020-02-26 08:41:34 +03:00
|
|
|
import json
|
|
|
|
import os
|
2020-01-24 19:39:55 +03:00
|
|
|
import shlex
|
|
|
|
import subprocess
|
2020-01-25 01:47:50 +03:00
|
|
|
import sys
|
2020-02-26 08:41:34 +03:00
|
|
|
import time
|
2020-01-25 01:47:50 +03:00
|
|
|
|
2020-04-04 05:27:15 +03:00
|
|
|
import azlog
|
|
|
|
|
|
|
|
log = azlog.getLogger(__name__)
|
2020-01-24 19:39:55 +03:00
|
|
|
|
|
|
|
def _make_subprocess_error_string(res):
|
2020-02-03 20:06:42 +03:00
|
|
|
return "\n args={}\n return code={}\n stdout={}\n stderr={}".format(res.args, res.returncode, res.stdout.decode("utf-8"), res.stderr.decode("utf-8"))
|
2020-01-24 19:39:55 +03:00
|
|
|
|
|
|
|
def get_subscription():
|
2020-01-25 06:54:44 +03:00
|
|
|
cmd = [ "az", "account", "show", "--output", "tsv", "--query", "[name,id]" ]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-25 06:54:44 +03:00
|
|
|
sys.exit(1)
|
|
|
|
return res.stdout
|
2020-01-24 19:39:55 +03:00
|
|
|
|
2020-02-07 22:18:20 +03:00
|
|
|
def get_vm_private_ip(resource_group, vm_name):
|
|
|
|
cmd = [
|
|
|
|
"az", "vm", "list-ip-addresses",
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--name", vm_name,
|
|
|
|
"--query", "[0].virtualMachine.network.privateIpAddresses",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-07 22:18:20 +03:00
|
|
|
sys.exit(1)
|
|
|
|
out = res.stdout.splitlines()
|
|
|
|
return out[0].decode("utf-8")
|
|
|
|
|
2020-02-06 06:24:17 +03:00
|
|
|
def get_fqdn(resource_group, public_ip):
|
|
|
|
cmd = [
|
|
|
|
"az", "network", "public-ip", "show",
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--name", public_ip,
|
|
|
|
"--query", "dnsSettings.fqdn",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-06 06:24:17 +03:00
|
|
|
sys.exit(1)
|
|
|
|
out = res.stdout.splitlines()
|
|
|
|
return out[0].decode("utf-8")
|
|
|
|
|
|
|
|
def get_vmss_instances(resource_group, vmss_name):
|
|
|
|
cmd = [
|
|
|
|
"az", "vmss", "list-instances",
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--name", vmss_name,
|
|
|
|
"--query", "[].osProfile.computerName",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-06 06:24:17 +03:00
|
|
|
sys.exit(1)
|
|
|
|
names = [ x.decode("utf-8") for x in res.stdout.splitlines() ]
|
|
|
|
return names
|
|
|
|
|
2020-03-10 15:32:41 +03:00
|
|
|
def create_resource_group(resource_group, location, tags=None):
|
2020-01-25 01:47:50 +03:00
|
|
|
log.debug("creating resource group")
|
2020-03-10 15:32:41 +03:00
|
|
|
if tags is None:
|
|
|
|
tag_args = []
|
|
|
|
else:
|
|
|
|
tag_args = [ "--tags" ] + [ f"{t['key']}={t['value']}" for t in tags ]
|
2020-01-25 01:47:50 +03:00
|
|
|
cmd = [
|
|
|
|
"az", "group", "create",
|
|
|
|
"--name", resource_group,
|
|
|
|
"--location", location
|
2020-03-10 15:32:41 +03:00
|
|
|
] + tag_args
|
2020-01-25 01:47:50 +03:00
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-25 01:47:50 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
2020-02-09 17:22:38 +03:00
|
|
|
def delete_resource_group(resource_group, nowait):
|
2020-01-25 01:47:50 +03:00
|
|
|
log.debug("deleting resource group")
|
|
|
|
cmd = [
|
|
|
|
"az", "group", "delete",
|
|
|
|
"--name", resource_group, "--yes"
|
|
|
|
]
|
2020-02-09 17:22:38 +03:00
|
|
|
if nowait == True:
|
|
|
|
cmd.append("--no-wait")
|
|
|
|
log.debug(" ".join(cmd))
|
2020-01-25 01:47:50 +03:00
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-25 01:47:50 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
|
|
|
|
def deploy(resource_group, arm_template):
|
|
|
|
log.debug("deploying template")
|
2020-02-26 08:41:34 +03:00
|
|
|
deployname = os.path.splitext(
|
|
|
|
os.path.basename(arm_template)
|
|
|
|
)[0] + time.strftime("%Y%m%d-%H%M%S")
|
2020-01-25 01:47:50 +03:00
|
|
|
cmd = [
|
2020-03-19 20:47:16 +03:00
|
|
|
"az", "deployment", "group", "create",
|
2020-01-25 01:47:50 +03:00
|
|
|
"--resource-group", resource_group,
|
2020-02-26 08:41:34 +03:00
|
|
|
"--template-file", arm_template,
|
|
|
|
"--name", deployname,
|
|
|
|
"--no-wait"
|
2020-01-25 01:47:50 +03:00
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-25 01:47:50 +03:00
|
|
|
sys.exit(1)
|
2020-02-26 08:41:34 +03:00
|
|
|
|
2020-02-27 19:54:54 +03:00
|
|
|
return deployname
|
2020-01-25 01:47:50 +03:00
|
|
|
|
2020-02-27 19:54:54 +03:00
|
|
|
def get_deployment_status(resource_group, deployname):
|
|
|
|
cmd = [
|
|
|
|
"az", "group", "deployment", "operation", "list",
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--name", deployname
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-27 19:54:54 +03:00
|
|
|
sys.exit(1)
|
|
|
|
|
|
|
|
return json.loads(res.stdout)
|
|
|
|
|
2020-01-24 19:39:55 +03:00
|
|
|
def get_keyvault_secret(vault, key):
|
2020-01-25 01:47:50 +03:00
|
|
|
cmd = [
|
|
|
|
"az", "keyvault", "secret", "show",
|
2020-02-09 00:34:13 +03:00
|
|
|
"--name", key, "--vault-name", vault,
|
2020-01-25 01:47:50 +03:00
|
|
|
"--query", "value", "--output", "tsv"
|
|
|
|
]
|
2020-02-09 00:34:13 +03:00
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2020-01-24 19:39:55 +03:00
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("expected output"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
secret = out[0].decode('utf-8')
|
|
|
|
return secret
|
|
|
|
|
2020-01-25 01:47:50 +03:00
|
|
|
def get_storage_url(account):
|
2020-02-09 00:34:13 +03:00
|
|
|
cmd = [
|
|
|
|
"az", "storage", "account", "show",
|
|
|
|
"--name", account,
|
|
|
|
"--query", "primaryEndpoints.blob",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2020-01-24 19:39:55 +03:00
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
url = out[0].decode('utf-8')
|
|
|
|
return url
|
|
|
|
|
2020-01-25 01:47:50 +03:00
|
|
|
def get_storage_key(account):
|
2020-02-09 00:34:13 +03:00
|
|
|
cmd = [
|
|
|
|
"az", "storage", "account", "keys", "list",
|
|
|
|
"--account-name", account,
|
|
|
|
"--query", "[0].value",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2020-01-24 19:39:55 +03:00
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
key = out[0].decode('utf-8')
|
|
|
|
return key
|
|
|
|
|
2020-03-10 04:20:30 +03:00
|
|
|
def get_storage_saskey(account, container, permissions):
|
|
|
|
log.debug(f"creating sas key: container={container}, permissions={permissions}")
|
2020-02-09 00:34:13 +03:00
|
|
|
start = (datetime.datetime.utcnow() - datetime.timedelta(hours=2)).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
expiry = (datetime.datetime.utcnow() + datetime.timedelta(hours=1)).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
|
|
cmd = [
|
|
|
|
"az", "storage", "container", "generate-sas",
|
|
|
|
"--account-name", account,
|
|
|
|
"--name", container,
|
2020-03-10 04:20:30 +03:00
|
|
|
"--permissions", permissions,
|
2020-02-09 00:34:13 +03:00
|
|
|
"--start", start,
|
|
|
|
"--expiry", expiry,
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
2020-01-24 19:39:55 +03:00
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-01-24 19:39:55 +03:00
|
|
|
saskey = out[0].decode('utf-8')
|
|
|
|
return saskey
|
|
|
|
|
2020-02-09 00:34:13 +03:00
|
|
|
def get_log_analytics_workspace(resource_group, name):
|
|
|
|
cmd = [
|
|
|
|
"az", "monitor", "log-analytics", "workspace", "list",
|
|
|
|
"--query", f"[?name=='{name}'&&resourceGroup=='{resource_group}'].customerId",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
saskey = out[0].decode('utf-8')
|
|
|
|
return saskey
|
|
|
|
|
|
|
|
def get_log_analytics_key(resource_group, name):
|
|
|
|
cmd = [
|
|
|
|
"az", "monitor", "log-analytics", "workspace", "get-shared-keys",
|
|
|
|
"--workspace-name", name,
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--query", "primarySharedKey",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
saskey = out[0].decode('utf-8')
|
|
|
|
return saskey
|
|
|
|
|
2020-03-14 12:19:38 +03:00
|
|
|
def get_anf_volume_ip(resource_group, account, pool, volume):
|
|
|
|
cmd = [
|
|
|
|
"az", "netappfiles", "list-mount-targets",
|
|
|
|
"--resource-group", resource_group,
|
|
|
|
"--account-name", account,
|
|
|
|
"--pool-name", pool,
|
|
|
|
"--volume-name", volume,
|
|
|
|
"--query", "[0].ipAddress",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
|
|
|
ip = out[0].decode('utf-8')
|
|
|
|
return ip
|
|
|
|
|
2020-02-09 00:34:13 +03:00
|
|
|
def get_acr_key(name):
|
|
|
|
cmd = [
|
|
|
|
"az", "acr", "credential", "show",
|
|
|
|
"--name", name,
|
|
|
|
"--query", "passwords[0].value",
|
|
|
|
"--output", "tsv"
|
|
|
|
]
|
|
|
|
res = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
|
|
|
if res.returncode != 0:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("invalid returncode"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
out = res.stdout.splitlines()
|
|
|
|
if len(out) != 1:
|
2020-03-10 04:20:30 +03:00
|
|
|
log.error("unexpected output"+_make_subprocess_error_string(res))
|
2020-02-09 00:34:13 +03:00
|
|
|
saskey = out[0].decode('utf-8')
|
|
|
|
return saskey
|
|
|
|
|
|
|
|
|