mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 18:01:38 +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
|
||||
"directory" -> Enso_Asset_Type.Directory
|
||||
"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+".")
|
||||
|
||||
## 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_File
|
||||
import project.Enso_Cloud.Enso_User.Enso_User
|
||||
import project.Enso_Cloud.Errors.Enso_Cloud_Error
|
||||
import project.Enso_Cloud.Internal.Utils
|
||||
import project.Error.Error
|
||||
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.Unimplemented.Unimplemented
|
||||
import project.Network.HTTP.HTTP_Method.HTTP_Method
|
||||
import project.Network.URI.URI
|
||||
import project.Runtime.Context
|
||||
from project.Data.Boolean import Boolean, False, True
|
||||
from project.Data.Text.Extensions import all
|
||||
@ -82,12 +84,17 @@ type Existing_Enso_Asset
|
||||
handle_not_found _ = if_not_found
|
||||
error_handlers = Map.from_vector [["resource_missing", handle_not_found]]
|
||||
|
||||
uri = Utils.cloud_root_uri+"path/resolve"
|
||||
payload = JS_Object.from_pairs [["path", path]]
|
||||
|
||||
# TODO remove workaround - this should be a Get endpoint, not Post
|
||||
response = Context.Output.with_enabled <|
|
||||
Utils.http_request_as_json HTTP_Method.Post uri payload error_handlers=error_handlers
|
||||
uri = ((URI.from Utils.cloud_root_uri) / "path/resolve") . add_query_argument "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 it after https://github.com/enso-org/cloud-v2/pull/1236 has been deployed
|
||||
response = r.catch Enso_Cloud_Error error-> case error of
|
||||
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
|
||||
|
||||
## 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
|
||||
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 <|
|
||||
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
|
||||
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
|
||||
|
||||
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.name . should_equal "my_test_secret"
|
||||
my_secret.name . should_equal name
|
||||
my_secret.id.is_empty . should_be_false
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
Panic.with_finalizer created_secret.delete <|
|
||||
Test.with_retries <|
|
||||
fetched_secret = Enso_Secret.get "my_test_secret-2"
|
||||
fetched_secret = Enso_Secret.get name
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
wait_until_secret_is_propagated created_secret
|
||||
Panic.with_finalizer created_secret.delete <|
|
||||
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
|
||||
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"
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
|
||||
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
|
||||
|
||||
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"
|
||||
|
||||
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
|
||||
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
|
||||
Panic.with_finalizer secret_password.delete <| Test.with_retries <|
|
||||
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
|
||||
|
||||
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
|
||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||
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__)"
|
||||
|
||||
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
|
||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||
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."
|
||||
|
||||
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
|
||||
Panic.with_finalizer secret1.delete <| Test.with_retries <|
|
||||
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 <|
|
||||
mock_setup = Cloud_Tests_Setup.prepare_mock_setup
|
||||
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
|
||||
Panic.with_finalizer secret1.delete <|
|
||||
credentials = Mock_Credentials.default mock_setup.httpbin_uri . remotely_expired
|
||||
|
@ -5,6 +5,7 @@ from Standard.Table 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.Temporary_Directory
|
||||
|
||||
import project.Util
|
||||
|
||||
@ -20,7 +21,7 @@ add_specs suite_builder =
|
||||
group_builder.specify "writing Excel" <|
|
||||
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
|
||||
Panic.with_finalizer f.delete_if_exists <|
|
||||
workbook = f.read
|
||||
|
@ -1,6 +1,5 @@
|
||||
package org.enso.shttp.cloud_mock;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.util.regex.Pattern;
|
||||
@ -27,8 +26,19 @@ public class PathResolver implements CloudHandler {
|
||||
|
||||
@Override
|
||||
public void handleCloudAPI(CloudExchange exchange) throws IOException {
|
||||
JsonNode root = jsonMapper.readTree(exchange.decodeBodyAsText());
|
||||
String path = root.get("path").asText();
|
||||
String queryString = exchange.getHttpExchange().getRequestURI().getQuery();
|
||||
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);
|
||||
if (!matcher.matches()) {
|
||||
exchange.sendResponse(400, "Invalid path: " + path);
|
||||
|
Loading…
Reference in New Issue
Block a user