diff --git a/Algorithmia/algorithm.py b/Algorithmia/algorithm.py index 7d2adcd..04dfbaf 100644 --- a/Algorithmia/algorithm.py +++ b/Algorithmia/algorithm.py @@ -38,6 +38,47 @@ def set_options(self, timeout=300, stdout=False, output=OutputType.default, **qu self.query_parameters.update(query_parameters) return self + def get_algorithm_id(self): + url = '/v1/algorithms/' + self.username + '/' + self.algoname + print(url) + api_response = self.client.getJsonHelper(url) + if 'id' in api_response: + return api_response['id'] + else: + raise Exception("field 'id' not found in response: ", api_response) + + + def get_secrets(self): + algorithm_id = self.get_algorithm_id() + url = "/v1/algorithms/" + algorithm_id + "/secrets" + api_response = self.client.getJsonHelper(url) + return api_response + + + def set_secret(self, short_name, secret_key, secret_value, description=None): + algorithm_id = self.get_algorithm_id() + url = "/v1/algorithms/" + algorithm_id + "/secrets" + secret_providers = self.client.get_secret_providers() + provider_id = secret_providers[0]['id'] + + create_parameters = { + "owner_type": "algorithm", + "owner_id": algorithm_id, + "short_name": short_name, + "provider_id": provider_id, + "secret_key": secret_key, + "secret_value": secret_value, + } + if description: + create_parameters['description'] = description + else: + create_parameters['description'] = " " + + print(create_parameters) + api_response = self.client.postJsonHelper(url, create_parameters, parse_response_as_json=True) + return api_response + + # Create a new algorithm def create(self, details, settings, version_info=None, source=None, scmsCredentials=None): url = "/v1/algorithms/" + self.username diff --git a/Algorithmia/client.py b/Algorithmia/client.py index ffc3f03..a5121f1 100644 --- a/Algorithmia/client.py +++ b/Algorithmia/client.py @@ -177,6 +177,11 @@ def get_supported_languages(self): response = self.getHelper(url) return response.json() + def get_secret_providers(self): + url = "/v1/secret-provider" + api_response = self.getJsonHelper(url) + return api_response + def get_organization_errors(self, org_name): """Gets the errors for the organization. diff --git a/Test/api/app.py b/Test/api/app.py index 825af29..0384ae6 100644 --- a/Test/api/app.py +++ b/Test/api/app.py @@ -60,7 +60,7 @@ async def process_hello_world(request: Request, username, algoname, githash): ### Algorithm Routes @regular_app.get('/v1/algorithms/{username}/{algoname}') -async def process_get_algo(request: Request, username, algoname): +async def process_get_algo(username, algoname): if algoname == "echo" and username == 'quality': return {"id": "21df7a38-eab8-4ac8-954c-41a285535e69", "name": "echo", "details": {"summary": "", "label": "echo", "tagline": ""}, @@ -444,3 +444,99 @@ async def get_environments_by_lang(language): } ] } + + +@regular_app.get("/v1/secret-provider") +async def get_service_providers(): + return [ + { + "id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "name": "algorithmia_internal_secret_provider", + "description": "Internal Secret Provider", + "moduleName": "module", + "factoryClassName": "com.algorithmia.plugin.sqlsecretprovider.InternalSecretProviderFactory", + "interfaceVersion": "1.0", + "isEnabled": True, + "isDefault": True, + "created": "2021-03-11T20:42:23Z", + "modified": "2021-03-11T20:42:23Z" + } + ] + + +@regular_app.get("/v1/algorithms/{algorithm_id}/secrets") +async def get_secrets_for_algorithm(algorithm_id): + return { + "secrets": [ + { + "id": "45e97c47-3ae6-46be-87ee-8ab23746706b", + "short_name": "MLOPS_SERVICE_URL", + "description": "", + "secret_key": "MLOPS_SERVICE_URL", + "owner_type": "algorithm", + "owner_id": "fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created": "2022-07-22T14:36:01Z", + "modified": "2022-07-22T14:36:01Z" + }, + { + "id": "50dca60e-317f-4582-8854-5b83b4d182d0", + "short_name": "deploy_id", + "description": "", + "secret_key": "DEPLOYMENT_ID", + "owner_type": "algorithm", + "owner_id": "fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created": "2022-07-21T19:04:31Z", + "modified": "2022-07-21T19:04:31Z" + }, + { + "id": "5a75cdc8-ecc8-4715-8c4b-8038991f1608", + "short_name": "model_path", + "description": "", + "secret_key": "MODEL_PATH", + "owner_type": "algorithm", + "owner_id": "fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created": "2022-07-21T19:04:31Z", + "modified": "2022-07-21T19:04:31Z" + }, + { + "id": "80e51ed3-f6db-419d-9349-f59f4bbfdcbb", + "short_name": "model_id", + "description": "", + "secret_key": "MODEL_ID", + "owner_type": "algorithm", + "owner_id": "fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created": "2022-07-21T19:04:30Z", + "modified": "2022-07-21T19:04:30Z" + }, + { + "id": "8773c654-ea2f-4ac5-9ade-55dfc47fec9d", + "short_name": "datarobot_api_token", + "description": "", + "secret_key": "DATAROBOT_MLOPS_API_TOKEN", + "owner_type": "algorithm", + "owner_id": "fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id": "dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created": "2022-07-21T19:04:31Z", + "modified": "2022-07-21T19:04:31Z" + } + ] + } + + +@regular_app.post("/v1/algorithms/{algorithm_id}/secrets") +async def set_algorithm_secret(algorithm_id): + return { + "id":"959af771-7cd8-4981-91c4-70def15bbcdc", + "short_name":"tst", + "description":"", + "secret_key":"test", + "owner_type":"algorithm", + "owner_id":"fa2cd80b-d22a-4548-b16a-45dbad2d3499", + "provider_id":"dee00b6c-05c4-4de7-98d8-e4a3816ed75f", + "created":"2022-07-22T18:28:42Z", + "modified":"2022-07-22T18:28:42Z" +} \ No newline at end of file diff --git a/Test/regular/algo_test.py b/Test/regular/algo_test.py index b1da4af..ab63c0d 100644 --- a/Test/regular/algo_test.py +++ b/Test/regular/algo_test.py @@ -20,13 +20,15 @@ def setUpClass(cls): def test_call_customCert(self): result = self.client.algo('quality/echo').pipe(bytearray('foo', 'utf-8')) - self.assertEquals('binary', result.metadata.content_type) - self.assertEquals(bytearray('foo', 'utf-8'), result.result) + self.assertEqual('binary', result.metadata.content_type) + self.assertEqual(bytearray('foo', 'utf-8'), result.result) + + def test_normal_call(self): result = self.client.algo('quality/echo').pipe("foo") - self.assertEquals("text", result.metadata.content_type) - self.assertEquals("foo", result.result) + self.assertEqual("text", result.metadata.content_type) + self.assertEqual("foo", result.result) def test_async_call(self): result = self.client.algo('quality/echo').set_options(output=OutputType.void).pipe("foo") @@ -35,20 +37,20 @@ def test_async_call(self): def test_raw_call(self): result = self.client.algo('quality/echo').set_options(output=OutputType.raw).pipe("foo") - self.assertEquals("foo", result) + self.assertEqual("foo", result) def test_dict_call(self): result = self.client.algo('quality/echo').pipe({"foo": "bar"}) - self.assertEquals("json", result.metadata.content_type) - self.assertEquals({"foo": "bar"}, result.result) + self.assertEqual("json", result.metadata.content_type) + self.assertEqual({"foo": "bar"}, result.result) def test_algo_exists(self): result = self.client.algo('quality/echo').exists() - self.assertEquals(True, result) + self.assertEqual(True, result) def test_algo_no_exists(self): result = self.client.algo('quality/not_echo').exists() - self.assertEquals(False, result) + self.assertEqual(False, result) #TODO: add more coverage examples to check kwargs def test_get_versions(self): @@ -56,19 +58,19 @@ def test_get_versions(self): self.assertTrue('results' in result) self.assertTrue('version_info' in result['results'][0]) self.assertTrue('semantic_version' in result['results'][0]['version_info']) - self.assertEquals('0.1.0', result['results'][0]['version_info']['semantic_version']) + self.assertEqual('0.1.0', result['results'][0]['version_info']['semantic_version']) def test_text_unicode(self): telephone = u"\u260E" # Unicode input to pipe() result1 = self.client.algo('quality/echo').pipe(telephone) - self.assertEquals('text', result1.metadata.content_type) - self.assertEquals(telephone, result1.result) + self.assertEqual('text', result1.metadata.content_type) + self.assertEqual(telephone, result1.result) # Unicode return in .result result2 = self.client.algo('quality/echo').pipe(result1.result) - self.assertEquals('text', result2.metadata.content_type) - self.assertEquals(telephone, result2.result) + self.assertEqual('text', result2.metadata.content_type) + self.assertEqual(telephone, result2.result) def test_algo_info(self): result = self.client.algo('quality/echo').info() @@ -175,6 +177,16 @@ def test_algorithm_programmatic_create_process(self): self.assertEqual(response['version_info']['semantic_version'], "0.1.0", "information is incorrect") + + def test_set_secret(self): + short_name = "tst" + secret_key = "test_key" + secret_value = "test_value" + description = "loreum epsum" + response = self.client.algo("quality/echo").set_secret(short_name, secret_key, secret_value, description) + self.assertEqual(response['id'], "959af771-7cd8-4981-91c4-70def15bbcdc", "invalid ID for created secret") + + else: class AlgoTest(unittest.TestCase): def setUp(self): @@ -184,8 +196,8 @@ def test_call_customCert(self): open("./test.pem", 'w') c = Algorithmia.client(ca_cert="./test.pem") result = c.algo('quality/echo').pipe(bytearray('foo', 'utf-8')) - self.assertEquals('binary', result.metadata.content_type) - self.assertEquals(bytearray('foo', 'utf-8'), result.result) + self.assertEqual('binary', result.metadata.content_type) + self.assertEqual(bytearray('foo', 'utf-8'), result.result) try: os.remove("./test.pem") except OSError as e: @@ -193,8 +205,8 @@ def test_call_customCert(self): def test_call_binary(self): result = self.client.algo('quality/echo').pipe(bytearray('foo', 'utf-8')) - self.assertEquals('binary', result.metadata.content_type) - self.assertEquals(bytearray('foo', 'utf-8'), result.result) + self.assertEqual('binary', result.metadata.content_type) + self.assertEqual(bytearray('foo', 'utf-8'), result.result) def test_async_call(self): result = self.client.algo('quality/echo').set_options(output=OutputType.void).pipe("foo") @@ -203,7 +215,7 @@ def test_async_call(self): def test_raw_call(self): result = self.client.algo('quality/echo').set_options(output=OutputType.raw).pipe("foo") - self.assertEquals("foo", result) + self.assertEqual("foo", result) #TODO: add more coverage examples to check kwargs def test_get_versions(self): @@ -211,20 +223,20 @@ def test_get_versions(self): self.assertTrue('results' in result) self.assertTrue('version_info' in result['results'][0]) self.assertTrue('semantic_version' in result['results'][0]['version_info']) - self.assertEquals('0.1.0', result['results'][0]['version_info']['semantic_version']) + self.assertEqual('0.1.0', result['results'][0]['version_info']['semantic_version']) def test_text_unicode(self): telephone = u"\u260E" # Unicode input to pipe() result1 = self.client.algo('quality/echo').pipe(telephone) - self.assertEquals('text', result1.metadata.content_type) - self.assertEquals(telephone, result1.result) + self.assertEqual('text', result1.metadata.content_type) + self.assertEqual(telephone, result1.result) # Unicode return in .result result2 = self.client.algo('quality/echo').pipe(result1.result) - self.assertEquals('text', result2.metadata.content_type) - self.assertEquals(telephone, result2.result) + self.assertEqual('text', result2.metadata.content_type) + self.assertEqual(telephone, result2.result) def test_get_scm_status(self): diff --git a/requirements.txt b/requirements.txt index f52fe4f..207a7f0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,7 +4,7 @@ enum-compat toml argparse algorithmia-api-client==1.5.1 -algorithmia-adk>=1.2,<1.3 +algorithmia-adk>=1.2,<1.4 numpy<2 uvicorn==0.14.0 fastapi==0.65.2 diff --git a/requirements27.txt b/requirements27.txt index 9668467..8a118ea 100644 --- a/requirements27.txt +++ b/requirements27.txt @@ -4,5 +4,5 @@ enum-compat toml argparse algorithmia-api-client==1.5.1 -algorithmia-adk>=1.2,<1.3 +algorithmia-adk>=1.2,<1.4 numpy<2 diff --git a/setup.py b/setup.py index aae416c..0069b73 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,7 @@ 'toml', 'argparse', 'algorithmia-api-client==1.5.1', - 'algorithmia-adk>=1.2,<1.3' + 'algorithmia-adk>=1.2,<1.4' ], include_package_data=True, classifiers=[