Skip to content

Add implementation and helpers for ResourceSetLatest and ResourceSync - #34

Merged
zainawaisn merged 3 commits into
mainfrom
zain/add-update-namespace
Oct 28, 2026
Merged

zainawaisn merged 3 commits into
mainfrom
zain/add-update-namespace

Conversation

@zainawaisn

@zainawaisn zainawaisn commented Oct 26, 2026 •

Copy link
Copy Markdown
Collaborator

What was changed

Issue #8

Implements ResourceSetLatest and ResourceSync for the Namespace reconciler. The operator can now create a Temporal Cloud namespace from a CR and keep its spec and tags in sync.

  • Upgrade github.com/temporalio/kube-temporal v0.5.0 → v0.6.0 for transform.TimeFromProto. v0.6.0 changes ResourceDelete to return (Resource, error), so the Namespace reconciler's (still stubbed) ResourceDelete is updated to match.
  • ResourceSetLatest now fetches the namespace from Temporal Cloud and rewrites latest's spec and status to match. If Status.ID is empty, it looks the namespace up by name with GetNamespaces(). This is how the qualified ID gets saved after a create, and it prevents duplicate creates if status is lost. A namespace that isn't found clears the spec and status, so ResourceSync recreates it.
  • ResourceSync makes at most one cloud call per reconcile and then requeues, because a namespace with an async operation in progress rejects new ones. In order: create if there's no ID; otherwise only an Active namespace proceeds. Activating, Updating, Deleting, Deleted and unknown states requeue and wait; ActivationFailed, UpdateFailed, DeleteFailed, Suspended and Expired return a terminal error, as does a project mismatch. Then UpdateNamespace if the spec differs, and UpdateNamespaceTags if the tags differ.
  • Conversions live on the API types: Namespace.FromProto/ToProto and NamespaceSpec.FromProto in api/cloud/v1alpha1/namespace.go, and ResourceState.FromProto/ToProto in api/cloud/common. Namespace.ToProto sets the Cloud spec.name from the CR's metadata.name, per the CRD conventions doc.
  • Unit tests for the converters, findNamespaceByName and tagsDiff. TestReconciler_ResourceSetLatest is updated for the ID-based lookup and covers the get-by-ID, lookup-by-name, NotFound and not-found-by-name paths. The fake Cloud server gains GetNamespaces support for this.

@tomba7 tomba7 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest we comment out TestReconciler_ResourceSetLatest for now and I can do that as a follow up after you merge. The fake cloud server looks like the right thing to use for this.

Comment thread controller/namespace/convert.go Outdated

// resourceStateFromProto converts a Temporal Cloud resource state to its CR
// name. Unspecified and unknown states map to "": the CR field is
// enum-validated, so an unrecognized value would fail the status patch.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good candidate to go under a common covert package IMO

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the namespace specific proto helpers have been moved to v1alpha1/namespace.go. general purpose proto helpers that work regardless of temporal resource have been moved to api/cloud/common and kube-temporal.

Comment thread controller/namespace/convert.go Outdated
}
}

func timeFromProto(ts *timestamppb.Timestamp) *metav1.Time {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smae with this.

Comment thread controller/namespace/convert.go Outdated

// resourceStatusFromProto returns the [cloudcommon.ResourceStatus] that
// represents the supplied Temporal Cloud Namespace.
func resourceStatusFromProto(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is also a good shared candidate. Plus I wanted to call out making it have the shape recommended here in this proposal comment

ctrlerrors.ErrResourceSync, id, state,
))
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would only Active fall through here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated the switch statement, only Active falls through. All async operations are blocked on the Temporal server side unless the state is Active, so we gate on that here so those requests don't start in the first place.

// async operation, and a namespace with an operation in flight rejects new
// ones, so after each call we requeue and let the next reconcile observe the
// result and take the next step.
func syncNamespace(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good to add a few unit tests for this as there are a few important paths to cover here, esp the ones requiring a requeue with the right errors. But I'm fine doing it as a follow up.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will do this in a follow-up pr.

@zainawaisn
zainawaisn merged commit b68380d into main Oct 28, 2026
7 checks passed
@zainawaisn
zainawaisn deleted the zain/add-update-namespace branch October 28, 2026 07:20
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