Black formatting 2 files
This commit is contained in:
Родитель
270fc46966
Коммит
3b59366313
|
@ -19,6 +19,7 @@ RoutingOptions: TypeAlias = Literal["None", "SkipTransferOnUpdate"]
|
|||
|
||||
class SOAPFault(Exception):
|
||||
"""SOAP 1.2 Fault"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
|
@ -26,7 +27,7 @@ class SOAPFault(Exception):
|
|||
reason: str,
|
||||
role: Optional[str] = None,
|
||||
node: Optional[str],
|
||||
detail: Optional[str] = None
|
||||
detail: Optional[str] = None,
|
||||
):
|
||||
self.code = code
|
||||
self.reason = reason
|
||||
|
@ -48,9 +49,15 @@ class AddOrUpdateIncident2Args(BaseModel):
|
|||
|
||||
class AddOrUpdateIncident2Result(BaseModel):
|
||||
IncidentId: int
|
||||
Status: Literal["Invalid", "AddedNew", "UpdatedExisting",
|
||||
"DidNotChangeExisting", "AlertSourceUpdatesPending",
|
||||
"UpdateToHoldingNotAllowed", "Discarded"]
|
||||
Status: Literal[
|
||||
"Invalid",
|
||||
"AddedNew",
|
||||
"UpdatedExisting",
|
||||
"DidNotChangeExisting",
|
||||
"AlertSourceUpdatesPending",
|
||||
"UpdateToHoldingNotAllowed",
|
||||
"Discarded",
|
||||
]
|
||||
|
||||
|
||||
class ActionArgs(BaseModel):
|
||||
|
@ -60,23 +67,20 @@ class ActionArgs(BaseModel):
|
|||
|
||||
|
||||
def sorted_dict(val: T) -> T:
|
||||
"""Returns a copy of dict `val` where key-values are inserted in
|
||||
"""Returns a copy of dict `val` where key-values are inserted in
|
||||
alphabetical order. If `val` is not a dict, it's returned unchanged
|
||||
|
||||
Args:
|
||||
val (T): Any value
|
||||
|
||||
Returns:
|
||||
T: Either the same value passed in if not a dict, or a copy
|
||||
T: Either the same value passed in if not a dict, or a copy
|
||||
with keys inserted in alphabetical order
|
||||
"""
|
||||
if not isinstance(val, dict):
|
||||
return val
|
||||
|
||||
return {
|
||||
k: sorted_dict(v)
|
||||
for k, v in sorted(val.items(), key=lambda kv: kv[0])
|
||||
}
|
||||
return {k: sorted_dict(v) for k, v in sorted(val.items(), key=lambda kv: kv[0])}
|
||||
|
||||
|
||||
@overload
|
||||
|
@ -122,11 +126,7 @@ def toXML(obj: dict, xsi_namespace="i") -> str:
|
|||
NAMESPACEKEY = "$namespace"
|
||||
|
||||
def tag(
|
||||
name: str,
|
||||
value: str,
|
||||
*,
|
||||
attributes: dict = {},
|
||||
namespace: str = None
|
||||
name: str, value: str, *, attributes: dict = {}, namespace: str = None
|
||||
) -> str:
|
||||
"""Surrounds a string in xml tags
|
||||
|
||||
|
@ -139,17 +139,17 @@ def toXML(obj: dict, xsi_namespace="i") -> str:
|
|||
Returns:
|
||||
str: xml string
|
||||
"""
|
||||
attributes_str = ' '.join(f'{k}="{v}"' for k, v in attributes.items())
|
||||
attributes_str = " ".join(f'{k}="{v}"' for k, v in attributes.items())
|
||||
ns = f"{namespace}:" if namespace else ""
|
||||
if attributes_str:
|
||||
attributes_str = ' ' + attributes_str
|
||||
attributes_str = " " + attributes_str
|
||||
if value:
|
||||
return f'<{ns}{name}{attributes_str}>{value}</{ns}{name}>'
|
||||
return f'<{ns}{name}{attributes_str} />'
|
||||
return f"<{ns}{name}{attributes_str}>{value}</{ns}{name}>"
|
||||
return f"<{ns}{name}{attributes_str} />"
|
||||
|
||||
def serialize_dict(val: dict, namespace: str = None) -> str:
|
||||
ns = val.pop(NAMESPACEKEY, namespace)
|
||||
return ''.join(serialize(k, v, ns) for k, v in val.items())
|
||||
return "".join(serialize(k, v, ns) for k, v in val.items())
|
||||
|
||||
def serialize(name: str, val: Any, namespace: str = None) -> str:
|
||||
"""Serializes a key value pair into an XML element
|
||||
|
@ -168,9 +168,7 @@ def toXML(obj: dict, xsi_namespace="i") -> str:
|
|||
attrs = val.pop(ATTRIBUTESKEY, {})
|
||||
return t(serialize_dict(val, namespace), attrs)
|
||||
if isinstance(val, list):
|
||||
return t(
|
||||
''.join(serialize_dict(v, namespace=namespace) for v in val)
|
||||
)
|
||||
return t("".join(serialize_dict(v, namespace=namespace) for v in val))
|
||||
elif isinstance(val, bool):
|
||||
return t(str(val).lower())
|
||||
elif val is None:
|
||||
|
@ -188,6 +186,7 @@ def parseArgs():
|
|||
Yields:
|
||||
_type_: ActionArgs
|
||||
"""
|
||||
|
||||
def getInput(name: str, *, required=False):
|
||||
val = os.environ.get(f'INPUT_{name.replace(" ", "_").upper()}', "")
|
||||
if not val and required:
|
||||
|
@ -205,80 +204,65 @@ def parseArgs():
|
|||
) as key_file:
|
||||
yield ActionArgs(
|
||||
host=host,
|
||||
auth=AuthCert(
|
||||
cert=Path(cert_file.name), private_key=Path(key_file.name)
|
||||
),
|
||||
args=AddOrUpdateIncident2Args(**body, connectorId=connectorId)
|
||||
auth=AuthCert(cert=Path(cert_file.name), private_key=Path(key_file.name)),
|
||||
args=AddOrUpdateIncident2Args(**body, connectorId=connectorId),
|
||||
)
|
||||
|
||||
|
||||
def add_or_update_incident_2(
|
||||
host: str, auth: AuthCert, args: AddOrUpdateIncident2Args
|
||||
):
|
||||
def add_or_update_incident_2(host: str, auth: AuthCert, args: AddOrUpdateIncident2Args):
|
||||
now = datetime.utcnow().isoformat()
|
||||
soap_ns = "http://www.w3.org/2003/05/soap-envelope"
|
||||
icm_ns = "http://schemas.datacontract.org/2004/07/Microsoft.AzureAd.Icm.Types"
|
||||
baseIncident = {
|
||||
"OccurringLocation": {},
|
||||
"RaisingLocation": {},
|
||||
"Source":
|
||||
{
|
||||
"CreatedBy": "Monitor",
|
||||
"Origin": "Monitor",
|
||||
"SourceId": args.connectorId,
|
||||
"CreateDate": now,
|
||||
"ModifiedDate": now,
|
||||
},
|
||||
"Source": {
|
||||
"CreatedBy": "Monitor",
|
||||
"Origin": "Monitor",
|
||||
"SourceId": args.connectorId,
|
||||
"CreateDate": now,
|
||||
"ModifiedDate": now,
|
||||
},
|
||||
"Severity": 4,
|
||||
}
|
||||
incident = sorted_dict(
|
||||
{
|
||||
"$attributes":
|
||||
{
|
||||
"xmlns:b": icm_ns,
|
||||
"xmlns:i": "http://www.w3.org/2001/XMLSchema-instance"
|
||||
},
|
||||
"$attributes": {
|
||||
"xmlns:b": icm_ns,
|
||||
"xmlns:i": "http://www.w3.org/2001/XMLSchema-instance",
|
||||
},
|
||||
"$namespace": "b",
|
||||
**mergeLeft(baseIncident, args.incident)
|
||||
**mergeLeft(baseIncident, args.incident),
|
||||
}
|
||||
)
|
||||
soap_message = {
|
||||
"s:Envelope":
|
||||
{
|
||||
"$attributes":
|
||||
{
|
||||
"xmlns:s": soap_ns,
|
||||
"xmlns:a": "http://www.w3.org/2005/08/addressing",
|
||||
},
|
||||
"s:Header":
|
||||
{
|
||||
"a:Action":
|
||||
"http://tempuri.org/IConnectorIncidentManager/AddOrUpdateIncident2",
|
||||
"a:To":
|
||||
f"https://{host}/Connector3/ConnectorIncidentManager.svc"
|
||||
},
|
||||
"s:Body":
|
||||
{
|
||||
# Key order is significant, must be in alphabetical
|
||||
# order
|
||||
"AddOrUpdateIncident2":
|
||||
{
|
||||
"connectorId": args.connectorId,
|
||||
"incident": incident,
|
||||
"routingOptions": args.routingOptions,
|
||||
"$attributes": {
|
||||
"xmlns": "http://tempuri.org/"
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"s:Envelope": {
|
||||
"$attributes": {
|
||||
"xmlns:s": soap_ns,
|
||||
"xmlns:a": "http://www.w3.org/2005/08/addressing",
|
||||
},
|
||||
"s:Header": {
|
||||
"a:Action": "http://tempuri.org/IConnectorIncidentManager/AddOrUpdateIncident2",
|
||||
"a:To": f"https://{host}/Connector3/ConnectorIncidentManager.svc",
|
||||
},
|
||||
"s:Body": {
|
||||
# Key order is significant, must be in alphabetical
|
||||
# order
|
||||
"AddOrUpdateIncident2": {
|
||||
"connectorId": args.connectorId,
|
||||
"incident": incident,
|
||||
"routingOptions": args.routingOptions,
|
||||
"$attributes": {"xmlns": "http://tempuri.org/"},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(
|
||||
f"https://{host}/Connector3/ConnectorIncidentManager.svc",
|
||||
cert=(auth.cert, auth.private_key),
|
||||
headers={'Content-Type': 'application/soap+xml; charset=utf-8'},
|
||||
data='<?xml version="1.0" encoding="UTF-8"?>\n' + toXML(soap_message)
|
||||
headers={"Content-Type": "application/soap+xml; charset=utf-8"},
|
||||
data='<?xml version="1.0" encoding="UTF-8"?>\n' + toXML(soap_message),
|
||||
)
|
||||
|
||||
xml_result = ElementTree.fromstring(response.text)
|
||||
|
@ -288,8 +272,8 @@ def add_or_update_incident_2(
|
|||
|
||||
def innerXML(element: Optional[ElementTree.Element]) -> Optional[str]:
|
||||
return element and (
|
||||
element.text or
|
||||
''.join(ElementTree.tostring(e, 'unicode') for e in element)
|
||||
element.text
|
||||
or "".join(ElementTree.tostring(e, "unicode") for e in element)
|
||||
)
|
||||
|
||||
raise SOAPFault(
|
||||
|
@ -301,8 +285,8 @@ def add_or_update_incident_2(
|
|||
)
|
||||
|
||||
return AddOrUpdateIncident2Result(
|
||||
IncidentId=int(xml_result.findtext(f'.//{{{icm_ns}}}IncidentId')),
|
||||
Status=xml_result.findtext(f'.//{{{icm_ns}}}Status')
|
||||
IncidentId=int(xml_result.findtext(f".//{{{icm_ns}}}IncidentId")),
|
||||
Status=xml_result.findtext(f".//{{{icm_ns}}}Status"),
|
||||
)
|
||||
|
||||
|
||||
|
@ -310,7 +294,7 @@ def main():
|
|||
# Utility functions to report status to Github Action Runner
|
||||
core = {
|
||||
"debug": lambda s: print(f"::debug::{s}"),
|
||||
"error": lambda s: print(f"::error::{s}")
|
||||
"error": lambda s: print(f"::error::{s}"),
|
||||
}
|
||||
|
||||
with parseArgs() as args:
|
||||
|
|
|
@ -41,12 +41,13 @@
|
|||
"\n",
|
||||
"# Authentication package\n",
|
||||
"from azure.identity import DefaultAzureCredential\n",
|
||||
"\n",
|
||||
"credential = DefaultAzureCredential()\n",
|
||||
"\n",
|
||||
"# Get a handle to the workspace. You can find the info on the workspace tab on ml.azure.com\n",
|
||||
"ml_client = MLClient(\n",
|
||||
" credential=credential,\n",
|
||||
" subscription_id=\"<SUBSCRIPTION_ID>\", # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n",
|
||||
" subscription_id=\"<SUBSCRIPTION_ID>\", # this will look like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx\n",
|
||||
" resource_group_name=\"<RESOURCE_GROUP>\",\n",
|
||||
" workspace_name=\"<AML_WORKSPACE_NAME>\",\n",
|
||||
")"
|
||||
|
@ -252,24 +253,27 @@
|
|||
"registered_model_name = \"credit_defaults_model\"\n",
|
||||
"\n",
|
||||
"# configure the command job\n",
|
||||
"job = command( \n",
|
||||
"job = command(\n",
|
||||
" inputs=dict(\n",
|
||||
" #uri_file refers to a specific file as a data asset\n",
|
||||
" data=Input(type=\"uri_file\", path=\"https://azuremlexamples.blob.core.windows.net/datasets/credit_card/default%20of%20credit%20card%20clients.csv\"), \n",
|
||||
" test_train_ratio=0.2, #input variable in main.py\n",
|
||||
" learning_rate=0.25, #input variable in main.py\n",
|
||||
" registered_model_name=registered_model_name #input variable in main.py\n",
|
||||
" # uri_file refers to a specific file as a data asset\n",
|
||||
" data=Input(\n",
|
||||
" type=\"uri_file\",\n",
|
||||
" path=\"https://azuremlexamples.blob.core.windows.net/datasets/credit_card/default%20of%20credit%20card%20clients.csv\",\n",
|
||||
" ),\n",
|
||||
" code=\"./src/\", #location of source code\n",
|
||||
" #The inputs/outputs are accessible in the command via the ${{ ... }} notation\n",
|
||||
" command=\"python main.py --data ${{inputs.data}} --test_train_ratio ${{inputs.test_train_ratio}} --learning_rate ${{inputs.learning_rate}} --registered_model_name ${{inputs.registered_model_name}}\", \n",
|
||||
" #This is the ready-made environment you are using\n",
|
||||
" test_train_ratio=0.2, # input variable in main.py\n",
|
||||
" learning_rate=0.25, # input variable in main.py\n",
|
||||
" registered_model_name=registered_model_name, # input variable in main.py\n",
|
||||
" ),\n",
|
||||
" code=\"./src/\", # location of source code\n",
|
||||
" # The inputs/outputs are accessible in the command via the ${{ ... }} notation\n",
|
||||
" command=\"python main.py --data ${{inputs.data}} --test_train_ratio ${{inputs.test_train_ratio}} --learning_rate ${{inputs.learning_rate}} --registered_model_name ${{inputs.registered_model_name}}\",\n",
|
||||
" # This is the ready-made environment you are using\n",
|
||||
" environment=\"AzureML-sklearn-1.0-ubuntu20.04-py38-cpu@latest\",\n",
|
||||
" #This is the compute you created earlier\n",
|
||||
" # This is the compute you created earlier\n",
|
||||
" compute=\"cpu-cluster\",\n",
|
||||
" #An experiment is a container for all the iterations one does on a certain project. All the jobs submitted under the same experiment name would be listed next to each other in Azure ML studio.\n",
|
||||
" # An experiment is a container for all the iterations one does on a certain project. All the jobs submitted under the same experiment name would be listed next to each other in Azure ML studio.\n",
|
||||
" experiment_name=\"train_model_credit_default_prediction\",\n",
|
||||
" display_name=\"credit_default_prediction\" \n",
|
||||
" display_name=\"credit_default_prediction\",\n",
|
||||
")"
|
||||
]
|
||||
},
|
||||
|
@ -378,9 +382,9 @@
|
|||
"endpoint = ManagedOnlineEndpoint(\n",
|
||||
" name=online_endpoint_name,\n",
|
||||
" description=\"this is an online endpoint\",\n",
|
||||
" auth_mode=\"key\", # use \"key\" for key-based authentication. Use \"aml_token\" for Azure Machine Learning token-based authentication. \n",
|
||||
" auth_mode=\"key\", # use \"key\" for key-based authentication. Use \"aml_token\" for Azure Machine Learning token-based authentication.\n",
|
||||
" tags={\n",
|
||||
" \"training_dataset\": \"credit_defaults\", # these tags are optional\n",
|
||||
" \"training_dataset\": \"credit_defaults\", # these tags are optional\n",
|
||||
" \"model_type\": \"sklearn.GradientBoostingClassifier\",\n",
|
||||
" },\n",
|
||||
")\n",
|
||||
|
@ -455,10 +459,10 @@
|
|||
"\n",
|
||||
"# create an online deployment.\n",
|
||||
"blue_deployment = ManagedOnlineDeployment(\n",
|
||||
" name=\"blue\", # we chose color names for the deployment, you can change.\n",
|
||||
" name=\"blue\", # we chose color names for the deployment, you can change.\n",
|
||||
" endpoint_name=online_endpoint_name,\n",
|
||||
" model=model,\n",
|
||||
" instance_type=\"Standard_DS3_v2\", # this is the compute we created earlier\n",
|
||||
" instance_type=\"Standard_DS3_v2\", # this is the compute we created earlier\n",
|
||||
" instance_count=1,\n",
|
||||
")\n",
|
||||
"\n",
|
||||
|
@ -496,14 +500,62 @@
|
|||
"# write a json query for testing\n",
|
||||
"%%writefile {deploy_dir}/sample-request.json\n",
|
||||
"{\n",
|
||||
" \"input_data\": {\n",
|
||||
" \"columns\": [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22],\n",
|
||||
" \"index\": [0, 1],\n",
|
||||
" \"data\": [\n",
|
||||
" [20000,2,2,1,24,2,2,-1,-1,-2,-2,3913,3102,689,0,0,0,0,689,0,0,0,0],\n",
|
||||
" [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8]\n",
|
||||
" ]\n",
|
||||
" }\n",
|
||||
" \"input_data\": {\n",
|
||||
" \"columns\": [\n",
|
||||
" 0,\n",
|
||||
" 1,\n",
|
||||
" 2,\n",
|
||||
" 3,\n",
|
||||
" 4,\n",
|
||||
" 5,\n",
|
||||
" 6,\n",
|
||||
" 7,\n",
|
||||
" 8,\n",
|
||||
" 9,\n",
|
||||
" 10,\n",
|
||||
" 11,\n",
|
||||
" 12,\n",
|
||||
" 13,\n",
|
||||
" 14,\n",
|
||||
" 15,\n",
|
||||
" 16,\n",
|
||||
" 17,\n",
|
||||
" 18,\n",
|
||||
" 19,\n",
|
||||
" 20,\n",
|
||||
" 21,\n",
|
||||
" 22,\n",
|
||||
" ],\n",
|
||||
" \"index\": [0, 1],\n",
|
||||
" \"data\": [\n",
|
||||
" [\n",
|
||||
" 20000,\n",
|
||||
" 2,\n",
|
||||
" 2,\n",
|
||||
" 1,\n",
|
||||
" 24,\n",
|
||||
" 2,\n",
|
||||
" 2,\n",
|
||||
" -1,\n",
|
||||
" -1,\n",
|
||||
" -2,\n",
|
||||
" -2,\n",
|
||||
" 3913,\n",
|
||||
" 3102,\n",
|
||||
" 689,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" 689,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" 0,\n",
|
||||
" ],\n",
|
||||
" [10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 10, 9, 8],\n",
|
||||
" ],\n",
|
||||
" }\n",
|
||||
"}"
|
||||
]
|
||||
},
|
||||
|
|
Загрузка…
Ссылка в новой задаче