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 "generate" command #1002

Merged

Conversation

isutton
Copy link
Contributor

@isutton isutton commented Oct 31, 2019

This PR create a new s2i top level command, generate.

The choice to create this command instead of just implementing the same functionality in the build --as-dockerfile flow, is that the semantics of builder image would change between build and build --as-dockerfile; the former would reflect changes made to local images, where the latter would ignore those. This means s2i build my-image . and s2i build --as-dockerfile my-image . | buildah commands could produce different results.

This new command expects the given builder image name to be available on a remote registry, and is inspected through the infrastructure provided by containers/image.

Once OCI support is implemented in s2i, this command could benefit and provide transparent access to local images as well, since it would delegate the inspection task to the container runtime itself and even deprecate build --as-dockerfile.

This PR requires some dependencies to be updated, since it depends on containers/image, and both depended (and still depend) on Docker.

In cli.go the gen-dockerfile command is registered.

In dockerfile.go, the CreateDockerfile() method was modified to inherit both scripts-url and destination labels.

gen-dockerfile.go is a new file, where the command is implemented.

In go.mod, dependency to containers/image was added, together with replacements for indirect dependencies based on containers/image go.mod file.

@openshift-ci-robot openshift-ci-robot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Oct 31, 2019
@openshift-ci-robot
Copy link

Hi @isutton. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /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.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@openshift-ci-robot openshift-ci-robot added needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. labels Oct 31, 2019
@bparees
Copy link
Contributor

bparees commented Oct 31, 2019

and even deprecate build --as-dockerfile.

i would definitely want to see --as-dockerfile deprecated when this new command is introduced, to avoid user confusion about which to use and differences in behavior between the two.

@otaviof
Copy link
Member

otaviof commented Oct 31, 2019

Naming wise I suggest calling this new sub-command generate instead, to follow the names of the other existing sub-commands.

@isutton
Copy link
Contributor Author

isutton commented Oct 31, 2019

and even deprecate build --as-dockerfile.

i would definitely want to see --as-dockerfile deprecated when this new command is introduced, to avoid user confusion about which to use and differences in behavior between the two.

I'm not sure about doing both at the same time, but I would definitely release a minor to introduce the command, and a major to remove the --as-dockerfile flag in the case this is the direction we want to move forward.

@sbose78
Copy link

sbose78 commented Oct 31, 2019

Thanks @isutton and @otaviof for this, and thank you @bparees for taking a quick look.

Even though I find s2i build --as-dockerfile super-confusing because it doesn't actually build, I feel there's a need to fix image inspection for it #973 instead of having a new command.

My worry is:

  1. s2i build : inspects image labels, builds images
  2. s2i build --as-dockerfile: doesn't inspect image labels, doesn't build image, generates dockerfile
  3. s2i gen-dockerfile inspects registry images image labels , doesn't build images, generates dockerfile

I would love to remove (2) entirely to avoid this. Or move (3) into (2).

@siamaksade , thoughts?

@bparees
Copy link
Contributor

bparees commented Oct 31, 2019

  1. s2i build : inspects image labels, builds images
  2. s2i build --as-dockerfile: doesn't inspect image labels, doesn't build image, generates dockerfile
  3. s2i gen-dockerfile inspects registry images image labels , doesn't build images, generates dockerfile

I would love to remove (2) entirely to avoid this. Or move (3) into (2).

why not get rid of (2) entirely to avoid this?

@bparees
Copy link
Contributor

bparees commented Oct 31, 2019

(long term, after a deprecation period)

@sbose78
Copy link

sbose78 commented Oct 31, 2019

👍 to removing (2) . I think we should do it as part of a version 1.x release?

@siamaksade
Copy link

@bparees @sbose78 I agree with deprecation and removal following its grace period

@adambkaplan
Copy link
Contributor

+1 to removal.

Now that we are switching to go modules, v2 may come sooner than we think. Any refactor that removes or alters an exported method/constant requires a major version bump.

https://github.com/golang/go/wiki/Modules#semantic-import-versioning

@sbose78
Copy link

sbose78 commented Oct 31, 2019

I was hoping v2 would look a lot more different ( a lot more breaking changes ;) ), but I'm good with getting to v2 sooner, and maybe postpone bigger changes to a future version.

@isutton
Copy link
Contributor Author

isutton commented Nov 8, 2019

The past couple of days @otaviof and I have been enabling buildah in s2i from start to end (#1003), and since this effort is being quite successful I'd like to propose a strategy for aligning that PR and this one.

As stated previously, the gen-dockerfile command was proposed because the same functionality present in s2i build --as-dockerfile:

  • Changed the semantics of the builder image, where without --as-dockerfile it would consult both local and remote builder images, but with it would consider only remote builder images. This alone makes the functionality incoherent and error prone for the end user.

  • Doesn't correctly represent the same actions s2i would do for the given input parameters, meaning images built by s2i and images built by a Dockerfile produced by s2i are not equivalent in some scenarios, making it harder for both the end user and s2i or builder image developers to correctly assess whether the right results are being yielded.

There are a couple of points I'm still unsure:

  • In the case Buildah is a first class citizen in s2i, I would expect that generating a Dockerfile might be not as important as before, since s2i build would work in OCP 4 with its Docker socket restrictions.
  • To produce a Dockerfile equivalent to the process s2i applies in its build process, the majority of build arguments and switches are required in this command to properly build the Dockerfile, since both commands would share the build process. I personally dislike this fact, and IMO it points back in the direction of --as-dockerfile in the developer experience front, since the result of s2i build would be equivalent to s2i build --as-dockerfile | buildah bud -f -.

My take on this is to finalize #1003, since it will enable s2i to build an application image without requiring a Docker socket, making it suitable to run in Tekton, Travis CI and other build pipelines. Additionally, it also gives us the foundation to produce an accurate Dockerfile based on the existing s2i build workflow.

@sbose78
Copy link

sbose78 commented Nov 8, 2019

https://github.com/openshift/builder does use the Dockerfile generation flow and then does a lot of other things. So, I wouldn't want to comment on the future of Dockerfile generation.

Dockerfile generation is handy because it lets us separate the concern of 'define strategy' v/s 'build the image using a strategy'.

So, irrespective of #1003 , we would need this to be in ASAP.

@isutton isutton marked this pull request as ready for review November 8, 2019 14:37
@openshift-ci-robot openshift-ci-robot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Nov 8, 2019
@bparees
Copy link
Contributor

bparees commented Nov 8, 2019

Dockerfile generation is handy because it lets us separate the concern of 'define strategy' v/s 'build the image using a strategy'.

+1. i think there is a lot of value in avoiding tying s2i to runtime libraries both on the inspection/generation side as well as the image construction side.

@sbose78
Copy link

sbose78 commented Nov 8, 2019

/ok-to-test

@openshift-ci-robot openshift-ci-robot added ok-to-test Indicates a non-member PR verified by an org member that is safe to test. and removed needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. labels Nov 8, 2019
@sbose78
Copy link

sbose78 commented Nov 8, 2019

/retest

2 similar comments
@isutton
Copy link
Contributor Author

isutton commented Nov 9, 2019

/retest

@isutton
Copy link
Contributor Author

isutton commented Nov 9, 2019

/retest

@bparees
Copy link
Contributor

bparees commented Nov 11, 2019

/test all

@bparees
Copy link
Contributor

bparees commented Nov 11, 2019

/refresh

@adambkaplan
Copy link
Contributor

/retest

@isutton
Copy link
Contributor Author

isutton commented Dec 5, 2019

Test is currently not compiling with the following:

# github.com/openshift/source-to-image/test/integration/docker [github.com/openshift/source-to-image/test/integration/docker.test]
test/integration/docker/integration_test.go:154:6: undefined: client.IsErrImageNotFound

Note that I believe our CI vms use golang 1.12

Fixed in cbcc36a.

@isutton
Copy link
Contributor Author

isutton commented Dec 5, 2019

@isutton Are there any tests for this new s2i generate command?

I considered all the important logic was already being tested, and the logic that creates the Dockerfile was already being tested, so I didn't do it at the time.

Will look at that.

All generate does is either encoded in very straightforward and simple code, or is already tested through either SBO's or vendored libraries unit tests, so tests specific to the generate command have not been implemented.

@isutton
Copy link
Contributor Author

isutton commented Dec 5, 2019

Is there anything I can do to move this PR and finalize this piece of work?

Copy link
Contributor

@adambkaplan adambkaplan left a comment

Choose a reason for hiding this comment

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

@isutton General logic here looks good. I think we can refactor the getImageLabels function in a follow-up PR, since openshift/builder implements its own logic to set image labels.

I'm worried a bit about the go mod bumps. From what I can gather all we need is containers/image/v5 and its dependencies.

Finally, these commits need to be squashed. I'd like to see the following:

  1. A clean commit with the dependencies bumped in go.mod and go.sum
  2. A bump(*) commit with the vendor updates.
  3. A commit with the new functionality

github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c // indirect
github.com/containers/image/v5 v5.0.0
github.com/coreos/etcd v3.3.17+incompatible // indirect
github.com/docker/distribution v2.7.1-0.20190205005809-0d3efadf0154+incompatible
Copy link
Contributor

Choose a reason for hiding this comment

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

this should be ok - docker/distribution on openshift/builder is 2.7.1

github.com/docker/distribution v2.6.0-rc.1.0.20170726174610-edc3ab29cdff+incompatible
github.com/docker/docker v0.0.0-20190404075923-dbe4a30928d4
github.com/containerd/fifo v0.0.0-20190816180239-bda0ff6ed73c // indirect
github.com/containers/image/v5 v5.0.0
Copy link
Contributor

Choose a reason for hiding this comment

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

this is ok - containers/image uses strict semvers so we won't have transitive dep conflicts in openshift/builder

Short: "Generate a Dockerfile based on the provided builder image",
Example: `
# Generate a Dockerfile from a remote builder image:
$ s2i generate docker://quay.io/redhat-developer/app-binding-operator Dockerfile.gen
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd use one of our canonical s2i images as an example - docker.io/centos/nodejs-10-centos7

Copy link

Choose a reason for hiding this comment

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

@isutton Could you please make the above change?

Copy link
Contributor

Choose a reason for hiding this comment

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

@isutton please update the example here.

Copy link
Contributor

Choose a reason for hiding this comment

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

Also a bit of a nit - is it worth switching the order around? Thoughts on the following semantics?

$ s2i generate DOCKERFILE [IMAGE]

or

$ s2i generate DOCKERFILE --from=[IMAGE]

Copy link
Contributor Author

@isutton isutton Jan 23, 2020

Choose a reason for hiding this comment

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

From what I understood, IMAGE is always required in this use case since there's no information regarding that; additionally, the protocol currently must be informed by the user to refer to the image since containers/image is responsible for retrieving its contents and inspecting its labels.

I believe the following example is closer to what we want, where DOCKERFILE could have the Dockerfile value by default:

$ s2i generate IMAGE [DOCKERFILE]

During implementation, I opted for DOCKERFILE to be mandatory and not having defaults to avoid unwillingly Dockerfile overwrites.


The requested example modification has been made.

Copy link

Choose a reason for hiding this comment

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

Right, IMAGE is always required since it is the s2i builder image. I think Adam is OK with that.

I do like s2i generate DOCKERFILE --from=quay.io/builder/image

instead of

s2i generate quay.io/builder/image Dockerfile.gen

Copy link
Contributor

Choose a reason for hiding this comment

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

From what I understood, IMAGE is always required in this use case since there's no information regarding that;

Correct

During implementation, I opted for DOCKERFILE to be mandatory and not having defaults to avoid unwillingly Dockerfile overwrites.

I agree with this choice for now. We can always opt to make it optional later; I have other ideas on how to arrange the arguments to this command that are worth discussing in a follow-up PR.

pkg/cmd/cli/cmd/generate.go Outdated Show resolved Hide resolved
cfg.BuilderImage = cmd.Flags().Arg(0)
cfg.AsDockerfile = cmd.Flags().Arg(1)

ctx := context.TODO()
Copy link
Contributor

Choose a reason for hiding this comment

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

context.Background() is acceptable here, since this is effectively the main entrypoint to the command.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done in 7eb02e7.

go.mod Outdated
github.com/moby/buildkit => github.com/dmcgowan/buildkit v0.0.0-20170731200553-da2b9dc7dab9
github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.2.0
github.com/containerd/containerd => github.com/containerd/containerd v1.3.0
github.com/docker/docker => github.com/docker/docker v0.0.0-20180522102801-da99009bbb11
Copy link
Contributor

Choose a reason for hiding this comment

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

Docker has been downgraded here - why?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

To use the same Docker version containers/image is using:

https://github.com/containers/image/blob/v5.0.0/go.mod#L13

github.com/Sirupsen/logrus => github.com/sirupsen/logrus v1.2.0
github.com/containerd/containerd => github.com/containerd/containerd v1.3.0
github.com/docker/docker => github.com/docker/docker v0.0.0-20180522102801-da99009bbb11
golang.org/x/crypto => golang.org/x/crypto v0.0.0-20180904163835-0709b304e793
Copy link
Contributor

Choose a reason for hiding this comment

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

golang.org/x/crypto has been added in the replace stanza, but is not referenced in the require stanza. Why is this necessary?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After I did my first changes, I noticed that make test didn't work. After I dug into it, I've noticed that buildkit and swarmkit should be updated as well, and this lead to all those dependencies

Tests use buildkit and swarmkit, which also had to be bumped and adjusted (see 9f3ead4 for reference).

@isutton
Copy link
Contributor Author

isutton commented Dec 8, 2019

@isutton General logic here looks good. I think we can refactor the getImageLabels function in a follow-up PR, since openshift/builder implements its own logic to set image labels.

Sounds fine.

I'm worried a bit about the go mod bumps. From what I can gather all we need is containers/image/v5 and its dependencies.

containers/image/v5 adds a new Docker version as a transitive dependency, being reflected on the replace section in go.mod (some dependencies have been added from Docker's dependencies and other libraries as well).

Finally, these commits need to be squashed. I'd like to see the following:

1. A clean commit with the dependencies bumped in `go.mod` and `go.sum`

2. A `bump(*)` commit with the vendor updates.

3. A commit with the new functionality

Will do.

@adambkaplan
Copy link
Contributor

@isutton note that we recently merged a go.mod bump that addressed some of the issues with buildkit.

@openshift-ci-robot openshift-ci-robot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Dec 17, 2019
@openshift-ci-robot openshift-ci-robot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jan 9, 2020
@sbose78
Copy link

sbose78 commented Jan 15, 2020

I think this is now ready?

@isutton
Copy link
Contributor Author

isutton commented Jan 20, 2020

I've updated the branch according to the project's guidelines.

/cc @adambkaplan @sbose78

@sbose78
Copy link

sbose78 commented Jan 23, 2020

@adambkaplan Should we take this in?

Copy link
Contributor

@adambkaplan adambkaplan left a comment

Choose a reason for hiding this comment

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

In general this looks good - only have the remaining nit on the example. @sbose78 I'd like you and perhaps @otaviof to weigh in on my comment regarding the command line argument order. Given our prior difficulties with go.mod, I need to verify the dep changes work with golang 1.13.

@isutton thanks so much for the effort you've put in thus far. I think we're almost there.

Short: "Generate a Dockerfile based on the provided builder image",
Example: `
# Generate a Dockerfile from a remote builder image:
$ s2i generate docker://quay.io/redhat-developer/app-binding-operator Dockerfile.gen
Copy link
Contributor

Choose a reason for hiding this comment

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

@isutton please update the example here.

Short: "Generate a Dockerfile based on the provided builder image",
Example: `
# Generate a Dockerfile from a remote builder image:
$ s2i generate docker://quay.io/redhat-developer/app-binding-operator Dockerfile.gen
Copy link
Contributor

Choose a reason for hiding this comment

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

Also a bit of a nit - is it worth switching the order around? Thoughts on the following semantics?

$ s2i generate DOCKERFILE [IMAGE]

or

$ s2i generate DOCKERFILE --from=[IMAGE]

This change adds the generate command to s2i, where it allows
the user to produce a Dockerfile able to be used by any build
system supporting the format, such as buildah and possibly
others.
@adambkaplan
Copy link
Contributor

/approve

/lgtm

Will follow up on my "other ideas" I have for the cli args.

@openshift-ci-robot openshift-ci-robot added the lgtm Indicates that a PR is ready to be merged. label Jan 23, 2020
@openshift-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: adambkaplan, isutton

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot openshift-ci-robot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jan 23, 2020
@openshift-merge-robot openshift-merge-robot merged commit 3311f0e into openshift:master Jan 23, 2020
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. lgtm Indicates that a PR is ready to be merged. ok-to-test Indicates a non-member PR verified by an org member that is safe to test. 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.

9 participants