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

introduce v1alpha2 api with auto conversion #1529

Closed
wants to merge 1 commit into from

Conversation

vdemeester
Copy link
Member

@vdemeester vdemeester commented Nov 6, 2019

Changes

This is related to #1526 and #1379.

This introduces a new api version v1alpha2 while still allowing user
to use v1alpha1 API.

  • Only one version of the CRD can be stored, so v1alpha1 is the one
    stored
  • All the version of the CRD must be schema compatible (before 1.16)
    • v1alpha1 gets all the fields, meaning :
      • the new ones (from v1alpha2, …)
      • the old deprecated ones (that will be removed from v1alpha2)
    • we may only document the "frozen" v1alpha1 field (and not the
      new one that are coming from the other api versions)
  • kubectl get returns the highest priority version, aka the most
    recent one, here v1alpha2. To make sure any object created from
    any version are valid (while getting), we convert them using the
    admission webhook (#blackmagic 🧙).
    • Object created using v1alpha1 API will automatically be
      converted (see below)
    • This has the downsize of not being able to get v1alpha1 object
      anymore (although it should be possible using the client-go and
      some even more #blackmagic 🧙 hack on the webhook side probably)
  • One benefit of this approach (apis.Convertible) is that once
    we only support 1.16 (the release with conversion webhook), this
    will be usable almost as is (for the conversion webhook) 👼.

This is done in a quick and dirty way:

  • Lot's of code is duplicated where it would not be needed, it was
    just quicker to do so at that point in time
  • I completely skipped the variable interpolation validation for
    Parameters as those values would/will need to be automatically
    transformed too (but it was a bit complicated for what I wanted to
    experiment on)
  • I did not implement the reconcilier part of this. It should be
    simple as:
    • it will use only one object (the store one, aka v1alpha1)
    • it will make the assumption that the objects are fully
      transformed (either by the webhook or in-memory by the
      controller), meaning there will be no handling
      backward-compatible
      piece of code in the reconcilier (all is
      contained in the Validable, Defaultable and Convertible impl.).
  • I did not run/fix the tests 😉

Possible next steps are:

  • Split this into smaller PR.
  • Introduce a v1alpha2 package early but not exposing it before we
    are ready to. This will allow us to not have to rush this for
    0.9, and to increment over this in smaller step.
  • Decide what v1alpha2 should look like — I did this experiment with
    TaskSpec.Inputs.Params to TaskSpec.Params but we should decide
    what we want to change and target that.
  • Reduce duplication by reusing anything that didn't change from
    v1alpha1 to v1alpha2 in v1alpha1 (aka refering the same type
    in go)
  • Related to this experiment, implement the variable interpolation
    validation thing and the reconcilier part too.
  • Need to figure out if the definition types (Task, Pipeline, …)
    need a controller (I don't think so but…)

Example of conversion

#This task deploys with kubectl apply -f <filename>
apiVersion: tekton.dev/v1alpha1
kind: Task
metadata:
  name: demo-deploy-kubectl
spec:
  inputs:
    resources:
    - name: workspace
      type: git
    - name: image
      type: image
    params:
    - name: path
      description: Path to the manifest to apply
    - name: yqArg
      description: Okay this is a hack, but I didn't feel right hard-codeing `-d1` down below
    - name: yamlPathToImage
      description: The path to the image to replace in the yaml manifest (arg to yq)
  steps:
  - name: replace-image
    image: mikefarah/yq
    command: ['yq']
    args:
    - "w"
    - "-i"
    - "$(inputs.params.yqArg)"
    - "$kube(inputs.params.path)"
    - "$(inputs.params.yamlPathToImage)"
    - "$(inputs.resources.image.url)"
  - name: run-kubectl
    image: lachlanevenson/k8s-kubectl
    command: ['kubectl']
    args:
    - 'apply'
    - '-f'
    - '$(inputs.params.path)'

becomes the following at creation

#This task deploys with kubectl apply -f <filename>
apiVersion: tekton.dev/v1alpha2
kind: Task
metadata:
  name: demo-deploy-kubectl
spec:
  inputs:
    resources:
    - name: workspace
      type: git
    - name: image
      type: image
  params:
  - name: path
    description: Path to the manifest to apply
  - name: yqArg
    description: Okay this is a hack, but I didn't feel right hard-codeing `-d1` down below
  - name: yamlPathToImage
    description: The path to the image to replace in the yaml manifest (arg to yq)
  steps:
  - name: replace-image
    image: mikefarah/yq
    command: ['yq']
    args:
    - "w"
    - "-i"
    - "$(inputs.params.yqArg)"
    - "$kube(inputs.params.path)"
    - "$(inputs.params.yamlPathToImage)"
    - "$(inputs.resources.image.url)"
  - name: run-kubectl
    image: lachlanevenson/k8s-kubectl
    command: ['kubectl']
    args:
    - 'apply'
    - '-f'
    - '$(inputs.params.path)'

Putting an hold as this is not meant to be merged, ever !

/hold
/cc @bobcatfish @skaegi @imjasonh @afrittoli @abayer

Signed-off-by: Vincent Demeester vdemeest@redhat.com

Submitter Checklist

These are the criteria that every PR should meet, please check them off as you
review them:

See the contribution guide for more details.

Double check this list of stuff that's easy to miss:

Reviewer Notes

If API changes are included, additive changes must be approved by at least two OWNERS and backwards incompatible changes must be approved by more than 50% of the OWNERS, and they must first be added in a backwards compatible way.

This introduces a new api version `v1alpha2` while still allowing user
to use `v1alpha1` API.

- Only one version of the CRD can be stored, so `v1alpha1` is the one
stored
- All the version of the CRD **must** be schema compatible (before 1.16)
  - `v1alpha1` gets **all** the fields, meaning :
    - the new ones (from `v1alpha2`, …)
    - the old deprecated ones (that will be removed from `v1alpha2`)
  - we may *only* document the "frozen" `v1alpha1` field (and not the
    new one that are coming from the other api versions)
- `kubectl` get returns the highest priority version, aka the most
  recent one, here `v1alpha2`. To make *sure* any object created from
  any version are valid (while getting), we convert them using the
  admission webhook (#blackmagic 🧙).
  - Object created using `v1alpha1` API will automatically be
  converted (see below)
  - This has the downsize of not being able to `get` v1alpha1 object
  anymore (although it should be possible using the `client-go` and
  some even more #blackmagic 🧙 hack on the webhook side probably)
- One benefit of this approach (`apis.Convertible`) is that once
  we *only* support 1.16 (the release with conversion webhook), this
  will be usable almost as is (for the conversion webhook) 👼.

This is done in a quick and dirty way:
- Lot's of code is duplicated where it would not be needed, it was
  just quicker to do so at that point in time
- I completely skipped the *variable interpolation* validation for
  `Parameters` as those values would/will need to be automatically
  transformed too (but it was a bit complicated for what I wanted to
  experiment on)
- I did not implement the **reconcilier** part of this. It should be
  simple as:
  - it will use only one object (the store one, aka `v1alpha1`)
  - it will make the assumption that the objects are fully
    transformed (either by the webhook or in-memory by the
    controller), meaning there will be no *handling
    backward-compatible* piece of code in the reconcilier (all is
    contained in the `Validable`, `Defaultable` and `Convertible` impl.).

Possible next steps are:
- Split this into smaller PR.
- Introduce a `v1alpha2` package early but not exposing it before we
  are ready to. This will allow us to not have to rush this for
  0.9, **and** to increment over this in smaller step.
- Decide what `v1alpha2` should look like — I did this experiment with
  `TaskSpec.Inputs.Params` to `TaskSpec.Params` but we should decide
  what we want to change and target that.
- Reduce duplication by reusing anything that didn't change from
  `v1alpha1` to `v1alpha2` in `v1alpha1` (aka refering the same type
  in go)
- Related to this experiment, implement the variable interpolation
  validation thing **and** the reconcilier part too.
- Need to figure out if the definition types (`Task`, `Pipeline`, …)
  need a `controller` (I don't think so but…)

Signed-off-by: Vincent Demeester <vdemeest@redhat.com>
@tekton-robot tekton-robot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Nov 6, 2019
@googlebot googlebot added the cla: yes Trying to make the CLA bot happy with ppl from different companies work on one commit label Nov 6, 2019
@tekton-robot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
To complete the pull request process, please assign vdemeester
You can assign the PR to them by writing /assign @vdemeester in a comment when ready.

The full list of commands accepted by this bot can be found here.

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@tekton-robot tekton-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Nov 6, 2019
@@ -104,7 +113,7 @@ func main() {

// Decorate contexts with the current state of the config.
ctxFunc := func(ctx context.Context) context.Context {
return v1alpha1.WithDefaultConfigurationName(store.ToContext(ctx))
return v1alpha2.WithUpgradeViaDefaulting(store.ToContext(ctx))
Copy link
Member Author

Choose a reason for hiding this comment

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

This tells the webhook to do the conversion 👼

Comment on lines +20 to +26
versions:
- name: v1alpha1
served: true
storage: true
- name: v1alpha2
served: true
storage: false
Copy link
Member Author

Choose a reason for hiding this comment

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

v1alpha1 is the stored version, but both are served

@tekton-robot
Copy link
Collaborator

The following is the coverage report on pkg/.
Say /test pull-tekton-pipeline-go-coverage to re-run this coverage report

File Old Coverage New Coverage Delta
pkg/reconciler/taskrun/taskrun.go 72.5% 72.3% -0.2

@@ -1,5 +1,5 @@
---
Copy link
Member Author

Choose a reason for hiding this comment

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

This files contains v1alpha2 and v1alpha1 Tasks

@@ -42,7 +42,7 @@ ${GOPATH}/bin/deepcopy-gen \
# Knative Injection
${KNATIVE_CODEGEN_PKG}/hack/generate-knative.sh "injection" \
github.com/tektoncd/pipeline/pkg/client github.com/tektoncd/pipeline/pkg/apis \
"pipeline:v1alpha1" \
"pipeline:v1alpha1,v1alpha2" \
Copy link
Member Author

Choose a reason for hiding this comment

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

This updates codegen to generate v1alpha1 and v1alpha2 clientset, informers, …

"knative.dev/pkg/apis"
)

func (source *Task) ConvertUp(ctx context.Context, obj apis.Convertible) error {
Copy link
Member Author

Choose a reason for hiding this comment

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

This allows us to take a v1alpha1 object and "convert it up" to a more recent version (that will be passed, by the webhook or the reconcilier for in-memory upgrade)

}

func (sink *Task) ConvertDown(ctx context.Context, obj apis.Convertible) error {
switch source := obj.(type) {
Copy link
Member Author

Choose a reason for hiding this comment

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

This does the opposite of ConvertUp, it takes a "higher" version of the Task object and converts it "back" to v1alpha1 (hence the need for v1alpha1 types to have all the fields

Comment on lines +32 to +45
if v1alpha2.IsUpgradeViaDefaulting(ctx) {
fmt.Println("********************************************")
v := v1alpha2.TaskSpec{}
if ts.ConvertUp(ctx, &v) == nil {
fmt.Printf("v: %+v\n", v)
fmt.Printf("v.inputs: %+v\n", v.Inputs)
fmt.Printf("v.outputs: %+v\n", v.Outputs)
alpha1 := TaskSpec{}
if alpha1.ConvertDown(ctx, v) == nil {
*ts = alpha1
}
}
}
fmt.Printf("ts: %+v\n", ts)
Copy link
Member Author

Choose a reason for hiding this comment

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

This combined with https://github.com/tektoncd/pipeline/pull/1529/files#diff-58de452513b7e8d8d3cfea23eb4ae6a8R116 make the conversion automatic from v1alpha1 to a v1alpha2 compatible object (still stored as v1alpha1)

// must be supplied as inputs in TaskRuns unless they declare a default
// value.
// +optional
Params []ParamSpec `json:"params,omitempty"`
Copy link
Member Author

Choose a reason for hiding this comment

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

This fields comes from v1alpha2 "struct" and "might not be documented"

// must be supplied as inputs in TaskRuns unless they declare a default
// value.
// +optional
Params []ParamSpec `json:"params,omitempty"`
DeprecatedParams []ParamSpec `json:"params,omitempty"`
Copy link
Member Author

Choose a reason for hiding this comment

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

Renaming it makes it easier to know it's deprecated and we shouldn't depend/looking at it in the reconcilier

Comment on lines +98 to +102
/*
if err := validateInputParameterVariables(ts.Steps, ts.Inputs); err != nil {
return err
}
*/
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 said in the comments, this is commented to skip the "auto" migrate variable interpolation

@vdemeester
Copy link
Member Author

btw, this is how knative/serving does it 👼 😉

@tekton-robot
Copy link
Collaborator

@vdemeester: The following tests failed, say /retest to rerun them all:

Test name Commit Details Rerun command
pull-tekton-pipeline-unit-tests d75b034 link /test tekton-pipeline-unit-tests
pull-tekton-pipeline-build-tests d75b034 link /test pull-tekton-pipeline-build-tests
pull-tekton-pipeline-integration-tests d75b034 link /test pull-tekton-pipeline-integration-tests

Full PR test history. Your PR dashboard.

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.

@vdemeester
Copy link
Member Author

  • Split this into smaller PR.

I'll start tackling this next week, especially the following items 👼

  • Introduce a v1alpha2 package early but not exposing it before we
    are ready to. This will allow us to not have to rush this for
    0.9, and to increment over this in smaller step.
  • Reduce duplication by reusing anything that didn't change from
    v1alpha1 to v1alpha2 in v1alpha1 (aka refering the same type
    in go)

@vdemeester vdemeester mentioned this pull request Nov 15, 2019
3 tasks
@@ -131,7 +131,7 @@ spec:
- "w"
- "-i"
- "$(inputs.params.yqArg)"
- "$(inputs.params.path)"
- "$kube(inputs.params.path)"
Copy link
Contributor

@cccfeng cccfeng Nov 16, 2019

Choose a reason for hiding this comment

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

Hi, it looks like this line of code has one more word “kube” .

@vdemeester
Copy link
Member Author

I am going to close as split work has started 😉
/close

@tekton-robot
Copy link
Collaborator

@vdemeester: Closed this PR.

In response to this:

I am going to close as split work has started 😉
/close

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes Trying to make the CLA bot happy with ppl from different companies work on one commit do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants