Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
devel:kubic
cni-plugin-flannel
cni-plugin-1.4.0.obscpio
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File cni-plugin-1.4.0.obscpio of Package cni-plugin-flannel
07070100000000000041ED00000000000000000000000265A95B7100000000000000000000000000000000000000000000001900000000cni-plugin-1.4.0/.github07070100000001000041ED00000000000000000000000265A95B7100000000000000000000000000000000000000000000002300000000cni-plugin-1.4.0/.github/workflows07070100000002000081A400000000000000000000000165A95B710000024A000000000000000000000000000000000000003300000000cni-plugin-1.4.0/.github/workflows/buildTests.yamlname: build tests for flannel cni-plugin on: push: branches: - main pull_request: branches: - main jobs: test: name: test runs-on: ubuntu-latest strategy: fail-fast: false matrix: go: [ "1.20.5" ] steps: - name: Check out code into the Go module directory uses: actions/checkout@v3 - name: Set up Go 1.x uses: actions/setup-go@v3 with: go-version: ${{ matrix.go }} - run: go version - name: build all run: make build_all - name: run tests run: make test_linux 07070100000003000081A400000000000000000000000165A95B71000009C8000000000000000000000000000000000000002F00000000cni-plugin-1.4.0/.github/workflows/release.ymlname: release flannel cni-plugin on: # You must provide a tag either via the action input or the git ref (i.e push / create a tag). # If you do not provide a tag the action will fail. # If the tag of the release you are creating does not yet exist, you should set # both the tag and commit action inputs. commit can point to a commit hash or a branch name (ex - main). # workflow_dispatch: # inputs: # branch: # description: 'Define branch name to run the release GH action against' # required: true # default: 'main' release: types: - created env: GO_VERSION: "1.20.5" REPOSITORY: flannel/flannel-cni-plugin jobs: build-and-release: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 with: fetch-depth: 1 - uses: actions/setup-go@v3 with: go-version: ${{ env.GO_VERSION }} - name: go mod vendor and tidy run: make vendor - name: build all binaries for release run: make build_all - name: run tests run: make test_linux - name: run go vet run: go vet - name: create packages for release if: success() run: make release - name: Upload release files uses: softprops/action-gh-release@v1 with: files: | dist/* release/* build-and-push-images: needs: [build-and-release] runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout repository uses: actions/checkout@v3 if: success() - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Docker meta id: meta uses: docker/metadata-action@v4 with: images: ${{ env.REPOSITORY }} flavor: latest=false tags: | type=ref,event=tag - name: Log in to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Build and push Docker image # if: github.repository_owner == 'flannel-io' && success() uses: docker/build-push-action@v5 with: context: . file: Dockerfile.image push: true platforms: linux/amd64,linux/arm64,linux/arm,linux/s390x,linux/ppc64le,linux/riscv64 tags: ${{ steps.meta.outputs.tags }} 07070100000004000081A400000000000000000000000165A95B710000003F000000000000000000000000000000000000001C00000000cni-plugin-1.4.0/.gitignore/bin /vendor /dist /release .idea* static-check.log .vscode/** 07070100000005000081A400000000000000000000000165A95B7100000A86000000000000000000000000000000000000001C00000000cni-plugin-1.4.0/DockerfileARG GOLANG_VERSION FROM library/golang:${GOLANG_VERSION}-alpine AS build ARG TAG RUN set -x \ && apk --no-cache add \ bash \ curl \ git \ tar COPY ./scripts/semver-parse.sh /semver-parse.sh RUN chmod +x /semver-parse.sh RUN curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s v1.43.0 RUN git clone -b $(/semver-parse.sh ${TAG} all) --depth=1 https://github.com/flannel-io/cni-plugin ${GOPATH}/src/github.com/flannel-io/cni-plugin WORKDIR ${GOPATH}/src/github.com/flannel-io/cni-plugin FROM build AS flannel-cni ARG TAG WORKDIR ${GOPATH}/src/github.com/flannel-io/cni-plugin RUN \ set -ex; \ source ./scripts/version.sh; \ chmod +x ./scripts/* ENV SRC_DIR=${SRC_DIR:-${pwd}} ENV DOCKER=${DOCKER:-docker} ENV GO=${GO:-go} ENV GOPATH=${GOPATH:-'${go env GOPATH}'} ENV RELEASE_DIR=${GOPATH}/src/github.com/flannel-io/cni-plugin/release-${TAG} ENV OUTPUT_DIR=${GOPATH}/src/github.com/flannel-io/cni-plugin/dist # Always clean first RUN \ rm -rf ${OUTPUT_DIR} \ && rm -rf ${RELEASE_DIR} \ && mkdir -p ${RELEASE_DIR} \ && mkdir -p ${OUTPUT_DIR} RUN go mod vendor && go mod tidy # for ARCH IN ${ALL_ARCH}; do RUN \ for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do \ GOARCH=${arch} ./scripts/build_flannel.sh; \ for format in tgz; do \ FILENAME=cni-plugin-flannel-linux-${arch}-${TAG}.${format}; \ FILEPATH=${RELEASE_DIR}/${FILENAME}; \ tar -C ${OUTPUT_DIR} --owner=0 --group=0 -caf ${FILEPATH} . ; \ done; \ done RUN \ GOOS=windows GOARCH=amd64 ./scripts/build_flannel.sh; \ for format in tgz; do \ FILENAME=cni-plugin-flannel-windows-${GOARCH}-${TAG}.${format}; \ FILEPATH=${RELEASE_DIR}/${FILENAME}; \ tar -C ${OUTPUT_DIR} --owner=0 --group=0 -caf ${FILEPATH} . ; \ done RUN \ for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do \ GOARCH=${arch} ./scripts/check_static.sh >> static-check.log; \ done WORKDIR ${RELEASE_DIR} RUN \ for f in *.tgz; do sha1sum ${f} > ./${f}.sha1; done; \ for f in *.tgz; do sha256sum ${f} > ./${f}.sha256; done; \ for f in *.tgz; do sha512sum ${f} > ./${f}.sha512; done; FROM build AS flannel-cni-collect ARG TAG COPY --from=flannel-cni ${GOPATH}/src/github.com/flannel-io/cni-plugin/dist/ /go/src/github.com/flannel-io/cni-plugin/dist/ COPY --from=flannel-cni ${GOPATH}/src/github.com/flannel-io/cni-plugin/release-${TAG}/ /go/src/github.com/flannel-io/cni-plugin/release-${TAG}/ COPY --from=flannel-cni ${GOPATH}/src/github.com/flannel-io/cni-plugin/static-check.log /go/src/github.com/flannel-io/cni-plugin/static-check.log 07070100000006000081A400000000000000000000000165A95B710000023A000000000000000000000000000000000000002200000000cni-plugin-1.4.0/Dockerfile.imageFROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx FROM --platform=$BUILDPLATFORM golang:alpine AS build # copy xx scripts to your build stage COPY --from=xx / / ARG TARGETPLATFORM ARG BUILDPLATFORM RUN apk --no-cache add bash COPY go.mod go.sum *.go /build/ COPY scripts /build/scripts WORKDIR /build RUN xx-info env RUN go mod tidy && go mod vendor RUN export GOOS=$(xx-info os) &&\ export GOARCH=$(xx-info arch) &&\ ./scripts/build_flannel.sh &&\ mv ./dist/flannel-${GOARCH} /flannel FROM alpine:20230901 ARG GOARCH COPY --from=build /flannel /flannel 07070100000007000081A400000000000000000000000165A95B7100002C5E000000000000000000000000000000000000001900000000cni-plugin-1.4.0/LICENSE Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. 07070100000008000081A400000000000000000000000165A95B7100000743000000000000000000000000000000000000001A00000000cni-plugin-1.4.0/Makefile.PHONY: vendor build_linux build_windows build_all build_all_docker .PHONY: clean vendor release REGISTRY?=docker.io/flannel/flannel-cni-plugin # Default tag and architecture. Can be overridden TAG?=$(shell git describe --tags --dirty --always) ARCH?=amd64 SRC_DIR?=$(pwd) GO?=$(go) GOPATH?=$(go env GOPATH) # this is the upstream CNI plugin version used for testing TEST_TAG?=v1.1.1 # Only enable CGO (and build the UDP backend) on AMD64 ifeq ($(ARCH),amd64) CGO_ENABLED=1 else CGO_ENABLED=0 endif # Go version to use for builds. Can be overridden GOLANG_VERSION?=1.20.5 build_all: vendor build_all_linux build_windows @echo "All arches should be built for $(TAG)" build_all_linux: vendor GOOS=linux GOARCH=amd64 scripts/build_flannel.sh GOOS=linux GOARCH=386 scripts/build_flannel.sh GOOS=linux GOARCH=arm scripts/build_flannel.sh GOOS=linux GOARCH=arm64 scripts/build_flannel.sh GOOS=linux GOARCH=s390x scripts/build_flannel.sh GOOS=linux GOARCH=ppc64le scripts/build_flannel.sh GOOS=linux GOARCH=riscv64 scripts/build_flannel.sh vendor: go mod tidy go mod vendor build_all_docker: vendor docker build \ --no-cache \ --build-arg GOLANG_VERSION=$(GOLANG_VERSION) \ --build-arg TAG=$(TAG) \ --tag $(REGISTRY):$(TAG) \ --tag $(REGISTRY):$(TAG)-$(ARCH) \ -f Dockerfile \ . build_linux: vendor GOOS=linux GOARCH=$(ARCH) scripts/build_flannel.sh build_windows: vendor GOOS=windows GOARCH=$(ARCH) scripts/build_flannel.sh test_linux: vendor build_linux TAG=$(TEST_TAG) scripts/test_linux.sh clean: rm -f dist/flannel* rm -f release/cni-plugin-flannel* package: vendor scripts/package.sh release: build_all scripts/package.sh release_docker: clean vendor scripts/release.sh @echo "Everything should be built for $(TAG)" @echo "Add all flannel-* and *.tar.gz files from dist/ and release/ to the Github release" 07070100000009000081A400000000000000000000000165A95B71000017FD000000000000000000000000000000000000001B00000000cni-plugin-1.4.0/README.md## Overview This plugin is designed to work in conjunction with [flannel](https://github.com/coreos/flannel), a network fabric for containers. When flannel daemon is started, it outputs a `/run/flannel/subnet.env` file that looks like this: ```bash FLANNEL_NETWORK=10.1.0.0/16 FLANNEL_SUBNET=10.1.17.1/24 FLANNEL_MTU=1472 FLANNEL_IPMASQ=true ``` This information reflects the attributes of flannel network on the host. The flannel CNI plugin uses this information to configure another CNI plugin, such as bridge plugin. ## Build Run `go mod vendor` and then `make`. The resulting `flannel` binary would be under the bin/ directory ## Operation Given the following network configuration file and the contents of `/run/flannel/subnet.env` above, ```json { "name": "mynet", "type": "flannel" } ``` the flannel plugin will generate another network configuration file: ```json { "name": "mynet", "type": "bridge", "mtu": 1472, "ipMasq": false, "isGateway": true, "ipam": { "type": "host-local", "subnet": "10.1.17.0/24" } } ``` It will then invoke the bridge plugin, passing it the generated configuration. As can be seen from above, the flannel plugin, by default, will delegate to the bridge plugin. If additional configuration values need to be passed to the bridge plugin, it can be done so via the `delegate` field: ```json { "name": "mynet", "type": "flannel", "delegate": { "bridge": "mynet0", "mtu": 1400 } } ``` This supplies a configuration parameter to the bridge plugin -- the created bridge will now be named `mynet0`. Notice that `mtu` has also been specified and this value will not be overwritten by flannel plugin. Additionally, the `delegate` field can be used to select a different kind of plugin altogether. To use `ipvlan` instead of `bridge`, the following configuration can be specified: ```json { "name": "mynet", "type": "flannel", "delegate": { "type": "ipvlan", "master": "eth0" } } ``` The `ipam` part of the network configuration generated for the delegated plugin, can also be customized by adding a base `ipam` section to the input flannel network configuration. This `ipam` element is then updated with the flannel subnet, a route to the flannel network and, unless provided, an `ipam` `type` set to `host-local` before being provided to the delegated plugin. ## Network configuration reference * `name` (string, required): the name of the network * `type` (string, required): "flannel" * `subnetFile` (string, optional): full path to the subnet file written out by flanneld. Defaults to /run/flannel/subnet.env * `dataDir` (string, optional): path to directory where plugin will store generated network configuration files. Defaults to `/var/lib/cni/flannel` * `delegate` (dictionary, optional): specifies configuration options for the delegated plugin. * `ipam` (dictionary, optional, Linux only): when specified, is used as basis to construct the `ipam` section of the delegated plugin configuration. flannel plugin will always set the following fields in the delegated plugin configuration: * `name`: value of its "name" field. * `ipam`: based on the received `ipam` section if present, with a `type` defaulting to `host-local`, a `subnet` set to `$FLANNEL_SUBNET` and (Linux only) a `routes` element assembled from the routes listed in the received `ipam` element and a route to the flannel network. Other fields present in the input `ipam` section will be transparently provided to the delegate. flannel plugin will set the following fields in the delegated plugin configuration if they are not present: * `ipMasq`: the inverse of `$FLANNEL_IPMASQ` * `mtu`: `$FLANNEL_MTU` Additionally, for the bridge plugin, `isGateway` will be set to `true`, if not present. The bridge plugin includes `isDefaultGateway` that when false allow adding back the routes to the cluster services and/or to the hosts. In that case, the bridge plugin does not install a default route and, as a result, only pod-to-pod connectivity would be available. ## Windows Support (Experimental) This plugin supports delegating to the windows CNI plugins (overlay.exe, l2bridge.exe) to work in conjunction with [Flannel on Windows](https://github.com/coreos/flannel/issues/833). Flannel sets up an [HNS Network](https://docs.microsoft.com/en-us/virtualization/windowscontainers/container-networking/architecture) in L2Bridge mode for host-gw and in Overlay mode for vxlan. The following fields must be set in the delegated plugin configuration: * `name` (string, required): the name of the network (must match the name in Flannel config / name of the HNS network) * `type` (string, optional): set to `win-l2bridge` by default. Can be set to `win-overlay` or other custom windows CNI * `ipMasq`: the inverse of `$FLANNEL_IPMASQ` * `endpointMacPrefix` (string, optional): required for `win-overlay` mode, set to the MAC prefix configured for Flannel * `clusterNetworkPrefix` (string, optional): required for `win-l2bridge` mode, setup NAT if `ipMasq` is set to true For `win-l2bridge`, the Flannel CNI plugin will set: * `ipam`: "host-local" type will be used with "subnet" set to `$FLANNEL_SUBNET` and gateway as the .2 address in `$FLANNEL_NETWORK` For `win-overlay`, the Flannel CNI plugin will set: * `ipam`: "host-local" type will be used with "subnet" set to `$FLANNEL_SUBNET` and gateway as the .1 address in `$FLANNEL_NETWORK` If IPMASQ is true, the Flannel CNI plugin will setup an OutBoundNAT policy and add FLANNEL_SUBNET to any existing exclusions. All other delegate config e.g. other HNS endpoint policies in AdditionalArgs will be passed to WINCNI as-is. Example VXLAN Flannel CNI config ```json { "name": "mynet", "type": "flannel", "delegate": { "type": "win-overlay", "endpointMacPrefix": "0E-2A" } } ``` For this example, Flannel CNI would generate the following config to delegate to the windows CNI when FLANNEL_NETWORK=10.244.0.0/16, FLANNEL_SUBNET=10.244.1.0/24 and IPMASQ=true ```json { "name": "mynet", "type": "win-overlay", "endpointMacPrefix": "0E-2A", "ipMasq": true, "ipam": { "subnet": "10.244.1.0/24", "type": "host-local" } } ``` 0707010000000A000081A400000000000000000000000165A95B7100000947000000000000000000000000000000000000001E00000000cni-plugin-1.4.0/RELEASING.md# Release process ## Resulting artifacts ### [Manual] Release using local artifacts Creating a new release via `make release` produces the following directories containg artifacts: - Binaries: - `${GOPATH}/src/github.com/flannel-io/cni-plugin/dist`) - `flannel-<ARCH>` binaries - Tarfiles: - `${GOPATH}/src/github.com/flannel-io/cni-plugin/release-"${TAG}"` - `cni-plugin-flannel-<OS>-<ARCH>-<TAG>.tar.gz` tarfiles containing one binary - `.sha1`, `.sha256`, and `.sha512` files for each tarfile. ### [Manual] Release using Docker artifacts Creating a new release via `make release_docker` produces the following artifacts: - Binaries (stored in the `release-<TAG>` directory) : - `flannel-<ARCH>-<VERSION>.tgz` binaries - `flannel-<ARCH>.tgz` binary (copy of amd64 platform binary) - `.sha1`, `.sha256`, and `.sha512` files for the above files. ## Preparing for a release 1. Releases are performed by maintainers and should usually be discussed and planned at a maintainer meeting. - Choose the version number. It should be prefixed with `v`, e.g. `v1.2.3` - Take a quick scan through the PRs and issues to make sure there isn't anything crucial that _must_ be in the next release. - Create a draft of the release note - Discuss the level of testing that's needed and create a test plan if sensible - Check what version of `go` is used in the build container, updating it if there's a new stable release. - Update the vendor directory and Godeps to pin to the corresponding containernetworking/cni release. Create a PR, makes sure it passes CI and get it merged. ## Creating the release artifacts 1. Make sure you are on the master branch and don't have any local uncommitted changes. 2. Create a signed tag for the release `git tag -s $VERSION` (Ensure that GPG keys are created and added to GitHub) 3. Run the release script from the root of the repository - `scripts/release.sh` - The script requires Docker and ensures that a consistent environment is used. - The artifacts will now be present in the `release-<TAG>` directory. 4. Test these binaries according to the test plan. ## Publishing the release 1. Push the tag to git `git push origin <TAG>` 2. Create a release on Github, using the tag which was just pushed. 3. Attach all the artifacts from the release directory. 4. Add the release note to the release. 0707010000000B000041ED00000000000000000000000265A95B7100000000000000000000000000000000000000000000001600000000cni-plugin-1.4.0/dist0707010000000C000081A400000000000000000000000165A95B710000001C000000000000000000000000000000000000002100000000cni-plugin-1.4.0/dist/.gitignoreflannel-* flanneld-* qemu-* 0707010000000D000081A400000000000000000000000165A95B71000020D6000000000000000000000000000000000000001C00000000cni-plugin-1.4.0/flannel.go// Copyright 2015 CNI authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This is a "meta-plugin". It reads in its own netconf, combines it with // the data from flannel generated subnet file and then invokes a plugin // like bridge or ipvlan to do the real work. package main import ( "bufio" "context" "encoding/json" "fmt" "io" "net" "os" "path/filepath" "runtime" "strconv" "strings" "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" cni "github.com/containernetworking/cni/pkg/version" ) const ( defaultSubnetFile = "/run/flannel/subnet.env" defaultDataDir = "/var/lib/cni/flannel" ) var ( Program string Version string Commit string buildDate string ) type NetConf struct { types.NetConf // IPAM field "replaces" that of types.NetConf which is incomplete IPAM map[string]interface{} `json:"ipam,omitempty"` SubnetFile string `json:"subnetFile"` DataDir string `json:"dataDir"` Delegate map[string]interface{} `json:"delegate"` RuntimeConfig map[string]interface{} `json:"runtimeConfig,omitempty"` } type subnetEnv struct { nws []*net.IPNet sn *net.IPNet ip6Nws []*net.IPNet ip6Sn *net.IPNet mtu *uint ipmasq *bool } func (se *subnetEnv) missing() string { m := []string{} if len(se.nws) == 0 && len(se.ip6Nws) == 0 { m = append(m, []string{"FLANNEL_NETWORK", "FLANNEL_IPV6_NETWORK"}...) } if se.sn == nil && se.ip6Sn == nil { m = append(m, []string{"FLANNEL_SUBNET", "FLANNEL_IPV6_SUBNET"}...) } if se.mtu == nil { m = append(m, "FLANNEL_MTU") } if se.ipmasq == nil { m = append(m, "FLANNEL_IPMASQ") } return strings.Join(m, ", ") } func loadFlannelNetConf(bytes []byte) (*NetConf, error) { n := &NetConf{ SubnetFile: defaultSubnetFile, DataDir: defaultDataDir, } if err := json.Unmarshal(bytes, n); err != nil { return nil, fmt.Errorf("failed to load netconf: %v", err) } return n, nil } func getIPAMRoutes(n *NetConf) ([]types.Route, error) { rtes := []types.Route{} if n.IPAM != nil && hasKey(n.IPAM, "routes") { buf, _ := json.Marshal(n.IPAM["routes"]) if err := json.Unmarshal(buf, &rtes); err != nil { return rtes, fmt.Errorf("failed to parse ipam.routes: %w", err) } } return rtes, nil } func isSubnetAlreadyPresent(nws []*net.IPNet, nw *net.IPNet) bool { compareMask := func(m1 net.IPMask, m2 net.IPMask) bool { for i := range m1 { if m1[i] != m2[i] { return false } } return true } for _, nwi := range nws { if nw.IP.Equal(nwi.IP) && compareMask(nw.Mask, nwi.Mask) { return true } } return false } func loadFlannelSubnetEnv(fn string) (*subnetEnv, error) { f, err := os.Open(fn) if err != nil { return nil, err } defer f.Close() se := &subnetEnv{} s := bufio.NewScanner(f) for s.Scan() { parts := strings.SplitN(s.Text(), "=", 2) switch parts[0] { case "FLANNEL_NETWORK": cidrs := strings.Split(parts[1], ",") se.nws = make([]*net.IPNet, 0, len(cidrs)) for i := range cidrs { _, nw, err := net.ParseCIDR(cidrs[i]) if err != nil { return nil, err } if !isSubnetAlreadyPresent(se.nws, nw) { se.nws = append(se.nws, nw) } } case "FLANNEL_SUBNET": _, se.sn, err = net.ParseCIDR(parts[1]) if err != nil { return nil, err } case "FLANNEL_IPV6_NETWORK": cidrs := strings.Split(parts[1], ",") se.ip6Nws = make([]*net.IPNet, 0, len(cidrs)) for i := range cidrs { _, ip6nw, err := net.ParseCIDR(cidrs[i]) if err != nil { return nil, err } if !isSubnetAlreadyPresent(se.ip6Nws, ip6nw) { se.ip6Nws = append(se.ip6Nws, ip6nw) } } case "FLANNEL_IPV6_SUBNET": _, se.ip6Sn, err = net.ParseCIDR(parts[1]) if err != nil { return nil, err } case "FLANNEL_MTU": mtu, err := strconv.ParseUint(parts[1], 10, 32) if err != nil { return nil, err } se.mtu = new(uint) *se.mtu = uint(mtu) case "FLANNEL_IPMASQ": ipmasq := parts[1] == "true" se.ipmasq = &ipmasq } } if err := s.Err(); err != nil { return nil, err } if m := se.missing(); m != "" { return nil, fmt.Errorf("%v is missing %v", fn, m) } return se, nil } func saveScratchNetConf(containerID, dataDir string, netconf []byte) error { if err := os.MkdirAll(dataDir, 0700); err != nil { return err } path := filepath.Join(dataDir, containerID) return writeAndSyncFile(path, netconf, 0600) } // WriteAndSyncFile behaves just like ioutil.WriteFile in the standard library, // but calls Sync before closing the file. WriteAndSyncFile guarantees the data // is synced if there is no error returned. func writeAndSyncFile(filename string, data []byte, perm os.FileMode) error { f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, perm) if err != nil { return err } n, err := f.Write(data) if err == nil && n < len(data) { err = io.ErrShortWrite } if err == nil { err = f.Sync() } if err1 := f.Close(); err == nil { err = err1 } return err } func consumeScratchNetConf(containerID, dataDir string) (func(error), []byte, error) { path := filepath.Join(dataDir, containerID) // cleanup will do clean job when no error happens in consuming/using process cleanup := func(err error) { if err == nil { // Ignore errors when removing - Per spec safe to continue during DEL _ = os.Remove(path) } } netConfBytes, err := os.ReadFile(path) return cleanup, netConfBytes, err } func delegateAdd(cid, dataDir string, netconf map[string]interface{}) error { netconfBytes, err := json.Marshal(netconf) fmt.Fprintf(os.Stderr, "delegateAdd: netconf sent to delegate plugin:\n") os.Stderr.Write(netconfBytes) if err != nil { return fmt.Errorf("error serializing delegate netconf: %v", err) } // save the rendered netconf for cmdDel if err = saveScratchNetConf(cid, dataDir, netconfBytes); err != nil { return err } result, err := invoke.DelegateAdd(context.TODO(), netconf["type"].(string), netconfBytes, nil) if err != nil { err = fmt.Errorf("failed to delegate add: %w", err) return err } return result.Print() } func hasKey(m map[string]interface{}, k string) bool { _, ok := m[k] return ok } func isString(i interface{}) bool { _, ok := i.(string) return ok } func cmdAdd(args *skel.CmdArgs) error { n, err := loadFlannelNetConf(args.StdinData) if err != nil { return fmt.Errorf("loadFlannelNetConf failed: %w", err) } fenv, err := loadFlannelSubnetEnv(n.SubnetFile) if err != nil { return fmt.Errorf("loadFlannelSubnetEnv failed: %w", err) } if n.Delegate == nil { n.Delegate = make(map[string]interface{}) } else { if hasKey(n.Delegate, "type") && !isString(n.Delegate["type"]) { return fmt.Errorf("'delegate' dictionary, if present, must have (string) 'type' field") } if hasKey(n.Delegate, "name") { return fmt.Errorf("'delegate' dictionary must not have 'name' field, it'll be set by flannel") } if hasKey(n.Delegate, "ipam") { return fmt.Errorf("'delegate' dictionary must not have 'ipam' field, it'll be set by flannel") } } if n.RuntimeConfig != nil { n.Delegate["runtimeConfig"] = n.RuntimeConfig } return doCmdAdd(args, n, fenv) } func cmdDel(args *skel.CmdArgs) error { nc, err := loadFlannelNetConf(args.StdinData) if err != nil { return err } if nc.RuntimeConfig != nil { if nc.Delegate == nil { nc.Delegate = make(map[string]interface{}) } nc.Delegate["runtimeConfig"] = nc.RuntimeConfig } return doCmdDel(args, nc) } func main() { fullVer := fmt.Sprintf("CNI Plugin %s version %s (%s/%s) commit %s built on %s", Program, Version, runtime.GOOS, runtime.GOARCH, Commit, buildDate) skel.PluginMain(cmdAdd, cmdCheck, cmdDel, cni.All, fullVer) } func cmdCheck(args *skel.CmdArgs) error { // TODO: implement return nil } 0707010000000E000081A400000000000000000000000165A95B7100000E31000000000000000000000000000000000000002200000000cni-plugin-1.4.0/flannel_linux.go// Copyright 2018 CNI authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This is a "meta-plugin". It reads in its own netconf, combines it with // the data from flannel generated subnet file and then invokes a plugin // like bridge or ipvlan to do the real work. package main import ( "context" "encoding/json" "fmt" "os" "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" ) // Return IPAM section for Delegate using input IPAM if present and replacing // or complementing as needed. func getDelegateIPAM(n *NetConf, fenv *subnetEnv) (map[string]interface{}, error) { ipam := n.IPAM if ipam == nil { ipam = map[string]interface{}{} } if !hasKey(ipam, "type") { ipam["type"] = "host-local" } var rangesSlice [][]map[string]interface{} if fenv.sn != nil && fenv.sn.String() != "" { rangesSlice = append(rangesSlice, []map[string]interface{}{ {"subnet": fenv.sn.String()}, }, ) } if fenv.ip6Sn != nil && fenv.ip6Sn.String() != "" { rangesSlice = append(rangesSlice, []map[string]interface{}{ {"subnet": fenv.ip6Sn.String()}, }, ) } ipam["ranges"] = rangesSlice rtes, err := getIPAMRoutes(n) if err != nil { return nil, fmt.Errorf("failed to read IPAM routes: %w", err) } for _, nw := range fenv.nws { if nw != nil { rtes = append(rtes, types.Route{Dst: *nw}) } } for _, nw := range fenv.ip6Nws { if nw != nil { rtes = append(rtes, types.Route{Dst: *nw}) } } ipam["routes"] = rtes return ipam, nil } func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error { n.Delegate["name"] = n.Name if !hasKey(n.Delegate, "type") { n.Delegate["type"] = "bridge" } if !hasKey(n.Delegate, "ipMasq") { // if flannel is not doing ipmasq, we should ipmasq := !*fenv.ipmasq n.Delegate["ipMasq"] = ipmasq } if !hasKey(n.Delegate, "mtu") { mtu := fenv.mtu n.Delegate["mtu"] = mtu } if n.Delegate["type"].(string) == "bridge" { if !hasKey(n.Delegate, "isGateway") { n.Delegate["isGateway"] = true } } if n.CNIVersion != "" { n.Delegate["cniVersion"] = n.CNIVersion } ipam, err := getDelegateIPAM(n, fenv) if err != nil { return fmt.Errorf("failed to assemble Delegate IPAM: %w", err) } n.Delegate["ipam"] = ipam fmt.Fprintf(os.Stderr, "\n%#v\n", n.Delegate) return delegateAdd(args.ContainerID, n.DataDir, n.Delegate) } func doCmdDel(args *skel.CmdArgs, n *NetConf) error { cleanup, netConfBytes, err := consumeScratchNetConf(args.ContainerID, n.DataDir) if err != nil { if os.IsNotExist(err) { // Per spec should ignore error if resources are missing / already removed return nil } return err } // cleanup will work when no error happens defer func() { cleanup(err) }() nc := &types.NetConf{} if err = json.Unmarshal(netConfBytes, nc); err != nil { // Interface will remain in the bridge but will be removed when rebooting the node fmt.Fprintf(os.Stderr, "failed to parse netconf: %v", err) return nil } return invoke.DelegateDel(context.TODO(), nc.Type, netConfBytes, nil) } 0707010000000F000081A400000000000000000000000165A95B7100006473000000000000000000000000000000000000002700000000cni-plugin-1.4.0/flannel_linux_test.go// Copyright 2015 CNI authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "encoding/json" "fmt" "os" "github.com/containernetworking/cni/pkg/skel" current "github.com/containernetworking/cni/pkg/types/100" "github.com/containernetworking/plugins/pkg/ns" "github.com/containernetworking/plugins/pkg/testutils" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) var _ = Describe("Flannel", func() { var ( originalNS ns.NetNS onlyIpv4Input string onlyIpv6Input string dualStackInput string onlyIpv4MultipleNetworksInput string onlyIpv4SubnetFile string onlyIpv6SubnetFile string dualStackSubnetFile string onlyIpv4MultipleNetworksSubnetFile string dataDir string ) BeforeEach(func() { var err error originalNS, err = testutils.NewNS() Expect(err).NotTo(HaveOccurred()) }) AfterEach(func() { Expect(originalNS.Close()).To(Succeed()) }) const hostLocalDataDir = "/var/lib/cni/networks/cni-flannel" const inputTemplate = ` { "name": "cni-flannel", "type": "flannel", "subnetFile": "%s", "dataDir": "%s"%s }` const inputIPAMTemplate = ` "unknown-param": "unknown-value", "routes": [%s]%s` const inputIPAMType = "my-ipam" const inputIPAMRoutes = ` { "dst": "10.96.0.0/12" }, { "dst": "192.168.244.0/24", "gw": "10.1.17.20" }` const onlyIpv4FlannelSubnetEnv = ` FLANNEL_NETWORK=10.1.0.0/16 FLANNEL_SUBNET=10.1.17.1/24 FLANNEL_MTU=1472 FLANNEL_IPMASQ=true ` const onlyIpv6FlannelSubnetEnv = ` FLANNEL_IPV6_NETWORK=fc00::/48 FLANNEL_IPV6_SUBNET=fc00::1/64 FLANNEL_MTU=1472 FLANNEL_IPMASQ=true ` const dualStackFlannelSubnetEnv = ` FLANNEL_NETWORK=10.1.0.0/16 FLANNEL_SUBNET=10.1.17.1/24 FLANNEL_IPV6_NETWORK=fc00::/48 FLANNEL_IPV6_SUBNET=fc00::1/64 FLANNEL_MTU=1472 FLANNEL_IPMASQ=true ` const onlyIpv4MultipleNetworksFlannelSubnetEnv = ` FLANNEL_NETWORK=10.1.0.0/16,192.168.0.0/16 FLANNEL_SUBNET=10.1.17.1/24 FLANNEL_MTU=1472 FLANNEL_IPMASQ=true ` var writeSubnetEnv = func(contents string) string { file, err := os.CreateTemp("", "subnet.env") Expect(err).NotTo(HaveOccurred()) _, err = file.WriteString(contents) Expect(err).NotTo(HaveOccurred()) return file.Name() } var makeInputIPAM = func(ipamType, routes, extra string) string { c := "{\n" if len(ipamType) > 0 { c += fmt.Sprintf(" \"type\": \"%s\",", ipamType) } c += fmt.Sprintf(inputIPAMTemplate, routes, extra) c += "\n}" return c } var makeInput = func(inputIPAM string, subnetFile string) string { ipamPart := "" if len(inputIPAM) > 0 { ipamPart = ",\n \"ipam\":\n" + inputIPAM } return fmt.Sprintf(inputTemplate, subnetFile, dataDir, ipamPart) } BeforeEach(func() { var err error // flannel subnet.env onlyIpv4SubnetFile = writeSubnetEnv(onlyIpv4FlannelSubnetEnv) onlyIpv6SubnetFile = writeSubnetEnv(onlyIpv6FlannelSubnetEnv) dualStackSubnetFile = writeSubnetEnv(dualStackFlannelSubnetEnv) onlyIpv4MultipleNetworksSubnetFile = writeSubnetEnv(onlyIpv4MultipleNetworksFlannelSubnetEnv) // flannel state dir dataDir, err = os.MkdirTemp("", "dataDir") Expect(err).NotTo(HaveOccurred()) onlyIpv4Input = makeInput("", onlyIpv4SubnetFile) onlyIpv6Input = makeInput("", onlyIpv6SubnetFile) dualStackInput = makeInput("", dualStackSubnetFile) onlyIpv4MultipleNetworksInput = makeInput("", onlyIpv4MultipleNetworksSubnetFile) }) AfterEach(func() { os.Remove(onlyIpv4SubnetFile) os.Remove(onlyIpv6SubnetFile) os.Remove(dualStackSubnetFile) os.Remove(onlyIpv4MultipleNetworksSubnetFile) os.RemoveAll(dataDir) os.RemoveAll(hostLocalDataDir) }) Describe("CNI lifecycle", func() { Context("when using only ipv4 stack", func() { It("uses dataDir for storing network configuration with ipv4 stack", func() { const IFNAME = "eth0" targetNs, err := testutils.NewNS() Expect(err).NotTo(HaveOccurred()) defer targetNs.Close() args := &skel.CmdArgs{ ContainerID: "some-container-id-ipv4", Netns: targetNs.Path(), IfName: IFNAME, StdinData: []byte(onlyIpv4Input), } err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() By("calling ADD with ipv4 stack") resI, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin writes the net config to dataDir with ipv4 stack") path := fmt.Sprintf("%s/%s", dataDir, "some-container-id-ipv4") Expect(path).Should(BeAnExistingFile()) netConfBytes, err := os.ReadFile(path) Expect(err).NotTo(HaveOccurred()) expected := `{ "ipMasq": false, "ipam": { "routes": [ { "dst": "10.1.0.0/16" } ], "ranges": [ [{ "subnet": "10.1.17.0/24" }] ], "type": "host-local" }, "isGateway": true, "mtu": 1472, "name": "cni-flannel", "type": "bridge" } ` Expect(netConfBytes).Should(MatchJSON(expected)) result, err := current.NewResultFromResult(resI) Expect(err).NotTo(HaveOccurred()) Expect(result.IPs).To(HaveLen(1)) By("calling DEL with ipv4 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin removes net config from state dir with ipv4 stack") Expect(path).ShouldNot(BeAnExistingFile()) By("calling DEL again with ipv4 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) By("check that plugin does not fail due to missing net config with ipv4 stack") Expect(err).NotTo(HaveOccurred()) return nil }) Expect(err).NotTo(HaveOccurred()) }) }) Context("when using ipv4 stack with two networks", func() { It("uses dataDir for storing network configuration with two ranges in ipv4 stack", func() { const IFNAME = "eth0" targetNs, err := testutils.NewNS() Expect(err).NotTo(HaveOccurred()) defer targetNs.Close() args := &skel.CmdArgs{ ContainerID: "some-container-id-ipv4-multiple", Netns: targetNs.Path(), IfName: IFNAME, StdinData: []byte(onlyIpv4MultipleNetworksInput), } err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() By("calling ADD with multi-network ipv4 stack") resI, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin writes the net config to dataDir with ipv4 stack") path := fmt.Sprintf("%s/%s", dataDir, "some-container-id-ipv4-multiple") Expect(path).Should(BeAnExistingFile()) netConfBytes, err := os.ReadFile(path) Expect(err).NotTo(HaveOccurred()) expected := `{ "ipMasq": false, "ipam": { "routes": [ { "dst": "10.1.0.0/16" }, { "dst": "192.168.0.0/16" } ], "ranges": [ [{ "subnet": "10.1.17.0/24" }] ], "type": "host-local" }, "isGateway": true, "mtu": 1472, "name": "cni-flannel", "type": "bridge" } ` Expect(netConfBytes).Should(MatchJSON(expected)) result, err := current.NewResultFromResult(resI) Expect(err).NotTo(HaveOccurred()) Expect(result.IPs).To(HaveLen(1)) By("calling DEL with ipv4 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin removes net config from state dir with ipv4 stack") Expect(path).ShouldNot(BeAnExistingFile()) By("calling DEL again with ipv4 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) By("check that plugin does not fail due to missing net config with ipv4 stack") Expect(err).NotTo(HaveOccurred()) return nil }) Expect(err).NotTo(HaveOccurred()) }) }) Context("when using only ipv6 stack", func() { It("uses dataDir for storing network configuration with ipv6 stack", func() { const IFNAME = "eth0" targetNs, err := testutils.NewNS() Expect(err).NotTo(HaveOccurred()) defer targetNs.Close() args := &skel.CmdArgs{ ContainerID: "some-container-id-ipv6", Netns: targetNs.Path(), IfName: IFNAME, StdinData: []byte(onlyIpv6Input), } err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() By("calling ADD with ipv6 stack") resI, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin writes the net config to dataDir with ipv6 stack") path := fmt.Sprintf("%s/%s", dataDir, "some-container-id-ipv6") Expect(path).Should(BeAnExistingFile()) netConfBytes, err := os.ReadFile(path) Expect(err).NotTo(HaveOccurred()) expected := `{ "ipMasq": false, "ipam": { "routes": [ { "dst": "fc00::/48" } ], "ranges": [ [{ "subnet": "fc00::/64" }] ], "type": "host-local" }, "isGateway": true, "mtu": 1472, "name": "cni-flannel", "type": "bridge" } ` Expect(netConfBytes).Should(MatchJSON(expected)) result, err := current.NewResultFromResult(resI) Expect(err).NotTo(HaveOccurred()) Expect(result.IPs).To(HaveLen(1)) By("calling DEL with ipv6 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin removes net config from state dir with ipv6 stack") Expect(path).ShouldNot(BeAnExistingFile()) By("calling DEL again with ipv6 stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) By("check that plugin does not fail due to missing net config with ipv6 stack") Expect(err).NotTo(HaveOccurred()) return nil }) Expect(err).NotTo(HaveOccurred()) }) }) Context("when using dual stack", func() { It("uses dataDir for storing network configuration with dual stack", func() { const IFNAME = "eth0" targetNs, err := testutils.NewNS() Expect(err).NotTo(HaveOccurred()) defer targetNs.Close() args := &skel.CmdArgs{ ContainerID: "some-container-id-dual-stack", Netns: targetNs.Path(), IfName: IFNAME, StdinData: []byte(dualStackInput), } err = originalNS.Do(func(ns.NetNS) error { defer GinkgoRecover() By("calling ADD with dual stack") resI, _, err := testutils.CmdAddWithArgs(args, func() error { return cmdAdd(args) }) Expect(err).ShouldNot(HaveOccurred()) By("check that plugin writes the net config to dataDir with dual stack") path := fmt.Sprintf("%s/%s", dataDir, "some-container-id-dual-stack") Expect(path).Should(BeAnExistingFile()) netConfBytes, err := os.ReadFile(path) Expect(err).NotTo(HaveOccurred()) expected := `{ "ipMasq": false, "ipam": { "routes": [ { "dst": "10.1.0.0/16" }, { "dst": "fc00::/48" } ], "ranges": [ [{ "subnet": "10.1.17.0/24" }], [{ "subnet": "fc00::/64" }] ], "type": "host-local" }, "isGateway": true, "mtu": 1472, "name": "cni-flannel", "type": "bridge" } ` Expect(netConfBytes).Should(MatchJSON(expected)) result, err := current.NewResultFromResult(resI) Expect(err).NotTo(HaveOccurred()) Expect(result.IPs).To(HaveLen(2)) By("calling DEL with dual stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) Expect(err).NotTo(HaveOccurred()) By("check that plugin removes net config from state dir with dual stack") Expect(path).ShouldNot(BeAnExistingFile()) By("calling DEL again with dual stack") err = testutils.CmdDelWithArgs(args, func() error { return cmdDel(args) }) By("check that plugin does not fail due to missing net config with dual stack") Expect(err).NotTo(HaveOccurred()) return nil }) Expect(err).NotTo(HaveOccurred()) }) }) }) Describe("loadFlannelNetConf", func() { Context("when subnetFile and dataDir are specified with ipv4 stack", func() { It("loads flannel network config with ipv4 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv4Input)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(onlyIpv4SubnetFile)) Expect(conf.DataDir).To(Equal(dataDir)) }) }) Context("when subnetFile and dataDir are specified with ipv6 stack", func() { It("loads flannel network config with ipv6 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv6Input)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(onlyIpv6SubnetFile)) Expect(conf.DataDir).To(Equal(dataDir)) }) }) Context("when subnetFile and dataDir are specified with dual stack", func() { It("loads flannel network config with dual stack", func() { conf, err := loadFlannelNetConf([]byte(dualStackInput)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(dualStackSubnetFile)) Expect(conf.DataDir).To(Equal(dataDir)) }) }) Context("when defaulting subnetFile and dataDir with ipv4 stack", func() { BeforeEach(func() { onlyIpv4Input = `{ "name": "cni-flannel", "type": "flannel" }` }) It("loads flannel network config with defaults with ipv4 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv4Input)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(defaultSubnetFile)) Expect(conf.DataDir).To(Equal(defaultDataDir)) }) }) Context("when defaulting subnetFile and dataDir with ipv6 stack", func() { BeforeEach(func() { onlyIpv6Input = `{ "name": "cni-flannel", "type": "flannel" }` }) It("loads flannel network config with defaults with ipv6 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv6Input)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(defaultSubnetFile)) Expect(conf.DataDir).To(Equal(defaultDataDir)) }) }) Context("when defaulting subnetFile and dataDir with dual stack", func() { BeforeEach(func() { dualStackInput = `{ "name": "cni-flannel", "type": "flannel" }` }) It("loads flannel network config with defaults with dual stack", func() { conf, err := loadFlannelNetConf([]byte(dualStackInput)) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.Name).To(Equal("cni-flannel")) Expect(conf.Type).To(Equal("flannel")) Expect(conf.SubnetFile).To(Equal(defaultSubnetFile)) Expect(conf.DataDir).To(Equal(defaultDataDir)) }) }) Describe("loadFlannelSubnetEnv", func() { Context("when flannel subnet env is valid with ipv4 stack", func() { It("loads flannel subnet config with ipv4 stack", func() { conf, err := loadFlannelSubnetEnv(onlyIpv4SubnetFile) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.nws[0].String()).To(Equal("10.1.0.0/16")) Expect(conf.sn.String()).To(Equal("10.1.17.0/24")) var mtu uint = 1472 Expect(*conf.mtu).To(Equal(mtu)) Expect(*conf.ipmasq).To(BeTrue()) }) }) Context("when flannel subnet env is valid with ipv6 stack", func() { It("loads flannel subnet config with ipv6 stack", func() { conf, err := loadFlannelSubnetEnv(onlyIpv6SubnetFile) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.ip6Nws[0].String()).To(Equal("fc00::/48")) Expect(conf.ip6Sn.String()).To(Equal("fc00::/64")) var mtu uint = 1472 Expect(*conf.mtu).To(Equal(mtu)) Expect(*conf.ipmasq).To(BeTrue()) }) }) Context("when flannel subnet env is valid with dual stack", func() { It("loads flannel subnet config with dual stack", func() { conf, err := loadFlannelSubnetEnv(dualStackSubnetFile) Expect(err).ShouldNot(HaveOccurred()) Expect(conf.nws[0].String()).To(Equal("10.1.0.0/16")) Expect(conf.sn.String()).To(Equal("10.1.17.0/24")) Expect(conf.ip6Nws[0].String()).To(Equal("fc00::/48")) Expect(conf.ip6Sn.String()).To(Equal("fc00::/64")) var mtu uint = 1472 Expect(*conf.mtu).To(Equal(mtu)) Expect(*conf.ipmasq).To(BeTrue()) }) }) Context("when flannel subnet env is invalid with ipv4 stack", func() { BeforeEach(func() { onlyIpv4SubnetFile = writeSubnetEnv("foo=bar") }) It("returns an error", func() { _, err := loadFlannelSubnetEnv(onlyIpv4SubnetFile) Expect(err).To(MatchError(ContainSubstring("missing FLANNEL_NETWORK, FLANNEL_IPV6_NETWORK, FLANNEL_SUBNET, FLANNEL_IPV6_SUBNET, FLANNEL_MTU, FLANNEL_IPMASQ"))) }) }) Context("when flannel subnet env is invalid with ipv6 stack", func() { BeforeEach(func() { onlyIpv6SubnetFile = writeSubnetEnv("foo=bar") }) It("returns an error", func() { _, err := loadFlannelSubnetEnv(onlyIpv6SubnetFile) Expect(err).To(MatchError(ContainSubstring("missing FLANNEL_NETWORK, FLANNEL_IPV6_NETWORK, FLANNEL_SUBNET, FLANNEL_IPV6_SUBNET, FLANNEL_MTU, FLANNEL_IPMASQ"))) }) }) Context("when flannel subnet env is invalid with dual stack", func() { BeforeEach(func() { dualStackSubnetFile = writeSubnetEnv("foo=bar") }) It("returns an error", func() { _, err := loadFlannelSubnetEnv(dualStackSubnetFile) Expect(err).To(MatchError(ContainSubstring("missing FLANNEL_NETWORK, FLANNEL_IPV6_NETWORK, FLANNEL_SUBNET, FLANNEL_IPV6_SUBNET, FLANNEL_MTU, FLANNEL_IPMASQ"))) }) }) }) }) Describe("getDelegateIPAM", func() { Context("when input IPAM is provided with ipv4 stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "") onlyIpv4Input = makeInput(inputIPAM, onlyIpv4SubnetFile) }) It("configures Delegate IPAM accordingly with ipv4 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv4Input)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(onlyIpv4SubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"10.1.0.0/16\" }\n" subnet := "\"ranges\": [[{\"subnet\": \"10.1.17.0/24\"}]]" expected := makeInputIPAM(inputIPAMType, inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided with two networks ipv4 stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM("host-local", "", "") onlyIpv4Input = makeInput(inputIPAM, onlyIpv4MultipleNetworksSubnetFile) }) It("configures Delegate IPAM accordingly with two routes in ipv4 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv4MultipleNetworksInput)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(onlyIpv4MultipleNetworksSubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) expected := `{ "ranges": [ [ { "subnet": "10.1.17.0/24" } ] ], "routes": [ { "dst": "10.1.0.0/16" }, { "dst": "192.168.0.0/16" } ], "type": "host-local" }` buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided with ipv6 stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "") onlyIpv6Input = makeInput(inputIPAM, onlyIpv6SubnetFile) }) It("configures Delegate IPAM accordingly with ipv6 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv6Input)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(onlyIpv6SubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"fc00::/48\" }\n" subnet := "\"ranges\": [[{ \"subnet\": \"fc00::/64\" }]]" expected := makeInputIPAM(inputIPAMType, inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided with dual stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM(inputIPAMType, inputIPAMRoutes, "") dualStackInput = makeInput(inputIPAM, dualStackSubnetFile) }) It("configures Delegate IPAM accordingly with dual stack", func() { conf, err := loadFlannelNetConf([]byte(dualStackInput)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(dualStackSubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"10.1.0.0/16\" }" + ",\n" + "{ \"dst\": \"fc00::/48\" }\n" subnet := "\"ranges\": [[{ \"subnet\": \"10.1.17.0/24\" }],\n[{ \"subnet\": \"fc00::/64\" }]]" expected := makeInputIPAM(inputIPAMType, inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided without 'type' with ipv4 stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM("", inputIPAMRoutes, "") onlyIpv4Input = makeInput(inputIPAM, onlyIpv4SubnetFile) }) It("configures Delegate IPAM with 'host-local' ipam with ipv4 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv4Input)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(onlyIpv4SubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"10.1.0.0/16\" }\n" subnet := "\"ranges\": [[{\"subnet\": \"10.1.17.0/24\"}]]" expected := makeInputIPAM("host-local", inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided without 'type' with ipv6 stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM("", inputIPAMRoutes, "") onlyIpv6Input = makeInput(inputIPAM, onlyIpv6SubnetFile) }) It("configures Delegate IPAM with 'host-local' ipam with ipv6 stack", func() { conf, err := loadFlannelNetConf([]byte(onlyIpv6Input)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(onlyIpv6SubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"fc00::/48\" }\n" subnet := "\"ranges\": [[{ \"subnet\": \"fc00::/64\" }]]" expected := makeInputIPAM("host-local", inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) Context("when input IPAM is provided without 'type' with dual stack", func() { BeforeEach(func() { inputIPAM := makeInputIPAM("", inputIPAMRoutes, "") dualStackInput = makeInput(inputIPAM, dualStackSubnetFile) }) It("configures Delegate IPAM with 'host-local' ipam with dual stack", func() { conf, err := loadFlannelNetConf([]byte(dualStackInput)) Expect(err).ShouldNot(HaveOccurred()) fenv, err := loadFlannelSubnetEnv(dualStackSubnetFile) Expect(err).ShouldNot(HaveOccurred()) ipam, err := getDelegateIPAM(conf, fenv) Expect(err).ShouldNot(HaveOccurred()) podsRoute := "{ \"dst\": \"10.1.0.0/16\" }" + ",\n" + "{ \"dst\": \"fc00::/48\" }\n" subnet := "\"ranges\": [[{ \"subnet\": \"10.1.17.0/24\" }],\n[{ \"subnet\": \"fc00::/64\" }]]" expected := makeInputIPAM("host-local", inputIPAMRoutes+",\n"+podsRoute, ",\n"+subnet) buf, _ := json.Marshal(ipam) Expect(buf).Should(MatchJSON(expected)) }) }) }) }) 07070100000010000081A400000000000000000000000165A95B710000030C000000000000000000000000000000000000002700000000cni-plugin-1.4.0/flannel_suite_test.go// Copyright 2015 CNI authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" "testing" ) func TestFlannel(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "plugins/meta/flannel") } 07070100000011000081A400000000000000000000000165A95B71000009BB000000000000000000000000000000000000002400000000cni-plugin-1.4.0/flannel_windows.go// Copyright 2018 CNI authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // This is a "meta-plugin". It reads in its own netconf, combines it with // the data from flannel generated subnet file and then invokes a plugin // like bridge or ipvlan to do the real work. package main import ( "context" "encoding/json" "fmt" "github.com/containernetworking/cni/pkg/invoke" "github.com/containernetworking/cni/pkg/skel" "github.com/containernetworking/cni/pkg/types" "github.com/containernetworking/cni/pkg/types/020" "github.com/containernetworking/plugins/pkg/hns" "os" ) func doCmdAdd(args *skel.CmdArgs, n *NetConf, fenv *subnetEnv) error { n.Delegate["name"] = n.Name if !hasKey(n.Delegate, "type") { n.Delegate["type"] = "win-bridge" } // if flannel needs ipmasq - get the plugin to configure it // (this is the opposite of how linux works - on linux the flannel daemon configure ipmasq) n.Delegate["ipMasq"] = *fenv.ipmasq n.Delegate["ipMasqNetwork"] = fenv.nws[0].String() n.Delegate["cniVersion"] = types020.ImplementedSpecVersion if len(n.CNIVersion) != 0 { n.Delegate["cniVersion"] = n.CNIVersion } n.Delegate["ipam"] = map[string]interface{}{ "type": "host-local", "subnet": fenv.sn.String(), } return delegateAdd(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir, n.Delegate) } func doCmdDel(args *skel.CmdArgs, n *NetConf) (err error) { cleanup, netConfBytes, err := consumeScratchNetConf(hns.GetSandboxContainerID(args.ContainerID, args.Netns), n.DataDir) if err != nil { if os.IsNotExist(err) { // Per spec should ignore error if resources are missing / already removed return nil } return err } // cleanup will work when no error happens defer func() { cleanup(err) }() nc := &types.NetConf{} if err = json.Unmarshal(netConfBytes, nc); err != nil { return fmt.Errorf("failed to parse netconf: %v", err) } return invoke.DelegateDel(context.TODO(), nc.Type, netConfBytes, nil) } 07070100000012000081A400000000000000000000000165A95B7100000588000000000000000000000000000000000000001800000000cni-plugin-1.4.0/go.modmodule github.com/flannel-io/cni-plugin go 1.20 require ( github.com/containernetworking/cni v1.1.2 github.com/containernetworking/plugins v1.4.0 github.com/onsi/ginkgo/v2 v2.13.2 github.com/onsi/gomega v1.30.0 ) require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Microsoft/hcsshim v0.11.4 // indirect github.com/buger/jsonparser v1.1.1 // indirect github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/containerd v1.6.23 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/go-cmp v0.6.0 // indirect github.com/google/pprof v0.0.0-20230323073829-e72429f035bd // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sirupsen/logrus v1.9.0 // indirect go.opencensus.io v0.24.0 // indirect golang.org/x/mod v0.13.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.15.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.14.0 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.3 // indirect google.golang.org/protobuf v1.30.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) 07070100000013000081A400000000000000000000000165A95B7100005182000000000000000000000000000000000000001800000000cni-plugin-1.4.0/go.sumcloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/Microsoft/hcsshim v0.11.4 h1:68vKo2VN8DE9AdN4tnkWnmdhqdbpUFM8OF3Airm7fz8= github.com/Microsoft/hcsshim v0.11.4/go.mod h1:smjE4dvqPX9Zldna+t5FG3rnoHhaB7QYxPRqGcpAD9w= github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/containerd v1.6.23 h1:KYJd6UJhKHzwMhiD70iTtSmU+k4565ac22GOTI3AuTA= github.com/containerd/containerd v1.6.23/go.mod h1:UrQOiyzrLi3n4aezYJbQH6Il+YzTvnHFbEuO3yfDrM4= github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ= github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw= github.com/containernetworking/plugins v1.4.0 h1:+w22VPYgk7nQHw7KT92lsRmuToHvb7wwSv9iTbXzzic= github.com/containernetworking/plugins v1.4.0/go.mod h1:UYhcOyjefnrQvKvmmyEKsUA+M9Nfn7tqULPpH0Pkcj0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd h1:r8yyd+DJDmsUhGrRBxH5Pj7KeFK5l+Y3FsgT8keqKtk= github.com/google/pprof v0.0.0-20230323073829-e72429f035bd/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs= github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.30.0 h1:hvMK7xYz4D3HapigLTeGdId/NcfQx1VHMJc60ew99+8= github.com/onsi/gomega v1.30.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 h1:KpwkzHKEF7B9Zxg18WzOa7djJ+Ha5DzthMyZYQfEn2A= google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1/go.mod h1:nKE/iIaLqn2bQwXBg8f1g2Ylh6r5MN5CmZvuzZCgsCU= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.56.3 h1:8I4C0Yq1EjstUzUJzpcRVbuYA2mODtEmpWiQoN/b2nc= google.golang.org/grpc v1.56.3/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 07070100000014000041ED00000000000000000000000265A95B7100000000000000000000000000000000000000000000001900000000cni-plugin-1.4.0/scripts07070100000015000081ED00000000000000000000000165A95B7100000633000000000000000000000000000000000000002A00000000cni-plugin-1.4.0/scripts/build_flannel.sh#!/usr/bin/env bash set -ex cd $(dirname $0)/.. source ./scripts/version.sh if [ -z "${GODEBUG}" ]; then EXTRA_LDFLAGS="${EXTRA_LDFLAGS} -w" DEBUG_GO_GCFLAGS="" DEBUG_TAGS="" else DEBUG_GO_GCFLAGS='-gcflags=all=-N -l' fi BUILDTAGS="netgo osusergo no_stage static_build" GO_BUILDTAGS="${GO_BUILDTAGS} ${BUILDTAGS} ${DEBUG_TAGS}" PKG="github.com/flannel-io/cni-plugin" VENDOR_PREFIX="${PKG}/vendor/" VERSION_FLAGS=" -X main.Version=${VERSION} -X main.Commit=${COMMIT:0:8} -X main.Program=${PROG:-flannel} -X main.buildDate=${BUILD_DATE} " # STATIC_FLAGS='-linkmode external -extldflags "-static"' #STATIC_FLAGS='-extldflags "-static -Wl,--fatal-warnings"' # shellcheck disable=SC2089 STATIC_FLAGS='-extldflags "-static"' GO_LDFLAGS="${STATIC_FLAGS} ${EXTRA_LDFLAGS}" if [ ${GOARCH} == "amd64" ]; then CGO_ENABLED="1" else CGO_ENABLED=0 fi echo "Building flannel for ${GOOS} in ${GOARCH}" echo "${DEBUG_GO_GCFLAGS}" if [ "${GOOS}" = "linux" ]; then go build \ -tags "${GO_BUILDTAGS}" \ ${GO_GCFLAGS} ${GO_BUILD_FLAGS} \ -o ${OUTPUT_DIR}/${PROG}-${GOARCH} \ -ldflags "${GO_LDFLAGS} ${VERSION_FLAGS}" \ ${GO_TAGS} elif [ "${GOOS}" = "windows" ]; then go build \ -tags "${GO_BUILDTAGS}" \ ${GO_GCFLAGS} ${GO_BUILD_FLAGS} \ -o ${OUTPUT_DIR}/${PROG}-${GOARCH}.exe \ -ldflags "${VERSION_FLAGS} ${GO_LDFLAGS}" else echo "GOOS:${GOOS} is not yet supported" echo "Please file a new GitHub issue requesting support for GOOS:${GOOS}" echo "https://github.com/flannel-io/cni-plugin/issues" exit 1 fi 07070100000016000081ED00000000000000000000000165A95B710000037A000000000000000000000000000000000000002900000000cni-plugin-1.4.0/scripts/check_static.sh#!/usr/bin/env bash set -ex cd $(dirname $0)/.. source ./scripts/version.sh # assert that the linux flannel cni-plugin binary is fully statically linked if [[ ${GOOS} == "linux" ]] && type -a scripts/go-assert-static.sh >/dev/null 2>&1; then if GOOS=${GOOS} scripts/go-assert-static.sh ${OUTPUT_DIR}/flannel-${GOARCH}; then printf 'verified static links for flannel-%s\n' "${GOARCH}" else echo "failed to verify static links for dist/flannel-${GOARCH}" fi fi # assert that the windows flannel cni-plugin binary is fully statically linked if [[ ${GOOS} == "windows" ]] && type -a scripts/go-assert-static.sh >/dev/null 2>&1; then if GOOS=${GOOS} scripts/go-assert-static.sh ${OUTPUT_DIR}/flannel-${GOARCH}.exe; then printf 'verified static links for flannel-%s.exe\n' "${GOARCH}" else echo "failed to verify static links for dist/flannel-${GOARCH}.exe" fi fi 07070100000017000081ED00000000000000000000000165A95B71000003AA000000000000000000000000000000000000002D00000000cni-plugin-1.4.0/scripts/go-assert-static.sh#!/bin/sh if [ -z "$*" ]; then echo "usage: $0 file1 [file2 ... fileN]" fi for exe in "${@}"; do if [ ! -x "${exe}" ]; then echo "$exe: file not found" >&2 exit 1 fi case $GOOS in linux) if ! file "${exe}" | grep -E '.*ELF.*executable, .*, statically linked,.*'; then file "${exe}" >&2 echo "${exe}: not a statically linked executable" >&2 exit 1 fi ;; windows) if ! ldd "${exe}" 2>&1 | grep -qE '.*not a dynamic executable' && ! objdump -T "${exe}" 2>&1 | tr -d '\n' | grep -E '.*pei-x86-64.*not a dynamic object.*no symbols'; then file "${exe}" >&2 echo "${exe}: not a statically linked Windows executable" >&2 exit 1 fi ;; *) echo "GOOS:${GOOS} is not yet supported" exit 1 ;; esac done 07070100000018000081ED00000000000000000000000165A95B71000004D1000000000000000000000000000000000000002400000000cni-plugin-1.4.0/scripts/package.sh#!/usr/bin/env bash set -ex cd $(dirname $0)/.. source ./scripts/version.sh mkdir -p release mkdir -p dist umask 0022 # linux archives for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do echo $arch for format in tgz; do FILENAME=cni-plugin-flannel-linux-$arch-"${TAG}".$format FILEPATH="${RELEASE_DIR}"/$FILENAME tar -C "${OUTPUT_DIR}" --owner=0 --group=0 -caf "$FILEPATH" flannel-$arch done done # windows archive FILENAME=cni-plugin-flannel-windows-"${GOARCH}"-"${TAG}".$format FILEPATH="${RELEASE_DIR}"/$FILENAME tar -C "${OUTPUT_DIR}" --owner=0 --group=0 -caf "$FILEPATH" flannel-amd64.exe cd "${SRC_DIR}" # linux for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do GOOS=${GOOS:-$("${GO}" env GOOS)} RELEASE_DIR=release \ OUTPUT_DIR=dist \ GOARCH=$arch ./scripts/check_static.sh >> static-check.log done # windows for arch in amd64; do unset GOARCH unset GOOS echo $arch RELEASE_DIR=release \ OUTPUT_DIR=dist \ GOARCH=$arch GOOS=windows ./scripts/check_static.sh >> static-check.log done cd "${RELEASE_DIR}" for f in *.tgz; do sha1sum $f > $f.sha1; done for f in *.tgz; do sha256sum $f > $f.sha256; done for f in *.tgz; do sha512sum $f > $f.sha512; done 07070100000019000081ED00000000000000000000000165A95B710000069B000000000000000000000000000000000000002400000000cni-plugin-1.4.0/scripts/release.sh#!/usr/bin/env bash set -ex cd "$(dirname "${0}")"/.. source ./scripts/version.sh SRC_DIR=${SRC_DIR:-$PWD} DOCKER=${DOCKER:-docker} GO=${GO:-go} GOPATH=${GOPATH:-$(go env GOPATH)} RELEASE_DIR=release OUTPUT_DIR=dist # Always clean first rm -rf "${OUTPUT_DIR}" rm -rf "${RELEASE_DIR}" mkdir -p "${RELEASE_DIR}" mkdir -p "${OUTPUT_DIR}" $DOCKER run -ti -v "${SRC_DIR}":z -e TAG="${TAG}" --rm golang:"${GOLANG_VERSION}-alpine" \ /bin/sh -ex -c "\ mkdir -p release; mkdir -p dist; umask 0022; apk --no-cache add bash tar git; \ source ./scripts/version.sh; \ chmod +x ./scripts/* ; go mod vendor && go mod tidy for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do \ echo \$arch;\ GOARCH=\$arch ./scripts/build_flannel.sh; \ for format in tgz; do \ FILENAME=cni-plugin-flannel-linux-\$arch-${TAG}.\$format; \ FILEPATH=${RELEASE_DIR}/\$FILENAME; \ tar -C ${OUTPUT_DIR} --owner=0 --group=0 -caf \$FILEPATH . ; \ done; \ done; GOOS=windows GOARCH=amd64 ./scripts/build_flannel.sh; \ for format in tgz; do \ FILENAME=cni-plugin-flannel-windows-${GOARCH}-${TAG}.\$format; \ FILEPATH=${RELEASE_DIR}/\$FILENAME; \ tar -C ${OUTPUT_DIR} --owner=0 --group=0 -caf \$FILEPATH . ; \ done; for arch in amd64 386 arm arm64 s390x ppc64le riscv64; do \ GOARCH=\$arch ./scripts/check_static.sh >> static-check.log; \ done; cd ${RELEASE_DIR}; \ for f in *.tgz; do sha1sum \$f > \$f.sha1; done; \ for f in *.tgz; do sha256sum \$f > \$f.sha256; done; \ for f in *.tgz; do sha512sum \$f > \$f.sha512; done; " 0707010000001A000081ED00000000000000000000000165A95B71000002A8000000000000000000000000000000000000002900000000cni-plugin-1.4.0/scripts/semver-parse.sh#!/bin/bash set -e if [ -z $1 ]; then echo "error: tag required as argument" exit 1 fi if [ -z $2 ]; then echo "error: version required as argument" exit 1 fi TAG=$1 VERSION=$2 MAJOR="" MINOR="" PATCH="" if [[ "${TAG}" =~ ^v([0-9]+)\.([0-9]+)\.([0-9]+)$ ]]; then MAJOR=${BASH_REMATCH[1]} MINOR=${BASH_REMATCH[2]} PATCH=${BASH_REMATCH[3]} fi if [ "${VERSION}" = "minor" ]; then echo "${MINOR}" elif [ "${VERSION}" = "major" ]; then echo "${MAJOR}" elif [ "${VERSION}" = "patch" ]; then echo "${PATCH}" elif [ "${VERSION}" = "all" ]; then echo "v${MAJOR}.${MINOR}.${PATCH}" else echo "error: unrecognized version" exit 2 fi 0707010000001B000081ED00000000000000000000000165A95B7100000625000000000000000000000000000000000000002700000000cni-plugin-1.4.0/scripts/test_linux.sh#!/usr/bin/env bash # # Run CNI plugin tests. # # This needs sudo, as we'll be creating net interfaces. # set -ex # switch into the repo root directory cd $(dirname "$0")/.. # What version of the containernetworking/plugins should we use for testing # We now set TEST_TAG in the Makefile and pass it in CNI_VERSION=${TAG} echo "Running tests" function download_cnis { pushd dist/ curl -L https://github.com/containernetworking/plugins/releases/download/$CNI_VERSION/cni-plugins-linux-amd64-$CNI_VERSION.tgz | tar -xz popd } function testrun { download_cnis sudo -E bash -c "umask 0; PATH=${GOPATH}/dist:$(pwd)/dist:${PATH} go test $@" } COVERALLS=${COVERALLS:-""} if [ -n "${COVERALLS}" ]; then echo "with coverage profile generation..." else echo "without coverage profile generation..." fi PKG=${PKG:-$(go list ./... | xargs echo)} i=0 for t in ${PKG}; do if [ -n "${COVERALLS}" ]; then COVERFLAGS="-covermode set -coverprofile ${i}.coverprofile" fi echo "${t}" testrun "${COVERFLAGS:-""} ${t}" i=$((i+1)) done echo "Checking gofmt..." fmtRes=$(go fmt $PKG) if [ -n "${fmtRes}" ]; then echo -e "go fmt checking failed:\n${fmtRes}" exit 255 fi echo "Checking govet..." vetRes=$(go vet $PKG) if [ -n "${vetRes}" ]; then echo -e "govet checking failed:\n${vetRes}" exit 255 fi # TODO: Figure out how to run this outside of the containernetworking # Run the pkg/ns tests as non root user #mkdir /tmp/cni-rootless #(export XDG_RUNTIME_DIR=/tmp/cni-rootless; cd pkg/ns/; unshare -rmn go test) 0707010000001C000081ED00000000000000000000000165A95B7100000661000000000000000000000000000000000000002400000000cni-plugin-1.4.0/scripts/version.sh#!/bin/bash set -ex PROG=${PROG:-flannel} REGISTRY=${REGISTRY:-docker.io/flannel/flannel-cni-plugin} REPO=${REPO:-rancher} GO=${GO-go} GOARCH=${GOARCH:-$("${GO}" env GOARCH)} GOOS=${GOOS:-$("${GO}" env GOOS)} SRC_DIR=${SRC_DIR:-$PWD} DOCKER=${DOCKER:-docker} GOPATH=${GOPATH:-$(go env GOPATH)} if [ -z "$GOOS" ]; then if [ "${OS}" == "Windows_NT" ]; then GOOS="windows" else UNAME_S=$(shell uname -s) if [ "${UNAME_S}" == "Linux" ]; then GOOS="linux" elif [ "${UNAME_S}" == "Darwin" ]; then GOOS="darwin" elif [ "${UNAME_S}" == "FreeBSD" ]; then GOOS="freebsd" fi fi fi GIT_TAG=${TAG} TREE_STATE=clean BUILD_DATE=$(date -u "+%Y-%m-%dT%H:%M:%SZ") COMMIT=$(git rev-parse HEAD)$(if ! git diff --no-ext-diff --quiet --exit-code; then echo .dirty; fi) PLATFORM=${GOOS}-${GOARCH} RELEASE=${PROG}-${GOARCH} # hardcode versions unless set specifically VERSION=${VERSION:-v1.0.0} GOLANG_VERSION=${GOLANG_VERSION:-1.20.5} if [ -d .git ]; then if [ -z "${GIT_TAG}" ]; then GIT_TAG=$(git tag -l --contains HEAD | head -n 1) fi if [ -n "$(git status --porcelain --untracked-files=no)" ]; then DIRTY="-dirty" TREE_STATE=dirty fi COMMIT=$(git log -n3 --pretty=format:"%H %ae" | cut -f1 -d\ | head -1) if [ -z "${COMMIT}" ]; then COMMIT=$(git rev-parse HEAD || true) fi fi if [[ -n "${GIT_TAG}" ]]; then VERSION=${GIT_TAG} else VERSION="${VERSION}-dev+${COMMIT:0:8}$DIRTY" fi if [ -z "${TAG}" ]; then TAG=${VERSION} fi RELEASE_DIR=release OUTPUT_DIR=dist echo "Version: ${VERSION}" echo "Commit: ${COMMIT}" 07070100000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000B00000000TRAILER!!!208 blocks
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor