From 605ee73ec977014c856a9f08bc43bf6af0ac265e Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 18:43:34 +1000 Subject: [PATCH 1/6] mockable-omnisdk Summary: - Consume mockable `omnisdk`. - Added robot test `Preview Omni Storage Buckets Describe Reports Uniform Blob Shape`. - Added robot test `Preview Omni Storage Buckets Show Methods Reports Required Region`. - Added robot test `Preview Omni Storage Buckets Select Without Region Reports Method Selection Error`. - Added robot test `Preview Show Providers Jsonl Set Is Order Insensitive`. - Added robot test `Preview Jsonl Row Set Is Order Insensitive`. - Added robot test `Preview Omni Storage Buckets Jsonl Row Set Matches Expectation`. --- go.mod | 2 +- go.sum | 4 +- internal/stackql/intrinsic/omnisdk.go | 23 +-- internal/stackql/intrinsic/omnisdk_test.go | 25 +--- .../preview/omni-storage-buckets.jsonl | 87 +++++++++++ .../stackql_test_tooling/StackQLInterfaces.py | 138 +++++++++++++++++- test/robot/functional/stackql.resource | 20 +++ .../stackql_mocked_from_cmd_line.robot | 104 +++++++++++++ 8 files changed, 369 insertions(+), 34 deletions(-) create mode 100644 test/assets/expected/preview/omni-storage-buckets.jsonl 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..bbb1566b 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 @@ -868,6 +869,142 @@ def should_stackql_exec_inline_equal( self.should_be_equal(result.stdout, expected_output, collapse_spaces=cfg.pop('collapse_spaces', False)) + @keyword + def get_omnisdk_mock_dir(self) -> str: + """Resolve the pinned omnisdk module's bundled flask mock, so the mock always + matches the version in go.mod rather than a vendored copy that can drift.""" + import subprocess + module_dir = subprocess.run( + ['go', 'list', '-m', '-f', '{{.Dir}}', 'github.com/stackql-labs/omnisdk'], + capture_output=True, text=True, check=True, + ).stdout.strip() + return os.path.join(module_dir, 'test', 'mock') + + @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.""" + import subprocess + os.makedirs(os.path.dirname(path), exist_ok=True) + pem = subprocess.run( + ['openssl', 'genpkey', '-algorithm', 'RSA', '-pkeyopt', 'rsa_keygen_bits:2048'], + capture_output=True, text=True, check=True, + ).stdout + 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) + + def _verify_jsonl_set(self, actual_stdout :str, expected_jsonl :str): + 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}\n' + f'Unexpected ({len(unexpected)}): {unexpected}' + ) + + 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 +1290,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/robot/functional/stackql.resource b/test/robot/functional/stackql.resource index 242c7ad2..da909613 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -10,6 +10,7 @@ ${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} ${CURDIR}${/}tmp${/}omnisdk-gcp-sa.json ${STACKQL_INTERFACE_LIBRARY} stackql_test_tooling.StackQLInterfaces ${CLOUD_INTEGRATION_LIBRARY} stackql_test_tooling.CloudIntegration @@ -192,3 +193,22 @@ Stackql Per Test Teardown Log Container removed # Should Be Equal As Integers ${restwo.rc} 0 END + +Start Omnisdk Mock + ${mock_dir} = Get Omnisdk Mock Dir + ${python} = Python Executable + ${port} = Get Free Port + Set Suite Variable ${OMNISDK_MOCK_PORT} ${port} + ${out} = Set Variable ${CURDIR}${/}tmp${/}omnisdk-mock.out + ${err} = Set Variable ${CURDIR}${/}tmp${/}omnisdk-mock.err + ${proc} = Start Process flask --app\=${mock_dir}${/}app.py run + ... --host\=0.0.0.0 --port\=${port} + ... stdout=${out} stderr=${err} + Set Suite Variable ${OMNISDK_MOCK_PROC} ${proc} + Wait For Server http://127.0.0.1:${port}/ stdout=${out} stderr=${err} + ${host} = Set Variable If "${EXECUTION_PLATFORM}" == "docker" host.docker.internal 127.0.0.1 + Set Suite Variable ${OMNISDK_MOCK_HOST} ${host} + Write Gcp Service Account ${OMNISDK_MOCK_GCP_SA} + +Stop Omnisdk Mock + Run Keyword And Ignore Error Terminate Process ${OMNISDK_MOCK_PROC} diff --git a/test/robot/functional/stackql_mocked_from_cmd_line.robot b/test/robot/functional/stackql_mocked_from_cmd_line.robot index 4dc2c52b..6e537d1b 100644 --- a/test/robot/functional/stackql_mocked_from_cmd_line.robot +++ b/test/robot/functional/stackql_mocked_from_cmd_line.robot @@ -10661,3 +10661,107 @@ 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 + +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 + +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 + +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 + +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} + +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] Start Omnisdk Mock + [Teardown] Stop Omnisdk Mock + ${expected} = OperatingSystem.Get File + ... ${CURDIR}${/}..${/}..${/}assets${/}expected${/}preview${/}omni-storage-buckets.jsonl + ${mock} = Set Variable {"scheme":"http","host":"${OMNISDK_MOCK_HOST}","port":"${OMNISDK_MOCK_PORT}"} + ${endpoints} = Catenate SEPARATOR= + ... {"aws.s3":${mock}, + ... "azure.login":${mock},"azure.mgmt":${mock}, + ... "gcp.oauth":${mock},"gcp.storage":${mock},"gcp.crm":${mock}} + ${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} + ... env:STACKQL_PREVIEW_ENDPOINT=${endpoints} + ... env:AWS_ACCESS_KEY_ID=AK + ... env:AWS_SECRET_ACCESS_KEY=SK + ... env:AZURE_TENANT_ID=mock-tenant + ... env:AZURE_CLIENT_ID=mock-client + ... env:AZURE_CLIENT_SECRET=mock-secret + ... env:GOOGLE_APPLICATION_CREDENTIALS=${OMNISDK_MOCK_GCP_SA} From 05341f2c9f474b6c694442df7883d8830f154525 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 19:45:30 +1000 Subject: [PATCH 2/6] de-vendor --- cicd/requirements.txt | 1 + .../stackql_test_tooling/StackQLInterfaces.py | 23 +- .../flask/omnisdk/OMNISDK_VERSION.txt | 1 + .../stackql_test_tooling/flask/omnisdk/app.py | 212 ++++++++ .../flask/omnisdk/collateral/buckets.json | 476 ++++++++++++++++++ .../omnisdk/collateral/ec2/provision.json | 4 + .../collateral/encryption/bucket-000.xml | 2 + .../collateral/encryption/bucket-001.xml | 2 + .../collateral/encryption/bucket-002.xml | 2 + .../collateral/encryption/bucket-003.xml | 2 + .../collateral/encryption/bucket-004.xml | 2 + .../collateral/encryption/bucket-005.xml | 2 + .../collateral/encryption/bucket-006.xml | 2 + .../collateral/encryption/bucket-007.xml | 2 + .../collateral/encryption/bucket-008.xml | 2 + .../collateral/encryption/bucket-009.xml | 2 + .../collateral/encryption/bucket-010.xml | 2 + .../collateral/encryption/bucket-011.xml | 2 + .../collateral/encryption/bucket-012.xml | 2 + .../collateral/encryption/bucket-013.xml | 2 + .../collateral/encryption/bucket-014.xml | 2 + .../collateral/encryption/bucket-015.xml | 2 + .../collateral/encryption/bucket-016.xml | 2 + .../collateral/encryption/bucket-017.xml | 2 + .../collateral/encryption/bucket-018.xml | 2 + .../collateral/encryption/bucket-019.xml | 2 + .../collateral/encryption/bucket-020.xml | 2 + .../collateral/encryption/bucket-021.xml | 2 + .../collateral/encryption/bucket-022.xml | 2 + .../collateral/encryption/bucket-023.xml | 2 + .../collateral/encryption/bucket-024.xml | 2 + .../collateral/encryption/bucket-025.xml | 2 + .../collateral/encryption/bucket-026.xml | 2 + .../collateral/encryption/bucket-027.xml | 2 + .../collateral/encryption/bucket-028.xml | 2 + .../collateral/encryption/bucket-029.xml | 2 + .../collateral/encryption/bucket-030.xml | 2 + .../collateral/encryption/bucket-031.xml | 2 + .../collateral/encryption/bucket-032.xml | 2 + .../collateral/encryption/bucket-033.xml | 2 + .../collateral/encryption/bucket-034.xml | 2 + .../collateral/encryption/bucket-035.xml | 2 + .../collateral/encryption/bucket-036.xml | 2 + .../collateral/encryption/bucket-037.xml | 2 + .../collateral/encryption/bucket-038.xml | 2 + .../collateral/encryption/bucket-039.xml | 2 + .../collateral/encryption/bucket-040.xml | 2 + .../collateral/encryption/bucket-041.xml | 2 + .../collateral/encryption/bucket-042.xml | 2 + .../collateral/encryption/bucket-043.xml | 2 + .../collateral/encryption/bucket-044.xml | 2 + .../collateral/encryption/bucket-045.xml | 2 + .../collateral/encryption/bucket-046.xml | 2 + .../collateral/encryption/bucket-047.xml | 2 + .../collateral/encryption/bucket-048.xml | 2 + .../collateral/encryption/bucket-049.xml | 2 + .../collateral/encryption/bucket-050.xml | 2 + .../collateral/encryption/bucket-051.xml | 2 + .../collateral/encryption/bucket-052.xml | 2 + .../collateral/encryption/bucket-053.xml | 2 + .../collateral/encryption/bucket-054.xml | 2 + .../collateral/encryption/bucket-055.xml | 2 + .../collateral/encryption/bucket-056.xml | 2 + .../collateral/encryption/bucket-057.xml | 2 + .../collateral/encryption/bucket-058.xml | 2 + .../collateral/encryption/bucket-059.xml | 2 + .../collateral/encryption/bucket-060.xml | 2 + .../collateral/encryption/bucket-061.xml | 2 + .../collateral/encryption/bucket-062.xml | 2 + .../collateral/encryption/bucket-063.xml | 2 + .../collateral/encryption/bucket-064.xml | 2 + .../collateral/encryption/bucket-065.xml | 2 + .../collateral/encryption/bucket-066.xml | 2 + .../collateral/encryption/bucket-067.xml | 2 + .../collateral/encryption/bucket-068.xml | 2 + .../collateral/encryption/bucket-069.xml | 2 + .../collateral/encryption/bucket-070.xml | 2 + .../collateral/encryption/bucket-071.xml | 2 + .../collateral/encryption/bucket-072.xml | 2 + .../collateral/encryption/bucket-073.xml | 2 + .../collateral/encryption/bucket-074.xml | 2 + .../collateral/encryption/bucket-075.xml | 2 + .../collateral/encryption/bucket-076.xml | 2 + .../collateral/encryption/bucket-077.xml | 2 + .../collateral/encryption/bucket-078.xml | 2 + .../omnisdk/templates/create_subnet.xml.j2 | 2 + .../flask/omnisdk/templates/create_vpc.xml.j2 | 2 + .../omnisdk/templates/list_buckets.xml.j2 | 2 + test/robot/functional/stackql.resource | 3 +- 89 files changed, 866 insertions(+), 18 deletions(-) create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/OMNISDK_VERSION.txt create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/app.py create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/buckets.json create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/ec2/provision.json create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-000.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-001.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-002.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-003.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-004.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-005.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-006.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-007.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-008.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-009.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-010.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-011.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-012.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-013.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-014.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-015.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-016.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-017.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-018.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-019.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-020.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-021.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-022.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-023.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-024.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-025.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-026.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-027.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-028.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-029.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-030.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-031.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-032.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-033.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-034.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-035.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-036.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-037.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-038.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-039.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-040.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-041.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-042.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-043.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-044.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-045.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-046.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-047.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-048.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-049.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-050.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-051.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-052.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-053.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-054.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-055.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-056.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-057.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-058.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-059.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-060.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-061.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-062.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-063.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-064.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-065.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-066.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-067.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-068.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-069.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-070.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-071.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-072.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-073.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-074.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-075.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-076.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-077.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/collateral/encryption/bucket-078.xml create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/templates/create_subnet.xml.j2 create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/templates/create_vpc.xml.j2 create mode 100644 test/python/stackql_test_tooling/flask/omnisdk/templates/list_buckets.xml.j2 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/test/python/stackql_test_tooling/StackQLInterfaces.py b/test/python/stackql_test_tooling/StackQLInterfaces.py index bbb1566b..c99368c6 100644 --- a/test/python/stackql_test_tooling/StackQLInterfaces.py +++ b/test/python/stackql_test_tooling/StackQLInterfaces.py @@ -869,17 +869,6 @@ def should_stackql_exec_inline_equal( self.should_be_equal(result.stdout, expected_output, collapse_spaces=cfg.pop('collapse_spaces', False)) - @keyword - def get_omnisdk_mock_dir(self) -> str: - """Resolve the pinned omnisdk module's bundled flask mock, so the mock always - matches the version in go.mod rather than a vendored copy that can drift.""" - import subprocess - module_dir = subprocess.run( - ['go', 'list', '-m', '-f', '{{.Dir}}', 'github.com/stackql-labs/omnisdk'], - capture_output=True, text=True, check=True, - ).stdout.strip() - return os.path.join(module_dir, 'test', 'mock') - @keyword def python_executable(self) -> str: return sys.executable @@ -921,12 +910,14 @@ def _read_if_present(self, path :str) -> str: 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.""" - import subprocess + from cryptography.hazmat.primitives import serialization + from cryptography.hazmat.primitives.asymmetric import rsa os.makedirs(os.path.dirname(path), exist_ok=True) - pem = subprocess.run( - ['openssl', 'genpkey', '-algorithm', 'RSA', '-pkeyopt', 'rsa_keygen_bits:2048'], - capture_output=True, text=True, check=True, - ).stdout + 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', 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/robot/functional/stackql.resource b/test/robot/functional/stackql.resource index da909613..166dbbba 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -195,8 +195,7 @@ Stackql Per Test Teardown END Start Omnisdk Mock - ${mock_dir} = Get Omnisdk Mock Dir - ${python} = Python Executable + ${mock_dir} = Set Variable ${LOCAL_LIB_HOME}${/}stackql_test_tooling${/}flask${/}omnisdk ${port} = Get Free Port Set Suite Variable ${OMNISDK_MOCK_PORT} ${port} ${out} = Set Variable ${CURDIR}${/}tmp${/}omnisdk-mock.out From 8f9c8734b6aec86265020ccef013aa8f7286e0e1 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 20:31:23 +1000 Subject: [PATCH 3/6] test fixes --- docker-compose-testing.yml | 23 ++++++++++++++++ .../stackql_test_tooling/stackql_context.py | 2 ++ .../web_service_keywords.py | 23 ++++++++++++++++ test/robot/functional/stackql.resource | 19 ++----------- .../stackql_mocked_from_cmd_line.robot | 27 ++++++++++++++++--- 5 files changed, 73 insertions(+), 21 deletions(-) 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/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 166dbbba..3bdfa57d 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -11,6 +11,7 @@ ${SUNDRY_CONFIG} {} # to be overridden from command line, ${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} ${CURDIR}${/}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 @@ -44,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 @@ -194,20 +196,3 @@ Stackql Per Test Teardown # Should Be Equal As Integers ${restwo.rc} 0 END -Start Omnisdk Mock - ${mock_dir} = Set Variable ${LOCAL_LIB_HOME}${/}stackql_test_tooling${/}flask${/}omnisdk - ${port} = Get Free Port - Set Suite Variable ${OMNISDK_MOCK_PORT} ${port} - ${out} = Set Variable ${CURDIR}${/}tmp${/}omnisdk-mock.out - ${err} = Set Variable ${CURDIR}${/}tmp${/}omnisdk-mock.err - ${proc} = Start Process flask --app\=${mock_dir}${/}app.py run - ... --host\=0.0.0.0 --port\=${port} - ... stdout=${out} stderr=${err} - Set Suite Variable ${OMNISDK_MOCK_PROC} ${proc} - Wait For Server http://127.0.0.1:${port}/ stdout=${out} stderr=${err} - ${host} = Set Variable If "${EXECUTION_PLATFORM}" == "docker" host.docker.internal 127.0.0.1 - Set Suite Variable ${OMNISDK_MOCK_HOST} ${host} - Write Gcp Service Account ${OMNISDK_MOCK_GCP_SA} - -Stop Omnisdk Mock - Run Keyword And Ignore Error Terminate Process ${OMNISDK_MOCK_PROC} diff --git a/test/robot/functional/stackql_mocked_from_cmd_line.robot b/test/robot/functional/stackql_mocked_from_cmd_line.robot index 6e537d1b..a0c6e974 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,6 +10668,8 @@ 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 @@ -10676,6 +10685,8 @@ Preview Omni Storage Buckets Describe Reports Uniform Blob Shape ... 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 @@ -10689,6 +10700,8 @@ Preview Omni Storage Buckets Show Methods Reports Required Region ... 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 @@ -10701,6 +10714,8 @@ Preview Omni Storage Buckets Select Without Region Reports Method Selection Erro ... ${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 @@ -10726,6 +10741,8 @@ Preview Jsonl Row Set Is Order Insensitive ... ${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 @@ -10736,11 +10753,10 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... the S3 leg, both Azure legs (login exchange then mgmt) and ... all three GCP legs (oauth exchange, storage, crm org ... descent). - [Setup] Start Omnisdk Mock - [Teardown] Stop Omnisdk Mock + [Setup] Write Gcp Service Account ${OMNISDK_MOCK_GCP_SA} ${expected} = OperatingSystem.Get File ... ${CURDIR}${/}..${/}..${/}assets${/}expected${/}preview${/}omni-storage-buckets.jsonl - ${mock} = Set Variable {"scheme":"http","host":"${OMNISDK_MOCK_HOST}","port":"${OMNISDK_MOCK_PORT}"} + ${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}, @@ -10765,3 +10781,6 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... env:AZURE_CLIENT_ID=mock-client ... env:AZURE_CLIENT_SECRET=mock-secret ... env:GOOGLE_APPLICATION_CREDENTIALS=${OMNISDK_MOCK_GCP_SA} + ... 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 + From 0642beaaed4fc7adec0c6e0da126ab72c7dad630 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 21:12:05 +1000 Subject: [PATCH 4/6] another-attempt --- test/python/stackql_test_tooling/StackQLInterfaces.py | 9 +++++---- test/robot/functional/stackql.resource | 2 +- test/robot/functional/stackql_mocked_from_cmd_line.robot | 6 ++++-- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/test/python/stackql_test_tooling/StackQLInterfaces.py b/test/python/stackql_test_tooling/StackQLInterfaces.py index c99368c6..e00e5294 100644 --- a/test/python/stackql_test_tooling/StackQLInterfaces.py +++ b/test/python/stackql_test_tooling/StackQLInterfaces.py @@ -969,9 +969,9 @@ def should_stackql_exec_inline_jsonl_set_equal( 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) + self._verify_jsonl_set(result.stdout, expected_jsonl, result.stderr) - def _verify_jsonl_set(self, actual_stdout :str, expected_jsonl :str): + 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: @@ -979,8 +979,9 @@ def _verify_jsonl_set(self, actual_stdout :str, expected_jsonl :str): 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}\n' - f'Unexpected ({len(unexpected)}): {unexpected}' + 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: diff --git a/test/robot/functional/stackql.resource b/test/robot/functional/stackql.resource index 3bdfa57d..aa155cad 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -10,7 +10,7 @@ ${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} ${CURDIR}${/}tmp${/}omnisdk-gcp-sa.json +${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 diff --git a/test/robot/functional/stackql_mocked_from_cmd_line.robot b/test/robot/functional/stackql_mocked_from_cmd_line.robot index a0c6e974..02868b5f 100644 --- a/test/robot/functional/stackql_mocked_from_cmd_line.robot +++ b/test/robot/functional/stackql_mocked_from_cmd_line.robot @@ -10753,9 +10753,11 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... 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} + [Setup] Write Gcp Service Account ${OMNISDK_MOCK_GCP_SA_HOST} ${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} ${mock} = Set Variable {"scheme":"http","host":"${LOCAL_HOST_ALIAS}","port":"${MOCKSERVER_PORT_OMNISDK}"} ${endpoints} = Catenate SEPARATOR= ... {"aws.s3":${mock}, @@ -10780,7 +10782,7 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... env:AZURE_TENANT_ID=mock-tenant ... env:AZURE_CLIENT_ID=mock-client ... env:AZURE_CLIENT_SECRET=mock-secret - ... env:GOOGLE_APPLICATION_CREDENTIALS=${OMNISDK_MOCK_GCP_SA} + ... env:GOOGLE_APPLICATION_CREDENTIALS=${gcp_sa} ... 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 From 9ef48755811591ef791ff35bac9406b3b87b6db8 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 21:22:37 +1000 Subject: [PATCH 5/6] fuxes --- .../stackql_test_tooling/StackQLInterfaces.py | 6 +++++- .../functional/stackql_mocked_from_cmd_line.robot | 14 +++++++------- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/test/python/stackql_test_tooling/StackQLInterfaces.py b/test/python/stackql_test_tooling/StackQLInterfaces.py index e00e5294..7af014b1 100644 --- a/test/python/stackql_test_tooling/StackQLInterfaces.py +++ b/test/python/stackql_test_tooling/StackQLInterfaces.py @@ -331,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' ] diff --git a/test/robot/functional/stackql_mocked_from_cmd_line.robot b/test/robot/functional/stackql_mocked_from_cmd_line.robot index 02868b5f..a22f8fa0 100644 --- a/test/robot/functional/stackql_mocked_from_cmd_line.robot +++ b/test/robot/functional/stackql_mocked_from_cmd_line.robot @@ -10758,11 +10758,18 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... ${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'; @@ -10776,13 +10783,6 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... ${SQL_BACKEND_CFG_STR_CANONICAL} ... ${query} ... ${expected} - ... env:STACKQL_PREVIEW_ENDPOINT=${endpoints} - ... env:AWS_ACCESS_KEY_ID=AK - ... env:AWS_SECRET_ACCESS_KEY=SK - ... env:AZURE_TENANT_ID=mock-tenant - ... env:AZURE_CLIENT_ID=mock-client - ... env:AZURE_CLIENT_SECRET=mock-secret - ... env:GOOGLE_APPLICATION_CREDENTIALS=${gcp_sa} ... 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 From 2bbd43f541186efb8e343cecdd3f1c647bc15b99 Mon Sep 17 00:00:00 2001 From: General Kroll Date: Wed, 12 Aug 2026 21:38:55 +1000 Subject: [PATCH 6/6] cleanup --- test/robot/functional/stackql.resource | 9 +++++++++ test/robot/functional/stackql_mocked_from_cmd_line.robot | 1 + 2 files changed, 10 insertions(+) diff --git a/test/robot/functional/stackql.resource b/test/robot/functional/stackql.resource index aa155cad..9296dbd6 100644 --- a/test/robot/functional/stackql.resource +++ b/test/robot/functional/stackql.resource @@ -196,3 +196,12 @@ Stackql Per Test Teardown # 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 a22f8fa0..02ce4a4c 100644 --- a/test/robot/functional/stackql_mocked_from_cmd_line.robot +++ b/test/robot/functional/stackql_mocked_from_cmd_line.robot @@ -10754,6 +10754,7 @@ Preview Omni Storage Buckets Jsonl Row Set Matches Expectation ... 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"