-
Notifications
You must be signed in to change notification settings - Fork 236
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: add direct controller for BigQueryDataTransferConfig #2688
feat: add direct controller for BigQueryDataTransferConfig #2688
Conversation
41af159
to
7fa396f
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yuwenma I added some notes on special handling for service generated ID.
// Get ResourceID | ||
resourceID := direct.ValueOf(obj.Spec.ResourceID) | ||
if resourceID == "" { | ||
serviceGeneratedID, err := parseServiceGeneratedIDFromExternalRef(obj) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resource ID is service generated. It could be "" prior to resource creation.
if a.id == nil { | ||
return false, nil | ||
} | ||
if a.id.transferConfigID == "" { // resource ID is not yet generated by the GCP service |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
special handling for finding resource prior to being created.
if err != nil { | ||
return fmt.Errorf("error converting %s to BigQueryDataTransferConfigIdentity: %w", created.Name, err) | ||
} | ||
a.id.transferConfigID = serviceGeneratedID |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to write the service generated ID back
if mapCtx.Err() != nil { | ||
return mapCtx.Err() | ||
} | ||
resource.Name = a.id.FullyQualifiedName() // need to pass service generated ID to GCP API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to pass the service generated ID when updating the resource.
|
||
GroupVersionKind = schema.GroupVersionKind{ | ||
Group: GroupVersion.Group, | ||
Version: GroupVersion.Version, | ||
Kind: "BigQueryDataTransferConfig", | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A better format could be adding
var BigQueryDataTransferConfigGVK = GroupVersion.WithKind("BigQueryDataTransferConfig")
in the _types.go, which is what the latest template does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. I am updating the controller template in #2692, so that we don't have a undefined GroupVersionKind
right after scaffolding the controller code.
@@ -55,7 +55,7 @@ go run ./scripts/crd-tools reflow-descriptions --dir apis/config/crd/ | |||
|
|||
# excluded_resources are resources that are under development for a direct conversion | |||
# we don't modify the CRD just yet for those but will in the future | |||
excluded_resources=("bigquerydatatransferconfig" "securesourcemanagerinstance") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
if obj.Spec.PubSubTopicRef != nil { | ||
topic, err := refv1beta1.ResolvePubSubTopic(ctx, reader, obj, obj.Spec.PubSubTopicRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
obj.Spec.PubSubTopicRef.External = topic.String() | ||
} | ||
|
||
// Resolve BigQueryDataSet Ref | ||
if obj.Spec.DatasetRef != nil { | ||
dataset, err := refv1beta1.ResolveBigQueryDataset(ctx, reader, obj, obj.Spec.DatasetRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
obj.Spec.DatasetRef.External = dataset.String() | ||
} | ||
|
||
// Resolve KMSCryptoKey Ref | ||
if obj.Spec.EncryptionConfiguration != nil { | ||
kmsCryptoKeyRef, err := refv1beta1.ResolveKMSCryptoKeyRef(ctx, reader, obj, obj.Spec.EncryptionConfiguration.KmsKeyRef) | ||
if err != nil { | ||
return nil, err | ||
} | ||
obj.Spec.EncryptionConfiguration.KmsKeyRef = kmsCryptoKeyRef | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we shall move the non-parent depedencies in the create and update calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Otherwise the presence of the dependency would block the target resource
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIUC, it mainly affects Find()
call? In other words, if the dependencies are not present, Create()
and Update()
will be blocked anyway, but Find()
should not be blocked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It affects Delete
. If a reference is missing, it cannot delete the object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is a blocker issue.
if a.id == nil { | ||
return false, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind explaining what this means?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will remove this block. I think it was from my previous iteration on how to handle the service generated ID. Thanks for spotting!
} | ||
|
||
// Get ResourceID | ||
resourceID := direct.ValueOf(obj.Spec.ResourceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you miss a case that metadata.name --> resourceID if spec.resourceID
is not given? Or is that not a valid case here? I mean the case that KCC acquire a GCP resource that matches the metadata.name
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For resource with service generated ID, I am not sure how useful is metadata.name
. It will be ignored during GCP resource creation, and later it cannot be used to match (acquire) the GCP resource. To acquire the GCP resource, we have to give GCP API the service generated ID (i.e., via setting spec.resourceID
)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean KCC acquire a GCP resource: the BigQuery server creates a Transfer object called "xyz", user then specify KCC metadata.name xyz
to acquire that pre-existing resource. Is the service generated ID a valid k8s name?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From my tests, the generated ID is something like "66e60359-0000-2d33-8bc7-c82add80addc". I think k8s name needs to start and end with an alphanumeric character?
Besides, when user try to acquire a GCP resource, I prefer them to explicitly set spec.ResourceID
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
kk, looks like all BigQuery service-generated ID is all using the UUID format. Then I'm good with this.
var id *BigQueryDataTransferConfigIdentity | ||
externalRef := direct.ValueOf(obj.Status.ExternalRef) | ||
if externalRef == "" { | ||
id = BuildID(projectID, location, resourceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the problem here is that since we do not assign metadata.name
to resourceID, if spec.resourceID
is not given and the GCP object is not created (no status.externalRef
), this will always pass in an empty resourceID
, which fails the following logics.
return nil, fmt.Errorf("BigQueryDataTransferConfig %s/%s has spec.location changed, expect %s, got %s", | ||
u.GetNamespace(), u.GetName(), id.location, location) | ||
} | ||
if id.transferConfigID != resourceID { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this only works for acquire but not KCC-created. Because the transferConfigID is server generated and KCC does not write it back to spec.resourceID (and not metadata.name)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the case of acquiring this resource, I believe we want users to specifically set spec.resourceID
to the service generated ID? (as opposed to set metadata.Name
to the service generated ID)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind elaborating a little bit more on why "we want users to specifically set spec.resourceID to the service generated ID"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was referring to
https://screenshot.googleplex.com/6Dcx5KjqfXvuexB
I think it makes sense to have users explicitly set spec.ResourceID
to express the intend to "acquire a resource".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay, the code is good because the service-generated ID is UUID so it can't be placed in metadata.name
I feel like maybe we can merge the tool-generated code first, and handle the service-generated ID in a follow up PR, because the change needs to happen in multiple places and I'd like to use that as a coding example. |
6d549e4
to
da9025a
Compare
da9025a
to
0afa310
Compare
0afa310
to
c3c84d4
Compare
Rebased to resolve a conflict. |
Surface the "serviceAccountName" in BigQueryDataTransferConfig API
c3c84d4
to
0f14fe0
Compare
var opts []option.ClientOption | ||
if m.config.UserAgent != "" { | ||
opts = append(opts, option.WithUserAgent(m.config.UserAgent)) | ||
} | ||
if m.config.HTTPClient != nil { | ||
opts = append(opts, option.WithHTTPClient(m.config.HTTPClient)) | ||
} | ||
if m.config.UserProjectOverride && m.config.BillingProject != "" { | ||
opts = append(opts, option.WithQuotaProject(m.config.BillingProject)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now we have a helper function for this. You can check the controller template
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool! update the code.
} | ||
|
||
// Get ResourceID | ||
resourceID := direct.ValueOf(obj.Spec.ResourceID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean KCC acquire a GCP resource: the BigQuery server creates a Transfer object called "xyz", user then specify KCC metadata.name xyz
to acquire that pre-existing resource. Is the service generated ID a valid k8s name?
return nil, fmt.Errorf("BigQueryDataTransferConfig %s/%s has spec.location changed, expect %s, got %s", | ||
u.GetNamespace(), u.GetName(), id.location, location) | ||
} | ||
if id.transferConfigID != resourceID { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mind elaborating a little bit more on why "we want users to specifically set spec.resourceID to the service generated ID"?
b8bf4dc
to
f8daaa5
Compare
/lgtm |
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: yuwenma The full list of commands accepted by this bot can be found here. The pull request process is described here
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
e6d725b
into
GoogleCloudPlatform:master
doc: update release notes for #2688
Fixes #1432