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

Add apply set-last-applied subcommand #41694

Merged
merged 1 commit into from
Feb 27, 2017

Conversation

shiywang
Copy link
Contributor

@shiywang shiywang commented Feb 18, 2017

implement part of kubernetes/community#287, will rebase after #41699 got merged, EDIT: since bug output format has been confirmed, will update the behavior of output format soon
cc @kubernetes/sig-cli-pr-reviews @adohe @pwittrock

Support kubectl apply set-last-applied command to update the applied-applied-configuration annotation

@k8s-ci-robot
Copy link
Contributor

Hi @shiywang. Thanks for your PR.

I'm waiting for a kubernetes member to verify that this patch is reasonable to test. If it is, they should reply with @k8s-bot ok to test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Feb 18, 2017
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. release-note-label-needed labels Feb 18, 2017
@k8s-reviewable
Copy link

This change is Reviewable

@k8s-github-robot k8s-github-robot added kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. and removed size/L Denotes a PR that changes 100-499 lines, ignoring generated files. labels Feb 18, 2017
@shiywang shiywang force-pushed the apply-set1 branch 2 times, most recently from 0a2c435 to 1b40c42 Compare February 18, 2017 16:31
@k8s-github-robot k8s-github-robot added size/L Denotes a PR that changes 100-499 lines, ignoring generated files. and removed kind/api-change Categorizes issue or PR as related to adding, removing, or otherwise changing an API size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Feb 18, 2017
@shiywang
Copy link
Contributor Author

why cc @kubernetes/sig-cli-pr-reviews doesn't assign to right people ?

@pwittrock
Copy link
Member

cc'ing doesn't set the reviewers, it just makes sure the right people get notified.

@pwittrock pwittrock assigned pwittrock and unassigned dshulyak Feb 18, 2017
"k8s.io/kubernetes/pkg/kubectl/resource"
)

type SetLastAppliedOptions struct {

Choose a reason for hiding this comment

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

this code snippet duplicate with view-last-applied, can refactor if that get merged.

Copy link
Contributor Author

@shiywang shiywang Feb 20, 2017

Choose a reason for hiding this comment

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

ok, I'll refactor it when all sub-commands get merged.

Long: applySetLastAppliedLong,
Example: applySetLastAppliedExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(options.RunApplySetLastApplied(f, args, cmd, out, err, options))

Choose a reason for hiding this comment

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

I would like this also follow Complete Validate and Run convention.

Copy link
Contributor Author

@shiywang shiywang Feb 20, 2017

Choose a reason for hiding this comment

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

forget that convention again, yuck.... will update soon

return cmd
}

func (o *SetLastAppliedOptions) RunApplySetLastApplied(f cmdutil.Factory, args []string, cmd *cobra.Command, out, errOut io.Writer, options *SetLastAppliedOptions) error {

Choose a reason for hiding this comment

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

pls avoid direct cobra dependency.


applySetLastAppliedExample = templates.Examples(`
# Set the current file's content to the latest-applied-configuration of this resource.
kubectl apply set-last-applied -f deploy.yaml`)

Choose a reason for hiding this comment

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

which resource to be updated? identified by deploy.yaml?

annotationsMap[annotations.LastAppliedConfigAnnotation] = string(localFile)
metadataMap["annotations"] = annotationsMap
objMap["metadata"] = metadataMap
jsonString, err := json.Marshal(objMap)

Choose a reason for hiding this comment

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

I am afraid this is not correct here, we should calculate the final patch between the current object and object with annotation updated.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

so, it's like run apply -f first, get the result object then calculate the final patch between current object and the result object I got before ? currently I think I just set the file's object to annotations then do a json-merge-patch

Copy link
Member

Choose a reason for hiding this comment

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

@adohe What is the result of the incorrect behavior? AFAICT this send just a regular mergepatch with the single annotation instead of calculating the full diff between objects. Is this incorrect or just not the recommended style?

Choose a reason for hiding this comment

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

generally this does the same thing as kubectl annotate, i would think the way annotate use is more clean.

Copy link
Member

Choose a reason for hiding this comment

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

@adohe Hm. I am not sure I totally agree. WDYT of of leaving it as is for now, so this makes feature freeze (tomorrow), and we can follow up if we decide we want to change it.

}
}

if !dryRun {

Choose a reason for hiding this comment

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

should add dry-run handling.

Copy link
Member

Choose a reason for hiding this comment

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

Should dryrun just print out the patch string that would be sent? Does dryrun make sense in this context at all? WDYT @adohe ?

Choose a reason for hiding this comment

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

dry-run means just print the object that would be sent~yep that would make sense print out the patch when dry-run

if err != nil {
return err
}
annotationsMap[annotations.LastAppliedConfigAnnotation] = string(localFile)
Copy link
Member

Choose a reason for hiding this comment

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

If there are no changes, we shouldn't do a patch

}

if cmdutil.ShouldRecord(cmd, info) {
if patch, patchType, err := cmdutil.ChangeResourcePatch(info, f.Command()); err == nil {
Copy link
Member

Choose a reason for hiding this comment

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

Why is this a separate patch command instead of part of the first patch command?

Copy link
Member

Choose a reason for hiding this comment

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

I am not really sure we should update this at all since it isn't updating the object itself. Lets not do this for now.

return err
}

if cmdutil.ShouldRecord(cmd, info) {
Copy link
Member

Choose a reason for hiding this comment

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

Add a comment


var (
applySetLastAppliedLong = templates.LongDesc(`
Set the latest last-applied-configuration annotations by file.`)
Copy link
Member

Choose a reason for hiding this comment

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

Set the latest last-applied-configuration annotations by setting it to match the contents of a file. This results in the last-applied-configuration being updated as though 'kubectl apply -f <file>' was run, without updating any other parts of the object.

Set the latest last-applied-configuration annotations by file.`)

applySetLastAppliedExample = templates.Examples(`
# Set the current file's content to the latest-applied-configuration of this resource.
Copy link
Member

Choose a reason for hiding this comment

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

Set the last-applied-configuration of a resource to match the contents of a file.

annotationsMap[annotations.LastAppliedConfigAnnotation] = string(localFile)
metadataMap["annotations"] = annotationsMap
objMap["metadata"] = metadataMap
jsonString, err := json.Marshal(objMap)
Copy link
Member

Choose a reason for hiding this comment

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

@adohe What is the result of the incorrect behavior? AFAICT this send just a regular mergepatch with the single annotation instead of calculating the full diff between objects. Is this incorrect or just not the recommended style?

return err
}

objMap := map[string]map[string]map[string]string{}
Copy link
Member

Choose a reason for hiding this comment

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

plz pull the patch calculation into its own function. e.g.

func (o *SetLastAppliedOptions) getPatch(info) string, error {
...
return json.Marshal(objMap)
}

return err
}

if err := info.Get(); err != nil {
Copy link
Member

Choose a reason for hiding this comment

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

pull this into the validation function. Add a comment explaining why we do this.

// Verify the object exists in the cluster before trying to patch it.

}
}

if !dryRun {
Copy link
Member

Choose a reason for hiding this comment

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

Should dryrun just print out the patch string that would be sent? Does dryrun make sense in this context at all? WDYT @adohe ?

filenameRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml"
filenameSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/service.yaml"
filenameRCSVC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc-service.yaml"
filenameRC = "../../../test/fixtures/pkg/kubectl/cmd/apply/rc.yaml"
Copy link
Member

Choose a reason for hiding this comment

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

also add an e2e test that does

kubectl apply -f deployment1.yaml // contains replicas = 2
kubectl apply view-last-applied -f deploymen1.yaml // check the last-applied matches expectations
kubectl apply set-last-applied -f deployment2.yaml // doesn't have replicas
kubectl apply view-last-applied -f deploymen1.yaml // check last-applied has been updated
kubectl scale deployment ... // set replicas = 3
kubectl apply -f deployment3.yaml // doesn't have replicas, and changes the images
kubectl get -f deployment3.yaml // verify replicas still = 3 and image has been updated

@adohe-zz
Copy link

@pwittrock I am wondering whether we should allow set last-applied on objects which are not managed by apply. wdyt?

@shiywang shiywang force-pushed the apply-set1 branch 2 times, most recently from 760a00b to b0c0ff2 Compare February 22, 2017 15:57
@pwittrock
Copy link
Member

@shiywang Please rebase to resolve conflicts.

@shiywang
Copy link
Contributor Author

@pwittrock ok, great, will do that

@k8s-github-robot k8s-github-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Feb 23, 2017
options := &SetLastAppliedOptions{Out: out, ErrOut: err}
cmd := &cobra.Command{
Use: "set-last-applied -f FILENAME",
Short: "Set latest last-applied-configuration annotations of by file",
Copy link
Member

Choose a reason for hiding this comment

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

Awkward language. Use:

Set the last-applied-configuration annotation on a live object to match the contents of a file.

# Set the last-applied-configuration of a resource to match the contents of a file.
kubectl apply set-last-applied -f deploy.yaml

# Set the last-applied-configuration of resourcesto match the contents of files in a directory.
Copy link
Member

Choose a reason for hiding this comment

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

typo + awkward:

Execute set-last-applied against each configuration file in a directory.

return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err)
}
if oringalBuf == nil {
return cmdutil.AddSourceToErr(fmt.Sprintf("no last-applied-configuration annotation found on resource: %s\n", info.Name), info.Source, err)
Copy link
Member

Choose a reason for hiding this comment

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

Lets add a flag --create-annotation that will allow this to be set if it is missing. Default should be false.

o.PatchBufferList = append(o.PatchBufferList, patchBuf)
o.InfoList = append(o.InfoList, info)
} else {
fmt.Fprintf(o.Out, "set-last-applied %s: no valid changes saved, won't be patch\n", info.Name)
Copy link
Member

Choose a reason for hiding this comment

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

Awkward:

set-last-applied %s: no changes required.\n

expectedOut: "replicationcontroller/test-rc\n",
},
{
name: "set with no-exist object",
Copy link
Member

Choose a reason for hiding this comment

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

Add test for the annotation does not exist on the live object.

{
name: "set with no-exist object",
filePath: filenameNoExistRC,
expectedErr: "Error from server (NotFound): the server could not find the requested resource (get replicationcontrollers no-exist)",
Copy link
Member

Choose a reason for hiding this comment

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

Add test for a json file

{
name: "set with no-exist object",
filePath: filenameNoExistRC,
expectedErr: "Error from server (NotFound): the server could not find the requested resource (get replicationcontrollers no-exist)",
Copy link
Member

Choose a reason for hiding this comment

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

Add test for a directory of files

# Set the last-applied-configuration of resourcesto match the contents of files in a directory.
kubectl apply set-last-applied -f path/

# Set the last-applied-configuration of a resource to match the contents of a file, will create if resource doesn't have one.
Copy link
Member

Choose a reason for hiding this comment

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

will create the annotation if it does not already exist

return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%v\nfrom server for:", info), info.Source, err)
}
if oringalBuf == nil && !o.CreateAnnotation {
return cmdutil.UsageError(cmd, "no last-applied-configuration annotation found on resource: %s, please use '--create-annotation' to create one", info.Name)
Copy link
Member

Choose a reason for hiding this comment

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

please use '--create-annotation' to create one

How about

to create the annotation, run the command with --create-annotation

@shiywang
Copy link
Contributor Author

shiywang commented Feb 23, 2017

@pwittrock ptal ?

@pwittrock
Copy link
Member

@k8s-bot test this

@k8s-github-robot k8s-github-robot added the release-note Denotes a PR that will be considered when it comes time to generate release notes. label Feb 24, 2017
@k8s-ci-robot
Copy link
Contributor

@shiywang: you can't request testing unless you are a kubernetes member.

In response to this comment:

@k8s-bot test this

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here.

@shiywang
Copy link
Contributor Author

shiywang commented Feb 24, 2017

@pwittrock hi, just can not reach you on slack, sorry, just forgot update bazel last night, could you please let bot tests again ?

@mengqiy
Copy link
Member

mengqiy commented Feb 24, 2017

@k8s-bot ok to test

update

update code

update unit tests

hack/update

remove spew

update bazel

updated

add comments

remove unused parameter

remove hardcode

bump unit tests

add new flags

add unit tests

add bazel

genreate doc
@shiywang
Copy link
Contributor Author

@pwittrock docs genreated, ptal

@shiywang
Copy link
Contributor Author

@k8s-bot unit test this

@pwittrock
Copy link
Member

/lgtm

@k8s-ci-robot k8s-ci-robot added the lgtm "Looks good to me", indicates that a PR is ready to be merged. label Feb 24, 2017
@pwittrock
Copy link
Member

/approve

@k8s-github-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

The following people have approved this PR: pwittrock, shiywang

Needs approval from an approver in each of these OWNERS Files:

You can indicate your approval by writing /approve in a comment
You can cancel your approval by writing /approve cancel in a comment

@k8s-github-robot k8s-github-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Feb 24, 2017
@k8s-github-robot
Copy link

Automatic merge from submit-queue (batch tested with PRs 42044, 41694, 41927, 42050, 41987)

@k8s-github-robot k8s-github-robot merged commit e6ecfd2 into kubernetes:master Feb 27, 2017
@shiywang shiywang mentioned this pull request Mar 31, 2017
4 tasks
@shiywang shiywang deleted the apply-set1 branch April 4, 2017 07:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
approved Indicates a PR has been approved by an approver from all required OWNERS files. cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. lgtm "Looks good to me", indicates that a PR is ready to be merged. release-note Denotes a PR that will be considered when it comes time to generate release notes. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants