umccr-illumina / libica

:snake: Python SDK for Illumina Connected Analytics (ICA) :dragon:
MIT License
5 stars 4 forks source link

Get Activation ID script fails #75

Closed alexiswl closed 1 year ago

alexiswl commented 1 year ago

Functions

Not complete

def get_activation_id(project_id: str, pipeline_id: str, analysis_input: Dict) -> str:
    # Enter a context with an instance of the API client
    with libica.openapi.v2.ApiClient(configuration) as api_client:
        # Create an instance of the API class
        api_instance = entitlement_detail_api.EntitlementDetailApi(api_client)
        search_matching_activation_codes_for_cwl_analysis = SearchMatchingActivationCodesForCwlAnalysis(
            project_id=project_id,
            pipeline_id=pipeline_id,
            analysis_input=analysis_input,
        ) # SearchMatchingActivationCodesForCwlAnalysis |  (optional)

        # example passing only required values which don't have defaults set
        # and optional values
        try:
            # Search the best matching activation code detail for Cwl pipeline.
            api_response = api_instance.find_best_matching_activation_code_for_cwl(
                search_matching_activation_codes_for_cwl_analysis=search_matching_activation_codes_for_cwl_analysis
            )
        except libica.openapi.v2.ApiException as e:
            raise ValueError("Exception when calling EntitlementDetailApi->find_best_matching_activation_code_for_cwl: %s\n" % e)

    return api_response.id

Run

Also not complete

get_activation_id = get_activation_id(
    project_id=project_id,
    pipeline_id=workflow_id,
    analysis_input=cwl_analysis_input
)

Returns the following traceback

---------------------------------------------------------------------------
ApiValueError                             Traceback (most recent call last)
Cell In [45], line 1
----> 1 get_activation_id = get_activation_id(
      2     project_id=project_id,
      3     pipeline_id=workflow_id,
      4     analysis_input=cwl_analysis_input
      5 )

Cell In [33], line 201, in get_activation_id(project_id, pipeline_id, analysis_input)
    197 # example passing only required values which don't have defaults set
    198 # and optional values
    199 try:
    200     # Search the best matching activation code detail for Cwl pipeline.
--> 201     api_response = api_instance.find_best_matching_activation_code_for_cwl(
    202         search_matching_activation_codes_for_cwl_analysis=search_matching_activation_codes_for_cwl_analysis
    203     )
    204 except libica.openapi.v2.ApiException as e:
    205     raise ValueError("Exception when calling EntitlementDetailApi->find_best_matching_activation_code_for_cwl: %s\n" % e)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/api/entitlement_detail_api.py:471, in EntitlementDetailApi.find_best_matching_activation_code_for_cwl(self, **kwargs)
    468 kwargs['_content_type'] = kwargs.get(
    469     '_content_type')
    470 kwargs['_host_index'] = kwargs.get('_host_index')
--> 471 return self.find_best_matching_activation_code_for_cwl_endpoint.call_with_http_info(**kwargs)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/api_client.py:850, in Endpoint.call_with_http_info(self, **kwargs)
    845             header_list = self.api_client.select_header_content_type(
    846                 content_type_headers_list, self.settings['http_method'],
    847                 params['body'])
    848             params['header']['Content-Type'] = header_list
--> 850 return self.api_client.call_api(
    851     self.settings['endpoint_path'], self.settings['http_method'],
    852     params['path'],
    853     params['query'],
    854     params['header'],
    855     body=params['body'],
    856     post_params=params['form'],
    857     files=params['file'],
    858     response_type=self.settings['response_type'],
    859     auth_settings=self.settings['auth'],
    860     async_req=kwargs['async_req'],
    861     _check_type=kwargs['_check_return_type'],
    862     _return_http_data_only=kwargs['_return_http_data_only'],
    863     _preload_content=kwargs['_preload_content'],
    864     _request_timeout=kwargs['_request_timeout'],
    865     _host=_host,
    866     collection_formats=params['collection_format'])

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/api_client.py:409, in ApiClient.call_api(self, resource_path, method, path_params, query_params, header_params, body, post_params, files, response_type, auth_settings, async_req, _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host, _check_type)
    355 """Makes the HTTP request (synchronous) and returns deserialized data.
    356 
    357 To make an async_req request, set the async_req parameter.
   (...)
    406     then the method will return the response directly.
    407 """
    408 if not async_req:
