diff --git a/cicd/requirements.txt b/cicd/requirements.txt index b52e1a07..5f05aab1 100644 --- a/cicd/requirements.txt +++ b/cicd/requirements.txt @@ -8,3 +8,4 @@ requests==2.32.3 robotframework==7.0.1 sqlalchemy==1.4.44 tabulate==0.9.0 +cryptography==43.0.3 diff --git a/docker-compose-testing.yml b/docker-compose-testing.yml index d606202d..239d5543 100644 --- a/docker-compose-testing.yml +++ b/docker-compose-testing.yml @@ -142,6 +142,29 @@ services: --host 0.0.0.0 \ --port \ 1090 + omnisdk_mockserver: + networks: + testing-network: + aliases: + - omnisdk.com + image: stackql/testlib + build: + context: . + dockerfile: testLib.Dockerfile + ports: + - "1071:1071/tcp" + environment: + IS_DOCKER: "${IS_DOCKER:-false}" + command: + - bash + - -c + - | + flask \ + --app=/opt/testlib/test/python/stackql_test_tooling/flask/omnisdk/app \ + run \ + --host 0.0.0.0 \ + --port \ + 1071 aws_mockserver: networks: testing-network: diff --git a/go.mod b/go.mod index 7d64b3ab..7bbc01a7 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,7 @@ require ( github.com/spf13/cobra v1.10.2 github.com/spf13/pflag v1.0.9 github.com/spf13/viper v1.10.1 - github.com/stackql-labs/omnisdk v0.1.0-alpha04 + github.com/stackql-labs/omnisdk v0.1.0-alpha06 github.com/stackql/any-sdk v0.5.4-alpha01 github.com/stackql/go-suffix-map v0.0.1-alpha01 github.com/stackql/psql-wire v0.1.2-beta01 diff --git a/go.sum b/go.sum index 09ca3590..f1d6e214 100644 --- a/go.sum +++ b/go.sum @@ -348,8 +348,8 @@ github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= github.com/spiffe/go-spiffe/v2 v2.7.0 h1:uXe1MflJoHw58wAUvxVlcM7WpKtijWG7I1UidcGh6g4= github.com/spiffe/go-spiffe/v2 v2.7.0/go.mod h1:47Q0Q9/AqGha8QLHp+kxpH4Wca7X7EnOtlIJy3mxZ3U= -github.com/stackql-labs/omnisdk v0.1.0-alpha04 h1:DRiAQ5E/tc5VtHlAfyjlzeam65+OqPi7ogeLHzUA1mA= -github.com/stackql-labs/omnisdk v0.1.0-alpha04/go.mod h1:SHUOryRWXeZip4JTWeA8iwmz4lYdBSp0nbWXDX29JrU= +github.com/stackql-labs/omnisdk v0.1.0-alpha06 h1:F8+2GCow29YMTj+VsuOOOTqHeEvvUX8+wV3nHjiLy1Y= +github.com/stackql-labs/omnisdk v0.1.0-alpha06/go.mod h1:SHUOryRWXeZip4JTWeA8iwmz4lYdBSp0nbWXDX29JrU= github.com/stackql/any-sdk v0.5.4-alpha01 h1:AyjD2Hyk7D8v1fHHtLpfeqQRxKuj7rC71dzi1Zh9LoA= github.com/stackql/any-sdk v0.5.4-alpha01/go.mod h1:BiE8uiAJMUa8n4U/yMlhvrVhE2M+5Rt8utBXYkwj9To= github.com/stackql/go-suffix-map v0.0.1-alpha01 h1:TDUDS8bySu41Oo9p0eniUeCm43mnRM6zFEd6j6VUaz8= diff --git a/internal/stackql/intrinsic/omnisdk.go b/internal/stackql/intrinsic/omnisdk.go index 892b92fc..87b189a8 100644 --- a/internal/stackql/intrinsic/omnisdk.go +++ b/internal/stackql/intrinsic/omnisdk.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "io" + "os" "sort" "strconv" "strings" @@ -19,7 +20,9 @@ import ( const methodPredicate = "method" -const streamBatchSize = 64 +// endpointEnvVar retargets omnisdk at a local mock. Transport configuration, so +// it stays out of the query. +const endpointEnvVar = "STACKQL_PREVIEW_ENDPOINT" func relationName(path string) string { return strings.ReplaceAll(path, ".", "_") @@ -147,7 +150,11 @@ func openStream( if err != nil { return nil, err } - args := omnisdk.Args{Params: params, Auth: omnisdkAuth(ctx, resourcePath)} + args := omnisdk.Args{ + Params: params, + Auth: omnisdkAuth(ctx, resourcePath), + Endpoint: os.Getenv(endpointEnvVar), + } plan, err := omnisdk.Default().New(method.Path, args) if err != nil { return nil, err @@ -175,19 +182,15 @@ func (rs *rowStream) Read() (sqldata.ISQLResult, error) { if rs.done { return rs.result(nil), io.EOF } - batch := make([]omnisdk.Row, 0, streamBatchSize) - for len(batch) < streamBatchSize && rs.rows.Next() { + rs.done = true + var batch []omnisdk.Row + for rs.rows.Next() { batch = append(batch, rs.rows.Row()) } if err := rs.rows.Err(); err != nil { - rs.done = true return rs.result(nil), err } - if len(batch) < streamBatchSize { - rs.done = true - return rs.result(batch), io.EOF - } - return rs.result(batch), nil + return rs.result(batch), io.EOF } func (rs *rowStream) result(batch []omnisdk.Row) sqldata.ISQLResult { diff --git a/internal/stackql/intrinsic/omnisdk_test.go b/internal/stackql/intrinsic/omnisdk_test.go index d0da9a27..8a6c2f80 100644 --- a/internal/stackql/intrinsic/omnisdk_test.go +++ b/internal/stackql/intrinsic/omnisdk_test.go @@ -94,31 +94,16 @@ func TestRowStreamEmitsRowsInColumnOrder(t *testing.T) { } } -func TestRowStreamBatchesLargeCursor(t *testing.T) { - total := streamBatchSize*2 + 3 +func TestRowStreamDrainsEntireCursor(t *testing.T) { + total := 200 rows := make([]omnisdk.Row, 0, total) for i := 0; i < total; i++ { rows = append(rows, omnisdk.Row{"a": fmt.Sprintf("v%d", i)}) } stream, _ := newTestStream(rows, []string{"a"}) - var reads int - var seen int - for { - res, err := stream.Read() - reads++ - seen += len(res.GetRows()) - if err != nil { - if errors.Is(err, io.EOF) { - break - } - t.Fatalf("unexpected error: %v", err) - } - } - if seen != total { - t.Fatalf("read %d rows, want %d", seen, total) - } - if reads < 3 { - t.Fatalf("cursor of %d rows was drained in %d reads; batching is not happening", total, reads) + got := drain(t, stream) + if len(got) != total { + t.Fatalf("read %d rows, want %d", len(got), total) } } diff --git a/test/assets/expected/preview/omni-storage-buckets.jsonl b/test/assets/expected/preview/omni-storage-buckets.jsonl new file mode 100644 index 00000000..19424cb0 --- /dev/null +++ b/test/assets/expected/preview/omni-storage-buckets.jsonl @@ -0,0 +1,87 @@ +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-000", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-001", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-002", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-003", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-004", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-005", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-006", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-007", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-008", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-009", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-010", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-011", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-012", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-013", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-014", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-015", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-016", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-017", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-018", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-019", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-020", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-021", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-022", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-023", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-024", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-025", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-026", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-027", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-028", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-029", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-030", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-031", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-032", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-033", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-034", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-035", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-036", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-037", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-038", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-039", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-040", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-041", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-042", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-043", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-044", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-045", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-046", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-047", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-048", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-049", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-050", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-051", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-052", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-053", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-054", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-055", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-056", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-057", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-058", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-059", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-060", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-061", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-062", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-063", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-064", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-065", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-066", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-067", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-068", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-069", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-070", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-071", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-072", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-073", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-074", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-075", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-076", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-077", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "AES256", "google_org": "123456789", "google_project": null, "https": null, "name": "bucket-078", "provider": "aws", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": "Microsoft.Storage", "google_org": "123456789", "google_project": null, "https": "true", "name": "storsub-1a", "provider": "azure", "public": "false", "region": "us-east-1", "versioning": null} +{"encryption_class": "customer-managed", "encryption_status": "Microsoft.Keyvault", "google_org": "123456789", "google_project": null, "https": "true", "name": "storsub-1b", "provider": "azure", "public": "true", "region": "us-east-1", "versioning": null} +{"encryption_class": "provider-managed", "encryption_status": "Microsoft.Storage", "google_org": "123456789", "google_project": null, "https": "true", "name": "storsub-2a", "provider": "azure", "public": "false", "region": "us-east-1", "versioning": null} +{"encryption_class": "customer-managed", "encryption_status": "Microsoft.Keyvault", "google_org": "123456789", "google_project": null, "https": "true", "name": "storsub-2b", "provider": "azure", "public": "true", "region": "us-east-1", "versioning": null} +{"encryption_class": "customer-managed", "encryption_status": "projects/p/locations/l/keyRings/r/cryptoKeys/k", "google_org": "123456789", "google_project": null, "https": "true", "name": "gcs-cmek", "provider": "gcp", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "customer-managed", "encryption_status": "projects/p/locations/l/keyRings/r/cryptoKeys/k", "google_org": "123456789", "google_project": null, "https": "true", "name": "gcs-cmek", "provider": "gcp", "public": "false", "region": "us-east-1", "versioning": "true"} +{"encryption_class": "provider-managed", "encryption_status": null, "google_org": "123456789", "google_project": null, "https": "true", "name": "gcs-plain", "provider": "gcp", "public": "true", "region": "us-east-1", "versioning": "false"} +{"encryption_class": "provider-managed", "encryption_status": null, "google_org": "123456789", "google_project": null, "https": "true", "name": "gcs-plain", "provider": "gcp", "public": "true", "region": "us-east-1", "versioning": "false"} diff --git a/test/python/stackql_test_tooling/StackQLInterfaces.py b/test/python/stackql_test_tooling/StackQLInterfaces.py index f36470e8..7af014b1 100644 --- a/test/python/stackql_test_tooling/StackQLInterfaces.py +++ b/test/python/stackql_test_tooling/StackQLInterfaces.py @@ -3,6 +3,7 @@ from asyncio import subprocess import json import os +import sys import time import typing @@ -330,10 +331,14 @@ def _run_stackql_exec_command_docker( def _get_allowed_docker_env_keys(self): return [ + 'AWS_ACCESS_KEY_ID', + 'AWS_SECRET_ACCESS_KEY', 'AZURE_CLIENT_ID', 'AZURE_CLIENT_SECRET', 'AZURE_INTEGRATION_TESTING_SUB_ID', - 'AZURE_TENANT_ID' + 'AZURE_TENANT_ID', + 'GOOGLE_APPLICATION_CREDENTIALS', + 'STACKQL_PREVIEW_ENDPOINT' ] @@ -868,6 +873,134 @@ def should_stackql_exec_inline_equal( self.should_be_equal(result.stdout, expected_output, collapse_spaces=cfg.pop('collapse_spaces', False)) + @keyword + def python_executable(self) -> str: + return sys.executable + + @keyword + def get_free_port(self) -> int: + """Reserve an ephemeral port from the OS. A fixed port is the usual cause of + a mock that starts on one CI run and not the next.""" + import socket + with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: + sock.bind(('127.0.0.1', 0)) + return sock.getsockname()[1] + + @keyword + def wait_for_server(self, url :str, timeout :float = 60, stdout :str = None, stderr :str = None): + import urllib.request + deadline = time.time() + float(timeout) + last = None + while time.time() < deadline: + try: + urllib.request.urlopen(url, timeout=2) + return + except Exception as exc: + last = exc + time.sleep(0.2) + raise AssertionError( + f'server not up at {url}: {last}\n' + f'--- stdout ---\n{self._read_if_present(stdout)}\n' + f'--- stderr ---\n{self._read_if_present(stderr)}' + ) + + def _read_if_present(self, path :str) -> str: + if not path or not os.path.exists(path): + return f'(no file at {path})' + with open(path) as fh: + return fh.read()[-4000:] + + @keyword + def write_gcp_service_account(self, path :str): + """Throwaway RSA service-account key so the OAuth exchange can sign a JWT; the + mock ignores the signature. Generated per run, never a real credential.""" + from cryptography.hazmat.primitives import serialization + from cryptography.hazmat.primitives.asymmetric import rsa + os.makedirs(os.path.dirname(path), exist_ok=True) + pem = rsa.generate_private_key(public_exponent=65537, key_size=2048).private_bytes( + serialization.Encoding.PEM, + serialization.PrivateFormat.PKCS8, + serialization.NoEncryption(), + ).decode() + with open(path, 'w') as fh: + json.dump({ + 'type': 'service_account', + 'project_id': 'mock-project', + 'client_email': 'mock@mock-project.iam.gserviceaccount.com', + 'private_key': pem, + 'token_uri': 'https://oauth2.googleapis.com/token', + }, fh) + + @keyword + def should_stackql_exec_inline_jsonl_set_equal( + self, + stackql_exe :str, + okta_secret_str :str, + github_secret_str :str, + k8s_secret_str :str, + registry_cfg :RegistryCfg, + auth_cfg_str :str, + sql_backend_cfg_str :str, + query :str, + expected_jsonl :str, + *args, + **cfg + ): + """ + Compare JSONL output against an expected set, ignoring row order. + + Relations whose rows are streamed cannot honour ORDER BY, because the rows + never reach the SQL backend. Their contents are still deterministic, so the + emitted objects are compared as an unordered multiset. + """ + repeat_count = int(cfg.pop('repeat_count', 1)) + for _ in range(repeat_count): + result = self._run_stackql_exec_command( + stackql_exe, + okta_secret_str, + github_secret_str, + k8s_secret_str, + registry_cfg, + auth_cfg_str, + sql_backend_cfg_str, + query, + '-o=jsonl', + *args, + **cfg + ) + # Under docker the compose status logs land on stderr (see + # _verify_both_streams), so stderr is only a usable failure signal natively. + if self._execution_platform != 'docker': + if result.stderr is not None and result.stderr.strip() != '': + raise Exception(f'query emitted stderr, so the row set is not trustworthy: {result.stderr.strip()}') + self._verify_jsonl_set(result.stdout, expected_jsonl, result.stderr) + + def _verify_jsonl_set(self, actual_stdout :str, expected_jsonl :str, actual_stderr :str = None): + actual = self._parse_jsonl(actual_stdout, 'actual') + expected = self._parse_jsonl(expected_jsonl, 'expected') + if actual == expected: + return + missing = [r for r in expected if expected.count(r) > actual.count(r)] + unexpected = [r for r in actual if actual.count(r) > expected.count(r)] + raise Exception( + f'JSONL row sets differ.\nMissing ({len(missing)}): {missing[:5]}\n' + f'Unexpected ({len(unexpected)}): {unexpected[:5]}\n' + f'stderr: {(actual_stderr or "").strip()[-2000:]}' + ) + + def _parse_jsonl(self, payload :str, label :str) -> list: + rows = [] + for line_number, line in enumerate(payload.splitlines(), start=1): + stripped = line.strip() + if not stripped: + continue + try: + parsed = json.loads(stripped) + except json.JSONDecodeError as exc: + raise Exception(f'{label} line {line_number} is not JSON: {stripped!r}') from exc + rows.append(json.dumps(parsed, sort_keys=True)) + return sorted(rows) + @keyword def should_stackql_exec_inline_equal_both_streams( self, @@ -1153,4 +1286,3 @@ def should_horrid_http_log_enabled_query_stackql_inline_equal( collapse_spaces=cfg.pop('collapse_spaces', False), strip_spaces=cfg.pop('strip_spaces', False), ) - diff --git a/test/python/stackql_test_tooling/flask/omnisdk/OMNISDK_VERSION.txt b/test/python/stackql_test_tooling/flask/omnisdk/OMNISDK_VERSION.txt new file mode 100644 index 00000000..d70f8948 --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/OMNISDK_VERSION.txt @@ -0,0 +1 @@ +omnisdk@v0.1.0-alpha06 diff --git a/test/python/stackql_test_tooling/flask/omnisdk/app.py b/test/python/stackql_test_tooling/flask/omnisdk/app.py new file mode 100644 index 00000000..859679fa --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/app.py @@ -0,0 +1,212 @@ +"""Mock AWS + GCP endpoints (path-style) for omnicli robot tests. + +AWS (from captured collateral): + GET / -> ListBuckets (jinja from collateral/buckets.json) + GET /?encryption -> GetBucketEncryption (raw collateral/encryption/.xml) + GET /?Action=Create* -> EC2 (jinja from collateral/ec2) + +GCP (synthesized; async create → operation → poll DONE): + POST /token -> OAuth token + POST /compute/v1/projects/

/global/networks -> Operation selfLink (op-net) + POST /compute/v1/projects/

/regions//subnetworks -> Operation selfLink (op-subnet) + GET /compute/v1/op/ -> DONE operation (targetId/targetLink) + +Run: PORT=8085 python test/mock/app.py (or via the robot suite). +""" + +import json +import os +import pathlib + +from flask import Flask, Response, jsonify, render_template, request + +HERE = pathlib.Path(__file__).parent +COLL = HERE / "collateral" +XML = "application/xml" + +app = Flask(__name__, template_folder=str(HERE / "templates")) +BUCKETS = json.loads((COLL / "buckets.json").read_text()) +PROVISION = json.loads((COLL / "ec2" / "provision.json").read_text()) + +NOT_FOUND = ( + '' + "ServerSideEncryptionConfigurationNotFoundError" +) + + +@app.get("/") +def list_buckets(): + # GET / is S3 ListBuckets. + return Response(render_template("list_buckets.xml.j2", buckets=BUCKETS), mimetype=XML) + + +@app.post("/") +def ec2_query(): + # EC2 Query API: params ride the POST form body (Action, VpcId, ...). + action = request.form.get("Action") + if action == "CreateVpc": + return Response(render_template("create_vpc.xml.j2", **PROVISION), mimetype=XML) + if action == "CreateSubnet": + # Enforce the β binding: CreateSubnet must carry the VPC id CreateVpc returned. + if request.form.get("VpcId") != PROVISION["vpc_id"]: + return Response("InvalidVpcID.NotFound", status=400, mimetype=XML) + return Response(render_template("create_subnet.xml.j2", **PROVISION), mimetype=XML) + return Response("InvalidAction", status=400, mimetype=XML) + + +@app.get("/") +def bucket_op(bucket): + if "versioning" in request.args: + return Response("Enabled", mimetype=XML) + if "publicAccessBlock" in request.args: + return Response( + "true" + "", mimetype=XML) + if "encryption" not in request.args: + return Response("NotImplemented", status=501, mimetype=XML) + path = COLL / "encryption" / f"{bucket}.xml" + if not path.exists(): + return Response(NOT_FOUND, status=404, mimetype=XML) + return Response(path.read_text(), mimetype=XML) + + +# --- GCP --------------------------------------------------------------------- + + +@app.post("/token") +def gcp_token(): + return jsonify(access_token="mock-access-token", expires_in=3600, token_type="Bearer") + + +@app.post("/compute/v1/projects//global/networks") +def gcp_create_network(project): + base = request.host_url.rstrip("/") + return jsonify(name="op-net", selfLink=f"{base}/compute/v1/op/op-net", status="PENDING") + + +@app.post("/compute/v1/projects//regions//subnetworks") +def gcp_create_subnet(project, region): + base = request.host_url.rstrip("/") + return jsonify(name="op-subnet", selfLink=f"{base}/compute/v1/op/op-subnet", status="PENDING") + + +@app.get("/compute/v1/op/") +def gcp_operation(op): + base = request.host_url.rstrip("/") + if op == "op-net": + return jsonify(name=op, status="DONE", targetId="1111", + targetLink=f"{base}/compute/v1/projects/mock-project/global/networks/mock-net") + return jsonify(name=op, status="DONE", targetId="2222", + targetLink=f"{base}/compute/v1/projects/mock-project/regions/us-central1/subnetworks/mock-subnet") + + +# --- Azure ------------------------------------------------------------------- +# client-credentials token; subscriptions (paginated via nextLink) → VNets per sub → subnets per VNet. + + +@app.post("//oauth2/v2.0/token") +def azure_token(tenant): + return jsonify(access_token="mock-azure-token", expires_in=3600, token_type="Bearer") + + +def require_azure_token(): + """Reject a request whose bearer is absent or empty, exactly as real ARM does. Without this the + mock answers 200 to an unauthenticated call, so a plan that binds an EMPTY {token} — e.g. a token + exchange that yielded no access_token — passes here and only fails against the real cloud with + `AuthenticationFailedMissingToken`. Returns an error response, or None when the token is good.""" + header = request.headers.get("Authorization", "") + token = header[len("Bearer "):].strip() if header.startswith("Bearer ") else "" + if not token: + return jsonify(error={ + "code": "AuthenticationFailedMissingToken", + "message": "Authentication failed. The 'Authorization' header is missing the access token.", + }), 401 + return None + + +@app.get("/subscriptions") +def azure_subscriptions(): + if (err := require_azure_token()): + return err + base = request.host_url.rstrip("/") + if request.args.get("_page") == "2": + return jsonify(value=[{"subscriptionId": "sub-2"}]) + # page 1 carries a nextLink to page 2 (exercises httpx ContFollow). + return jsonify(value=[{"subscriptionId": "sub-1"}], + nextLink=f"{base}/subscriptions?api-version=2020-01-01&_page=2") + + +@app.get("/subscriptions//providers/Microsoft.Network/virtualNetworks") +def azure_vnets(sub): + vid = f"/subscriptions/{sub}/resourceGroups/rg1/providers/Microsoft.Network/virtualNetworks/vnet-{sub}" + return jsonify(value=[{"id": vid, "name": f"vnet-{sub}", "location": "eastus"}]) + + +@app.get("/subscriptions//resourceGroups//providers/Microsoft.Network/virtualNetworks//subnets") +def azure_subnets(sub, rg, vnet): + vid = f"/subscriptions/{sub}/resourceGroups/{rg}/providers/Microsoft.Network/virtualNetworks/{vnet}" + return jsonify(value=[ + {"id": f"{vid}/subnets/sn-a", "name": "sn-a", "properties": {"addressPrefix": "10.0.0.0/24"}}, + {"id": f"{vid}/subnets/sn-b", "name": "sn-b", "properties": {"addressPrefix": "10.0.1.0/24"}}, + ]) + + +@app.get("/subscriptions//providers/Microsoft.Storage/storageAccounts") +def azure_storage_accounts(sub): + if (err := require_azure_token()): + return err + return jsonify(value=[ + {"name": f"stor{sub}a", "properties": { + "encryption": {"keySource": "Microsoft.Storage"}, + "allowBlobPublicAccess": False, "supportsHttpsTrafficOnly": True}}, + {"name": f"stor{sub}b", "properties": { + "encryption": {"keySource": "Microsoft.Keyvault"}, + "allowBlobPublicAccess": True, "supportsHttpsTrafficOnly": True}}, + ]) + + +# --- GCP Cloud Storage ------------------------------------------------------- + + +# Cloud Resource Manager v3: the org → folder → project hierarchy the recursive descent walks. +# Tree: org 123456789 ─ folders/100 ─ folders/200 (2 deep), a project at each node — so a full +# descent finds proj-deep (under a nested folder) that a direct-children-only pass would miss. +_GCP_FOLDERS = { + "organizations/123456789": ["folders/100"], + "folders/100": ["folders/200"], +} +_GCP_PROJECTS = { + "organizations/123456789": ["proj-root"], + "folders/100": ["proj-100"], + # folders/200 intentionally has NO project: an empty scope must not leak a ?project= call. +} + + +@app.get("/v3/folders") +def gcp_v3_folders(): + parent = request.args.get("parent", "") + if "000000000" in parent: # org whose hierarchy the caller can't list (grants at project, not org) + return Response( + '{"error":{"code":403,"message":"The caller does not have permission","status":"PERMISSION_DENIED"}}', + status=403, mimetype="application/json") + return jsonify(folders=[{"name": f} for f in _GCP_FOLDERS.get(parent, [])]) + + +@app.get("/v3/projects") +def gcp_v3_projects(): + parent = request.args.get("parent", "") + return jsonify(projects=[{"projectId": p} for p in _GCP_PROJECTS.get(parent, [])]) + + +@app.get("/storage/v1/b") +def gcp_storage_buckets(): + return jsonify(items=[ + {"name": "gcs-plain", "iamConfiguration": {"publicAccessPrevention": "inherited"}, + "versioning": {"enabled": False}}, + {"name": "gcs-cmek", "encryption": {"defaultKmsKeyName": "projects/p/locations/l/keyRings/r/cryptoKeys/k"}, + "iamConfiguration": {"publicAccessPrevention": "enforced"}, "versioning": {"enabled": True}}, + ]) + + +if __name__ == "__main__": + app.run(host="127.0.0.1", port=int(os.environ.get("PORT", "8085")), threaded=True) diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/buckets.json b/test/python/stackql_test_tooling/flask/omnisdk/collateral/buckets.json new file mode 100644 index 00000000..b84021a0 --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/buckets.json @@ -0,0 +1,476 @@ +[ + { + "name": "bucket-000", + "created": "2024-11-17T11:08:52.000Z", + "arn": "arn:aws:s3:::bucket-000", + "region": "us-west-2" + }, + { + "name": "bucket-001", + "created": "2025-08-01T01:25:25.000Z", + "arn": "arn:aws:s3:::bucket-001", + "region": "us-east-1" + }, + { + "name": "bucket-002", + "created": "2025-07-28T08:20:58.000Z", + "arn": "arn:aws:s3:::bucket-002", + "region": "us-east-1" + }, + { + "name": "bucket-003", + "created": "2025-07-31T23:35:42.000Z", + "arn": "arn:aws:s3:::bucket-003", + "region": "us-east-1" + }, + { + "name": "bucket-004", + "created": "2024-02-07T05:07:45.000Z", + "arn": "arn:aws:s3:::bucket-004", + "region": "ap-southeast-2" + }, + { + "name": "bucket-005", + "created": "2026-04-18T23:49:50.000Z", + "arn": "arn:aws:s3:::bucket-005", + "region": "ap-southeast-2" + }, + { + "name": "bucket-006", + "created": "2026-04-18T23:49:26.000Z", + "arn": "arn:aws:s3:::bucket-006", + "region": "ap-southeast-2" + }, + { + "name": "bucket-007", + "created": "2026-04-16T02:37:42.000Z", + "arn": "arn:aws:s3:::bucket-007", + "region": "ap-southeast-2" + }, + { + "name": "bucket-008", + "created": "2026-04-16T02:26:50.000Z", + "arn": "arn:aws:s3:::bucket-008", + "region": "ap-southeast-2" + }, + { + "name": "bucket-009", + "created": "2025-10-16T04:58:22.000Z", + "arn": "arn:aws:s3:::bucket-009", + "region": "us-east-1" + }, + { + "name": "bucket-010", + "created": "2025-10-16T04:57:58.000Z", + "arn": "arn:aws:s3:::bucket-010", + "region": "us-east-1" + }, + { + "name": "bucket-011", + "created": "2025-10-16T05:01:48.000Z", + "arn": "arn:aws:s3:::bucket-011", + "region": "us-west-2" + }, + { + "name": "bucket-012", + "created": "2025-10-16T05:01:24.000Z", + "arn": "arn:aws:s3:::bucket-012", + "region": "us-west-2" + }, + { + "name": "bucket-013", + "created": "2025-10-13T20:50:11.000Z", + "arn": "arn:aws:s3:::bucket-013", + "region": "us-west-2" + }, + { + "name": "bucket-014", + "created": "2025-10-13T20:49:52.000Z", + "arn": "arn:aws:s3:::bucket-014", + "region": "us-west-2" + }, + { + "name": "bucket-015", + "created": "2026-01-11T03:35:33.000Z", + "arn": "arn:aws:s3:::bucket-015", + "region": "ap-southeast-2" + }, + { + "name": "bucket-016", + "created": "2025-11-02T02:35:36.000Z", + "arn": "arn:aws:s3:::bucket-016", + "region": "us-west-2" + }, + { + "name": "bucket-017", + "created": "2025-11-02T01:54:53.000Z", + "arn": "arn:aws:s3:::bucket-017", + "region": "us-east-1" + }, + { + "name": "bucket-018", + "created": "2025-07-27T22:22:37.000Z", + "arn": "arn:aws:s3:::bucket-018", + "region": "us-east-1" + }, + { + "name": "bucket-019", + "created": "2026-05-04T11:52:06.000Z", + "arn": "arn:aws:s3:::bucket-019", + "region": "ap-southeast-2" + }, + { + "name": "bucket-020", + "created": "2024-11-17T07:21:04.000Z", + "arn": "arn:aws:s3:::bucket-020", + "region": "us-west-2" + }, + { + "name": "bucket-021", + "created": "2026-05-03T04:39:45.000Z", + "arn": "arn:aws:s3:::bucket-021", + "region": "ap-southeast-2" + }, + { + "name": "bucket-022", + "created": "2026-04-27T05:46:53.000Z", + "arn": "arn:aws:s3:::bucket-022", + "region": "ap-southeast-2" + }, + { + "name": "bucket-023", + "created": "2026-04-27T05:44:58.000Z", + "arn": "arn:aws:s3:::bucket-023", + "region": "ap-southeast-2" + }, + { + "name": "bucket-024", + "created": "2024-04-24T09:35:52.000Z", + "arn": "arn:aws:s3:::bucket-024", + "region": "ap-southeast-1" + }, + { + "name": "bucket-025", + "created": "2024-04-24T09:41:08.000Z", + "arn": "arn:aws:s3:::bucket-025", + "region": "ap-southeast-1" + }, + { + "name": "bucket-026", + "created": "2024-04-24T09:51:47.000Z", + "arn": "arn:aws:s3:::bucket-026", + "region": "ap-southeast-1" + }, + { + "name": "bucket-027", + "created": "2024-04-24T10:06:48.000Z", + "arn": "arn:aws:s3:::bucket-027", + "region": "ap-southeast-1" + }, + { + "name": "bucket-028", + "created": "2024-05-10T01:36:20.000Z", + "arn": "arn:aws:s3:::bucket-028", + "region": "ap-southeast-1" + }, + { + "name": "bucket-029", + "created": "2024-05-09T09:46:24.000Z", + "arn": "arn:aws:s3:::bucket-029", + "region": "ap-southeast-1" + }, + { + "name": "bucket-030", + "created": "2024-05-10T04:31:37.000Z", + "arn": "arn:aws:s3:::bucket-030", + "region": "ap-southeast-1" + }, + { + "name": "bucket-031", + "created": "2024-05-08T11:05:59.000Z", + "arn": "arn:aws:s3:::bucket-031", + "region": "ap-southeast-1" + }, + { + "name": "bucket-032", + "created": "2024-05-08T11:15:37.000Z", + "arn": "arn:aws:s3:::bucket-032", + "region": "ap-southeast-1" + }, + { + "name": "bucket-033", + "created": "2024-05-08T11:17:13.000Z", + "arn": "arn:aws:s3:::bucket-033", + "region": "ap-southeast-1" + }, + { + "name": "bucket-034", + "created": "2024-05-08T11:56:26.000Z", + "arn": "arn:aws:s3:::bucket-034", + "region": "ap-southeast-1" + }, + { + "name": "bucket-035", + "created": "2024-05-08T12:10:23.000Z", + "arn": "arn:aws:s3:::bucket-035", + "region": "ap-southeast-1" + }, + { + "name": "bucket-036", + "created": "2024-05-08T10:15:30.000Z", + "arn": "arn:aws:s3:::bucket-036", + "region": "ap-southeast-1" + }, + { + "name": "bucket-037", + "created": "2024-07-21T22:04:42.000Z", + "arn": "arn:aws:s3:::bucket-037", + "region": "ap-southeast-2" + }, + { + "name": "bucket-038", + "created": "2026-06-22T10:00:02.000Z", + "arn": "arn:aws:s3:::bucket-038", + "region": "ap-southeast-2" + }, + { + "name": "bucket-039", + "created": "2026-03-29T00:24:23.000Z", + "arn": "arn:aws:s3:::bucket-039", + "region": "ap-southeast-2" + }, + { + "name": "bucket-040", + "created": "2026-05-13T23:04:30.000Z", + "arn": "arn:aws:s3:::bucket-040", + "region": "us-west-2" + }, + { + "name": "bucket-041", + "created": "2026-05-13T23:03:24.000Z", + "arn": "arn:aws:s3:::bucket-041", + "region": "us-west-2" + }, + { + "name": "bucket-042", + "created": "2024-01-07T11:06:06.000Z", + "arn": "arn:aws:s3:::bucket-042", + "region": "ap-southeast-2" + }, + { + "name": "bucket-043", + "created": "2024-01-04T21:40:04.000Z", + "arn": "arn:aws:s3:::bucket-043", + "region": "ap-southeast-2" + }, + { + "name": "bucket-044", + "created": "2024-01-04T21:40:29.000Z", + "arn": "arn:aws:s3:::bucket-044", + "region": "ap-southeast-2" + }, + { + "name": "bucket-045", + "created": "2026-03-25T05:07:40.000Z", + "arn": "arn:aws:s3:::bucket-045", + "region": "ap-southeast-2" + }, + { + "name": "bucket-046", + "created": "2026-03-25T05:05:46.000Z", + "arn": "arn:aws:s3:::bucket-046", + "region": "ap-southeast-2" + }, + { + "name": "bucket-047", + "created": "2026-05-26T06:39:47.000Z", + "arn": "arn:aws:s3:::bucket-047", + "region": "us-east-1" + }, + { + "name": "bucket-048", + "created": "2024-04-18T20:16:29.000Z", + "arn": "arn:aws:s3:::bucket-048", + "region": "ap-southeast-2" + }, + { + "name": "bucket-049", + "created": "2024-04-18T07:59:31.000Z", + "arn": "arn:aws:s3:::bucket-049", + "region": "ap-southeast-2" + }, + { + "name": "bucket-050", + "created": "2023-11-07T01:41:20.000Z", + "arn": "arn:aws:s3:::bucket-050", + "region": "ap-southeast-2" + }, + { + "name": "bucket-051", + "created": "2026-01-09T07:39:27.000Z", + "arn": "arn:aws:s3:::bucket-051", + "region": "ap-southeast-2" + }, + { + "name": "bucket-052", + "created": "2026-01-09T07:40:13.000Z", + "arn": "arn:aws:s3:::bucket-052", + "region": "ap-southeast-2" + }, + { + "name": "bucket-053", + "created": "2022-12-19T00:21:41.000Z", + "arn": "arn:aws:s3:::bucket-053", + "region": "us-west-1" + }, + { + "name": "bucket-054", + "created": "2025-09-03T06:37:10.000Z", + "arn": "arn:aws:s3:::bucket-054", + "region": "us-east-1" + }, + { + "name": "bucket-055", + "created": "2025-09-03T06:36:50.000Z", + "arn": "arn:aws:s3:::bucket-055", + "region": "us-east-1" + }, + { + "name": "bucket-056", + "created": "2025-07-19T09:34:34.000Z", + "arn": "arn:aws:s3:::bucket-056", + "region": "us-east-1" + }, + { + "name": "bucket-057", + "created": "2025-07-09T01:28:12.000Z", + "arn": "arn:aws:s3:::bucket-057", + "region": "us-east-1" + }, + { + "name": "bucket-058", + "created": "2025-09-21T21:44:53.000Z", + "arn": "arn:aws:s3:::bucket-058", + "region": "ap-southeast-2" + }, + { + "name": "bucket-059", + "created": "2025-09-21T21:44:33.000Z", + "arn": "arn:aws:s3:::bucket-059", + "region": "ap-southeast-2" + }, + { + "name": "bucket-060", + "created": "2026-01-10T00:28:59.000Z", + "arn": "arn:aws:s3:::bucket-060", + "region": "ap-southeast-2" + }, + { + "name": "bucket-061", + "created": "2026-01-10T00:33:15.000Z", + "arn": "arn:aws:s3:::bucket-061", + "region": "ap-southeast-2" + }, + { + "name": "bucket-062", + "created": "2022-08-29T12:10:03.000Z", + "arn": "arn:aws:s3:::bucket-062", + "region": "ap-southeast-1" + }, + { + "name": "bucket-063", + "created": "2022-09-01T08:52:59.000Z", + "arn": "arn:aws:s3:::bucket-063", + "region": "ap-southeast-2" + }, + { + "name": "bucket-064", + "created": "2026-05-06T02:42:09.000Z", + "arn": "arn:aws:s3:::bucket-064", + "region": "ap-southeast-2" + }, + { + "name": "bucket-065", + "created": "2026-05-06T02:38:19.000Z", + "arn": "arn:aws:s3:::bucket-065", + "region": "ap-southeast-2" + }, + { + "name": "bucket-066", + "created": "2024-03-04T10:12:07.000Z", + "arn": "arn:aws:s3:::bucket-066", + "region": "ap-southeast-2" + }, + { + "name": "bucket-067", + "created": "2024-11-17T11:11:46.000Z", + "arn": "arn:aws:s3:::bucket-067", + "region": "eu-west-2" + }, + { + "name": "bucket-068", + "created": "2024-11-17T11:11:47.000Z", + "arn": "arn:aws:s3:::bucket-068", + "region": "eu-west-2" + }, + { + "name": "bucket-069", + "created": "2024-11-17T02:26:11.000Z", + "arn": "arn:aws:s3:::bucket-069", + "region": "eu-west-2" + }, + { + "name": "bucket-070", + "created": "2024-11-17T11:11:48.000Z", + "arn": "arn:aws:s3:::bucket-070", + "region": "eu-west-2" + }, + { + "name": "bucket-071", + "created": "2024-11-17T11:11:46.000Z", + "arn": "arn:aws:s3:::bucket-071", + "region": "eu-west-2" + }, + { + "name": "bucket-072", + "created": "2024-11-17T11:11:46.000Z", + "arn": "arn:aws:s3:::bucket-072", + "region": "eu-west-2" + }, + { + "name": "bucket-073", + "created": "2024-11-17T11:11:37.000Z", + "arn": "arn:aws:s3:::bucket-073", + "region": "us-west-2" + }, + { + "name": "bucket-074", + "created": "2024-11-17T11:11:38.000Z", + "arn": "arn:aws:s3:::bucket-074", + "region": "us-west-2" + }, + { + "name": "bucket-075", + "created": "2024-11-17T02:26:08.000Z", + "arn": "arn:aws:s3:::bucket-075", + "region": "us-west-2" + }, + { + "name": "bucket-076", + "created": "2024-11-17T11:11:40.000Z", + "arn": "arn:aws:s3:::bucket-076", + "region": "us-west-2" + }, + { + "name": "bucket-077", + "created": "2024-11-17T11:11:40.000Z", + "arn": "arn:aws:s3:::bucket-077", + "region": "us-west-2" + }, + { + "name": "bucket-078", + "created": "2024-11-17T11:11:39.000Z", + "arn": "arn:aws:s3:::bucket-078", + "region": "us-west-2" + } +] diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/ec2/provision.json b/test/python/stackql_test_tooling/flask/omnisdk/collateral/ec2/provision.json new file mode 100644 index 00000000..29aeaecc --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/ec2/provision.json @@ -0,0 +1,4 @@ +{ + "vpc_id": "vpc-03ff6ab0b5272cf86", + "subnet_id": "subnet-097e2de092ee7d629" +} diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-000.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-000.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-000.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-001.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-001.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-001.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-002.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-002.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-002.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-003.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-003.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-003.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-004.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-004.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-004.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-005.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-005.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-005.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-006.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-006.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-006.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-007.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-007.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-007.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-008.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-008.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-008.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-009.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-009.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-009.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-010.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-010.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-010.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-011.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-011.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-011.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-012.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-012.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-012.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-013.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-013.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-013.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-014.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-014.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-014.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-015.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-015.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-015.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-016.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-016.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-016.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-017.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-017.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-017.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-018.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-018.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-018.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-019.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-019.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-019.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-020.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-020.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-020.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-021.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-021.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-021.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-022.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-022.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-022.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-023.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-023.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-023.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-024.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-024.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-024.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-025.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-025.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-025.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-026.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-026.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-026.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-027.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-027.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-027.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-028.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-028.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-028.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-029.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-029.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-029.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-030.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-030.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-030.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-031.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-031.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-031.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-032.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-032.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-032.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-033.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-033.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-033.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-034.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-034.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-034.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-035.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-035.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-035.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-036.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-036.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-036.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-037.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-037.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-037.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-038.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-038.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-038.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-039.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-039.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-039.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-040.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-040.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-040.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-041.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-041.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-041.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-042.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-042.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-042.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-043.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-043.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-043.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-044.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-044.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-044.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-045.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-045.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-045.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-046.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-046.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-046.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-047.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-047.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-047.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-048.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-048.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-048.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-049.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-049.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-049.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-050.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-050.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-050.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-051.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-051.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-051.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-052.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-052.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-052.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-053.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-053.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-053.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-054.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-054.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-054.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-055.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-055.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-055.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-056.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-056.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-056.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-057.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-057.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-057.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-058.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-058.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-058.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-059.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-059.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-059.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-060.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-060.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-060.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-061.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-061.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-061.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-062.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-062.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-062.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-063.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-063.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-063.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-064.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-064.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-064.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-065.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-065.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-065.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-066.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-066.xml new file mode 100644 index 00000000..3574257e --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-066.xml @@ -0,0 +1,2 @@ + +trueAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-067.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-067.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-067.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-068.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-068.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-068.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-069.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-069.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-069.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-070.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-070.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-070.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-071.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-071.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-071.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-072.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-072.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-072.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-073.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-073.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-073.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-074.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-074.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-074.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-075.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-075.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-075.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-076.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-076.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-076.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-077.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-077.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-077.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-078.xml b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-078.xml new file mode 100644 index 00000000..04f3836f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-078.xml @@ -0,0 +1,2 @@ + +falseAES256SSE-C \ No newline at end of file diff --git a/test/python/stackql_test_tooling/flask/omnisdk/templates/create_subnet.xml.j2 b/test/python/stackql_test_tooling/flask/omnisdk/templates/create_subnet.xml.j2 new file mode 100644 index 00000000..11d0dbc3 --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/templates/create_subnet.xml.j2 @@ -0,0 +1,2 @@ + +mock{{ subnet_id }}{{ vpc_id }}pending diff --git a/test/python/stackql_test_tooling/flask/omnisdk/templates/create_vpc.xml.j2 b/test/python/stackql_test_tooling/flask/omnisdk/templates/create_vpc.xml.j2 new file mode 100644 index 00000000..72a0e76f --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/templates/create_vpc.xml.j2 @@ -0,0 +1,2 @@ + +mock{{ vpc_id }}pending diff --git a/test/python/stackql_test_tooling/flask/omnisdk/templates/list_buckets.xml.j2 b/test/python/stackql_test_tooling/flask/omnisdk/templates/list_buckets.xml.j2 new file mode 100644 index 00000000..b8c901ed --- /dev/null +++ b/test/python/stackql_test_tooling/flask/omnisdk/templates/list_buckets.xml.j2 @@ -0,0 +1,2 @@ + +{% for b in buckets %}{{ b.name }}{{ b.created }}{{ b.arn }}{{ b.region }}{% endfor %}mock diff --git a/test/python/stackql_test_tooling/stackql_context.py b/test/python/stackql_test_tooling/stackql_context.py index 0818a632..9d20c19c 100644 --- a/test/python/stackql_test_tooling/stackql_context.py +++ b/test/python/stackql_test_tooling/stackql_context.py @@ -547,6 +547,7 @@ def get_object_count_dict(count :int) -> dict: MOCKSERVER_JAR = os.path.join(repository_root, 'test', 'downloads', 'mockserver-netty-5.12.0-shaded.jar') JSON_INIT_FILE_PATH_GOOGLE = os.path.join(repository_root, 'test', 'mockserver', 'expectations', 'static-gcp-expectations.json') + MOCKSERVER_PORT_OMNISDK = 1071 MOCKSERVER_PORT_GOOGLE = 1080 JSON_INIT_FILE_PATH_GOOGLEADMIN = os.path.join(repository_root, 'test', 'mockserver', 'expectations', 'static-google-admin-expectations.json') @@ -916,6 +917,7 @@ def get_registry_mock_url(execution_env :str) -> str: 'MOCKSERVER_PORT_AWS': MOCKSERVER_PORT_AWS, 'MOCKSERVER_PORT_AZURE': MOCKSERVER_PORT_AZURE, 'MOCKSERVER_PORT_GITHUB': MOCKSERVER_PORT_GITHUB, + 'MOCKSERVER_PORT_OMNISDK': MOCKSERVER_PORT_OMNISDK, 'MOCKSERVER_PORT_GOOGLE': MOCKSERVER_PORT_GOOGLE, 'MOCKSERVER_PORT_GOOGLEADMIN': MOCKSERVER_PORT_GOOGLEADMIN, 'MOCKSERVER_PORT_STACKQL_AUTH_TESTING': MOCKSERVER_PORT_STACKQL_AUTH_TESTING, diff --git a/test/python/stackql_test_tooling/web_service_keywords.py b/test/python/stackql_test_tooling/web_service_keywords.py index b4955008..f5125f8a 100644 --- a/test/python/stackql_test_tooling/web_service_keywords.py +++ b/test/python/stackql_test_tooling/web_service_keywords.py @@ -36,6 +36,7 @@ class web_service_keywords(Process): _DEFAULT_MOCKSERVER_PORT_REGISTRY = 1094 _DEFAULT_MOCKSERVER_PORT_RETRY = 1199 _DEFAULT_MOCKSERVER_PORT_NATIVE_TEST = 1070 + _DEFAULT_MOCKSERVER_PORT_OMNISDK = 1071 def _get_dsn(self) -> str: return self._sqlite_db_path @@ -71,6 +72,7 @@ def __init__( self._okta_app: str = f'{_app_root}/okta/app' self._static_auth_testing_app: str = f'{_app_root}/static_auth/app' self._aws_app: str = f'{_app_root}/aws/app' + self._omnisdk_app: str = f'{_app_root}/omnisdk/app' self._azure_app: str = f'{_app_root}/azure/app' self._digitalocean_app: str = f'{_app_root}/digitalocean/app' self._googleadmin_app: str = f'{_app_root}/googleadmin/app' @@ -172,6 +174,26 @@ def create_okta_web_service( cwd=self._cwd, ) + @keyword + def create_omnisdk_web_service( + self, + port: int, + host: str = '0.0.0.0' + ) -> None: + """ + Sign the input. + """ + return self.start_process( + 'flask', + f'--app={self._omnisdk_app}', + 'run', + f'--host={host}', # generally, `0.0.0.0`; otherwise, invisible on `docker.host.internal` etc + f'--port={port}', + stdout=os.path.abspath(os.path.join(self._log_root, f'omnisdk-server-{port}-stdout.txt')), + stderr=os.path.abspath(os.path.join(self._log_root, f'omnisdk-server-{port}-stderr.txt')), + cwd=self._cwd, + ) + @keyword def create_aws_web_service( self, @@ -414,6 +436,7 @@ def start_all_webservers(self, port_dict: Optional[dict] = None) -> None: self.create_google_admin_web_service(_port_dict.get('googleadmin', self._DEFAULT_MOCKSERVER_PORT_GOOGLEADMIN)) self.create_azure_web_service(_port_dict.get('azure', self._DEFAULT_MOCKSERVER_PORT_AZURE)) self.create_aws_web_service(_port_dict.get('aws', self._DEFAULT_MOCKSERVER_PORT_AWS)) + self.create_omnisdk_web_service(_port_dict.get('omnisdk', self._DEFAULT_MOCKSERVER_PORT_OMNISDK)) self.create_static_auth_web_service(_port_dict.get('static_auth_testing', self._DEFAULT_MOCKSERVER_PORT_STACKQL_AUTH_TESTING)) self.create_okta_web_service(_port_dict.get('okta', self._DEFAULT_MOCKSERVER_PORT_OKTA)) self.create_gcp_web_service(_port_dict.get('gcp', self._DEFAULT_MOCKSERVER_PORT_GOOGLE)) diff --git a/test/robot/functional/stackql.resource b/test/robot/functional/stackql.resource index 242c7ad2..9296dbd6 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -10,6 +10,8 @@ ${USE_STACKQL_PREINSTALLED} false # to be overridden from command l ${SUNDRY_CONFIG} {} # to be overridden from command line, with string value ${CWD_FOR_EXEC} ${REPOSITORY_ROOT} # works for self repository, can be overwritten when shared ${WEB_SERVICE_LIBRARY} stackql_test_tooling.web_service_keywords +${OMNISDK_MOCK_GCP_SA_HOST} ${REPOSITORY_ROOT}${/}test${/}tmp${/}omnisdk-gcp-sa.json +${OMNISDK_MOCK_URL} http://${LOCAL_HOST_ALIAS}:${MOCKSERVER_PORT_OMNISDK} ${STACKQL_INTERFACE_LIBRARY} stackql_test_tooling.StackQLInterfaces ${CLOUD_INTEGRATION_LIBRARY} stackql_test_tooling.CloudIntegration @@ -43,6 +45,7 @@ Start All Mock Servers ... digitalocean=${MOCKSERVER_PORT_DIGITALOCEAN} ... retry=${MOCKSERVER_PORT_RETRY} ... native_test=${MOCKSERVER_PORT_NATIVE_TEST} + ... omnisdk=${MOCKSERVER_PORT_OMNISDK} Start All Webservers port_dict=${port_dict} Reset Retry Mock Counters @@ -192,3 +195,13 @@ Stackql Per Test Teardown Log Container removed # Should Be Equal As Integers ${restwo.rc} 0 END + +Remove Preview Mock Environment + [Documentation] Set Environment Variable is process wide, so the mock + ... credentials must not outlive the test that needs them. + FOR ${name} IN + ... AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY + ... AZURE_TENANT_ID AZURE_CLIENT_ID AZURE_CLIENT_SECRET + ... GOOGLE_APPLICATION_CREDENTIALS STACKQL_PREVIEW_ENDPOINT + Remove Environment Variable ${name} + END diff --git a/test/robot/functional/stackql_mocked_from_cmd_line.robot b/test/robot/functional/stackql_mocked_from_cmd_line.robot index 4dc2c52b..02ce4a4c 100644 --- a/test/robot/functional/stackql_mocked_from_cmd_line.robot +++ b/test/robot/functional/stackql_mocked_from_cmd_line.robot @@ -10609,6 +10609,8 @@ Preview Show Services Returns Audit Service ... show services in stackql_preview; ... id,name,title\naudit:internal,audit,omnisdk audited resources ... \-o\=csv + ... stdout=${CURDIR}${/}tmp${/}Preview-Show-Services-Returns-Audit-Service.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Show-Services-Returns-Audit-Service-stderr.tmp Preview Show Resources Mirrors Omnisdk Catalog Should StackQL Exec Inline Equal @@ -10622,7 +10624,8 @@ Preview Show Resources Mirrors Omnisdk Catalog ... show resources in stackql_preview.audit; ... name,id\naws_ec2_networks,stackql_preview.audit.aws_ec2_networks\naws_s3_buckets,stackql_preview.audit.aws_s3_buckets\nazure_network_subnets,stackql_preview.audit.azure_network_subnets\nazure_storage_accounts,stackql_preview.audit.azure_storage_accounts\ngcp_compute_networks,stackql_preview.audit.gcp_compute_networks\ngoogle_storage_buckets,stackql_preview.audit.google_storage_buckets\nomni_storage_buckets,stackql_preview.audit.omni_storage_buckets ... \-o\=csv - + ... stdout=${CURDIR}${/}tmp${/}Preview-Show-Resources-Mirrors-Omnisdk-Catalog.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Show-Resources-Mirrors-Omnisdk-Catalog-stderr.tmp Preview Show Methods Reports Omnisdk Required Params Should StackQL Exec Inline Equal @@ -10636,6 +10639,8 @@ Preview Show Methods Reports Omnisdk Required Params ... show methods in stackql_preview.audit.aws_ec2_networks; ... MethodName,RequiredParams,SQLVerb\nprovision,"region, vpc_cidr, subnet_cidr",SELECT ... \-o\=csv + ... stdout=${CURDIR}${/}tmp${/}Preview-Show-Methods-Reports-Omnisdk-Required-Params.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Show-Methods-Reports-Omnisdk-Required-Params-stderr.tmp Preview Describe Reports Omnisdk Column Types Should StackQL Exec Inline Equal @@ -10649,6 +10654,8 @@ Preview Describe Reports Omnisdk Column Types ... describe stackql_preview.audit.aws_s3_buckets; ... name,type\nprovider,string\nname,string\nencryption_status,string\nencryption_class,string\npublic,bool\nversioning,bool\nhttps,bool ... \-o\=csv + ... stdout=${CURDIR}${/}tmp${/}Preview-Describe-Reports-Omnisdk-Column-Types.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Describe-Reports-Omnisdk-Column-Types-stderr.tmp Preview Select Without Required Params Reports Method Selection Error Should StackQL Exec Inline Contain Stderr @@ -10661,3 +10668,122 @@ Preview Select Without Required Params Reports Method Selection Error ... ${SQL_BACKEND_CFG_STR_CANONICAL} ... select * from stackql_preview.audit.aws_ec2_networks; ... no method of 'aws.ec2.networks' has its required parameters supplied + ... stdout=${CURDIR}${/}tmp${/}Preview-Select-Without-Required-Params-Reports-Method-Selection-Error.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Select-Without-Required-Params-Reports-Method-Selection-Error-stderr.tmp + +Preview Omni Storage Buckets Describe Reports Uniform Blob Shape + [Documentation] The multi-cloud relation projects one uniform shape + ... regardless of which cloud a row came from. + Should StackQL Exec Inline Equal + ... ${STACKQL_EXE} + ... ${OKTA_SECRET_STR} + ... ${GITHUB_SECRET_STR} + ... ${K8S_SECRET_STR} + ... ${REGISTRY_NO_VERIFY_CFG_STR} + ... ${AUTH_CFG_STR} + ... ${SQL_BACKEND_CFG_STR_CANONICAL} + ... describe stackql_preview.audit.omni_storage_buckets; + ... name,type\nprovider,string\nname,string\nencryption_status,string\nencryption_class,string\npublic,bool\nversioning,bool\nhttps,bool + ... \-o\=csv + ... stdout=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Describe-Reports-Uniform-Blob-Shape.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Describe-Reports-Uniform-Blob-Shape-stderr.tmp + +Preview Omni Storage Buckets Show Methods Reports Required Region + Should StackQL Exec Inline Equal + ... ${STACKQL_EXE} + ... ${OKTA_SECRET_STR} + ... ${GITHUB_SECRET_STR} + ... ${K8S_SECRET_STR} + ... ${REGISTRY_NO_VERIFY_CFG_STR} + ... ${AUTH_CFG_STR} + ... ${SQL_BACKEND_CFG_STR_CANONICAL} + ... show methods in stackql_preview.audit.omni_storage_buckets; + ... MethodName,RequiredParams,SQLVerb\nlist,region,SELECT + ... \-o\=csv + ... stdout=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Show-Methods-Reports-Required-Region.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Show-Methods-Reports-Required-Region-stderr.tmp + +Preview Omni Storage Buckets Select Without Region Reports Method Selection Error + Should StackQL Exec Inline Contain Stderr + ... ${STACKQL_EXE} + ... ${OKTA_SECRET_STR} + ... ${GITHUB_SECRET_STR} + ... ${K8S_SECRET_STR} + ... ${REGISTRY_NO_VERIFY_CFG_STR} + ... ${AUTH_CFG_STR} + ... ${SQL_BACKEND_CFG_STR_CANONICAL} + ... select * from stackql_preview.audit.omni_storage_buckets; + ... no method of 'omni.storage.buckets' has its required parameters supplied + ... stdout=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Select-Without-Region-Reports-Method-Selection-Error.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Select-Without-Region-Reports-Method-Selection-Error-stderr.tmp + +Preview Jsonl Row Set Is Order Insensitive + [Documentation] Streamed relations cannot honour ORDER BY, since their + ... rows never reach the SQL backend. Contents remain + ... deterministic, so JSONL rows are asserted as an unordered + ... set. Deliberately declared in an order the query does not + ... emit, so an order-sensitive comparison would fail here. + ${expected} = Catenate SEPARATOR=\n + ... {"id":"stackql_preview.audit.omni_storage_buckets","name":"omni_storage_buckets"} + ... {"id":"stackql_preview.audit.aws_s3_buckets","name":"aws_s3_buckets"} + ... {"id":"stackql_preview.audit.gcp_compute_networks","name":"gcp_compute_networks"} + ... {"id":"stackql_preview.audit.aws_ec2_networks","name":"aws_ec2_networks"} + ... {"id":"stackql_preview.audit.google_storage_buckets","name":"google_storage_buckets"} + ... {"id":"stackql_preview.audit.azure_network_subnets","name":"azure_network_subnets"} + ... {"id":"stackql_preview.audit.azure_storage_accounts","name":"azure_storage_accounts"} + Should StackQL Exec Inline Jsonl Set Equal + ... ${STACKQL_EXE} + ... ${OKTA_SECRET_STR} + ... ${GITHUB_SECRET_STR} + ... ${K8S_SECRET_STR} + ... ${REGISTRY_NO_VERIFY_CFG_STR} + ... ${AUTH_CFG_STR} + ... ${SQL_BACKEND_CFG_STR_CANONICAL} + ... show resources in stackql_preview.audit; + ... ${expected} + ... stdout=${CURDIR}${/}tmp${/}Preview-Jsonl-Row-Set-Is-Order-Insensitive.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Jsonl-Row-Set-Is-Order-Insensitive-stderr.tmp + +Preview Omni Storage Buckets Jsonl Row Set Matches Expectation + [Documentation] The multi-cloud audit select, order-insensitive, against + ... omnisdk's bundled mock. Rows are declared by omnisdk's own + ... fixture; no ORDER BY, because a streamed relation never + ... reaches the SQL backend and ordering is not applied. + ... Each service the fan-out touches is retargeted explicitly: + ... the S3 leg, both Azure legs (login exchange then mgmt) and + ... all three GCP legs (oauth exchange, storage, crm org + ... descent). + [Setup] Write Gcp Service Account ${OMNISDK_MOCK_GCP_SA_HOST} + [Teardown] Remove Preview Mock Environment + ${expected} = OperatingSystem.Get File + ... ${CURDIR}${/}..${/}..${/}assets${/}expected${/}preview${/}omni-storage-buckets.jsonl + ${gcp_sa} = Set Variable If "${EXECUTION_PLATFORM}" == "docker" + ... /opt/test/tmp/omnisdk-gcp-sa.json ${OMNISDK_MOCK_GCP_SA_HOST} + Set Environment Variable AWS_ACCESS_KEY_ID AK + Set Environment Variable AWS_SECRET_ACCESS_KEY SK + Set Environment Variable AZURE_TENANT_ID mock-tenant + Set Environment Variable AZURE_CLIENT_ID mock-client + Set Environment Variable AZURE_CLIENT_SECRET mock-secret + Set Environment Variable GOOGLE_APPLICATION_CREDENTIALS ${gcp_sa} + ${mock} = Set Variable {"scheme":"http","host":"${LOCAL_HOST_ALIAS}","port":"${MOCKSERVER_PORT_OMNISDK}"} + ${endpoints} = Catenate SEPARATOR= + ... {"aws.s3":${mock}, + ... "azure.login":${mock},"azure.mgmt":${mock}, + ... "gcp.oauth":${mock},"gcp.storage":${mock},"gcp.crm":${mock}} + Set Environment Variable STACKQL_PREVIEW_ENDPOINT ${endpoints} + ${query} = Catenate SEPARATOR=${SPACE} + ... select * from stackql_preview.audit.omni_storage_buckets + ... where region = 'us-east-1' and google_org = '123456789'; + Should StackQL Exec Inline Jsonl Set Equal + ... ${STACKQL_EXE} + ... ${OKTA_SECRET_STR} + ... ${GITHUB_SECRET_STR} + ... ${K8S_SECRET_STR} + ... ${REGISTRY_NO_VERIFY_CFG_STR} + ... ${AUTH_CFG_STR} + ... ${SQL_BACKEND_CFG_STR_CANONICAL} + ... ${query} + ... ${expected} + ... stdout=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Jsonl-Row-Set-Matches-Expectation.tmp + ... stderr=${CURDIR}${/}tmp${/}Preview-Omni-Storage-Buckets-Jsonl-Row-Set-Matches-Expectation-stderr.tmp +