Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions pkg/controller/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@ func WithOwner(owner string) DeleteOption {
return owned.WithOwner(owner)
}

// CreateOption for operation Create.
type CreateOption = owned.CreateOption

// WithCreateNoOwner creates the resource without setting the owner.
func WithCreateNoOwner() CreateOption {
return owned.WithCreateNoOwner()
}

// ModifyOption for operation Modify.
type ModifyOption = owned.ModifyOption

Expand All @@ -162,3 +170,8 @@ func WithExpectedPhase(phase resource.Phase) ModifyOption {
func WithExpectedPhaseAny() ModifyOption {
return owned.WithExpectedPhaseAny()
}

// WithModifyNoOwner creates/updates the resource without setting the controller as the owner.
func WithModifyNoOwner() ModifyOption {
return owned.WithModifyNoOwner()
}
4 changes: 2 additions & 2 deletions pkg/controller/runtime/internal/controllerstate/adapter.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ func (adapter *StateAdapter) ContextWithTeardown(ctx context.Context, resourcePo
}

// Create implements controller.Runtime interface.
func (adapter *StateAdapter) Create(ctx context.Context, r resource.Resource) error {
func (adapter *StateAdapter) Create(ctx context.Context, r resource.Resource, options ...controller.CreateOption) error {
if err := adapter.UpdateLimiter.Wait(ctx); err != nil {
return fmt.Errorf("create rate limited: %w", err)
}
Expand All @@ -179,7 +179,7 @@ func (adapter *StateAdapter) Create(ctx context.Context, r resource.Resource) er
r.Metadata().Namespace(), r.Metadata().Type(), adapter.Name, r.Metadata().ID())
}

return adapter.OwnedState.Create(ctx, r)
return adapter.OwnedState.Create(ctx, r, options...)
}

// Update implements controller.Runtime interface.
Expand Down
5 changes: 3 additions & 2 deletions pkg/controller/runtime/internal/rruntime/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (

"github.com/cosi-project/runtime/pkg/controller"
"github.com/cosi-project/runtime/pkg/resource"
"github.com/cosi-project/runtime/pkg/state/owned"
)

// Create augments StateAdapter Create with output tracking.
func (adapter *Adapter) Create(ctx context.Context, r resource.Resource) error {
err := adapter.StateAdapter.Create(ctx, r)
func (adapter *Adapter) Create(ctx context.Context, r resource.Resource, options ...owned.CreateOption) error {
err := adapter.StateAdapter.Create(ctx, r, options...)

if adapter.outputTracker != nil {
adapter.outputTracker[makeOutputTrackingID(r.Metadata())] = struct{}{}
Expand Down
25 changes: 24 additions & 1 deletion pkg/state/owned/owned.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ type Reader interface {
//
// Write methods enforce that the resources are owned by the designated owner.
type Writer interface {
Create(context.Context, resource.Resource) error
Create(context.Context, resource.Resource, ...CreateOption) error
Update(context.Context, resource.Resource) error
Modify(context.Context, resource.Resource, func(resource.Resource) error, ...ModifyOption) error
ModifyWithResult(context.Context, resource.Resource, func(resource.Resource) error, ...ModifyOption) (resource.Resource, error)
Expand Down Expand Up @@ -69,12 +69,28 @@ func ToDeleteOptions(opts ...DeleteOption) DeleteOptions {
return options
}

// CreateOptions for operation Create.
type CreateOptions struct {
WithNoOwner bool
}

// WithCreateNoOwner creates the resource without setting the owner.
func WithCreateNoOwner() CreateOption {
return func(o *CreateOptions) {
o.WithNoOwner = true
}
}

// CreateOption for operation Create.
type CreateOption func(*CreateOptions)

// ModifyOption for operation Modify.
type ModifyOption func(*ModifyOptions)

// ModifyOptions for operation Modify.
type ModifyOptions struct {
ExpectedPhase *resource.Phase
WithNoOwner bool
}

// WithExpectedPhase allows to specify expected phase of the resource.
Expand All @@ -91,6 +107,13 @@ func WithExpectedPhaseAny() ModifyOption {
}
}

// WithModifyNoOwner creates/updates the resource without setting the owner.
func WithModifyNoOwner() ModifyOption {
return func(o *ModifyOptions) {
o.WithNoOwner = true
}
}

// ToModifyOptions converts variadic options to ModifyOptions.
func ToModifyOptions(opts ...ModifyOption) ModifyOptions {
phase := resource.PhaseRunning
Expand Down
22 changes: 22 additions & 0 deletions pkg/state/owned/owned_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,4 +123,26 @@ func TestOwned(t *testing.T) {

rtestutils.AssertNoResource[*A](ctx, t, st, r1.Metadata().ID())
rtestutils.AssertNoResource[*A](ctx, t, st, r2.Metadata().ID())

r3 := NewA("r3")

err = ownedState1.Modify(ctx, r3, func(r resource.Resource) error {
return nil
}, owned.WithModifyNoOwner())
require.NoError(t, err)

res, err := ownedState1.Get(ctx, r3.Metadata())

require.NoError(t, err)
require.Empty(t, res.Metadata().Owner())

r4 := NewA("r4")

err = ownedState1.Create(ctx, r4, owned.WithCreateNoOwner())
require.NoError(t, err)

res, err = ownedState1.Get(ctx, r4.Metadata())

require.NoError(t, err)
require.Empty(t, res.Metadata().Owner())
}
25 changes: 22 additions & 3 deletions pkg/state/owned/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,20 @@ func (st *State) ContextWithTeardown(ctx context.Context, ptr resource.Pointer)
// Create creates a resource in the state.
//
// Create enforces that the resource is owned by the designated owner.
func (st *State) Create(ctx context.Context, res resource.Resource) error {
return st.state.Create(ctx, res, state.WithCreateOwner(st.owner))
func (st *State) Create(ctx context.Context, res resource.Resource, options ...CreateOption) error {
var opts CreateOptions

for _, o := range options {
o(&opts)
}

owner := st.owner

if opts.WithNoOwner {
owner = ""
}

return st.state.Create(ctx, res, state.WithCreateOwner(owner))
}

// Update updates a resource in the state.
Expand All @@ -67,9 +79,16 @@ func (st *State) Modify(ctx context.Context, emptyResource resource.Resource, up
//
// ModifyWithResult enforces that the resource is owned by the designated owner.
func (st *State) ModifyWithResult(ctx context.Context, emptyResource resource.Resource, updateFunc func(resource.Resource) error, options ...ModifyOption) (resource.Resource, error) {
updateOptions := []state.UpdateOption{state.WithUpdateOwner(st.owner)}
owner := st.owner

modifyOptions := ToModifyOptions(options...)

if modifyOptions.WithNoOwner {
owner = ""
}

updateOptions := []state.UpdateOption{state.WithUpdateOwner(owner)}

if modifyOptions.ExpectedPhase != nil {
updateOptions = append(updateOptions, state.WithExpectedPhase(*modifyOptions.ExpectedPhase))
} else {
Expand Down
Loading