--> 409     return self.__call_api(resource_path, method,
    410                            path_params, query_params, header_params,
    411                            body, post_params, files,
    412                            response_type, auth_settings,
    413                            _return_http_data_only, collection_formats,
    414                            _preload_content, _request_timeout, _host,
    415                            _check_type)
    417 return self.pool.apply_async(self.__call_api, (resource_path,
    418                                                method, path_params,
    419                                                query_params,
   (...)
    427                                                _request_timeout,
    428                                                _host, _check_type))

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/api_client.py:224, in ApiClient.__call_api(self, resource_path, method, path_params, query_params, header_params, body, post_params, files, response_type, auth_settings, _return_http_data_only, collection_formats, _preload_content, _request_timeout, _host, _check_type, _content_type)
    221                 encoding = match.group(1)
    222         response_data.data = response_data.data.decode(encoding)
--> 224     return_data = self.deserialize(
    225         response_data,
    226         response_type,
    227         _check_type
    228     )
    229 else:
    230     return_data = None

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/api_client.py:325, in ApiClient.deserialize(self, response, response_type, _check_type)
    321     received_data = response.data
    323 # store our data under the key of 'received_data' so users have some
    324 # context if they are deserializing a string and the data type is wrong
--> 325 deserialized_data = validate_and_convert_types(
    326     received_data,
    327     response_type,
    328     ['received_data'],
    329     True,
    330     _check_type,
    331     configuration=self.configuration
    332 )
    333 return deserialized_data

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1569, in validate_and_convert_types(input_value, required_types_mixed, path_to_item, spec_property_naming, _check_type, configuration)
   1566 if not valid_type:
   1567     if configuration:
   1568         # if input_value is not valid_type try to convert it
-> 1569         converted_instance = attempt_convert_item(
   1570             input_value,
   1571             valid_classes,
   1572             path_to_item,
   1573             configuration,
   1574             spec_property_naming,
   1575             key_type=False,
   1576             must_convert=True,
   1577             check_type=_check_type
   1578         )
   1579         return converted_instance
   1580     else:

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1462, in attempt_convert_item(input_value, valid_classes, path_to_item, configuration, spec_property_naming, key_type, must_convert, check_type)
   1460 except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc:
   1461     if must_convert:
-> 1462         raise conversion_exc
   1463     # if we have conversion errors when must_convert == False
   1464     # we ignore the exception and move on to the next class
   1465     continue

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1453, in attempt_convert_item(input_value, valid_classes, path_to_item, configuration, spec_property_naming, key_type, must_convert, check_type)
   1451 try:
   1452     if issubclass(valid_class, OpenApiModel):
-> 1453         return deserialize_model(input_value, valid_class,
   1454                                  path_to_item, check_type,
   1455                                  configuration, spec_property_naming)
   1456     elif valid_class == file_type:
   1457         return deserialize_file(input_value, configuration)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1373, in deserialize_model(model_data, model_class, path_to_item, check_type, configuration, spec_property_naming)
   1371 if isinstance(model_data, dict):
   1372     kw_args.update(model_data)
-> 1373     return model_class._new_from_openapi_data(**kw_args)
   1374 elif isinstance(model_data, PRIMITIVE_TYPES):
   1375     return model_class._new_from_openapi_data(model_data, **kw_args)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:45, in convert_js_args_to_python_args.<locals>.wrapped_init(_self, *args, **kwargs)
     43 if spec_property_naming:
     44     kwargs = change_keys_js_to_python(kwargs, _self if isinstance(_self, type) else _self.__class__)
---> 45 return fn(_self, *args, **kwargs)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:369, in OpenApiModel._new_from_openapi_data(cls, *args, **kwargs)
    348 visited_composed_classes = kwargs.get('_visited_composed_classes', ())
    349 if (
    350     cls.discriminator is None or
    351     cls in visited_composed_classes
   (...)
    366     # through Animal's discriminator because we passed in
    367     # _visited_composed_classes = (Animal,)
--> 369     return cls._from_openapi_data(*args, **kwargs)
    371 # Get the name and value of the discriminator property.
    372 # The discriminator name is obtained from the discriminator meta-data
    373 # and the discriminator value is obtained from the input data.
    374 discr_propertyname_py = list(cls.discriminator.keys())[0]

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:45, in convert_js_args_to_python_args.<locals>.wrapped_init(_self, *args, **kwargs)
     43 if spec_property_naming:
     44     kwargs = change_keys_js_to_python(kwargs, _self if isinstance(_self, type) else _self.__class__)
---> 45 return fn(_self, *args, **kwargs)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model/activation_code_detail.py:194, in ActivationCodeDetail._from_openapi_data(cls, id, pipeline_bundle, usages, *args, **kwargs)
    191 self._visited_composed_classes = _visited_composed_classes + (self.__class__,)
    193 self.id = id
--> 194 self.pipeline_bundle = pipeline_bundle
    195 self.usages = usages
    196 for var_name, var_value in kwargs.items():

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:184, in OpenApiModel.__setattr__(self, attr, value)
    182 def __setattr__(self, attr, value):
    183     """set the value of an attribute using dot notation: `instance.attr = val`"""
--> 184     self[attr] = value

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:509, in ModelNormal.__setitem__(self, name, value)
    506     self.__dict__[name] = value
    507     return
--> 509 self.set_attribute(name, value)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:156, in OpenApiModel.set_attribute(self, name, value)
    148     raise ApiTypeError(
    149         error_msg,
    150         path_to_item=path_to_item,
    151         valid_classes=(str,),
    152         key_type=True
    153     )
    155 if self._check_type:
--> 156     value = validate_and_convert_types(
    157         value, required_types_mixed, path_to_item, self._spec_property_naming,
    158         self._check_type, configuration=self._configuration)
    159 if (name,) in self.allowed_values:
    160     check_allowed_values(
    161         self.allowed_values,
    162         (name,),
    163         value
    164     )

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1569, in validate_and_convert_types(input_value, required_types_mixed, path_to_item, spec_property_naming, _check_type, configuration)
   1566 if not valid_type:
   1567     if configuration:
   1568         # if input_value is not valid_type try to convert it
-> 1569         converted_instance = attempt_convert_item(
   1570             input_value,
   1571             valid_classes,
   1572             path_to_item,
   1573             configuration,
   1574             spec_property_naming,
   1575             key_type=False,
   1576             must_convert=True,
   1577             check_type=_check_type
   1578         )
   1579         return converted_instance
   1580     else:

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1462, in attempt_convert_item(input_value, valid_classes, path_to_item, configuration, spec_property_naming, key_type, must_convert, check_type)
   1460 except (ApiTypeError, ApiValueError, ApiKeyError) as conversion_exc:
   1461     if must_convert:
-> 1462         raise conversion_exc
   1463     # if we have conversion errors when must_convert == False
   1464     # we ignore the exception and move on to the next class
   1465     continue

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1453, in attempt_convert_item(input_value, valid_classes, path_to_item, configuration, spec_property_naming, key_type, must_convert, check_type)
   1451 try:
   1452     if issubclass(valid_class, OpenApiModel):
-> 1453         return deserialize_model(input_value, valid_class,
   1454                                  path_to_item, check_type,
   1455                                  configuration, spec_property_naming)
   1456     elif valid_class == file_type:
   1457         return deserialize_file(input_value, configuration)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1373, in deserialize_model(model_data, model_class, path_to_item, check_type, configuration, spec_property_naming)
   1371 if isinstance(model_data, dict):
   1372     kw_args.update(model_data)
-> 1373     return model_class._new_from_openapi_data(**kw_args)
   1374 elif isinstance(model_data, PRIMITIVE_TYPES):
   1375     return model_class._new_from_openapi_data(model_data, **kw_args)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:45, in convert_js_args_to_python_args.<locals>.wrapped_init(_self, *args, **kwargs)
     43 if spec_property_naming:
     44     kwargs = change_keys_js_to_python(kwargs, _self if isinstance(_self, type) else _self.__class__)
---> 45 return fn(_self, *args, **kwargs)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:369, in OpenApiModel._new_from_openapi_data(cls, *args, **kwargs)
    348 visited_composed_classes = kwargs.get('_visited_composed_classes', ())
    349 if (
    350     cls.discriminator is None or
    351     cls in visited_composed_classes
   (...)
    366     # through Animal's discriminator because we passed in
    367     # _visited_composed_classes = (Animal,)
--> 369     return cls._from_openapi_data(*args, **kwargs)
    371 # Get the name and value of the discriminator property.
    372 # The discriminator name is obtained from the discriminator meta-data
    373 # and the discriminator value is obtained from the input data.
    374 discr_propertyname_py = list(cls.discriminator.keys())[0]

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:45, in convert_js_args_to_python_args.<locals>.wrapped_init(_self, *args, **kwargs)
     43 if spec_property_naming:
     44     kwargs = change_keys_js_to_python(kwargs, _self if isinstance(_self, type) else _self.__class__)
---> 45 return fn(_self, *args, **kwargs)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model/pipeline_bundle.py:216, in PipelineBundle._from_openapi_data(cls, id, name, active_pipelines, canceled_pipelines, retired_pipelines, regions, analysis_storages, *args, **kwargs)
    210     if var_name not in self.attribute_map and \
    211                 self._configuration is not None and \
    212                 self._configuration.discard_unknown_keys and \
    213                 self.additional_properties_type is None:
    214         # discard variable.
    215         continue
--> 216     setattr(self, var_name, var_value)
    217 return self

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:184, in OpenApiModel.__setattr__(self, attr, value)
    182 def __setattr__(self, attr, value):
    183     """set the value of an attribute using dot notation: `instance.attr = val`"""
--> 184     self[attr] = value

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:509, in ModelNormal.__setitem__(self, name, value)
    506     self.__dict__[name] = value
    507     return
--> 509 self.set_attribute(name, value)

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:166, in OpenApiModel.set_attribute(self, name, value)
    160     check_allowed_values(
    161         self.allowed_values,
    162         (name,),
    163         value
    164     )
    165 if (name,) in self.validations:
--> 166     check_validations(
    167         self.validations,
    168         (name,),
    169         value,
    170         self._configuration
    171     )
    172 self.__dict__['_data_store'][name] = value

File ~/miniforge3/envs/cwl-ica/lib/python3.8/site-packages/libica/openapi/v2/model_utils.py:1019, in check_validations(validations, input_variable_path, input_values, configuration)
   1008     raise ApiValueError(
   1009         "Invalid value for `%s`, must be a value greater than `%s`" %
   1010         (
   (...)
   1013         )
   1014     )
   1016 if (is_json_validation_enabled('minimum', configuration) and
   1017         'inclusive_minimum' in current_validations and
   1018         min_val < current_validations['inclusive_minimum']):
-> 1019     raise ApiValueError(
   1020         "Invalid value for `%s`, must be a value greater than or equal "
   1021         "to `%s`" % (
   1022             input_variable_path[0],
   1023             current_validations['inclusive_minimum']
   1024         )
   1025     )
   1026 flags = current_validations.get('regex', {}).get('flags', 0)
   1027 if (is_json_validation_enabled('pattern', configuration) and
   1028         'regex' in current_validations and
   1029         not re.search(current_validations['regex']['pattern'],
   1030                       input_values, flags=flags)):

ApiValueError: Invalid value for `max_number_of_allowed_slots`, must be a value greater than or equal to `0`

When running through curl

curl_command_list = [
    "curl", 
    "--fail", "--silent", "--location",
    "--request", "POST",
    "--url", "https://ica.illumina.com/ica/rest/api/activationCodes:findBestMatchingForCwl", \
    "--header", "Accept: application/vnd.illumina.v3+json",
    "--header", f"Authorization: Bearer {icav2_access_token}",
    "--header", "Content-Type: application/vnd.illumina.v3+json", 
    "--data", json.dumps(
        {

            "projectId": project_id,
            "pipelineId": workflow_id,
            "analysisInput": {
                "objectType": "JSON",
                "inputJson": json.dumps(input_json_converted),
                "dataIds": list(map(lambda x: x.data_id, mount_list)),
                "mounts": [
                    {
                        "dataId": mount_item.data_id,
                        "mountPath": mount_item.mount_path
                    }
                    for mount_item in mount_list
                ]
            }
        }
    )
]

curl_command_proc = run(curl_command_list, capture_output=True)

if not curl_command_proc.returncode == 0:
    print(curl_command_proc.stderr.decode())

activation_object = json.loads(curl_command_proc.stdout.decode())

print(json.dumps(activation_object, indent=2))

This shows that both allowedSlots and originalSlots are -1 even if these exceed the expected range

{
  "id": "e35494c2-0dd0-4106-9d1a-289435430a7a",
  "allowedSlots": -1,
  "usedSlots": 0,
  "movedSlots": 0,
  "originalSlots": -1,
  "pipelineBundle": {
    "id": "4318bd93-0abb-4581-8b8f-31471740f88c",
    "name": "ICA_Ent-AU_Pipeline_Entitlement",
    "maxNumberOfAllowedSlots": -1,
    "activePipelines": [],
    "canceledPipelines": [],
    "retiredPipelines": [],
    "regions": [
      {
        "id": "1efd315d-6309-4d7e-826b-d3824b0b5acb",
        "timeCreated": "2021-11-05T10:12:33Z",
        "timeModified": "2021-11-19T15:03:12Z",
        "ownerId": "8ec463f6-1acb-341b-b321-043c39d8716a",
        "tenantId": "f91bb1a0-c55f-4bce-8014-b2e60c0ec7d3",
        "tenantName": "ica-cp-admin",
        "code": "AU",
        "country": {
          "id": "68d3ebe4-83d4-4945-9e96-c140779ea107",
          "timeCreated": "2021-10-29T09:44:25Z",
          "timeModified": "2021-10-29T09:44:25Z",
          "ownerId": "499bfe9d-85bd-4588-ba70-fbc2f664bb9e",
          "tenantId": "9fec8354-853b-4ee5-b211-eb03e484d876",
          "tenantName": "Illumina",
          "code": "AU",
          "name": "Australia",
          "region": "earth"
        },
        "cityName": "Sydney"
      }
    ],
    "analysisStorages": [
      {
        "id": "3fab13dd-46e7-4b54-bb34-b80a01a99379",
        "timeCreated": "2021-11-05T10:28:20Z",
        "timeModified": "2021-11-05T10:28:20Z",
        "ownerId": "8ec463f6-1acb-341b-b321-043c39d8716a",
        "tenantId": "f91bb1a0-c55f-4bce-8014-b2e60c0ec7d3",
        "tenantName": "ica-cp-admin",
        "name": "Large",
        "description": "7.2TB"
      },
      {
        "id": "96b5a0a9-30d7-4bdb-b3f0-3113b095ef04",
        "timeCreated": "2021-11-05T10:28:20Z",
        "timeModified": "2021-11-05T10:28:20Z",
        "ownerId": "8ec463f6-1acb-341b-b321-043c39d8716a",
        "tenantId": "f91bb1a0-c55f-4bce-8014-b2e60c0ec7d3",
        "tenantName": "ica-cp-admin",
        "name": "Medium",
        "description": "2.4TB"
      },
      {
        "id": "6e1b6c8f-f913-48b2-9bd0-7fc13eda0fd0",
        "timeCreated": "2021-11-05T10:28:20Z",
        "timeModified": "2021-11-05T10:28:20Z",
        "ownerId": "8ec463f6-1acb-341b-b321-043c39d8716a",
        "tenantId": "f91bb1a0-c55f-4bce-8014-b2e60c0ec7d3",
        "tenantName": "ica-cp-admin",
        "name": "Small",
        "description": "1.2 TB"
      }
    ]
  },
  "usages": []
}
victorskl commented 1 year ago

Yup. They have fixed it in OpenAPI; in 2.1.0 it was 0.

https://github.com/umccr-illumina/libica/blob/37c75449cc7b705ad11e541c97b72e0ac8479bd4/libica/openapi/v2/model/pipeline_bundle.py#L68-L73

Now. Fixed by #84 and will come with 2.2.0

https://github.com/umccr-illumina/libica/blob/ec9e5ce82e3eef66910eaf407604706b64354677/libica/openapi/v2/model/pipeline_bundle.py#L68-L72