mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 23:31:42 +03:00
Prepare for the Path resolver change to GET (#9958)
- Prepares for the Cloud API change, together with a fallback for the old API to avoid problems during migration. - This PR should be merged before the https://github.com/enso-org/cloud-v2/pull/1236 PR is _deployed_.
This commit is contained in:
parent
a53b2f0b18
commit
a2481036e6
@ -432,7 +432,7 @@ Enso_Asset_Type.from (that:Text) = case that of
|
|||||||
"file" -> Enso_Asset_Type.File
|
"file" -> Enso_Asset_Type.File
|
||||||
"directory" -> Enso_Asset_Type.Directory
|
"directory" -> Enso_Asset_Type.Directory
|
||||||
"secret" -> Enso_Asset_Type.Secret
|
"secret" -> Enso_Asset_Type.Secret
|
||||||
"connector" -> Enso_Asset_Type.Data_Link
|
"datalink" -> Enso_Asset_Type.Data_Link
|
||||||
_ -> Error.throw (Illegal_Argument.Error "Invalid asset type: "+that.pretty+".")
|
_ -> Error.throw (Illegal_Argument.Error "Invalid asset type: "+that.pretty+".")
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
|
@ -11,6 +11,7 @@ import project.Enso_Cloud.Cloud_Caching_Settings
|
|||||||
import project.Enso_Cloud.Enso_File.Enso_Asset_Type
|
import project.Enso_Cloud.Enso_File.Enso_Asset_Type
|
||||||
import project.Enso_Cloud.Enso_File.Enso_File
|
import project.Enso_Cloud.Enso_File.Enso_File
|
||||||
import project.Enso_Cloud.Enso_User.Enso_User
|
import project.Enso_Cloud.Enso_User.Enso_User
|
||||||
|
import project.Enso_Cloud.Errors.Enso_Cloud_Error
|
||||||
import project.Enso_Cloud.Internal.Utils
|
import project.Enso_Cloud.Internal.Utils
|
||||||
import project.Error.Error
|
import project.Error.Error
|
||||||
import project.Errors.Common.Not_Found
|
import project.Errors.Common.Not_Found
|
||||||
@ -18,6 +19,7 @@ import project.Errors.File_Error.File_Error
|
|||||||
import project.Errors.Illegal_Argument.Illegal_Argument
|
import project.Errors.Illegal_Argument.Illegal_Argument
|
||||||
import project.Errors.Unimplemented.Unimplemented
|
import project.Errors.Unimplemented.Unimplemented
|
||||||
import project.Network.HTTP.HTTP_Method.HTTP_Method
|
import project.Network.HTTP.HTTP_Method.HTTP_Method
|
||||||
|
import project.Network.URI.URI
|
||||||
import project.Runtime.Context
|
import project.Runtime.Context
|
||||||
from project.Data.Boolean import Boolean, False, True
|
from project.Data.Boolean import Boolean, False, True
|
||||||
from project.Data.Text.Extensions import all
|
from project.Data.Text.Extensions import all
|
||||||
@ -82,12 +84,17 @@ type Existing_Enso_Asset
|
|||||||
handle_not_found _ = if_not_found
|
handle_not_found _ = if_not_found
|
||||||
error_handlers = Map.from_vector [["resource_missing", handle_not_found]]
|
error_handlers = Map.from_vector [["resource_missing", handle_not_found]]
|
||||||
|
|
||||||
uri = Utils.cloud_root_uri+"path/resolve"
|
uri = ((URI.from Utils.cloud_root_uri) / "path/resolve") . add_query_argument "path" path
|
||||||
payload = JS_Object.from_pairs [["path", path]]
|
r = Utils.http_request_as_json HTTP_Method.Get uri error_handlers=error_handlers
|
||||||
|
## Workaround to keep compatibility with old cloud API
|
||||||
# TODO remove workaround - this should be a Get endpoint, not Post
|
TODO remove it after https://github.com/enso-org/cloud-v2/pull/1236 has been deployed
|
||||||
response = Context.Output.with_enabled <|
|
response = r.catch Enso_Cloud_Error error-> case error of
|
||||||
Utils.http_request_as_json HTTP_Method.Post uri payload error_handlers=error_handlers
|
Enso_Cloud_Error.Unexpected_Service_Error status _ ->
|
||||||
|
if status.code != 404 then r else
|
||||||
|
old_uri = (URI.from Utils.cloud_root_uri) / "path/resolve"
|
||||||
|
old_payload = JS_Object.from_pairs [["path", path]]
|
||||||
|
Context.Output.with_enabled <| Utils.http_request_as_json HTTP_Method.Post old_uri old_payload error_handlers=error_handlers
|
||||||
|
_ -> r
|
||||||
Existing_Enso_Asset.from_json response
|
Existing_Enso_Asset.from_json response
|
||||||
|
|
||||||
## PRIVATE
|
## PRIVATE
|
||||||
|
1075
package-lock.json
generated
1075
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -177,8 +177,10 @@ type Mock_Credentials
|
|||||||
type Temporary_Directory
|
type Temporary_Directory
|
||||||
Value ~get
|
Value ~get
|
||||||
|
|
||||||
|
timestamp_text -> Text = Date_Time.now.format "yyyy-MM-dd_HHmmss.fV" . replace "/" "."
|
||||||
|
|
||||||
make (name : Text) (with_initializer : (Enso_File -> Any) = (_->Nothing)) -> Temporary_Directory = Temporary_Directory.Value <|
|
make (name : Text) (with_initializer : (Enso_File -> Any) = (_->Nothing)) -> Temporary_Directory = Temporary_Directory.Value <|
|
||||||
directory_name = "test-run-"+name+"-"+(Date_Time.now.format "yyyy-MM-dd_HHmmss.fV" . replace "/" "|")
|
directory_name = "test-run-"+name+"-"+Temporary_Directory.timestamp_text
|
||||||
test_root = (Enso_File.root / directory_name).create_directory
|
test_root = (Enso_File.root / directory_name).create_directory
|
||||||
with_initializer test_root . if_not_error test_root
|
with_initializer test_root . if_not_error test_root
|
||||||
|
|
||||||
|
@ -33,9 +33,10 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
Enso_Secret.list . should_be_a Vector
|
Enso_Secret.list . should_be_a Vector
|
||||||
|
|
||||||
group_builder.specify "should allow to create, list and delete secrets" <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to create, list and delete secrets" <| setup.with_prepared_environment <|
|
||||||
my_secret = Enso_Secret.create "my_test_secret" "my_secret_value"
|
name = "my_test_secret"+Temporary_Directory.timestamp_text
|
||||||
|
my_secret = Enso_Secret.create name "my_secret_value"
|
||||||
my_secret.should_succeed
|
my_secret.should_succeed
|
||||||
my_secret.name . should_equal "my_test_secret"
|
my_secret.name . should_equal name
|
||||||
my_secret.id.is_empty . should_be_false
|
my_secret.id.is_empty . should_be_false
|
||||||
|
|
||||||
delete_on_fail my_secret <| Test.with_retries <|
|
delete_on_fail my_secret <| Test.with_retries <|
|
||||||
@ -47,26 +48,28 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
Enso_Secret.list . should_not_contain my_secret
|
Enso_Secret.list . should_not_contain my_secret
|
||||||
|
|
||||||
group_builder.specify "should allow to get a secret by name or path" <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to get a secret by name or path" <| setup.with_prepared_environment <|
|
||||||
created_secret = Enso_Secret.create "my_test_secret-2" "my_secret_value"
|
name = "my-test-secret-2-"+Temporary_Directory.timestamp_text
|
||||||
|
created_secret = Enso_Secret.create name "my_secret_value"
|
||||||
created_secret.should_succeed
|
created_secret.should_succeed
|
||||||
Panic.with_finalizer created_secret.delete <|
|
Panic.with_finalizer created_secret.delete <|
|
||||||
Test.with_retries <|
|
Test.with_retries <|
|
||||||
fetched_secret = Enso_Secret.get "my_test_secret-2"
|
fetched_secret = Enso_Secret.get name
|
||||||
fetched_secret . should_equal created_secret
|
fetched_secret . should_equal created_secret
|
||||||
|
|
||||||
path_secret = Enso_Secret.get "enso://"+Enso_User.current.organization_name+"/my_test_secret-2"
|
path_secret = Enso_Secret.get "enso://"+Enso_User.current.organization_name+"/"+name
|
||||||
path_secret . should_equal created_secret
|
path_secret . should_equal created_secret
|
||||||
|
|
||||||
group_builder.specify "does not allow both parent and path in Enso_Secret.get" <| setup.with_prepared_environment <|
|
group_builder.specify "does not allow both parent and path in Enso_Secret.get" <| setup.with_prepared_environment <|
|
||||||
Enso_Secret.get "enso://"+Enso_User.current.organization_name+"/SOME-SECRET" parent=Enso_File.root . should_fail_with Illegal_Argument
|
Enso_Secret.get "enso://"+Enso_User.current.organization_name+"/SOME-SECRET" parent=Enso_File.root . should_fail_with Illegal_Argument
|
||||||
|
|
||||||
group_builder.specify "should fail to create a secret if it already exists" <| setup.with_prepared_environment <|
|
group_builder.specify "should fail to create a secret if it already exists" <| setup.with_prepared_environment <|
|
||||||
created_secret = Enso_Secret.create "my_test_secret-3" "my_secret_value"
|
name = "my_test_secret-3-"+Temporary_Directory.timestamp_text
|
||||||
|
created_secret = Enso_Secret.create name "my_secret_value"
|
||||||
created_secret.should_succeed
|
created_secret.should_succeed
|
||||||
wait_until_secret_is_propagated created_secret
|
wait_until_secret_is_propagated created_secret
|
||||||
Panic.with_finalizer created_secret.delete <|
|
Panic.with_finalizer created_secret.delete <|
|
||||||
Test.with_retries <|
|
Test.with_retries <|
|
||||||
r1 = Enso_Secret.create "my_test_secret-3" "my_secret_value"
|
r1 = Enso_Secret.create name "my_secret_value"
|
||||||
|
|
||||||
## If the secret was created due to race condition - we clean it up
|
## If the secret was created due to race condition - we clean it up
|
||||||
TODO: this should be addressed at Cloud level, disallowing to create a secret with the same name
|
TODO: this should be addressed at Cloud level, disallowing to create a secret with the same name
|
||||||
@ -76,7 +79,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
r1.catch.to_display_text . should_contain "already exists"
|
r1.catch.to_display_text . should_contain "already exists"
|
||||||
|
|
||||||
group_builder.specify "should allow to use secrets in HTTPS request headers" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to use secrets in HTTPS request headers" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
||||||
secret1 = Enso_Secret.create "my_test_secret-6" "Yet another Mystery"
|
secret1 = Enso_Secret.create "my_test_secret-6"+Temporary_Directory.timestamp_text "Yet another Mystery"
|
||||||
secret1.should_succeed
|
secret1.should_succeed
|
||||||
|
|
||||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||||
@ -85,7 +88,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
response.decode_as_json.at "headers" . at "X-My-Secret" . should_equal "Yet another Mystery"
|
response.decode_as_json.at "headers" . at "X-My-Secret" . should_equal "Yet another Mystery"
|
||||||
|
|
||||||
group_builder.specify "should allow to derive values from secrets in Header.authorization_bearer" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to derive values from secrets in Header.authorization_bearer" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
||||||
secret_token = Enso_Secret.create "my_test_secret-7" "MySecretToken"
|
secret_token = Enso_Secret.create "my_test_secret-7"+Temporary_Directory.timestamp_text "MySecretToken"
|
||||||
secret_token.should_succeed
|
secret_token.should_succeed
|
||||||
|
|
||||||
Panic.with_finalizer secret_token.delete <| Test.with_retries <|
|
Panic.with_finalizer secret_token.delete <| Test.with_retries <|
|
||||||
@ -95,10 +98,10 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
response_json.at "headers" . at "Authorization" . should_equal "Bearer MySecretToken"
|
response_json.at "headers" . at "Authorization" . should_equal "Bearer MySecretToken"
|
||||||
|
|
||||||
group_builder.specify "should allow to derive values from secrets in Header.authorization_basic" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to derive values from secrets in Header.authorization_basic" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
||||||
secret_username = Enso_Secret.create "my_test_secret-8" "MyUsername"
|
secret_username = Enso_Secret.create "my_test_secret-8"+Temporary_Directory.timestamp_text "MyUsername"
|
||||||
secret_username.should_succeed
|
secret_username.should_succeed
|
||||||
Panic.with_finalizer secret_username.delete <|
|
Panic.with_finalizer secret_username.delete <|
|
||||||
secret_password = Enso_Secret.create "my_test_secret-9" "MyP@ssword"
|
secret_password = Enso_Secret.create "my_test_secret-9"+Temporary_Directory.timestamp_text "MyP@ssword"
|
||||||
secret_password.should_succeed
|
secret_password.should_succeed
|
||||||
Panic.with_finalizer secret_password.delete <| Test.with_retries <|
|
Panic.with_finalizer secret_password.delete <| Test.with_retries <|
|
||||||
https = setup.httpbin_secure_client
|
https = setup.httpbin_secure_client
|
||||||
@ -109,7 +112,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
response_json.at "headers" . at "Authorization" . should_equal expected
|
response_json.at "headers" . at "Authorization" . should_equal expected
|
||||||
|
|
||||||
group_builder.specify "should allow to derive values from secrets" <| setup.with_prepared_environment <|
|
group_builder.specify "should allow to derive values from secrets" <| setup.with_prepared_environment <|
|
||||||
secret1 = Enso_Secret.create "my_test_secret-10" "Something"
|
secret1 = Enso_Secret.create "my_test_secret-10"+Temporary_Directory.timestamp_text "Something"
|
||||||
secret1.should_succeed
|
secret1.should_succeed
|
||||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||||
x = Derived_Secret_Value.from "X"
|
x = Derived_Secret_Value.from "X"
|
||||||
@ -135,7 +138,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
b2.to_text . should_equal "base64(X__SECRET__)"
|
b2.to_text . should_equal "base64(X__SECRET__)"
|
||||||
|
|
||||||
group_builder.specify "does not allow secrets in HTTP headers" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
group_builder.specify "does not allow secrets in HTTP headers" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
||||||
secret1 = Enso_Secret.create "my_test_secret-11" "Something"
|
secret1 = Enso_Secret.create "my_test_secret-11"+Temporary_Directory.timestamp_text "Something"
|
||||||
secret1.should_succeed
|
secret1.should_succeed
|
||||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||||
uri = setup.httpbin_uri / "get"
|
uri = setup.httpbin_uri / "get"
|
||||||
@ -144,7 +147,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
r1.catch.to_display_text . should_contain "Secrets are not allowed in HTTP connections, use HTTPS instead."
|
r1.catch.to_display_text . should_contain "Secrets are not allowed in HTTP connections, use HTTPS instead."
|
||||||
|
|
||||||
group_builder.specify "API exposing secrets to external libraries should not be accessible from unauthorized code" <| setup.with_prepared_environment <|
|
group_builder.specify "API exposing secrets to external libraries should not be accessible from unauthorized code" <| setup.with_prepared_environment <|
|
||||||
secret1 = Enso_Secret.create "my_test_secret-12" "Something"
|
secret1 = Enso_Secret.create "my_test_secret-12"+Temporary_Directory.timestamp_text "Something"
|
||||||
secret1.should_succeed
|
secret1.should_succeed
|
||||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||||
java_repr = as_hideable_value secret1
|
java_repr = as_hideable_value secret1
|
||||||
@ -221,7 +224,7 @@ add_specs suite_builder setup:Cloud_Tests_Setup =
|
|||||||
group_builder.specify "should be able to retry fetching a secret if the token is expired" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
group_builder.specify "should be able to retry fetching a secret if the token is expired" pending=setup.httpbin_pending <| setup.with_prepared_environment <|
|
||||||
mock_setup = Cloud_Tests_Setup.prepare_mock_setup
|
mock_setup = Cloud_Tests_Setup.prepare_mock_setup
|
||||||
mock_setup.with_prepared_environment <|
|
mock_setup.with_prepared_environment <|
|
||||||
secret1 = Enso_Secret.create "my_test_secret-"+Random.uuid "Something123"
|
secret1 = Enso_Secret.create "my_test_secret-"+Temporary_Directory.timestamp_text "Something123"
|
||||||
secret1.should_succeed
|
secret1.should_succeed
|
||||||
Panic.with_finalizer secret1.delete <|
|
Panic.with_finalizer secret1.delete <|
|
||||||
credentials = Mock_Credentials.default mock_setup.httpbin_uri . remotely_expired
|
credentials = Mock_Credentials.default mock_setup.httpbin_uri . remotely_expired
|
||||||
|
@ -5,6 +5,7 @@ from Standard.Table import all
|
|||||||
from Standard.Test import all
|
from Standard.Test import all
|
||||||
|
|
||||||
import enso_dev.Base_Tests.Network.Enso_Cloud.Cloud_Tests_Setup.Cloud_Tests_Setup
|
import enso_dev.Base_Tests.Network.Enso_Cloud.Cloud_Tests_Setup.Cloud_Tests_Setup
|
||||||
|
import enso_dev.Base_Tests.Network.Enso_Cloud.Cloud_Tests_Setup.Temporary_Directory
|
||||||
|
|
||||||
import project.Util
|
import project.Util
|
||||||
|
|
||||||
@ -20,7 +21,7 @@ add_specs suite_builder =
|
|||||||
group_builder.specify "writing Excel" <|
|
group_builder.specify "writing Excel" <|
|
||||||
t = Table.new [["X", [1, 2, 3]], ["Y", ["a", "b", "c"]]]
|
t = Table.new [["X", [1, 2, 3]], ["Y", ["a", "b", "c"]]]
|
||||||
|
|
||||||
f = Enso_File.root / "write-test-"+(Date_Time.now.format "yyyy-MM-dd_HHmmss.fV" . replace "/" "|")+".xlsx"
|
f = Enso_File.root / "write-test-"+Temporary_Directory.timestamp_text+".xlsx"
|
||||||
t.write f . should_equal f
|
t.write f . should_equal f
|
||||||
Panic.with_finalizer f.delete_if_exists <|
|
Panic.with_finalizer f.delete_if_exists <|
|
||||||
workbook = f.read
|
workbook = f.read
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.enso.shttp.cloud_mock;
|
package org.enso.shttp.cloud_mock;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.JsonNode;
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -27,8 +26,19 @@ public class PathResolver implements CloudHandler {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleCloudAPI(CloudExchange exchange) throws IOException {
|
public void handleCloudAPI(CloudExchange exchange) throws IOException {
|
||||||
JsonNode root = jsonMapper.readTree(exchange.decodeBodyAsText());
|
String queryString = exchange.getHttpExchange().getRequestURI().getQuery();
|
||||||
String path = root.get("path").asText();
|
if (queryString == null) {
|
||||||
|
exchange.sendResponse(400, "Missing `path` parameter in query string (empty).");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String prefix = "path=";
|
||||||
|
if (!queryString.startsWith(prefix)) {
|
||||||
|
exchange.sendResponse(400, "Missing `path` parameter in query string: `" + queryString + "`");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String path = queryString.substring(prefix.length());
|
||||||
var matcher = pathPattern.matcher(path);
|
var matcher = pathPattern.matcher(path);
|
||||||
if (!matcher.matches()) {
|
if (!matcher.matches()) {
|
||||||
exchange.sendResponse(400, "Invalid path: " + path);
|
exchange.sendResponse(400, "Invalid path: " + path);
|
||||||
|
Loading…
Reference in New Issue
Block a user