Skip to content

Claimed resources api - #185

Closed
lhaendler wants to merge 12 commits into
kbind-dev:mainfrom
lhaendler:claimed_resources_api
Closed

Claimed resources api#185
lhaendler wants to merge 12 commits into
kbind-dev:mainfrom
lhaendler:claimed_resources_api

Conversation

@lhaendler

@lhaendler lhaendler commented Oct 18, 2023

Copy link
Copy Markdown
Contributor

based on discussions from #155

lhaendler and others added 5 commits October 16, 2023 21:05
Add human readable prompts for permission claims to cli plugin
Add unit tests for permission claim prompts
Co-authored-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
Co-authored-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
// +required
// +kubebuilder:validation:Required
// +kubebuilder:validation:Enum=Accepted;Rejected
State AcceptablePermissionClaimState `json:"state"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

how is the flow? The cli (or some other means under the user identity) creates these acceptable claims and sets the accepted or rejected? What is the consequence of rejected (vs. not being listed)?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

rejected claims are not reconciled. Saving them as rejected could allow the user to accept them later on via cli.

sttts added 2 commits October 23, 2023 16:44
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>

type Matcher struct {
// +optional
Pattern string `json:"pattern,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what did we agree on is a pattern? A regex? A wildcard pattern?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

	// pattern is a wildcard pattern that is matched against the key. This means
	// it is either a literal string or start or ends in `*` but is not '*'
	// itself.

?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Also we should make this required for now, until we have another type and can make this a sum type.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Why not '*' itself?

sttts added 3 commits October 23, 2023 18:38
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>

@mjudeikis mjudeikis left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for this! APIS are hard :/
I think we could try modeling this more like client-go. Its not ideal, but is what people are used to. I mean like

Create(ctx context.Context, aPIBinding *v1alpha1.APIBinding, opts v1.CreateOptions) (*v1alpha1.APIBinding, error)
Try to isolate things into duplets - Action(Get,Update,Create,Delete) and ActionsOptions so stucts would be something like:

type PermissionClaim struct {
	GroupResource `json:","
	PermissionClaimActions `json:","
	...
}

type PermissionClaimActions{
  Get *PermissionClaimGetOptions `json:"get,omitempty"`
  Create *PermissionClaimCreateOptions `json:"create,omitempty"`

and thing like OnConflict *PermissionClaimOnConflictOptions json:"onConflict,omitempty"`` is explisit to Update/Create only and nested inside options, not on the parent struct.

//
// +optional
// +kubebuilder:default:={}
Selector *ResourceSelector `json:"selector,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

resourceSelector - mainly 2 reasons. selector is so overloaded these days. It can be pod selector, node selector. I would like us to be explicit. And bonus - match KCP.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it's actually objectSelector. We select objects, not resources. Resources are pods, namespaces, services, as in GVRs.

//
// +kubebuilder:validation:Required
// +kubebuilder:validation:MinLength:=1
Version string `json:"version"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Do we need this? Is there scenarios where we might want to claim v1 and not v1alpha1?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The version also determines what to sync. So yes, we have to know.

Comment on lines +81 to +90
AutoAdopt bool `json:"autoAdopt,omitempty"`

// autoDonate set to true means that a newly created object synced from the
// provider to the consumer cluster is immediately donated to the consumer
// by marking it as owned by the consumer on both sides.
//
// autoDonate is mutually exclusive with autoAdopt.
//
// +optional
AutoDonate bool `json:"autoDonate,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Can this become something like AdoptStratety and enum? So if more comes in the future we would not keep adding them like list of booleans?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

ownerTransfer = Adopt|Donate|None ?

// Note that update permissions do not imply create permissions.
//
// +optional
Update *PermissionClaimUpdateOptions `json:"update,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Just readability? Move close to Read, Create, Update and maybe we cloud do something like GroupResource json:","`` with PermissionsClaimsVerbOptions and I was thinking maybe worth matching RBAC syntax `GET, UPDATE, CREATE` ? I this case Read would change to Get? But not fully sold on last one myself.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

it's not really about requests. Hence not "get".

// If set to false, deleted provider-owned objects get deleted on the provider cluster as well.
//
// +kubebuilder:default:=true
RecreateWhenConsumerSideDeleted bool `json:"recreateWhenConsumerSideDeleted"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These looks like they will be mutual exlusive too, maybe something similar to:

// Similarly to above, these are constants to support HTTP PATCH utilized by
// both the client and server that didn't make sense for a whole package to be
// dedicated to.
type PatchType string

const (
	JSONPatchType           PatchType = "application/json-patch+json"
	MergePatchType          PatchType = "application/merge-patch+json"
	StrategicMergePatchType PatchType = "application/strategic-merge-patch+json"
	ApplyPatchType          PatchType = "application/apply-patch+yaml"
)

As I bet these will be more here, like ForceRecreate, DeleteAndRecreate, etc

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

you write above to move this into update or create. Neither is really a fit.

@sttts sttts Oct 24, 2023

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe create.onDelete: Recreate|DeleteOnProviderSide.

@Danil-Grigorev Danil-Grigorev Nov 6, 2023

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I’m not sure if it was brought up in the previous discussions, but what about deletion scenarios? Currently an object removed from the consumer cluster is triggering deletion on the provider side. If you remove the object on the provider side, it will be re-created from the consumer copy. Meaning that in the Recreate state there is no way to remove the object from the cluster without stopping the konnector instance. Shouldn’t it be more general? Recreate|FollowDeletion|Orphan? allowing for both sides being equal in having right for resource eviction?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

That's where the onConflict part of the field name comes from. The action is performed when the lifecycle of the object conflicts with the state on the cluster.

Meaning that in the Recreate state there is no way to remove the object from the cluster without stopping the konnector instance
For provider owned objects, that is true (short of undoing the binding). Claimed resources are objects that support objects of a bound api. For example, creating a MangoDB object should spawn a secret containing credentials to use the MangoDB instance. It is expected that the supporting objects are removed upon deletion of the 'main' resource.

The behavior in case of deletion looks like the following:

Recreate: false

provider owned object deleted: not recreated on the consumer side. Since the provide still manages the object, the provider will eventually delete it on the provider cluster.

consumer owned object: the object will be deleted on the provider cluster, since the consumer object controls the lifecycle

Recreate: true

provider owned object: the object is created again on the consumer cluster, once the provider deletes it on the provider cluster, it is deleted on the consumer cluster

consumer owned object: the object will be deleted on the provider cluster, since the consumer object controls the lifecycle

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

maybe onConflict.userDeletesProviderOwnedObject = Recreate | Orphan?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

So an object created on the provider side and synchronized on the consumer side will behave the same way as the object created on the consumer side and synchronized on the provider side is idempotent when it comes to deletion? Basically the FollowDeletion or Follow scenario, is supported by the api?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

An object that is created by the provider and synchronized to the consumer could be donated using ownerTransfer=Donate. In that case, if the consumer deletes it, it will be deleted on the provider cluster too. Since donation means that the consumer will own the object, the provider may have to claim update fields to continue writing to the object after creation in the consumer cluster

// If not true, and a conflicting consumer object exists, it is not touched.
//
// +optional
ReplaceExisting bool `json:"replaceExisting,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Same as above. We could reuse these if done right.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

what is "above"?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I mean, can we have more of these and be exclusive? Like:

CreateStrategy:
    DeleteAndCreate (some object in k8s world cant be updated)
    UpdateInplace

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

How about onConflict.userObjectExists = Replace | Keep?

//
// +optional
// +kubebuilder:default:={}
OnConflict *PermissionClaimOnConflictOptions `json:"onConflict,omitempty"`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Somehow this does not look right. You will have conflict on Create/Update only. Now this still being optional but implied to get and Deletes too. Some logical shuffling might be needed. Like Clients logic: Delete(ctx context.Context, name string, opts v1.DeleteOptions) error where DeleteOptions are only for delete struct and we can reuse them inside.

sttts and others added 2 commits October 24, 2023 09:58
Signed-off-by: Dr. Stefan Schimanski <stefan.schimanski@gmail.com>
@mjudeikis

Copy link
Copy Markdown
Contributor

implemented in #304

@mjudeikis mjudeikis closed this Oct 9, 2025
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.

5 participants