Skip to content
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

Enable support for taints, annotations and labels #256

Merged
merged 6 commits into from May 3, 2019

Conversation

hardikdr
Copy link
Member

@hardikdr hardikdr commented Apr 21, 2019

What this PR does / why we need it: This PR implements a feature to propagate and maintain the taints, annotations and labels from machine-api-objects till node-objects.
Proposal doc: https://docs.google.com/document/d/1yNTCJ7hwAhYPmBwACZvnKqO10G_aZ8kotcuSkiN4NAA/edit

Which issue(s) this PR fixes:
Fixes #174

Special notes for your reviewer:

Release note:

Enables support for propagating and maintaining the taints, annotations and labels from machine-api objects to node-objects.

@hardikdr hardikdr requested review from ggaurav10 and a team as code owners April 21, 2019 09:19
@gardener-robot-ci-1 gardener-robot-ci-1 added the reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) label Apr 21, 2019
@hardikdr hardikdr changed the title Sync metadata Enable support for taints, annotations and labels Apr 21, 2019
@gardener-robot-ci-1 gardener-robot-ci-1 added needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels Apr 21, 2019
Copy link
Contributor

@prashanth26 prashanth26 left a comment

Choose a reason for hiding this comment

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

Some minor comments can choose to ignore wherever it is not applicable.

@@ -199,6 +210,11 @@ func (c *controller) reconcileClusterMachine(machine *v1alpha1.Machine) error {
Machine controller - nodeToMachine
*/
func (c *controller) addNodeToMachine(obj interface{}) {
if !cache.WaitForCacheSync(nil, c.nodeSynced) {
Copy link
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?

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed offline, we can avoid it here I guess, thanks for bringing it up.

// It ensures, that any nodeTemplate element available on Machine should be available on node-object.
// Although there could be more elements already available on node-object which will not be touched.
func (c *controller) syncMachineNodeTemplates(machine *v1alpha1.Machine) error {
if machine.Status.Node == "" {
Copy link
Contributor

Choose a reason for hiding this comment

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

If a machine object doesn't have a node object associated with it due to some error while creation. Could it be a possibility that the object doesn't get deleted? as syncMachineNodeTemplates are tried before syncing machine creation/deletion/update? or maybe I didn't get it.

Copy link
Member Author

@hardikdr hardikdr Apr 23, 2019

Choose a reason for hiding this comment

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

Yes, this is a very good catch, thanks.
Basically if, for any reason, node-object is available and Status.Node has not been updated then the controller can get stuck into the loop, taking care of it.

}
nCopy[mkey] = mvalue
}
// Update is not required.
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a suggestion for better code readability. Can choose to ignore it.

if updateNeeded  {
       node.Labels = nCopy
}

return updateNeeded

Copy link
Member Author

Choose a reason for hiding this comment

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

Suggestion looks good to me, taking it in.

}
nCopy[mkey] = mvalue
}
// Update is not required.
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above

Just a suggestion for better code readability. Can choose to ignore it.

if updateNeeded  {
       node.Annotations = nCopy
}

return updateNeeded

Copy link
Member Author

Choose a reason for hiding this comment

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

Suggestion looks good to me, taking it in.

updateNeeded = true
}
}
node.Spec.Taints = nTaintsCopy
Copy link
Contributor

Choose a reason for hiding this comment

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

Might need this to maintain consistency?

if updateNeeded  {
       node.Spec.Taints = nTaintsCopy
}

return updateNeeded

Copy link
Member Author

Choose a reason for hiding this comment

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

Suggestion looks good to me, taking it in.

Copy link
Collaborator

@amshuman-kr amshuman-kr left a comment

Choose a reason for hiding this comment

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

Suggested some changes. Label/Annotation/Taint deletion is not yet supported, right?

if newIS.Annotations == nil {
newIS.Annotations = make(map[string]string)
}
oldRevision, ok := newIS.Annotations[RevisionAnnotation]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Would it not be better to use the status section to store the old revision rather than in annotations? Please ignore if this was already used for other MachineSet controller logic.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this logic is being used at other places in controllers.


oldRevisionInt, err := strconv.ParseInt(oldRevision, 10, 64)
if err != nil {
if oldRevision != "" {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not check for oldRevision == "" before the parsing?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think this is being tackled at very initial steps in ParseInt, not sure if required to check again here.
Basically, the template for the core logic of this method is taken from the existing code, wanted to keep it consistence.

//If the RS annotation is empty then initialise it to 0
oldRevisionInt = 0
}
newRevisionInt, err := strconv.ParseInt(newRevision, 10, 64)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why not pass newRevisionInt as a parameter and avoid a parsing?

Copy link
Member Author

Choose a reason for hiding this comment

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

The template is adapted from an existing method, just wanted to keep it consistent.

isNodeTemplateChanged := false

deploymentNodeTemplateCopy := deployment.Spec.Template.Spec.NodeTemplateSpec.DeepCopy()
machineSetNodeTemplateCopy := is.Spec.Template.Spec.NodeTemplateSpec.DeepCopy()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Is this required? We will be overriding is.Spec.Template.Spec.NodeTemplateSpec later anyway, right?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, just wanted to be safe as deployment is a pointer. Though might not be required really for machineset, again wanted to keep the behavior similar for both parameters in a method.

func copyMachineDeploymentNodeTemplatesToMachineSet(deployment *v1alpha1.MachineDeployment, is *v1alpha1.MachineSet) bool {
isNodeTemplateChanged := false

deploymentNodeTemplateCopy := deployment.Spec.Template.Spec.NodeTemplateSpec.DeepCopy()
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can't we postpone this until after the isNodeTemplateChanged check?

Copy link
Member Author

Choose a reason for hiding this comment

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

I think, isNodeTemplateChanged is using the copy, so not sure if we can really postpone it.

Copy link
Collaborator

Choose a reason for hiding this comment

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

No. The point was that you do not need a copy for DeepEqual. If isNodeTemplateChanged returns false, we can skip a spurious DeepCopy.

isNodeTemplateChanged = !(apiequality.Semantic.DeepEqual(deploymentNodeTemplateCopy, machineSetNodeTemplateCopy))

if isNodeTemplateChanged {
is.Spec.Template.Spec.NodeTemplateSpec = deployment.Spec.Template.Spec.NodeTemplateSpec
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't there be a DeepCopy of deployment.Spec.Template.Spec.NodeTemplateSpec here?

Copy link
Member Author

Choose a reason for hiding this comment

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

It's mainly an assignment to the machineset, so not sure we necessarily need to use the deep copy here.

Copy link
Collaborator

Choose a reason for hiding this comment

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

We are assigning a subtree of the MachineDeployment struct (which might have references/pointers) as a subtree of MachineSet. Is that a good idea?

if _, ok := nCopy[mkey]; !ok || mvalue != nCopy[mkey] {
updateNeeded = true
}
nCopy[mkey] = mvalue
Copy link
Collaborator

Choose a reason for hiding this comment

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

Here nCopy is not really a copy, is it? It will actually modify the node.Labels? Is this expected? According to this line, it seems that nCopy is treated as a true (possibly shallow) copy.

Copy link
Member Author

Choose a reason for hiding this comment

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

I see, thanks this is a really good catch. I think we don't need to explicitly assign the nCopy to node.Labels.


// SyncMachineAnnotations syncs the annotations of the machine with node-objects.
// It returns true if update is needed else false.
func SyncMachineAnnotations(machine *v1alpha1.Machine, node *v1.Node) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comments as SyncMachineLabels.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, taking care of it, thanks.


// SyncMachineTaints syncs the annotations of the machine with node-objects.
// It returns true if update is needed else false.
func SyncMachineTaints(machine *v1alpha1.Machine, node *v1.Node) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Same comments as SyncMachineLabels.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, taking care of it, thanks.

// copyMachineSetNodeTemplatesToMachines copies machineset's nodeTemplate to machine's nodeTemplate,
// and returns true if machine's nodeTemplate is changed.
// Note that apply and revision nodeTemplates are not copied.
func copyMachineSetNodeTemplatesToMachines(machineset *v1alpha1.MachineSet, machine *v1alpha1.Machine) bool {
Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Member Author

Choose a reason for hiding this comment

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

Basically, the same answer, hope though I didn't miss anything in there.

@hardikdr
Copy link
Member Author

@amshuman-kr Yes, deletion is not supported in this logic, although not sure if we need to according to proposal discussed.

@amshuman-kr
Copy link
Collaborator

@hardikdr It is fine to keep out deletion from the scope. I have responded to a couple of comments. PTAL.

Copy link
Contributor

@prashanth26 prashanth26 left a comment

Choose a reason for hiding this comment

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

Just take care of header changes.

@hardikdr hardikdr added reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 2, 2019
@gardener-robot-ci-1 gardener-robot-ci-1 added needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 2, 2019
@hardikdr hardikdr added reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 2, 2019
@gardener-robot-ci-1 gardener-robot-ci-1 added needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 2, 2019
@hardikdr hardikdr removed the needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) label May 3, 2019
@hardikdr hardikdr added the reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) label May 3, 2019
@gardener-robot-ci-1 gardener-robot-ci-1 added needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD) and removed reviewed/ok-to-test Has approval for testing (check PR in detail before setting this label because PR is run on CI/CD) labels May 3, 2019
@prashanth26 prashanth26 merged commit 9e544fe into gardener:master May 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs/ok-to-test Needs approval for testing (check PR in detail before setting this label because PR is run on CI/CD)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Enable support for taints, annotations and labels
4 participants