Skip to content

v2.0.0 — Role-based restructure, /v2 module, and five new SDK-compat services#267

Merged
NitinKumar004 merged 76 commits into
masterfrom
development
Jul 12, 2026
Merged

v2.0.0 — Role-based restructure, /v2 module, and five new SDK-compat services#267
NitinKumar004 merged 76 commits into
masterfrom
development

Conversation

@NitinKumar004

@NitinKumar004 NitinKumar004 commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

cloudemu Release Notes — v2.0.0

A major release. cloudemu is now organized by role so the repository stays legible as it grows — service packages live under services/, the cross-cutting wrappers under features/, and shared plumbing under internal/. Because that moves public import paths, the module is now github.com/stackshy/cloudemu/v2. On top of the restructure this release adds five new SDK-compat surfaces — AWS STS, AWS SSM Parameter Store, S3 multipart / tagging / versioning, Azure Queue & Table Storage, and Azure AI — and ships a full CI/CD + security pipeline.

⚠️ Breaking Changes

  • Module path is now /v2. Update the dependency and your imports:
    go get github.com/stackshy/cloudemu/[email protected]
    // before
    import "github.com/stackshy/cloudemu/storage"
    // after
    import "github.com/stackshy/cloudemu/v2/services/storage"
  • Public packages moved by role (import path == directory, so these are the source-visible changes):
    • Every emulated service → services/<name> (e.g. storageservices/storage, computeservices/compute, kubernetesservices/kubernetes, resourcediscoveryservices/resourcediscovery, costservices/cost).
    • Cross-cutting wrappers → features/<name>: chaos, recorder, metrics, ratelimit, inject, topology.
    • Shared helpers → internal/: statemachineinternal/statemachine, paginationinternal/pagination.
    • providers/{aws,azure,gcp} and server/{aws,azure,gcp} are unchanged — only their import prefixes gain /v2.
  • No behavior changed in the move: the entrypoints (cloudemu.NewAWS(), NewAzure(), NewGCP()) and every driver, wire protocol, and error type are identical. The upgrade is a find-and-replace of the import prefix.

✨ Features

AWS STS — SDK-compat (query protocol)

The real aws-sdk-go-v2 STS client now works against cloudemu: GetCallerIdentity, AssumeRole, and GetSessionToken return well-formed credentials/identity envelopes so code that resolves an identity or assumes a role before calling other services runs end-to-end.

AWS SSM Parameter Store — SDK-compat (#239)

AWS Systems Manager Parameter Store drives a new parameterstore service: PutParameter (with overwrite + version bump), GetParameter / GetParameters / GetParametersByPath (recursive), DeleteParameter(s), and parameter labels — including String, StringList, and SecureString types and typed ParameterNotFound / ParameterAlreadyExists errors.

S3 — multipart upload, tagging, and versioning

The S3 handler gains the advanced object surface the SDK exercises for large and mutable objects: multipart (CreateMultipartUploadUploadPartCompleteMultipartUpload / AbortMultipartUpload, parts assembled in PartNumber order), object tagging (PutObjectTagging / GetObjectTagging / DeleteObjectTagging), and versioning (PutBucketVersioning plus version-aware GetObject / DeleteObject).

Azure Queue Storage + Table Storage — SDK-compat (#243)

Two Azure data-plane services land: Queue Storage (queue create/delete, put / get / peek / update / delete message with visibility-timeout and dequeue-count semantics) and Table Storage (table CRUD; insert / upsert / merge / replace / delete entity and OData-style query). Both speak the real azure-sdk-for-go wire format.

Azure AI — CognitiveServices + Machine Learning (#232)

Azure AI emulation across ARM and data plane: CognitiveServices accounts (ARM lifecycle) plus an assistants data plane, and Azure Machine Learning workspaces and their child resources. Unmodified azure-sdk-for-go clients drive both control-plane provisioning and data-plane calls.

🔧 Enhancements

CI/CD + security pipeline

A complete GitHub Actions setup lands with this release:

  • ci.ymlbuild-vet (build then vet, sharing one cache), test, tidy, and advisory format / lint (golangci-lint v2) jobs, running in parallel with Go build + module caching (actions/cache@v4 with restore-keys) so repeat runs finish in well under a minute. Triggers on PRs and pushes to master, with concurrency cancel-in-progress.
  • security.ymlgovulncheck, gosec, CodeQL, and dependency-review (PR-only, fail-on high) as a separate parallel workflow.

Security hardening (CodeQL)

  • Bounded RunInstances count across AWS EC2, Azure Virtual Machines, and GCP GCE — a request over the per-call maximum (1000) now returns InvalidArgument instead of attempting an uncontrolled allocation.
  • Dropped a request-sized pre-allocation in Vertex AI FindNeighbors.

Correctness fixes

  • S3 multipart now sorts parts by PartNumber before assembly, maps unknown upload IDs to NoSuchUpload, and rejects an empty CompleteMultipartUpload.
  • SSM validates parameter labels and threads context through the PutParameter retry path.
  • Azure Table supports UpsertEntity; Queue/Blob/Table shared-hostname collisions are documented.

Documentation

Every in-repo doc (architecture.md, services.md, features.md, getting-started.md) and the package overview were rewritten for the services/ / features/ / internal/ layout, and all import paths and badges updated to the /v2 module.

Technical Details

Repository restructure & /v2 module
  • chore(v2)!: bump module path to github.com/stackshy/cloudemu/v2go.mod module path gains the required /v2 suffix; every internal import rewritten in lockstep across providers, servers, examples, and helpers.
  • Service packages moved under services/ (28 services), cross-cutting wrappers under features/ (chaos, recorder, metrics, ratelimit, inject, topology), and generic helpers under internal/ (statemachine, pagination).
  • providers/ and server/ trees kept their internal shape; only import prefixes changed. Build, go vet, and the full test suite are green on the new layout.
AWS STS & SSM Parameter Store
  • STS (server/aws/sts, query protocol) — GetCallerIdentity, AssumeRole, GetSessionToken; typed error envelopes; registered with a disjoint action set.
  • SSM (server/aws/ssm, query protocol → providers/aws/ssm) — PutParameter / GetParameter / GetParameters / GetParametersByPath (recursive) / DeleteParameter(s); label + version handling; String / StringList / SecureString; typed ParameterNotFound / ParameterAlreadyExists. fix(ssm) adds label validation and context threading in the Put retry path.
S3 — multipart, tagging, versioning
  • feat(s3): add multipart, tagging, and versioning wire operations — CreateMultipartUpload / UploadPart / CompleteMultipartUpload / AbortMultipartUpload; PutObjectTagging / GetObjectTagging / DeleteObjectTagging; PutBucketVersioning with version-aware read/delete.
  • fix(s3): sort multipart parts, map NoSuchUpload, reject empty Complete + test(s3) — out-of-order parts now assemble by PartNumber (regression test asserts AAAA…BBBB ordering), unknown upload IDs map to NoSuchUpload, and an empty Complete is rejected.
Azure Queue & Table Storage
  • Queue (server/azure/queue) — queue create/delete; put / get / peek / update / delete message with visibility-timeout and dequeue-count semantics.
  • Table (server/azure/table) — table CRUD; insert / upsert / merge / replace / delete entity; OData-style query. fix(azure-table) adds UpsertEntity support and documents Queue/Blob/Table shared-hostname collisions.
Azure AI (CognitiveServices + Machine Learning)
  • CognitiveServices (server/azure/azureai) — ARM accounts lifecycle plus an assistants data plane.
  • Machine Learning — workspaces and child resources (machinelearning*.go) over ARM, with data-plane round-trip coverage.
CI/CD & security workflows
  • ci.ymlbuild-vet shares a single Go build+module cache (actions/cache@v4, restore-keys: go-${{ runner.os }}-); test, tidy, advisory format (gofmt, report-only) and lint (golangci-lint v2 via the official install script, report-only) run in parallel. Triggers: pull_request + push to master; concurrency with cancel-in-progress.
  • security.ymlgovulncheck (report-only), gosec (report-only), CodeQL (init/autobuild/analyze@v3, security-events: write), and dependency-review (fail-on-severity: high, PR-only), run as an independent parallel workflow.
  • fix(security)const maxRunInstances = 1000 guard in EC2/VM/GCE RunInstances; drop sized alloc in Vertex AI FindNeighbors. Resolves the CodeQL go/uncontrolled-allocation-size findings.

thzgajendra and others added 30 commits July 12, 2026 00:39
…ata Plane) (#232)

* Add Azure AI Driver And In-Memory Provider

Add the azureai driver interfaces and in-memory provider Mock spanning both
ARM providers that make up Azure AI — Microsoft.CognitiveServices (AI Foundry /
AI Studio / the AI Services resource / Azure OpenAI) and
Microsoft.MachineLearningServices (Azure ML) — plus the data planes: Azure
OpenAI inference (chat/completions, embeddings, completions), the AI Foundry
Agents/Assistants API, and AML online-endpoint scoring.

CognitiveServices covers accounts (CRUD, keys, models, skus, usages),
deployments, projects, raiPolicies, commitmentPlans, and private-endpoint
connections. MachineLearningServices covers workspaces, computes (with a
start/stop/restart state machine), online/batch endpoints + deployments, jobs,
versioned assets (models/data/environments/components/featuresets), datastores,
connections, schedules, and registries. Slices/maps are deep-copied on store
and return and mutators use copy-then-Set. Auto-metrics push to Azure Monitor
via SetMonitoring; wired into the Azure provider.

* Add Azure AI SDK-Compat ARM And Data-Plane Servers

Serve Microsoft.CognitiveServices and Microsoft.MachineLearningServices over
the ARM JSON wire protocol, plus the Azure OpenAI inference / Assistants and
AML scoring data planes. Real armcognitiveservices / armmachinelearning clients
(and any REST caller) configured with a custom endpoint hit these handlers the
same way they hit management.azure.com.

CognitiveServices uses the shared azurearm.ParsePath; Azure ML nests deeper
(onlineEndpoints/{e}/deployments/{d}, models/{n}/versions/{v}, computes/{c}/start)
so its handler parses the trailing segments itself. The data plane is
host/path-routed on /openai/ and /score, with the account scope derived from the
request Host subdomain. Roundtrip tests start a real httptest server and cover
every family over HTTP. Wired into the Azure server Drivers bundle.

* Add Azure AI Portable Layer-1 Wrapper, Chaos And Cost Integration

Add the portable azureai.AzureAI Layer-1 wrapper implementing the full
driver.AzureAI surface through a single do() pipeline (recorder, metrics, rate
limiting, error injection, latency), mirroring sagemaker/vertexai. Add a chaos
wrapper (chaos.WrapAzureAI) that injects failures on account/workspace and
deployment/job creation and the inference/scoring runtimes, plus default Azure
AI cost rates. Brings Azure AI to full parity with how the other AI services
participate in the cross-cutting layers.

* Document Azure AI In Services Reference

* Add Azure AI Search Driver And In-Memory Provider

Add the azuresearch driver interfaces and in-memory provider Mock for Azure
AI Search (Microsoft.Search) — the ARM control plane (searchServices lifecycle,
admin/query keys, shared private links, private-endpoint connections) and the
{service}.search.windows.net data plane (indexes, documents with
upload/merge/delete + search/suggest/autocomplete/count/get, indexers with
run/reset/status, data sources, skillsets, synonym maps, aliases, service
statistics). Slices/maps are deep-copied and mutators copy-then-Set; document
search is a deterministic substring match bounded by maxSearchTop. Auto-metrics
push to Azure Monitor; wired into the Azure provider.

* Add Azure AI Search SDK-Compat ARM And Data-Plane Servers

Serve Microsoft.Search/searchServices over ARM and the search data plane over
its host/path-routed surface (/indexes, /indexes/{i}/docs/*, /indexers,
/datasources, /skillsets, /synonymmaps, /aliases, /servicestats). The data-plane
service scope is derived from the {service}.search.windows.net Host subdomain.
Roundtrip tests start a real httptest server and cover service lifecycle + keys
+ private links and the full index/document/indexer/datasource/skillset/synonym/
alias/stats surface. Wired into the Azure server Drivers bundle.

* Add Azure AI Search Layer-1 Wrapper, Chaos And Cost Integration

Add the portable azuresearch.AzureSearch Layer-1 wrapper implementing the full
driver.AzureSearch surface through a do() pipeline (recorder, metrics, rate
limiting, error injection, latency), a chaos wrapper (chaos.WrapAzureSearch)
that injects failures on service/index creation, document indexing and the
query runtime, and default Azure AI Search cost rates.

* Document Azure AI Search In Services Reference

* Address Review Comments On Azure AI And Search Emulation

Resolve PR #232 review feedback across the CognitiveServices,
MachineLearningServices, and Azure AI Search provider and server layers:

- Search: mergeOrUpload now merges onto the existing document instead of
  replacing it; reject documents missing the key field; honor $filter
  (single OData comparison), $orderby, $top, $skip and $select; return
  207 Multi-Status on partial-failure index batches.
- Persist regenerated admin/query and Cognitive Services account keys so
  rotation is observable via a subsequent list.
- Sort ListMessages/ListAssistants by creation sequence for deterministic
  ordering; pick the latest asset version numerically, not lexically.
- Derive the AML online-endpoint name from the inference host so /score
  no longer collapses every endpoint to "default".
- Emit a string error.code (not the numeric status) in data-plane error
  envelopes, and enforce the correct HTTP method on key/account actions.

Add regression tests to the existing roundtrip test files.

* Add Real-SDK Roundtrip Tests And Fix Data-Plane Input Handling

Address the re-review follow-ups on PR #232:

- Embeddings: parseEmbeddingInput now accepts token-array inputs ([]int and
  [][]int) in addition to string / []string, rendering each to a synthetic
  string so every input yields one embedding row.
- Search data plane: normalize the fused OData key form the SDKs emit, so
  /indexes('name') and /docs('key') route identically to the slash forms.

Add real-client roundtrip tests driving the official Azure SDKs against the
in-memory server, proving wire compatibility per surface:

- armcognitiveservices: account lifecycle + key rotation
- armmachinelearning: workspace + versioned assets (numeric latest version)
- azopenai: chat completions + embeddings
- armsearch: service lifecycle + admin/query key rotation

Azure ships no Go data-plane search SDK, so the search data plane's wire
fidelity (paren-form routing) is covered by explicit fused-URL tests.
No CI existed. Adds .github/workflows/ci.yml running go build / vet / test on
push to development|master and on every PR (Go 1.25, module cache). A
golangci-lint v2 job runs advisory-only for now (the repo's strict config was
never enforced in CI); flip continue-on-error once the tree is lint-clean.
golangci-lint-action@v6 installs golangci-lint v1, incompatible with the
repo's v2 config. Install v2 via the official script instead. Still advisory
(continue-on-error) until the tree is lint-clean.
Add server/aws/sts implementing the AWS STS query protocol
(GetCallerIdentity, AssumeRole, GetSessionToken) so the real
aws-sdk-go-v2/service/sts client works against cloudemu. Many SDK code
paths call sts:GetCallerIdentity/AssumeRole on init; this removes that
friction.

STS needs no driver: identity is derived from the existing
Drivers.AccountID / Region. It is gated on a new Drivers.STS bool and
registered among the query-protocol handlers before EC2. Its Matches
parses the form and claims only its disjoint action set, so it does not
shadow RDS/Redshift/IAM/ELBv2/ElastiCache/SNS/EC2.

Tests drive the real STS SDK against httptest, plus a dispatch test
proving STS does not shadow EC2 RunInstances.

Closes #241
Public repo, so Actions minutes are free — but keep it lean: trigger on
pull_request (feature pushes covered by their PR) plus push to master; drop
the separate golangci-lint download job (go vet stays); keep caching and
cancel-in-progress.
Extend the SDK-compat S3 server handler to speak the multipart upload,
object tagging, and bucket versioning REST/XML operations against the
existing storage driver (handler-only; no new driver methods).

Operations:
- Multipart: CreateMultipartUpload, UploadPart, CompleteMultipartUpload,
  AbortMultipartUpload, ListParts, ListMultipartUploads
- Object tagging: PutObjectTagging, GetObjectTagging, DeleteObjectTagging
- Bucket versioning: PutBucketVersioning, GetBucketVersioning
- ListObjectVersions (current objects reported as the null version)

Sub-resource routing keys on query params (?uploads, ?tagging,
?versioning, ?versions, ?uploadId) checked before the existing
method-based object/bucket dispatch, leaving PUT/GET/DELETE untouched.

Adds sdk_roundtrip_test.go driving the real aws-sdk-go-v2 S3 client:
multipart upload of a multi-part object then GetObject returns the
concatenated body; object tagging put/get/delete round-trip; bucket
versioning Enabled round-trip.

Refs #118
CI (ci.yml): Build, Vet, Test, Tidy as blocking parallel jobs; Format and
Lint advisory (pre-existing test-file gofmt + never-enforced golangci config).
Security (security.yml): govulncheck, gosec, CodeQL, and Dependency Review as
separate parallel jobs (advisory scanners to start), on PR / push-to-master /
weekly. Every job restores the Go build+module cache to stay fast.
Add two Azure Storage data-plane REST handlers so real azqueue and
aztables clients work against cloudemu:

- server/azure/queue: Azure Queue Storage REST+XML handler backed by the
  existing messagequeue driver (create/delete/list queue, enqueue,
  dequeue, delete message). Wired as azure.Drivers.QueueStorage, reusing a
  dedicated servicebus.Mock instance as the messagequeue backend.
- server/azure/table: Azure Table Storage OData/JSON handler backed by a
  new lightweight tablestorage/driver plus an in-memory
  providers/azure/tablestorage provider (create/delete/list table; insert/
  get/update(merge|replace)/delete/query entities).

Both register before the permissive Blob fallback. Detection signals are
disjoint from Blob/Cosmos/Databricks and each other except the one
inherently-ambiguous root GET /?comp=list shape (list-queues vs
list-containers), documented in the handler.

Includes real-SDK round-trip tests per service plus a no-shadowing
dispatch test registering Blob+Queue+Table together.
Format, Lint, govulncheck, and gosec now run and surface findings as workflow
annotations without failing the check, so the PR isn't red on pre-existing
findings while the real gates (Build/Vet/Test/Tidy) stay blocking. CodeQL
reports to the Security tab; Dependency Review blocks new high-severity CVEs.
Address review of #241: gofmt-align xml.go, and trim trailing slashes in
roleNameFromArn so a stray 'MyRole/' doesn't produce an empty last segment
(and fall back to a default if the name resolves empty).
- Fix pre-existing 'using resp before checking for errors' (httpresponse vet
  check) in kubernetes/handlers_http_test.go: check the Do() error before
  deferring resp.Body.Close() (4 sites).
- Combine Build and Vet into one job so 'go vet' reuses the compile cache
  'go build' just populated, instead of a standalone 'go vet ./...' that
  recompiles the whole module (~4-5 min). Test stays a parallel job.
setup-go's built-in cache keys on an exact go.sum hash, so every branch that
adds a dependency gets a cold cache and recompiles the whole cloud-SDK tree
(~4-5 min). Switch to actions/cache with a restore-keys fallback (go-<os>-*)
so a changed go.sum still restores the previous build cache and only the
changed deps recompile — repeat/PR runs drop to ~1-2 min.
Address review of #118:
- assemblePartsInOrder sorts parts by PartNumber before concatenating, so an
  out-of-order (or unsorted-SDK) CompleteMultipartUpload no longer corrupts the
  object (data-integrity bug).
- Multipart ops (Upload/Complete/Abort) map a driver not-found to NoSuchUpload
  instead of the object-level NoSuchKey, so the SDK decodes the right typed
  error.
- CompleteMultipartUpload with an empty part list now returns MalformedXML
  instead of silently writing a 0-byte object.
The prior test codified the pre-fix bug (reversed parts yielding part2||part1);
update it to assert the correct AAAABBBB ordering now that parts are sorted.
…stname collisions

Address review of #243:
- Table PUT/MERGE with no If-Match against a missing row now inserts
  (insert-or-replace/merge) instead of 404, matching aztables UpsertEntity.
- Correct the Queue Matches docstring: the /{queue}/messages and /?comp=list
  shapes are NOT strictly disjoint from Blob (a blob named "messages", or
  list-containers) — Azure separates them only by hostname, so they're a
  documented, inherent limitation of serving Queue+Blob on one endpoint.
ci/cd: parallel CI jobs + security scanning (build, vet, test, tidy, lint, govulncheck, gosec, CodeQL, dependency-review)
feat(s3): advanced ops — multipart, object tagging, bucket versioning
feat(sts): AWS STS SDK-compat handler
feat(azure): Storage Queues + Table Storage SDK-compat
Emulate AWS Systems Manager Parameter Store so the real
aws-sdk-go-v2/service/ssm client works against cloudemu.

- parameterstore/driver: portable ParameterStore driver interface
- parameterstore: portable wrapper (recorder/metrics/ratelimit/inject/latency)
- providers/aws/ssm: in-memory memstore-backed provider (versioning, labels,
  hierarchical paths, history)
- server/aws/ssm: AWS JSON 1.1 handler dispatched on X-Amz-Target AmazonSSM.*
- wired SSM onto providers/aws.Provider and server/aws Drivers/Register

Operations: PutParameter (Overwrite + versioning), GetParameter,
GetParameters, GetParametersByPath (Recursive), DeleteParameter,
DeleteParameters, DescribeParameters, GetParameterHistory,
LabelParameterVersion. Version/label selectors via ':' suffix.

SecureString is stored as-is (no KMS); WithDecryption is a no-op.

Tests: sdk_roundtrip_test.go drives the real SDK client against httptest,
asserting typed responses and a typed ParameterNotFound.
Address review of #239:
- LabelParameterVersion now rejects labels that start with a digit or with
  aws/ssm (case-insensitive), returning them in InvalidLabels instead of
  attaching them — which also stops a numeric label (e.g. "5") from being
  attached and then made unreachable by version-number selector resolution.
- PutParameter's Overwrite-race retry now uses the caller's context instead of
  context.Background().
feat(ssm): AWS SSM Parameter Store (driver + provider + SDK-compat handler)
…ghbors

Resolves the 4 CodeQL go/uncontrolled-allocation-size high-severity alerts
(pre-existing; first surfaced now that CodeQL runs in CI):
- EC2/GCE/Azure-VM RunInstances validated count>0 but had no upper bound, so an
  oversized MaxCount could drive an unbounded slice allocation (OOM). Cap at
  1000 per call, mirroring real provider limits.
- Vertex AI FindNeighbors was already clamped to maxNeighbors (1000); drop the
  sized make() capacity so the (already-safe) allocation isn't flagged.
refactor(v2)!: restructure repo into services/ + features/, bump module to /v2
@NitinKumar004 NitinKumar004 changed the title v1.10.0 v2.0.0 Jul 12, 2026
The v2 restructure moved service packages under services/ and cross-cutting
ones under features/. Update the architecture directory tree and the prose
path references (e.g. storage/driver -> services/storage/driver, topology/ ->
features/topology/) in architecture.md, services.md, and features.md.
architecture.md prose (storage/, compute/, database/) and services.md
kubernetes/ references now point at services/<name>/.
docs(v2): update in-repo docs to the services/features layout
@NitinKumar004 NitinKumar004 changed the title v2.0.0 v2.0.0 — Role-based restructure, /v2 module, and five new SDK-compat services Jul 12, 2026
@NitinKumar004 NitinKumar004 merged commit dab6416 into master Jul 12, 2026
10 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants