Skip to content

[FEATURE] HanaTenant CRD + Controller E2E #84

Description

@jn-av

[Feature] HanaTenant CRD + Controller E2E

Epic: [Epic] HANA Multi-Tenancy Support via HANA-MT API v2.6.2
ADR: 20260120-adr-hana-mt.md
Dependency: #83 must be completed first
Labels: enhancement multi-tenancy hana-mt

Context

HanaTenant is the aggregate root of the HANA-MT hierarchy. A tenant represents a top-level HANA Cloud resource object. All other MT resources (containers, credentials) belong to a tenant.

This issue implements the HanaTenant custom resource type and its controller end-to-end: CRD definition, reconciler logic, unit tests, E2E test, and example YAMLs.

CRD Spec (Proposal — please review before implementation)

spec.serviceInstanceID    (string, required)      HANA Cloud Service Instance ID
spec.dataEncryption.mode  (string, optional)      DEDICATED_KEY | MANAGED_KEY
spec.labels[]             ([]string, optional)    HANA-MT API labels: max 3, format "key=value"
spec.guid                 (string, optional)      If set: adopt an existing tenant
spec.apiCredentialsRef    (object, optional)      OAuth2 credentials secret reference
  .name                   (string)                Secret name (default: "hana-mt-api-credentials")
  .namespace              (string, optional)      Secret namespace (default: CR namespace)

CRD Status (Proposal — please review before implementation)

status.phase              Creating | Ready | Updating | Deleting | FailedDelete | Failed
status.guid               HANA tenant GUID (populated after creation/adoption)
status.etag               ETag from last API GET
status.observedGeneration Generation of the spec this status reflects
status.containerRefs[]    List of managed HanaContainer CRs (name + guid)
status.createTimestamp    Creation timestamp from API (RFC3339)
status.purgeTimestamp     Expiry time for soft-deleted tenant (14 days after deletion)
status.conditions[]       Detailed status conditions

Tasks

  • HanaTenant type definition (Spec, Status — no xpv1 embedding)
  • groupversion_info.go for the new MT API group
  • CRD manifest via go generate ./apis/...
  • Custom controller internal/controller/hanatenant/reconciler.go
  • Reconciler logic:
    • Observe: GET tenant, store ETag in status, update phase
    • Create (guid absent): POST tenant, Location header → polling, write GUID to status
    • Update: PUT tenant with If-Match: {etag} header
    • Soft Delete (default): DELETE without ?immediate=true, status → Deleting + purgeTimestamp
    • Hard Delete (annotation hana.sap.com/immediate-delete: "true"): DELETE with ?immediate=true
    • Cascade Delete: finalizer sets deletionTimestamp on all referenced HanaContainer CRs before own deletion
    • Adoption (guid present): GET tenant, status → Ready, populate containerRefs
    • Cascade Adoption (annotation hana.sap.com/cascade-adopt: "true"): automatically create HanaContainer CRs for each container found via API
  • Register controller in internal/controller/hana.go
  • Register MT API group in apis/custom_register.go
  • Unit tests using fake HanaMT client
  • E2E test: Create → Ready, Delete (soft)
  • Example YAMLs in examples/

Acceptance Criteria

  • HanaTenant type definition with complete Spec/Status
  • groupversion_info.go for the new MT API group
  • CRD manifest generated in package/crds/
  • Custom controller internal/controller/hanatenant/reconciler.go
  • Observe: GET tenant, store ETag in status, update phase
  • Create (guid absent): POST tenant, Location header → polling, write GUID to status
  • Update: PUT tenant with If-Match: {etag} header
  • Soft Delete (default): DELETE tenant without ?immediate=true, status → Deleting + purgeTimestamp
  • Hard Delete (annotation set): DELETE tenant with ?immediate=true
  • Cascade Delete: finalizer sets deletionTimestamp on all referenced HanaContainer CRs
  • Adoption (guid present): GET tenant, status → Ready, populate containerRefs
  • Cascade Adoption (cascade-adopt: "true"): automatically create HanaContainer CRs for all containers discovered via API
  • status.conditions[] correctly updated (Ready, OperationInProgress, DeletionFailed types)
  • Unit tests using fake HanaMT client (from Issue 1)
  • E2E test: Create → Ready, Delete (soft) — test/e2e/hanatenant_test.go with //go:build e2e
  • Example YAMLs in examples/: hanatenant-create.yaml, hanatenant-adopt.yaml, hanatenant-cascade-adopt.yaml

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions