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
openSUSE Build Service is sponsored by