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

Support architecture targeted builds #837

Merged
merged 13 commits into from
Mar 13, 2020
Merged

Support architecture targeted builds #837

merged 13 commits into from
Mar 13, 2020

Conversation

jahkeup
Copy link
Member

@jahkeup jahkeup commented Feb 11, 2020

Issue #, if available:

Related: #687

Description of changes:

These changes clean up the Makefile in order to widely update references for building cross-arch artifacts and images in some configurations. I've added many docstrings to the updated sections as well as the left in place sections, hopefully this a welcome addition - please let me know if I've misunderstood or misinterpreted usages in any way!

With these changes in place I have been able to build container images for both aarch64 and x86_64 (on the same host using QEMU as binfmt handlers!) as well as the bare executables by providing the GOARCH styled architecture names as ARCH:

# Build container images for aarch64 (either *on* aarch64 or using `binfmt` method)
make all ARCH=arm64
# and the executables:
make build-linux ARCH=arm64

# Build container images for x86_64 explicitly
make all ARCH=amd64
# and the executables:
make build-linux ARCH=amd64

The updated targets also take into account the currently running host and enforce the use of the native build where required (such as testing with -race enabled).

I've updated the Circle CI builds to utilize these code paths that build for aarch64 and x86_64, though I have not yet tested this and would like help to validate this proposed change.

cc: @mogren

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

Copy link
Contributor

@mogren mogren left a comment

Choose a reason for hiding this comment

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

@jahkeup Nice! Thanks a lot for fixing this. Just some minor nitpicks and comments...

Makefile Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
Makefile Outdated Show resolved Hide resolved
@jahkeup jahkeup force-pushed the arches branch 2 times, most recently from ec6f884 to ce2b3a8 Compare February 12, 2020 01:18
@jahkeup jahkeup requested a review from mogren February 12, 2020 16:50
Copy link
Contributor

@mogren mogren left a comment

Choose a reason for hiding this comment

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

@jahkeup Thanks a lot, this all looks a lot better!

Makefile Outdated Show resolved Hide resolved
Copy link
Contributor

@jaypipes jaypipes left a comment

Choose a reason for hiding this comment

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

Hi @jahkeup! Thanks very much for this contribution!

Just FYI for future PRs, I would prefer that code changes be tightly scoped to a specific feature described in the PR/commit summary. This change introduces a wholesale set of feature changes, style changes, cleanups and more, which usually makes reviewing PRs like this more difficult (because code reviewers need to examine each line in the PR to determine whether that line correlates to something the PR claims to add or whether the line is merely a style-only change).

I don't mind style-only changes, of course, and most of the style-only changes you've included in here are awesome. It's just for future PRs, please try to keep those in a separate PR entirely so reviewers can more easily group code changes in their head :)

Anyway, the only thing that I'd like you to functionally change in this PR is the handling of the golint stuff. Please see inline comment for an explanation.

Thanks!
-jay

build-linux docker \
unit-test unit-test-race build-docker-test docker-func-test \
build-metrics docker-metrics \
metrics-unit-test docker-metrics-test
Copy link
Contributor

Choose a reason for hiding this comment

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

missing portmap above.

Copy link
Member Author

Choose a reason for hiding this comment

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

portmap isn't phony, its a file that's created by downloading it - if portmap were to be listed here it will be downloaded every time the target is activated.

If the goal is to be sure that we're getting the Makefile's specific binary, then Makefile can be added as dependency for portmap which would cause portmap to be considered stale and then redownloaded. I don't see usages of portmap outside of the container build at the moment (which doesn't get stale where Make can help) so I'd recommend not doing that at this time.

Copy link
Contributor

Choose a reason for hiding this comment

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

portmap isn't phony, its a file that's created by downloading it - if portmap were to be listed here it will be downloaded every time the target is activated.

ack, yes, good point.

Makefile Outdated Show resolved Hide resolved
Makefile Outdated

# Default to build the Linux binary
# Build the VPC CNI plugin agent using host Go toolchain.
Copy link
Contributor

Choose a reason for hiding this comment

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

s/using host Go toolchain/using the Linux Go toolchain/

..since GOOS is always linux, 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.

..since GOOS is always linux, right?

I'm not sure if you're implying something here, the Makefile does set GOOS=linux for builds.

Not that this is what's at hand, but I personally think that -linux suffix is unnecessary. Any additional GOOS/GOARCH combinations can be specified to influence the build when make is invoked. To me, then, this target should be named build (another OS/Arch combination can be built using eg: make build GOOS=windows[1]). I chose to leave build-linux in place as its a target that's very likely to be referenced in places I'm not aware of. With the appropriate variables set in the Makefile, ie: GOOS, the effect/output of build-linux remains the same as it was before.

s/using host Go toolchain/using the Linux Go toolchain/

I'd argue that it is still accurate to say using the host Go toolchain as it'll be up to the host's Go toolchain to build for GOOS=linux. It's certainly feasible that builds are possible on native Mac OS X for instance using a multi-arch equipped distribution of Go. The syscall provided by the stdlib should allow for the binary to build on developer's native machines (with the caveat that their Go toolchains have the support).


[1]: definitely would not build because of syscall dependencies deeply rooted in Linux land.

Makefile Outdated
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/networkutils/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/utils/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/eniconfig/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/ipamd/...
Copy link
Contributor

Choose a reason for hiding this comment

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

Might clean this up in a future commit with:

unit-test-race: COVER_ARGS = -v -mod=readonly -cover -race
    go test $(COVER_ARGS) -timeout 10s ./cmd/*/...
...

Copy link
Member Author

Choose a reason for hiding this comment

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

Is this an ask? Or a note for another time? Happy to make the change now if that's welcome.

Copy link
Contributor

Choose a reason for hiding this comment

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

it's a note for a future PR :) no need to make the change here.

-type d \
-not -path ./rpc -not -path ./pkg -not -path ./cmd -not -path './.*' \
-not -name mocks -not -name mock \
-not -name 'mock_*' -not -name 'mocks_*' \
Copy link
Contributor

Choose a reason for hiding this comment

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

the above includes the docs/, testdata/, misc/, /config and /scripts directories which should be excluded from Go linting.

Probably better to just search for Go files and exclude mocks:

find . -name *.go -not -name *mock*

but be aware that there are linter failures in the tree's current code, so we'll need to clean these up before adding lint to the check target that gates CI:

jaypipes@udb42383a8e5155:~/go/src/github.com/aws/amazon-vpc-cni-k8s$ for f in `find . -name *.go -not -name *mock*`; do GO111MODULE=on golint $f; done
./pkg/awsutils/awsutils.go:194:1: exported method ENIMetadata.PrimaryIPv4Address should have comment or be unexported
./pkg/ec2metadatawrapper/ec2metadatawrapper.go:17:6: type HttpClient should be HTTPClient
./pkg/ipwrapper/ip.go:23:6: exported type IP should have comment or be unexported
./pkg/ipwrapper/ip.go:30:1: exported function NewIP should have comment or be unexported
./pkg/eniconfig/eniconfig.go:50:6: exported type ENIConfig should have comment or be unexported
./pkg/eniconfig/eniconfig.go:55:5: exported var ErrNoENIConfig should have comment or be unexported
./pkg/eniconfig/eniconfig.go:58:6: type name will be used as eniconfig.ENIConfigController by other packages, and that stutters; consider calling this Controller
./pkg/eniconfig/eniconfig.go:68:6: type name will be used as eniconfig.ENIConfigInfo by other packages, and that stutters; consider calling this Info
./pkg/eniconfig/eniconfig.go:162:1: exported method ENIConfigController.Getter should have comment or be unexported
./pkg/utils/ttime/ttime.go:14:6: exported type Timer should have comment or be unexported
./pkg/utils/retry/retry.go:27:6: func name will be used as retry.RetryWithBackoff by other packages, and that stutters; consider calling this WithBackoff
./pkg/utils/retry/retry.go:35:6: func name will be used as retry.RetryWithBackoffCtx by other packages, and that stutters; consider calling this WithBackoffCtx
./pkg/utils/retry/retry.go:57:6: func name will be used as retry.RetryNWithBackoff by other packages, and that stutters; consider calling this NWithBackoff
./pkg/utils/retry/retry.go:66:6: func name will be used as retry.RetryNWithBackoffCtx by other packages, and that stutters; consider calling this NWithBackoffCtx
./pkg/utils/retry/backoff.go:23:6: exported type Backoff should have comment or be unexported
./pkg/utils/retry/backoff.go:28:6: exported type SimpleBackoff should have comment or be unexported
./pkg/utils/retry/backoff.go:51:1: exported method SimpleBackoff.Duration should have comment or be unexported
./pkg/utils/retry/backoff.go:59:1: exported method SimpleBackoff.Reset should have comment or be unexported
./pkg/utils/retry/errors.go:21:6: exported type Retriable should have comment or be unexported
./pkg/utils/retry/errors.go:25:6: exported type DefaultRetriable should have comment or be unexported
./pkg/utils/retry/errors.go:29:1: exported method DefaultRetriable.Retry should have comment or be unexported
./pkg/utils/retry/errors.go:33:1: exported function NewRetriable should have comment or be unexported
./pkg/utils/retry/errors.go:39:6: exported type RetriableError should have comment or be unexported
./pkg/utils/retry/errors.go:44:6: exported type DefaultRetriableError should have comment or be unexported
./pkg/utils/retry/errors.go:49:1: exported function NewRetriableError should have comment or be unexported
./pkg/utils/retry/errors.go:56:6: exported type AttributeError should have comment or be unexported
./pkg/typeswrapper/client.go:20:6: exported type CNITYPES should have comment or be unexported
./pkg/typeswrapper/client.go:27:1: exported function New should have comment or be unexported
./pkg/apis/crd/v1alpha1/register.go:17:2: exported var SchemeBuilder should have comment or be unexported
./pkg/apis/crd/v1alpha1/types.go:9:6: exported type ENIConfigList should have comment or be unexported
./pkg/apis/crd/v1alpha1/types.go:17:6: exported type ENIConfig should have comment or be unexported
./pkg/apis/crd/v1alpha1/types.go:24:6: exported type ENIConfigSpec should have comment or be unexported
./pkg/apis/crd/v1alpha1/types.go:28:6: exported type ENIConfigStatus should have comment or be unexported
./pkg/rpcwrapper/client.go:21:6: exported type RPC should have comment or be unexported
./pkg/rpcwrapper/client.go:27:1: exported function New should have comment or be unexported
./pkg/cri/cri.go:27:6: exported type APIs should have comment or be unexported
./pkg/cri/cri.go:31:6: exported type Client should have comment or be unexported
./pkg/cri/cri.go:33:1: exported function New should have comment or be unexported
./pkg/cri/cri.go:37:1: exported method Client.GetRunningPodSandboxes should have comment or be unexported
./pkg/ipamd/ipamd.go:188:1: comment on exported type ReconcileCooldownCache should be of the form "ReconcileCooldownCache ..." (with optional leading article)
./pkg/ipamd/ipamd_test.go:275:2: var warmIpTarget should be warmIPTarget
./pkg/grpcwrapper/client.go:20:6: exported type GRPC should have comment or be unexported
./pkg/grpcwrapper/client.go:26:1: exported function New should have comment or be unexported
./pkg/k8sapi/discovery.go:120:1: comment on exported method Controller.DiscoverCNIK8SPods should be of the form "DiscoverCNIK8SPods ..."
./pkg/ec2wrapper/ec2wrapper.go:1:1: package comment should be of the form "Package ec2wrapper ..."
./pkg/ec2wrapper/ec2wrapper.go:30:1: comment on exported function NewMetricsClient should be of the form "NewMetricsClient ..."
./pkg/ec2wrapper/client.go:23:6: exported type EC2 should have comment or be unexported
./pkg/ec2wrapper/client.go:37:1: exported function New should have comment or be unexported
./pkg/nswrapper/ns.go:20:6: exported type NS should have comment or be unexported
./pkg/nswrapper/ns.go:27:1: exported function NewNS should have comment or be unexported
./cmd/routed-eni-cni-plugin/cni.go:82:2: don't use ALL_CAPS in Go names; use CamelCase
./cmd/routed-eni-cni-plugin/cni.go:85:2: don't use ALL_CAPS in Go names; use CamelCase
./cmd/routed-eni-cni-plugin/cni.go:88:2: don't use ALL_CAPS in Go names; use CamelCase
./cmd/routed-eni-cni-plugin/cni.go:288:10: if block ends with a return statement, so drop this else and outdent its block
./cmd/routed-eni-cni-plugin/cni.go:301:2: var deletedPodIp should be deletedPodIP

Copy link
Member Author

Choose a reason for hiding this comment

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

but be aware that there are linter failures in the tree's current code, so we'll need to clean these up before adding lint to the check target that gates CI:

Yeah, this is why its configured as a soft-fail/no-fail in CI. The lint failures will print without causing the step to exit non-zero. Locally, this target will report lint failures with a non-zero exit code by default (unless disabled as it is in the CI script).

jaypipes@udb42383a8e5155:~/go/src/github.com/aws/amazon-vpc-cni-k8s$ for f in find . -name *.go -not -name mock; do GO111MODULE=on golint $f; done

Ah, so we'll have to do it a file at a time then. The reason for the interesting find is that invoking golint on a set of files that cross package boundaries is not supported and so this find is/was to avoid invoking golint for each file. I'll rework this with the approach you've suggested.

RUN yum update -y && \
yum clean all
yum clean all
Copy link
Contributor

@jaypipes jaypipes Feb 21, 2020

Choose a reason for hiding this comment

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

do you need to put the below in this Dockerfile? (you added it to the release Dockerfile below)

ENV GOARCH=$arch

Copy link
Member Author

Choose a reason for hiding this comment

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

Good catch, yes, this'll need to be plumbed in (in the builder stage). Will update.


A side note:

With a static build, I think that the CNI metrics helper's container image can be shrunk down into a final image of:

FROM scratch
# Copy our bundled certs to the first place go will check: see
# https://golang.org/src/pkg/crypto/x509/root_unix.go
COPY ./misc/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=builder /go/src/github.com/aws/amazon-vpc-cni-k8s/cni-metrics-helper /app

That's a change for another time though.

jahkeup and others added 4 commits February 21, 2020 15:54
This reworks much of the Makefile and, to a lesser extent, the
Dockerfiles for building the CNI plugins for other platforms.

Additional clean up work is included as well as this was combed
through to support these builds.

Including:

- ARCH resolver to identify the ARCH (GOARCH styled) to pass around
- Updated ARCH and GOARCH references throughout to support
  against other ARCHes
- Make base container build appropriately for ARCH
  - Docker explicit multiarch references in targets and Dockerfiles
  - Updated related container images to allow testing where possible
- Eliminate ./tmp usage with tar unpacking from a pipe
- Clean up and consistent call sites all around
   - Reconciled image naming
   - Updated stale golang images references
- Added docstrings for reference
Though the tests don't require CGO with cross-compilation support, the
tests do still require support to exec the golang test binaries.
@jahkeup
Copy link
Member Author

jahkeup commented Feb 22, 2020

Just FYI for future PRs, I would prefer that code changes be tightly scoped to a specific feature described in the PR/commit summary. This change introduces a wholesale set of feature changes, style changes, cleanups and more, which usually makes reviewing PRs like this more difficult (because code reviewers need to examine each line in the PR to determine whether that line correlates to something the PR claims to add or whether the line is merely a style-only change).

My apologies for the scope this grew to - most of these changes I had discussed with @mogren offline about and also sent along early versions of the patches before opening this PR. My understanding was that the set of changes was welcome and welcome to be bundled together - with the tangentially related changes included (which admittedly, yes, is wide reaching).

I don't mind style-only changes, of course, and most of the style-only changes you've included in here are awesome. It's just for future PRs, please try to keep those in a separate PR entirely so reviewers can more easily group code changes in their head :)

I'll keep this in mind for the next time when scoping the work out in my mind and in my posted changes 👍

Copy link
Contributor

@jaypipes jaypipes left a comment

Choose a reason for hiding this comment

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

Great stuff @jahkeup :) Thanks very much!

-jay

build-linux docker \
unit-test unit-test-race build-docker-test docker-func-test \
build-metrics docker-metrics \
metrics-unit-test docker-metrics-test
Copy link
Contributor

Choose a reason for hiding this comment

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

portmap isn't phony, its a file that's created by downloading it - if portmap were to be listed here it will be downloaded every time the target is activated.

ack, yes, good point.

Makefile Outdated
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/networkutils/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/utils/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/eniconfig/...
go test -v -mod=readonly -cover -race -timeout 10s ./pkg/ipamd/...
Copy link
Contributor

Choose a reason for hiding this comment

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

it's a note for a future PR :) no need to make the change here.

@mogren
Copy link
Contributor

mogren commented Mar 5, 2020

@jahkeup Hey, sorry this never got merged earlier. It seems like #851 introduced some incompatible changes since it no longer builds. Do you have bandwidth to resolve the rebase issue?

Makefile Outdated
unit-test:
GOOS=linux CGO_ENABLED=1 go test -v -cover $(ALLPKGS)
go test -mod=readonly -v -cover $(ALLPKGS)
Copy link
Contributor

Choose a reason for hiding this comment

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

We will need to run go mod tidy before using -mod=readonly...

https://www.reddit.com/r/golang/comments/c2ckjz/why_does_my_gosum_file_keep_changing/

@jahkeup
Copy link
Member Author

jahkeup commented Mar 11, 2020

@mogren sorry I don't currently have the bandwidth to circle back this week. I'll take a look at what's going on if I end up with time on my hands or early next week!

@jaypipes
Copy link
Contributor

@mogren sorry I don't currently have the bandwidth to circle back this week. I'll take a look at what's going on if I end up with time on my hands or early next week!

Not a problem @jahkeup! Either Claes or myself can push a commit that addresses the issue.

Copy link
Contributor

@mogren mogren left a comment

Choose a reason for hiding this comment

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

@jaypipes Thanks for fixing. We need to update the merge checks after this gets merged, since the name of the build task has changed.

ci/circleci: build Expected — Waiting for status to be reported

We need to check for build_x86_64 and build_aarch64 instead.

@@ -5,28 +5,46 @@ orbs:
aws-cli: circleci/[email protected]
k8s: circleci/[email protected]

jobs:
build:
references:
Copy link
Contributor

Choose a reason for hiding this comment

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

I actually realized what was wrong with this this morning, when I noticed CircleCI was waiting for a "build" job to report a successful status even though there was no build job defined any more.

Then I remembered CircleCI requires a job named "build" when you do not use workflows. I'm wondering if there's something messed up by not having a job or a workflow called "build".

Copy link
Contributor

Choose a reason for hiding this comment

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

If we can't change that name in CircleCI, we could just rename the build_x86_64 to build again, since that would be the default.

Copy link
Contributor

Choose a reason for hiding this comment

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

If we can't change that name in CircleCI, we could just rename the build_x86_64 to build again, since that would be the default.

I'm going to see if this issue just goes away. I think maybe (?) the old config YAML was cached somehow and that was the reason for the empty "build" step status check being expected...

@jaypipes jaypipes merged commit a4dc9f5 into aws:master Mar 13, 2020
nithu0115 pushed a commit to nithu0115/amazon-vpc-cni-k8s that referenced this pull request Mar 13, 2020
This reworks much of the Makefile and, to a lesser extent, the
Dockerfiles for building the CNI plugins for other platforms.

Additional clean up work is included as well as this was combed
through to support these builds.

Including:

- ARCH resolver to identify the ARCH (GOARCH styled) to pass around
- Updated ARCH and GOARCH references throughout to support
  against other ARCHes
- Make base container build appropriately for ARCH
  - Docker explicit multiarch references in targets and Dockerfiles
  - Updated related container images to allow testing where possible
- Eliminate ./tmp usage with tar unpacking from a pipe
- Clean up and consistent call sites all around
   - Reconciled image naming
   - Updated stale golang images references
- Added docstrings for reference
mogren pushed a commit to mogren/amazon-vpc-cni-k8s that referenced this pull request Apr 20, 2020
This reworks much of the Makefile and, to a lesser extent, the
Dockerfiles for building the CNI plugins for other platforms.

Additional clean up work is included as well as this was combed
through to support these builds.

Including:

- ARCH resolver to identify the ARCH (GOARCH styled) to pass around
- Updated ARCH and GOARCH references throughout to support
  against other ARCHes
- Make base container build appropriately for ARCH
  - Docker explicit multiarch references in targets and Dockerfiles
  - Updated related container images to allow testing where possible
- Eliminate ./tmp usage with tar unpacking from a pipe
- Clean up and consistent call sites all around
   - Reconciled image naming
   - Updated stale golang images references
- Added docstrings for reference
mogren pushed a commit that referenced this pull request Apr 20, 2020
This reworks much of the Makefile and, to a lesser extent, the
Dockerfiles for building the CNI plugins for other platforms.

Additional clean up work is included as well as this was combed
through to support these builds.

Including:

- ARCH resolver to identify the ARCH (GOARCH styled) to pass around
- Updated ARCH and GOARCH references throughout to support
  against other ARCHes
- Make base container build appropriately for ARCH
  - Docker explicit multiarch references in targets and Dockerfiles
  - Updated related container images to allow testing where possible
- Eliminate ./tmp usage with tar unpacking from a pipe
- Clean up and consistent call sites all around
   - Reconciled image naming
   - Updated stale golang images references
- Added docstrings for reference
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants