├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── CHANGELOG ├── CHANGELOG-10.0.md ├── CHANGELOG-11.0.md └── CHANGELOG-9.0.md ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── RELEASE.md ├── SECURITY_CONTACTS ├── allocator ├── doc.go ├── minmax.go └── minmax_test.go ├── code-of-conduct.md ├── controller ├── controller.go ├── controller_test.go ├── doc.go ├── metrics │ ├── doc.go │ └── metrics.go ├── volume.go └── volume_store.go ├── examples └── hostpath-provisioner │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile.scratch │ ├── Makefile │ ├── README.md │ ├── claim.yaml │ ├── class.yaml │ ├── go.mod │ ├── go.sum │ ├── hostpath-provisioner.go │ ├── pod.yaml │ ├── rbac.yaml │ └── test-pod.yaml ├── gidallocator ├── doc.go └── gidallocator.go ├── go.mod ├── go.sum ├── hack └── verify-logcheck.sh ├── mount ├── LICENSE ├── doc.go ├── mount.go ├── mountinfo.go ├── mountinfo_linux.go └── mountinfo_unsupported.go ├── repo-infra └── verify │ ├── README.md │ ├── boilerplate │ ├── BUILD.bazel │ ├── boilerplate.Dockerfile.txt │ ├── boilerplate.Makefile.txt │ ├── boilerplate.bzl.txt │ ├── boilerplate.go.txt │ ├── boilerplate.py │ ├── boilerplate.py.txt │ ├── boilerplate.sh.txt │ ├── boilerplate_test.py │ └── test │ │ ├── BUILD.bazel │ │ ├── fail.go │ │ ├── fail.py │ │ ├── pass.go │ │ └── pass.py │ ├── go-tools │ ├── verify-gofmt.sh │ └── verify-govet.sh │ ├── go_install_from_commit.sh │ ├── update-bazel.sh │ ├── verify-bazel.sh │ ├── verify-boilerplate.sh │ ├── verify-errexit.sh │ └── verify-go-src.sh ├── test └── e2e │ ├── .gitignore │ └── test.sh └── util ├── doc.go └── util.go /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 7 | 8 | **What type of PR is this?** 9 | > Uncomment only one ` /kind <>` line, hit enter to put that in a new line, and remove leading whitespaces from that line: 10 | > 11 | > /kind api-change 12 | > /kind bug 13 | > /kind cleanup 14 | > /kind design 15 | > /kind documentation 16 | > /kind failing-test 17 | > /kind feature 18 | > /kind flake 19 | 20 | **What this PR does / why we need it**: 21 | 22 | **Which issue(s) this PR fixes**: 23 | 28 | Fixes # 29 | 30 | **Special notes for your reviewer**: 31 | 32 | **Does this PR introduce a user-facing change?**: 33 | 38 | ```release-note 39 | 40 | ``` 41 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | Gopkg.toml 3 | Gopkg.lock 4 | **/*.pyc 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go_import_path: sigs.k8s.io/sig-storage-lib-external-provisioner 3 | go: 4 | - 1.13.7 5 | services: docker 6 | script: 7 | - make verify 8 | - make test 9 | - ./test/e2e/test.sh 10 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-10.0.md: -------------------------------------------------------------------------------- 1 | # Release notes for v10.0.0 2 | 3 | # Changelog since v9.0.3 4 | 5 | ## Urgent Upgrade Notes 6 | 7 | ### (No, really, you MUST read this before you upgrade) 8 | - Using patch to update finalizers. Any external-provisioner now needs permission rules to patch PersistentVolumes. Please update RBAC rules of your provisioner. ([#164](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/164), [@carlory](https://github.com/carlory)) 9 | 10 | ## Changes by Kind 11 | 12 | ### Feature 13 | 14 | - Contextual logging added. Some function arguments have been modified. ([#154](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/154), [@bells17](https://github.com/bells17)) 15 | 16 | ### Uncategorized 17 | 18 | - Added debug logs to shouldDelete function ([#146](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/146), [@amacaskill](https://github.com/amacaskill)) 19 | - Update to Kubernetes 1.30 and go 1.22. Removed gometalinter. ([#167](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/167), [@jsafrane](https://github.com/jsafrane)) 20 | 21 | ## Dependencies 22 | 23 | ### Added 24 | - cloud.google.com/go/compute/metadata: v0.2.3 25 | - cloud.google.com/go/compute: v1.20.1 26 | - github.com/fxamacker/cbor/v2: [v2.6.0](https://github.com/fxamacker/cbor/v2/tree/v2.6.0) 27 | - github.com/go-task/slim-sprig: [52ccab3](https://github.com/go-task/slim-sprig/tree/52ccab3) 28 | - github.com/google/gnostic-models: [v0.6.8](https://github.com/google/gnostic-models/tree/v0.6.8) 29 | - github.com/gorilla/websocket: [v1.5.0](https://github.com/gorilla/websocket/tree/v1.5.0) 30 | - github.com/x448/float16: [v0.8.4](https://github.com/x448/float16/tree/v0.8.4) 31 | - k8s.io/gengo/v2: 51d4e06 32 | 33 | ### Changed 34 | - github.com/emicklei/go-restful/v3: [v3.9.0 → v3.11.0](https://github.com/emicklei/go-restful/v3/compare/v3.9.0...v3.11.0) 35 | - github.com/evanphx/json-patch: [v4.12.0+incompatible → v5.6.0+incompatible](https://github.com/evanphx/json-patch/compare/v4.12.0...v5.6.0) 36 | - github.com/go-logr/logr: [v1.2.3 → v1.4.1](https://github.com/go-logr/logr/compare/v1.2.3...v1.4.1) 37 | - github.com/go-openapi/jsonpointer: [v0.19.5 → v0.19.6](https://github.com/go-openapi/jsonpointer/compare/v0.19.5...v0.19.6) 38 | - github.com/go-openapi/jsonreference: [v0.20.0 → v0.20.2](https://github.com/go-openapi/jsonreference/compare/v0.20.0...v0.20.2) 39 | - github.com/go-openapi/swag: [v0.19.14 → v0.22.3](https://github.com/go-openapi/swag/compare/v0.19.14...v0.22.3) 40 | - github.com/golang/protobuf: [v1.5.2 → v1.5.4](https://github.com/golang/protobuf/compare/v1.5.2...v1.5.4) 41 | - github.com/google/go-cmp: [v0.5.9 → v0.6.0](https://github.com/google/go-cmp/compare/v0.5.9...v0.6.0) 42 | - github.com/google/gofuzz: [v1.1.0 → v1.2.0](https://github.com/google/gofuzz/compare/v1.1.0...v1.2.0) 43 | - github.com/google/pprof: [1a94d86 → 4bb14d4](https://github.com/google/pprof/compare/1a94d86...4bb14d4) 44 | - github.com/google/uuid: [v1.1.2 → v1.3.0](https://github.com/google/uuid/compare/v1.1.2...v1.3.0) 45 | - github.com/kr/pretty: [v0.2.0 → v0.3.1](https://github.com/kr/pretty/compare/v0.2.0...v0.3.1) 46 | - github.com/mailru/easyjson: [v0.7.6 → v0.7.7](https://github.com/mailru/easyjson/compare/v0.7.6...v0.7.7) 47 | - github.com/onsi/ginkgo/v2: [v2.4.0 → v2.15.0](https://github.com/onsi/ginkgo/v2/compare/v2.4.0...v2.15.0) 48 | - github.com/onsi/gomega: [v1.23.0 → v1.31.0](https://github.com/onsi/gomega/compare/v1.23.0...v1.31.0) 49 | - github.com/rogpeppe/go-internal: [v1.3.0 → v1.10.0](https://github.com/rogpeppe/go-internal/compare/v1.3.0...v1.10.0) 50 | - github.com/stretchr/objx: [v0.1.1 → v0.5.0](https://github.com/stretchr/objx/compare/v0.1.1...v0.5.0) 51 | - github.com/stretchr/testify: [v1.8.0 → v1.8.4](https://github.com/stretchr/testify/compare/v1.8.0...v1.8.4) 52 | - golang.org/x/crypto: v0.1.0 → v0.21.0 53 | - golang.org/x/mod: 86c51ed → v0.15.0 54 | - golang.org/x/net: 1e63c2f → v0.23.0 55 | - golang.org/x/oauth2: ee48083 → v0.10.0 56 | - golang.org/x/sys: v0.3.0 → v0.18.0 57 | - golang.org/x/term: v0.3.0 → v0.18.0 58 | - golang.org/x/text: v0.5.0 → v0.14.0 59 | - golang.org/x/time: 90d013b → v0.3.0 60 | - golang.org/x/tools: v0.1.12 → v0.18.0 61 | - golang.org/x/xerrors: 5ec99f8 → 04be3eb 62 | - google.golang.org/protobuf: v1.28.1 → v1.33.0 63 | - gopkg.in/check.v1: 8fa4692 → 10cb982 64 | - k8s.io/api: v0.26.0 → v0.30.0 65 | - k8s.io/apimachinery: v0.26.0 → v0.30.0 66 | - k8s.io/client-go: v0.26.0 → v0.30.0 67 | - k8s.io/klog/v2: v2.80.1 → v2.120.1 68 | - k8s.io/kube-openapi: 172d655 → 70dd376 69 | - k8s.io/utils: 1a15be2 → 3b25d92 70 | - sigs.k8s.io/json: f223a00 → bc3834c 71 | - sigs.k8s.io/structured-merge-diff/v4: v4.2.3 → v4.4.1 72 | 73 | ### Removed 74 | - cloud.google.com/go/bigquery: v1.8.0 75 | - cloud.google.com/go/datastore: v1.1.0 76 | - cloud.google.com/go/pubsub: v1.3.1 77 | - cloud.google.com/go/storage: v1.10.0 78 | - cloud.google.com/go: v0.65.0 79 | - dmitri.shuralyov.com/gpu/mtl: 666a987 80 | - github.com/BurntSushi/toml: [v0.3.1](https://github.com/BurntSushi/toml/tree/v0.3.1) 81 | - github.com/BurntSushi/xgb: [27f1227](https://github.com/BurntSushi/xgb/tree/27f1227) 82 | - github.com/PuerkitoBio/purell: [v1.1.1](https://github.com/PuerkitoBio/purell/tree/v1.1.1) 83 | - github.com/PuerkitoBio/urlesc: [de5bf2a](https://github.com/PuerkitoBio/urlesc/tree/de5bf2a) 84 | - github.com/census-instrumentation/opencensus-proto: [v0.2.1](https://github.com/census-instrumentation/opencensus-proto/tree/v0.2.1) 85 | - github.com/chzyer/logex: [v1.1.10](https://github.com/chzyer/logex/tree/v1.1.10) 86 | - github.com/chzyer/readline: [2972be2](https://github.com/chzyer/readline/tree/2972be2) 87 | - github.com/chzyer/test: [a1ea475](https://github.com/chzyer/test/tree/a1ea475) 88 | - github.com/client9/misspell: [v0.3.4](https://github.com/client9/misspell/tree/v0.3.4) 89 | - github.com/cncf/udpa/go: [269d4d4](https://github.com/cncf/udpa/go/tree/269d4d4) 90 | - github.com/docopt/docopt-go: [ee0de3b](https://github.com/docopt/docopt-go/tree/ee0de3b) 91 | - github.com/elazarl/goproxy: [947c36d](https://github.com/elazarl/goproxy/tree/947c36d) 92 | - github.com/envoyproxy/go-control-plane: [v0.9.4](https://github.com/envoyproxy/go-control-plane/tree/v0.9.4) 93 | - github.com/envoyproxy/protoc-gen-validate: [v0.1.0](https://github.com/envoyproxy/protoc-gen-validate/tree/v0.1.0) 94 | - github.com/go-gl/glfw/v3.3/glfw: [6f7a984](https://github.com/go-gl/glfw/v3.3/glfw/tree/6f7a984) 95 | - github.com/go-gl/glfw: [e6da0ac](https://github.com/go-gl/glfw/tree/e6da0ac) 96 | - github.com/golang/glog: [23def4e](https://github.com/golang/glog/tree/23def4e) 97 | - github.com/golang/mock: [v1.4.4](https://github.com/golang/mock/tree/v1.4.4) 98 | - github.com/google/gnostic: [v0.5.7-v3refs](https://github.com/google/gnostic/tree/v0.5.7-v3refs) 99 | - github.com/google/martian/v3: [v3.0.0](https://github.com/google/martian/v3/tree/v3.0.0) 100 | - github.com/google/martian: [v2.1.0+incompatible](https://github.com/google/martian/tree/v2.1.0) 101 | - github.com/google/renameio: [v0.1.0](https://github.com/google/renameio/tree/v0.1.0) 102 | - github.com/googleapis/gax-go/v2: [v2.0.5](https://github.com/googleapis/gax-go/v2/tree/v2.0.5) 103 | - github.com/hashicorp/golang-lru: [v0.5.1](https://github.com/hashicorp/golang-lru/tree/v0.5.1) 104 | - github.com/ianlancetaylor/demangle: [5e5cf60](https://github.com/ianlancetaylor/demangle/tree/5e5cf60) 105 | - github.com/jstemmer/go-junit-report: [v0.9.1](https://github.com/jstemmer/go-junit-report/tree/v0.9.1) 106 | - github.com/mitchellh/mapstructure: [v1.1.2](https://github.com/mitchellh/mapstructure/tree/v1.1.2) 107 | - github.com/niemeyer/pretty: [a10e7ca](https://github.com/niemeyer/pretty/tree/a10e7ca) 108 | - github.com/stoewer/go-strcase: [v1.2.0](https://github.com/stoewer/go-strcase/tree/v1.2.0) 109 | - go.opencensus.io: v0.22.4 110 | - golang.org/x/exp: 6cc2880 111 | - golang.org/x/image: cff245a 112 | - golang.org/x/lint: 738671d 113 | - golang.org/x/mobile: d2bd2a2 114 | - google.golang.org/api: v0.30.0 115 | - google.golang.org/genproto: 1ed22bb 116 | - google.golang.org/grpc: v1.31.0 117 | - gopkg.in/errgo.v2: v2.1.0 118 | - honnef.co/go/tools: v0.0.1-2020.1.4 119 | - k8s.io/gengo: 485abfe 120 | - rsc.io/binaryregexp: v0.2.0 121 | - rsc.io/quote/v3: v3.1.0 122 | - rsc.io/sampler: v1.3.0 123 | v0.3.0 124 | - golang.org/x/tools: v0.1.12 → v0.18.0 125 | - golang.org/x/xerrors: 5ec99f8 → 04be3eb 126 | - google.golang.org/protobuf: v1.28.1 → v1.33.0 127 | - gopkg.in/check.v1: 8fa4692 → 10cb982 128 | - k8s.io/api: v0.26.0 → v0.30.0 129 | - k8s.io/apimachinery: v0.26.0 → v0.30.0 130 | - k8s.io/client-go: v0.26.0 → v0.30.0 131 | - k8s.io/klog/v2: v2.80.1 → v2.120.1 132 | - k8s.io/kube-openapi: 172d655 → 70dd376 133 | - k8s.io/utils: 1a15be2 → 3b25d92 134 | - sigs.k8s.io/json: f223a00 → bc3834c 135 | - sigs.k8s.io/structured-merge-diff/v4: v4.2.3 → v4.4.1 136 | 137 | ### Removed 138 | - cloud.google.com/go/bigquery: v1.8.0 139 | - cloud.google.com/go/datastore: v1.1.0 140 | - cloud.google.com/go/pubsub: v1.3.1 141 | - cloud.google.com/go/storage: v1.10.0 142 | - cloud.google.com/go: v0.65.0 143 | - dmitri.shuralyov.com/gpu/mtl: 666a987 144 | - github.com/BurntSushi/toml: [v0.3.1](https://github.com/BurntSushi/toml/tree/v0.3.1) 145 | - github.com/BurntSushi/xgb: [27f1227](https://github.com/BurntSushi/xgb/tree/27f1227) 146 | - github.com/PuerkitoBio/purell: [v1.1.1](https://github.com/PuerkitoBio/purell/tree/v1.1.1) 147 | - github.com/PuerkitoBio/urlesc: [de5bf2a](https://github.com/PuerkitoBio/urlesc/tree/de5bf2a) 148 | - github.com/census-instrumentation/opencensus-proto: [v0.2.1](https://github.com/census-instrumentation/opencensus-proto/tree/v0.2.1) 149 | - github.com/chzyer/logex: [v1.1.10](https://github.com/chzyer/logex/tree/v1.1.10) 150 | - github.com/chzyer/readline: [2972be2](https://github.com/chzyer/readline/tree/2972be2) 151 | - github.com/chzyer/test: [a1ea475](https://github.com/chzyer/test/tree/a1ea475) 152 | - github.com/client9/misspell: [v0.3.4](https://github.com/client9/misspell/tree/v0.3.4) 153 | - github.com/cncf/udpa/go: [269d4d4](https://github.com/cncf/udpa/go/tree/269d4d4) 154 | - github.com/docopt/docopt-go: [ee0de3b](https://github.com/docopt/docopt-go/tree/ee0de3b) 155 | - github.com/elazarl/goproxy: [947c36d](https://github.com/elazarl/goproxy/tree/947c36d) 156 | - github.com/envoyproxy/go-control-plane: [v0.9.4](https://github.com/envoyproxy/go-control-plane/tree/v0.9.4) 157 | - github.com/envoyproxy/protoc-gen-validate: [v0.1.0](https://github.com/envoyproxy/protoc-gen-validate/tree/v0.1.0) 158 | - github.com/go-gl/glfw/v3.3/glfw: [6f7a984](https://github.com/go-gl/glfw/v3.3/glfw/tree/6f7a984) 159 | - github.com/go-gl/glfw: [e6da0ac](https://github.com/go-gl/glfw/tree/e6da0ac) 160 | - github.com/golang/glog: [23def4e](https://github.com/golang/glog/tree/23def4e) 161 | - github.com/golang/mock: [v1.4.4](https://github.com/golang/mock/tree/v1.4.4) 162 | - github.com/google/gnostic: [v0.5.7-v3refs](https://github.com/google/gnostic/tree/v0.5.7-v3refs) 163 | - github.com/google/martian/v3: [v3.0.0](https://github.com/google/martian/v3/tree/v3.0.0) 164 | - github.com/google/martian: [v2.1.0+incompatible](https://github.com/google/martian/tree/v2.1.0) 165 | - github.com/google/renameio: [v0.1.0](https://github.com/google/renameio/tree/v0.1.0) 166 | - github.com/googleapis/gax-go/v2: [v2.0.5](https://github.com/googleapis/gax-go/v2/tree/v2.0.5) 167 | - github.com/hashicorp/golang-lru: [v0.5.1](https://github.com/hashicorp/golang-lru/tree/v0.5.1) 168 | - github.com/ianlancetaylor/demangle: [5e5cf60](https://github.com/ianlancetaylor/demangle/tree/5e5cf60) 169 | - github.com/jstemmer/go-junit-report: [v0.9.1](https://github.com/jstemmer/go-junit-report/tree/v0.9.1) 170 | - github.com/mitchellh/mapstructure: [v1.1.2](https://github.com/mitchellh/mapstructure/tree/v1.1.2) 171 | - github.com/niemeyer/pretty: [a10e7ca](https://github.com/niemeyer/pretty/tree/a10e7ca) 172 | - github.com/stoewer/go-strcase: [v1.2.0](https://github.com/stoewer/go-strcase/tree/v1.2.0) 173 | - go.opencensus.io: v0.22.4 174 | - golang.org/x/exp: 6cc2880 175 | - golang.org/x/image: cff245a 176 | - golang.org/x/lint: 738671d 177 | - golang.org/x/mobile: d2bd2a2 178 | - google.golang.org/api: v0.30.0 179 | - google.golang.org/genproto: 1ed22bb 180 | - google.golang.org/grpc: v1.31.0 181 | - gopkg.in/errgo.v2: v2.1.0 182 | - honnef.co/go/tools: v0.0.1-2020.1.4 183 | - k8s.io/gengo: 485abfe 184 | - rsc.io/binaryregexp: v0.2.0 185 | - rsc.io/quote/v3: v3.1.0 186 | - rsc.io/sampler: v1.3.0 187 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-11.0.md: -------------------------------------------------------------------------------- 1 | # Release notes for v11.0.0 2 | 3 | # Changelog since v10.0.1 4 | 5 | ## Changes by Kind 6 | 7 | ### Feature 8 | 9 | - Signature of NewProvisionController has been changed to support contextual logging for eventRecorder. This is a breaking change that requires updates to code that calls this function. ([#171](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/171), [@bells17](https://github.com/bells17)) 10 | 11 | ### Bug or Regression 12 | 13 | - Add a callback to customize PV name ([#178](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/178), [@smileusd](https://github.com/smileusd)) 14 | 15 | ### Uncategorized 16 | 17 | - Fixed overwriting of internal informer cache. This could lead to multiple Provision() calls for a single PVC in very rare (impossible?) cases. The library relies on idempotency of the Provision() call. Please report any frequent duplicate Provision() calls. ([#179](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/179), [@goushicui](https://github.com/goushicui)) 18 | 19 | ## Dependencies 20 | 21 | ### Added 22 | _Nothing has changed._ 23 | 24 | ### Changed 25 | _Nothing has changed._ 26 | 27 | ### Removed 28 | _Nothing has changed._ 29 | -------------------------------------------------------------------------------- /CHANGELOG/CHANGELOG-9.0.md: -------------------------------------------------------------------------------- 1 | # Release notes for v9.0.3 2 | 3 | # Changelog since v9.0.2 4 | 5 | ## Changes by Kind 6 | 7 | ### Uncategorized 8 | 9 | - Added debug logs to shouldDelete function ([#146](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/146), [@amacaskill](https://github.com/amacaskill)) 10 | 11 | # Release notes for v9.0.2 12 | 13 | # Changelog since v9.0.1 14 | 15 | ## Changes by Kind 16 | 17 | ### Uncategorized 18 | 19 | - Fix indefinite stuck Pending pod on a deleted node ([#139](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/139), [@sunnylovestiramisu](https://github.com/sunnylovestiramisu)) 20 | 21 | # Release notes for v9.0.1 22 | 23 | # Changelog since v9.0.0 24 | 25 | ## Changes by Kind 26 | 27 | ### Uncategorized 28 | 29 | - Fixed go.mod for v9. 30 | 31 | # Release notes for v9.0.0 32 | 33 | # Changelog since v8.0.0 34 | 35 | ## Changes by Kind 36 | 37 | ### Uncategorized 38 | 39 | - Action Needed: Updated leader election to use Endpoints + Lease. All provisioners based on this library must have RBAC permissions to create/update Lease objects in coordination.k8s.io/v1 API. ([#120](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/120), [@NikhilSharmaWe](https://github.com/NikhilSharmaWe)) 40 | - Added a new label `source` to `controller_persistentvolumeclaim_provision_total` metric. ([#128](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/128), [@RaunakShah](https://github.com/RaunakShah)) 41 | - Added support for `external-provisioner.volume.kubernetes.io/finalizer` on statically provisioned volumes. ([#129](https://github.com/kubernetes-sigs/sig-storage-lib-external-provisioner/pull/129), [@deepakkinni](https://github.com/deepakkinni)) 42 | 43 | 44 | ## Dependencies 45 | 46 | ### Added 47 | - github.com/armon/go-socks5: [e753329](https://github.com/armon/go-socks5/tree/e753329) 48 | - github.com/asaskevich/govalidator: [f61b66f](https://github.com/asaskevich/govalidator/tree/f61b66f) 49 | - github.com/cncf/udpa/go: [269d4d4](https://github.com/cncf/udpa/go/tree/269d4d4) 50 | - github.com/creack/pty: [v1.1.9](https://github.com/creack/pty/tree/v1.1.9) 51 | - github.com/emicklei/go-restful/v3: [v3.9.0](https://github.com/emicklei/go-restful/v3/tree/v3.9.0) 52 | - github.com/go-gl/glfw: [e6da0ac](https://github.com/go-gl/glfw/tree/e6da0ac) 53 | - github.com/google/gnostic: [v0.5.7-v3refs](https://github.com/google/gnostic/tree/v0.5.7-v3refs) 54 | - github.com/google/martian/v3: [v3.0.0](https://github.com/google/martian/v3/tree/v3.0.0) 55 | - github.com/josharian/intern: [v1.0.0](https://github.com/josharian/intern/tree/v1.0.0) 56 | - github.com/mitchellh/mapstructure: [v1.1.2](https://github.com/mitchellh/mapstructure/tree/v1.1.2) 57 | - github.com/moby/spdystream: [v0.2.0](https://github.com/moby/spdystream/tree/v0.2.0) 58 | - github.com/niemeyer/pretty: [a10e7ca](https://github.com/niemeyer/pretty/tree/a10e7ca) 59 | - github.com/onsi/ginkgo/v2: [v2.4.0](https://github.com/onsi/ginkgo/v2/tree/v2.4.0) 60 | - github.com/stoewer/go-strcase: [v1.2.0](https://github.com/stoewer/go-strcase/tree/v1.2.0) 61 | - github.com/yuin/goldmark: [v1.2.1](https://github.com/yuin/goldmark/tree/v1.2.1) 62 | - golang.org/x/term: v0.3.0 63 | - gopkg.in/yaml.v3: v3.0.1 64 | - rsc.io/quote/v3: v3.1.0 65 | - rsc.io/sampler: v1.3.0 66 | - sigs.k8s.io/json: f223a00 67 | 68 | ### Changed 69 | - cloud.google.com/go/bigquery: v1.0.1 → v1.8.0 70 | - cloud.google.com/go/datastore: v1.0.0 → v1.1.0 71 | - cloud.google.com/go/pubsub: v1.0.1 → v1.3.1 72 | - cloud.google.com/go/storage: v1.0.0 → v1.10.0 73 | - cloud.google.com/go: v0.51.0 → v0.65.0 74 | - github.com/PuerkitoBio/purell: [v1.0.0 → v1.1.1](https://github.com/PuerkitoBio/purell/compare/v1.0.0...v1.1.1) 75 | - github.com/PuerkitoBio/urlesc: [5bd2802 → de5bf2a](https://github.com/PuerkitoBio/urlesc/compare/5bd2802...de5bf2a) 76 | - github.com/envoyproxy/go-control-plane: [5f8ba28 → v0.9.4](https://github.com/envoyproxy/go-control-plane/compare/5f8ba28...v0.9.4) 77 | - github.com/evanphx/json-patch: [v4.9.0+incompatible → v4.12.0+incompatible](https://github.com/evanphx/json-patch/compare/v4.9.0...v4.12.0) 78 | - github.com/go-gl/glfw/v3.3/glfw: [12ad95a → 6f7a984](https://github.com/go-gl/glfw/v3.3/glfw/compare/12ad95a...6f7a984) 79 | - github.com/go-logr/logr: [v0.2.0 → v1.2.3](https://github.com/go-logr/logr/compare/v0.2.0...v1.2.3) 80 | - github.com/go-openapi/jsonpointer: [46af16f → v0.19.5](https://github.com/go-openapi/jsonpointer/compare/46af16f...v0.19.5) 81 | - github.com/go-openapi/jsonreference: [13c6e35 → v0.20.0](https://github.com/go-openapi/jsonreference/compare/13c6e35...v0.20.0) 82 | - github.com/go-openapi/swag: [1d0bd11 → v0.19.14](https://github.com/go-openapi/swag/compare/1d0bd11...v0.19.14) 83 | - github.com/gogo/protobuf: [v1.3.1 → v1.3.2](https://github.com/gogo/protobuf/compare/v1.3.1...v1.3.2) 84 | - github.com/golang/groupcache: [215e871 → 41bb18b](https://github.com/golang/groupcache/compare/215e871...41bb18b) 85 | - github.com/golang/mock: [v1.3.1 → v1.4.4](https://github.com/golang/mock/compare/v1.3.1...v1.4.4) 86 | - github.com/golang/protobuf: [v1.4.2 → v1.5.2](https://github.com/golang/protobuf/compare/v1.4.2...v1.5.2) 87 | - github.com/google/btree: [v1.0.0 → v1.0.1](https://github.com/google/btree/compare/v1.0.0...v1.0.1) 88 | - github.com/google/go-cmp: [v0.4.0 → v0.5.9](https://github.com/google/go-cmp/compare/v0.4.0...v0.5.9) 89 | - github.com/google/pprof: [d4f498a → 1a94d86](https://github.com/google/pprof/compare/d4f498a...1a94d86) 90 | - github.com/google/uuid: [v1.1.1 → v1.1.2](https://github.com/google/uuid/compare/v1.1.1...v1.1.2) 91 | - github.com/imdario/mergo: [v0.3.5 → v0.3.6](https://github.com/imdario/mergo/compare/v0.3.5...v0.3.6) 92 | - github.com/json-iterator/go: [v1.1.10 → v1.1.12](https://github.com/json-iterator/go/compare/v1.1.10...v1.1.12) 93 | - github.com/kisielk/errcheck: [v1.2.0 → v1.5.0](https://github.com/kisielk/errcheck/compare/v1.2.0...v1.5.0) 94 | - github.com/kr/text: [v0.1.0 → v0.2.0](https://github.com/kr/text/compare/v0.1.0...v0.2.0) 95 | - github.com/mailru/easyjson: [d5b7844 → v0.7.6](https://github.com/mailru/easyjson/compare/d5b7844...v0.7.6) 96 | - github.com/modern-go/reflect2: [v1.0.1 → v1.0.2](https://github.com/modern-go/reflect2/compare/v1.0.1...v1.0.2) 97 | - github.com/munnerz/goautoneg: [a547fc6 → a7dc8b6](https://github.com/munnerz/goautoneg/compare/a547fc6...a7dc8b6) 98 | - github.com/onsi/gomega: [v1.9.0 → v1.23.0](https://github.com/onsi/gomega/compare/v1.9.0...v1.23.0) 99 | - github.com/stretchr/testify: [v1.4.0 → v1.8.0](https://github.com/stretchr/testify/compare/v1.4.0...v1.8.0) 100 | - go.opencensus.io: v0.22.2 → v0.22.4 101 | - golang.org/x/crypto: 75b2880 → v0.1.0 102 | - golang.org/x/exp: da58074 → 6cc2880 103 | - golang.org/x/lint: fdd1cda → 738671d 104 | - golang.org/x/mod: c90efee → 86c51ed 105 | - golang.org/x/net: ab34263 → 1e63c2f 106 | - golang.org/x/oauth2: bf48bf1 → ee48083 107 | - golang.org/x/sync: cd5d95a → 886fb93 108 | - golang.org/x/sys: ed371f2 → v0.3.0 109 | - golang.org/x/text: v0.3.3 → v0.5.0 110 | - golang.org/x/time: 555d28b → 90d013b 111 | - golang.org/x/tools: 7b8e75d → v0.1.12 112 | - golang.org/x/xerrors: 9bdfabe → 5ec99f8 113 | - google.golang.org/api: v0.15.0 → v0.30.0 114 | - google.golang.org/appengine: v1.6.5 → v1.6.7 115 | - google.golang.org/genproto: cb27e3a → 1ed22bb 116 | - google.golang.org/grpc: v1.27.0 → v1.31.0 117 | - google.golang.org/protobuf: v1.24.0 → v1.28.1 118 | - gopkg.in/check.v1: 41f04d3 → 8fa4692 119 | - gopkg.in/yaml.v2: v2.2.8 → v2.4.0 120 | - honnef.co/go/tools: v0.0.1-2019.2.3 → v0.0.1-2020.1.4 121 | - k8s.io/api: v0.19.1 → v0.26.0 122 | - k8s.io/apimachinery: v0.19.1 → v0.26.0 123 | - k8s.io/client-go: v0.19.1 → v0.26.0 124 | - k8s.io/gengo: 3a45101 → 485abfe 125 | - k8s.io/klog/v2: v2.3.0 → v2.80.1 126 | - k8s.io/kube-openapi: 6aeccd4 → 172d655 127 | - k8s.io/utils: d5654de → 1a15be2 128 | - sigs.k8s.io/structured-merge-diff/v4: v4.0.1 → v4.2.3 129 | - sigs.k8s.io/yaml: v1.2.0 → v1.3.0 130 | 131 | ### Removed 132 | - github.com/Azure/go-autorest/autorest/adal: [v0.8.2](https://github.com/Azure/go-autorest/autorest/adal/tree/v0.8.2) 133 | - github.com/Azure/go-autorest/autorest/date: [v0.2.0](https://github.com/Azure/go-autorest/autorest/date/tree/v0.2.0) 134 | - github.com/Azure/go-autorest/autorest/mocks: [v0.3.0](https://github.com/Azure/go-autorest/autorest/mocks/tree/v0.3.0) 135 | - github.com/Azure/go-autorest/autorest: [v0.9.6](https://github.com/Azure/go-autorest/autorest/tree/v0.9.6) 136 | - github.com/Azure/go-autorest/logger: [v0.1.0](https://github.com/Azure/go-autorest/logger/tree/v0.1.0) 137 | - github.com/Azure/go-autorest/tracing: [v0.5.0](https://github.com/Azure/go-autorest/tracing/tree/v0.5.0) 138 | - github.com/dgrijalva/jwt-go: [v3.2.0+incompatible](https://github.com/dgrijalva/jwt-go/tree/v3.2.0) 139 | - github.com/docker/spdystream: [449fdfc](https://github.com/docker/spdystream/tree/449fdfc) 140 | - github.com/emicklei/go-restful: [ff4f55a](https://github.com/emicklei/go-restful/tree/ff4f55a) 141 | - github.com/fsnotify/fsnotify: [v1.4.9](https://github.com/fsnotify/fsnotify/tree/v1.4.9) 142 | - github.com/ghodss/yaml: [73d445a](https://github.com/ghodss/yaml/tree/73d445a) 143 | - github.com/go-openapi/spec: [6aced65](https://github.com/go-openapi/spec/tree/6aced65) 144 | - github.com/googleapis/gnostic: [v0.4.1](https://github.com/googleapis/gnostic/tree/v0.4.1) 145 | - github.com/hpcloud/tail: [v1.0.0](https://github.com/hpcloud/tail/tree/v1.0.0) 146 | - github.com/onsi/ginkgo: [v1.12.0](https://github.com/onsi/ginkgo/tree/v1.12.0) 147 | - github.com/spf13/afero: [v1.2.2](https://github.com/spf13/afero/tree/v1.2.2) 148 | - gopkg.in/fsnotify.v1: v1.4.7 149 | - gopkg.in/tomb.v1: dd63297 150 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Welcome to Kubernetes. We are excited about the prospect of you joining our [community](https://github.com/kubernetes/community)! The Kubernetes community abides by the CNCF [code of conduct](code-of-conduct.md). Here is an excerpt: 4 | 5 | _As contributors and maintainers of this project, and in the interest of fostering an open and welcoming community, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities._ 6 | 7 | ## Getting Started 8 | 9 | We have full documentation on how to get started contributing here: 10 | 11 | 14 | 15 | - [Contributor License Agreement](https://git.k8s.io/community/CLA.md) Kubernetes projects require that you sign a Contributor License Agreement (CLA) before we can accept your pull requests 16 | - [Kubernetes Contributor Guide](http://git.k8s.io/community/contributors/guide) - Main contributor documentation, or you can just jump directly to the [contributing section](http://git.k8s.io/community/contributors/guide#contributing) 17 | - [Contributor Cheat Sheet](https://github.com/kubernetes/community/blob/master/contributors/guide/contributor-cheatsheet/README.md) - Common resources for existing developers 18 | 19 | ## Mentorship 20 | 21 | - [Mentoring Initiatives](https://git.k8s.io/community/mentoring) - We have a diverse set of mentorship programs available that are always looking for volunteers! 22 | 23 | 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2018 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | all: verify test logcheck 16 | 17 | dep: 18 | go mod tidy 19 | 20 | verify: dep 21 | PATH=$$(go env GOPATH)/bin:$$PATH repo-infra/verify/verify-go-src.sh -v 22 | PATH=$$(go env GOPATH)/bin:$$PATH repo-infra/verify/verify-boilerplate.sh 23 | 24 | test: dep 25 | go test ./controller -v 26 | go test ./allocator -v 27 | 28 | # Check contextual logging. 29 | .PHONY: logcheck 30 | logcheck: 31 | hack/verify-logcheck.sh 32 | 33 | clean: 34 | rm -rf ./test/e2e/kubernetes 35 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | # See the OWNERS docs: https://git.k8s.io/community/contributors/guide/owners.md 2 | 3 | approvers: 4 | - wongma7 5 | - jsafrane 6 | - msau42 7 | - saad-ali 8 | - xing-yang 9 | 10 | reviewers: 11 | - wongma7 12 | - andyzhangx 13 | - chrishenzie 14 | - gnufied 15 | - humblec 16 | - mauriciopoppe 17 | - jingxu97 18 | - jsafrane 19 | - pohly 20 | - RaunakShah 21 | - sunnylovestiramisu 22 | - xing-yang 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # sig-storage-lib-external-provisioner 2 | 3 | A library for writing [external provisioners](https://kubernetes.io/docs/concepts/storage/storage-classes/#provisioner). Projects using this library include: 4 | - https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner - Dynamic sub-dir volume provisioner on a remote NFS server. 5 | - https://github.com/kubernetes-sigs/nfs-ganesha-server-and-external-provisioner - NFS Ganesha Server and Volume Provisioner. 6 | - https://github.com/kubernetes-csi/external-provisioner - Sidecar container that watches Kubernetes PersistentVolumeClaim objects and triggers CreateVolume/DeleteVolume against a CSI endpoint 7 | 8 | ## Packages 9 | ### `controller` 10 | Contains the Provisioner interface and ProvisionController, a custom Kubernetes [controller](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-api-machinery/controllers.md) that watches PersistentVolumes and PersistentVolumeClaims. Implement the Provisioner interface, pass the implementation to a ProvisionController, and Run the controller, which then takes care of calling the Provisioner's Provision or Delete as needed. 11 | 12 | ## Optional Packages 13 | ### `util` 14 | Contains an assortment of useful functions, e.g. any used by [in-tree plugins](https://github.com/kubernetes/kubernetes/tree/master/pkg/volume) that aren't otherwise easily importable. 15 | 16 | ### `gidallocator` and `allocator` 17 | `gidallocator` is used to allocate a GID from a range specified by StorageClass parameters gidMin & gidMax. `allocator` is the underlying implementation and can be used to write other allocators. An example use-case for `gidallocator` is an NFS-based provisioner that chowns each export to a unique GID. See [Volume Security](https://docs.openshift.com/container-platform/3.11/install_config/persistent_storage/pod_security_context.html#supplemental-groups/) for more context. 18 | 19 | ### `mount` 20 | Is used to read the mount table. Copied from [moby](https://github.com/moby/moby/tree/17.05.x/pkg/mount). 21 | 22 | ## Community, discussion, contribution, and support 23 | 24 | Learn how to engage with the Kubernetes community on the [community page](http://kubernetes.io/community/). 25 | 26 | You can reach the maintainers of this project at: 27 | 28 | - [Slack](http://slack.k8s.io/) 29 | - [Mailing List](https://groups.google.com/forum/#!forum/kubernetes-dev) 30 | 31 | ### Code of conduct 32 | 33 | Participation in the Kubernetes community is governed by the [Kubernetes Code of Conduct](code-of-conduct.md). 34 | 35 | [owners]: https://git.k8s.io/community/contributors/guide/owners.md 36 | [Creative Commons 4.0]: https://git.k8s.io/website/LICENSE 37 | -------------------------------------------------------------------------------- /RELEASE.md: -------------------------------------------------------------------------------- 1 | # Release Process 2 | 3 | The Kubernetes Template Project is released on an as-needed basis. The process is as follows: 4 | 5 | 1. An issue is proposing a new release with a changelog since the last release 6 | 1. All [OWNERS](OWNERS) must LGTM this release 7 | 1. An OWNER runs `git tag -s $VERSION` and inserts the changelog and pushes the tag with `git push $VERSION` 8 | 1. The release issue is closed 9 | 1. An announcement email is sent to `kubernetes-dev@googlegroups.com` with the subject `[ANNOUNCE] kubernetes-template-project $VERSION is released` 10 | -------------------------------------------------------------------------------- /SECURITY_CONTACTS: -------------------------------------------------------------------------------- 1 | # Defined below are the security contacts for this repo. 2 | # 3 | # They are the contact point for the Product Security Team to reach out 4 | # to for triaging and handling of incoming issues. 5 | # 6 | # The below names agree to abide by the 7 | # [Embargo Policy](https://github.com/kubernetes/sig-release/blob/master/security-release-process-documentation/security-release-process.md#embargo-policy) 8 | # and will be removed and replaced if they violate that agreement. 9 | # 10 | # DO NOT REPORT SECURITY VULNERABILITIES DIRECTLY TO THESE NAMES, FOLLOW THE 11 | # INSTRUCTIONS AT https://kubernetes.io/security/ 12 | 13 | wongma7 14 | jsafrane 15 | childsb 16 | -------------------------------------------------------------------------------- /allocator/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package allocator // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/allocator" 18 | -------------------------------------------------------------------------------- /allocator/minmax.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // 18 | // This implementation is space-efficient for a sparse 19 | // allocation over a big range. Could be optimized 20 | // for high absolute allocation number with a bitmap. 21 | // 22 | 23 | package allocator 24 | 25 | import ( 26 | "errors" 27 | "sync" 28 | ) 29 | 30 | var ( 31 | //ErrConflict returned when value is already in use. 32 | ErrConflict = errors.New("number already allocated") 33 | 34 | //ErrInvalidRange returned invalid range, for eg# min > max 35 | ErrInvalidRange = errors.New("invalid range") 36 | 37 | //ErrOutOfRange returned when value is not in pool range. 38 | ErrOutOfRange = errors.New("out of range") 39 | 40 | //ErrRangeFull returned when no more free values in the pool. 41 | ErrRangeFull = errors.New("range full") 42 | 43 | //ErrInternal returned when no free item found, but a.free != 0. 44 | ErrInternal = errors.New("internal error") 45 | ) 46 | 47 | // MinMaxAllocator defines allocator struct. 48 | type MinMaxAllocator struct { 49 | lock sync.Mutex 50 | min int 51 | max int 52 | free int 53 | used map[int]bool 54 | } 55 | 56 | var _ Rangeable = &MinMaxAllocator{} 57 | 58 | // Rangeable is an Interface that can adjust its min/max range. 59 | // Rangeable should be threadsafe 60 | type Rangeable interface { 61 | Allocate(int) (bool, error) 62 | AllocateNext() (int, bool, error) 63 | Release(int) error 64 | Has(int) bool 65 | Free() int 66 | SetRange(min, max int) error 67 | } 68 | 69 | // NewMinMaxAllocator return a new allocator or error based on provided min/max value. 70 | func NewMinMaxAllocator(min, max int) (*MinMaxAllocator, error) { 71 | if min > max { 72 | return nil, ErrInvalidRange 73 | } 74 | return &MinMaxAllocator{ 75 | min: min, 76 | max: max, 77 | free: 1 + max - min, 78 | used: map[int]bool{}, 79 | }, nil 80 | } 81 | 82 | // SetRange defines the range/pool with provided min and max values. 83 | func (a *MinMaxAllocator) SetRange(min, max int) error { 84 | if min > max { 85 | return ErrInvalidRange 86 | } 87 | 88 | a.lock.Lock() 89 | defer a.lock.Unlock() 90 | 91 | // Check if we need to change 92 | if a.min == min && a.max == max { 93 | return nil 94 | } 95 | 96 | a.min = min 97 | a.max = max 98 | 99 | // Recompute how many free we have in the range 100 | numUsed := 0 101 | for i := range a.used { 102 | if a.inRange(i) { 103 | numUsed++ 104 | } 105 | } 106 | a.free = 1 + max - min - numUsed 107 | 108 | return nil 109 | } 110 | 111 | // Allocate allocates provided value in the allocator and mark it as used. 112 | func (a *MinMaxAllocator) Allocate(i int) (bool, error) { 113 | a.lock.Lock() 114 | defer a.lock.Unlock() 115 | 116 | if !a.inRange(i) { 117 | return false, ErrOutOfRange 118 | } 119 | 120 | if a.has(i) { 121 | return false, ErrConflict 122 | } 123 | 124 | a.used[i] = true 125 | a.free-- 126 | 127 | return true, nil 128 | } 129 | 130 | // AllocateNext allocates next value from the allocator. 131 | func (a *MinMaxAllocator) AllocateNext() (int, bool, error) { 132 | a.lock.Lock() 133 | defer a.lock.Unlock() 134 | 135 | // Fast check if we're out of items 136 | if a.free <= 0 { 137 | return 0, false, ErrRangeFull 138 | } 139 | 140 | // Scan from the minimum until we find a free item 141 | for i := a.min; i <= a.max; i++ { 142 | if !a.has(i) { 143 | a.used[i] = true 144 | a.free-- 145 | return i, true, nil 146 | } 147 | } 148 | 149 | // no free item found, but a.free != 0 150 | return 0, false, ErrInternal 151 | } 152 | 153 | // Release free/delete provided value from the allocator. 154 | func (a *MinMaxAllocator) Release(i int) error { 155 | a.lock.Lock() 156 | defer a.lock.Unlock() 157 | 158 | if !a.has(i) { 159 | return nil 160 | } 161 | 162 | delete(a.used, i) 163 | 164 | if a.inRange(i) { 165 | a.free++ 166 | } 167 | 168 | return nil 169 | } 170 | 171 | func (a *MinMaxAllocator) has(i int) bool { 172 | _, ok := a.used[i] 173 | return ok 174 | } 175 | 176 | // Has check whether the provided value is used in the allocator 177 | func (a *MinMaxAllocator) Has(i int) bool { 178 | a.lock.Lock() 179 | defer a.lock.Unlock() 180 | 181 | return a.has(i) 182 | } 183 | 184 | // Free returns the number of free values in the allocator. 185 | func (a *MinMaxAllocator) Free() int { 186 | a.lock.Lock() 187 | defer a.lock.Unlock() 188 | return a.free 189 | } 190 | 191 | func (a *MinMaxAllocator) inRange(i int) bool { 192 | return a.min <= i && i <= a.max 193 | } 194 | -------------------------------------------------------------------------------- /allocator/minmax_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package allocator 18 | 19 | import ( 20 | "testing" 21 | ) 22 | 23 | func TestNewFree(t *testing.T) { 24 | min := 1 25 | max := 10 26 | 27 | m, err := NewMinMaxAllocator(min, max) 28 | if err != nil { 29 | t.Errorf("error creating new allocator: '%v'", err) 30 | } 31 | 32 | if f := m.Free(); f != (max - min + 1) { 33 | t.Errorf("expect to get %d free, but got %d", (max - min + 1), f) 34 | } 35 | } 36 | 37 | func TestNewInvalidRange(t *testing.T) { 38 | if _, err := NewMinMaxAllocator(10, 1); err != ErrInvalidRange { 39 | t.Errorf("expect to get Error '%v', got '%v'", ErrInvalidRange, err) 40 | } 41 | } 42 | 43 | func TestSetRange(t *testing.T) { 44 | min := 1 45 | max := 10 46 | 47 | m, err := NewMinMaxAllocator(min, max) 48 | if err != nil { 49 | t.Errorf("error creating new allocator: '%v'", err) 50 | } 51 | 52 | if err = m.SetRange(10, 1); err != ErrInvalidRange { 53 | t.Errorf("expected to get error '%v', got '%v'", ErrInvalidRange, err) 54 | } 55 | 56 | if err = m.SetRange(1, 2); err != nil { 57 | t.Errorf("error setting range: '%v'", err) 58 | } 59 | 60 | if f := m.Free(); f != 2 { 61 | t.Errorf("expect to get %d free, but got %d", 2, f) 62 | } 63 | 64 | if ok, _ := m.Allocate(1); !ok { 65 | t.Errorf("error allocate offset %v", 1) 66 | } 67 | 68 | if f := m.Free(); f != 1 { 69 | t.Errorf("expect to get 1 free, but got %d", f) 70 | } 71 | 72 | if err = m.SetRange(1, 1); err != nil { 73 | t.Errorf("error setting range: '%v'", err) 74 | } 75 | 76 | if f := m.Free(); f != 0 { 77 | t.Errorf("expect to get 0 free, but got %d", f) 78 | } 79 | 80 | if err = m.SetRange(2, 2); err != nil { 81 | t.Errorf("error setting range: '%v'", err) 82 | } 83 | 84 | if f := m.Free(); f != 1 { 85 | t.Errorf("expect to get 1 free, but got %d", f) 86 | } 87 | } 88 | 89 | func TestAllocateNext(t *testing.T) { 90 | min := 1 91 | max := 10 92 | 93 | m, err := NewMinMaxAllocator(min, max) 94 | if err != nil { 95 | t.Errorf("error creating new allocator: '%v'", err) 96 | } 97 | 98 | el, ok, _ := m.AllocateNext() 99 | if !ok { 100 | t.Fatalf("unexpected error") 101 | } 102 | 103 | if !m.Has(el) { 104 | t.Errorf("expect element %v allocated", el) 105 | } 106 | 107 | if f := m.Free(); f != (max-min+1)-1 { 108 | t.Errorf("expect to get %d free, but got %d", (max-min+1)-1, f) 109 | } 110 | } 111 | 112 | func TestAllocateMax(t *testing.T) { 113 | min := 1 114 | max := 10 115 | 116 | m, err := NewMinMaxAllocator(min, max) 117 | if err != nil { 118 | t.Errorf("error creating new allocator: '%v'", err) 119 | } 120 | 121 | for i := 1; i <= max; i++ { 122 | if _, ok, _ := m.AllocateNext(); !ok { 123 | t.Fatalf("unexpected error") 124 | } 125 | } 126 | 127 | if _, ok, _ := m.AllocateNext(); ok { 128 | t.Errorf("unexpected success") 129 | } 130 | 131 | if f := m.Free(); f != 0 { 132 | t.Errorf("expect to get %d free, but got %d", 0, f) 133 | } 134 | } 135 | 136 | func TestAllocate(t *testing.T) { 137 | min := 1 138 | max := 10 139 | offset := 3 140 | 141 | m, err := NewMinMaxAllocator(min, max) 142 | if err != nil { 143 | t.Errorf("error creating new allocator: '%v'", err) 144 | } 145 | 146 | if ok, err := m.Allocate(offset); !ok { 147 | t.Errorf("error allocate offset %v: %v", offset, err) 148 | } 149 | 150 | if !m.Has(offset) { 151 | t.Errorf("expect element %v allocated", offset) 152 | } 153 | 154 | if f := m.Free(); f != (max-min+1)-1 { 155 | t.Errorf("expect to get %d free, but got %d", (max-min+1)-1, f) 156 | } 157 | } 158 | 159 | func TestAllocateConflict(t *testing.T) { 160 | min := 1 161 | max := 10 162 | offset := 3 163 | 164 | m, err := NewMinMaxAllocator(min, max) 165 | if err != nil { 166 | t.Errorf("error creating new allocator: '%v'", err) 167 | } 168 | 169 | ok, err := m.Allocate(offset) 170 | if !ok { 171 | t.Errorf("error allocate offset %v: %v", offset, err) 172 | } 173 | 174 | ok, err = m.Allocate(offset) 175 | if ok { 176 | t.Errorf("unexpected success") 177 | } 178 | if err != ErrConflict { 179 | t.Errorf("expected error '%v', got '%v'", ErrConflict, err) 180 | } 181 | } 182 | 183 | func TestAllocateOutOfRange(t *testing.T) { 184 | min := 1 185 | max := 10 186 | offset := 11 187 | 188 | m, err := NewMinMaxAllocator(min, max) 189 | if err != nil { 190 | t.Errorf("error creating new allocator: '%v'", err) 191 | } 192 | 193 | ok, err := m.Allocate(offset) 194 | if ok { 195 | t.Errorf("unexpected success") 196 | } 197 | if err != ErrOutOfRange { 198 | t.Errorf("expected error '%v', got '%v'", ErrOutOfRange, err) 199 | } 200 | } 201 | 202 | func TestRelease(t *testing.T) { 203 | min := 1 204 | max := 10 205 | offset := 3 206 | 207 | m, err := NewMinMaxAllocator(min, max) 208 | if err != nil { 209 | t.Errorf("error creating new allocator: '%v'", err) 210 | } 211 | 212 | ok, err := m.Allocate(offset) 213 | if !ok { 214 | t.Errorf("error allocate offset %v: %v", offset, err) 215 | } 216 | 217 | if !m.Has(offset) { 218 | t.Errorf("expect offset %v allocated", offset) 219 | } 220 | 221 | if err = m.Release(offset); err != nil { 222 | t.Errorf("unexpected error: %v", err) 223 | } 224 | 225 | if m.Has(offset) { 226 | t.Errorf("expect offset %v not allocated", offset) 227 | } 228 | } 229 | -------------------------------------------------------------------------------- /code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Kubernetes Community Code of Conduct 2 | 3 | Please refer to our [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md) 4 | -------------------------------------------------------------------------------- /controller/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/controller" 18 | -------------------------------------------------------------------------------- /controller/metrics/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/controller/metrics" 18 | -------------------------------------------------------------------------------- /controller/metrics/metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | import ( 20 | "github.com/prometheus/client_golang/prometheus" 21 | ) 22 | 23 | // Metrics contains the metrics for a certain subsystem name. 24 | type Metrics struct { 25 | // PersistentVolumeClaimProvisionTotal is used to collect accumulated count of persistent volumes provisioned. 26 | PersistentVolumeClaimProvisionTotal *prometheus.CounterVec 27 | // PersistentVolumeClaimProvisionFailedTotal is used to collect accumulated count of persistent volume provision failed attempts. 28 | PersistentVolumeClaimProvisionFailedTotal *prometheus.CounterVec 29 | // PersistentVolumeClaimProvisionDurationSeconds is used to collect latency in seconds to provision persistent volumes. 30 | PersistentVolumeClaimProvisionDurationSeconds *prometheus.HistogramVec 31 | // PersistentVolumeDeleteTotal is used to collect accumulated count of persistent volumes deleted. 32 | PersistentVolumeDeleteTotal *prometheus.CounterVec 33 | // PersistentVolumeDeleteFailedTotal is used to collect accumulated count of persistent volume delete failed attempts. 34 | PersistentVolumeDeleteFailedTotal *prometheus.CounterVec 35 | // PersistentVolumeDeleteDurationSeconds is used to collect latency in seconds to delete persistent volumes. 36 | PersistentVolumeDeleteDurationSeconds *prometheus.HistogramVec 37 | } 38 | 39 | // New creates a new set of metrics with the goven subsystem name. 40 | func New(subsystem string) Metrics { 41 | return Metrics{ 42 | PersistentVolumeClaimProvisionTotal: prometheus.NewCounterVec( 43 | prometheus.CounterOpts{ 44 | Subsystem: subsystem, 45 | Name: "persistentvolumeclaim_provision_total", 46 | Help: "Total number of persistent volumes provisioned succesfully. Broken down by storage class name and source of the claim.", 47 | }, 48 | []string{"class", "source"}, 49 | ), 50 | PersistentVolumeClaimProvisionFailedTotal: prometheus.NewCounterVec( 51 | prometheus.CounterOpts{ 52 | Subsystem: subsystem, 53 | Name: "persistentvolumeclaim_provision_failed_total", 54 | Help: "Total number of persistent volume provision failed attempts. Broken down by storage class name and source of the claim.", 55 | }, 56 | []string{"class", "source"}, 57 | ), 58 | PersistentVolumeClaimProvisionDurationSeconds: prometheus.NewHistogramVec( 59 | prometheus.HistogramOpts{ 60 | Subsystem: subsystem, 61 | Name: "persistentvolumeclaim_provision_duration_seconds", 62 | Help: "Latency in seconds to provision persistent volumes. Failed provisioning attempts are ignored. Broken down by storage class name and source of the claim.", 63 | Buckets: prometheus.DefBuckets, 64 | }, 65 | []string{"class", "source"}, 66 | ), 67 | PersistentVolumeDeleteTotal: prometheus.NewCounterVec( 68 | prometheus.CounterOpts{ 69 | Subsystem: subsystem, 70 | Name: "persistentvolume_delete_total", 71 | Help: "Total number of persistent volumes deleted succesfully. Broken down by storage class name.", 72 | }, 73 | []string{"class"}, 74 | ), 75 | PersistentVolumeDeleteFailedTotal: prometheus.NewCounterVec( 76 | prometheus.CounterOpts{ 77 | Subsystem: subsystem, 78 | Name: "persistentvolume_delete_failed_total", 79 | Help: "Total number of persistent volume delete failed attempts. Broken down by storage class name.", 80 | }, 81 | []string{"class"}, 82 | ), 83 | PersistentVolumeDeleteDurationSeconds: prometheus.NewHistogramVec( 84 | prometheus.HistogramOpts{ 85 | Subsystem: subsystem, 86 | Name: "persistentvolume_delete_duration_seconds", 87 | Help: "Latency in seconds to delete persistent volumes. Failed deletion attempts are ignored. Broken down by storage class name.", 88 | Buckets: prometheus.DefBuckets, 89 | }, 90 | []string{"class"}, 91 | ), 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /controller/volume.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2016 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | 23 | "k8s.io/api/core/v1" 24 | storageapis "k8s.io/api/storage/v1" 25 | ) 26 | 27 | // Provisioner is an interface that creates templates for PersistentVolumes 28 | // and can create the volume as a new resource in the infrastructure provider. 29 | // It can also remove the volume it created from the underlying storage 30 | // provider. 31 | type Provisioner interface { 32 | // Provision creates a volume i.e. the storage asset and returns a PV object 33 | // for the volume. The provisioner can return an error (e.g. timeout) and state 34 | // ProvisioningInBackground to tell the controller that provisioning may be in 35 | // progress after Provision() finishes. The controller will call Provision() 36 | // again with the same parameters, assuming that the provisioner continues 37 | // provisioning the volume. The provisioner must return either final error (with 38 | // ProvisioningFinished) or success eventually, otherwise the controller will try 39 | // forever (unless FailedProvisionThreshold is set). 40 | Provision(context.Context, ProvisionOptions) (*v1.PersistentVolume, ProvisioningState, error) 41 | // Delete removes the storage asset that was created by Provision backing the 42 | // given PV. Does not delete the PV object itself. 43 | // 44 | // May return IgnoredError to indicate that the call has been ignored and no 45 | // action taken. 46 | Delete(context.Context, *v1.PersistentVolume) error 47 | } 48 | 49 | // Qualifier is an optional interface implemented by provisioners to determine 50 | // whether a claim should be provisioned as early as possible (e.g. prior to 51 | // leader election). 52 | type Qualifier interface { 53 | // ShouldProvision returns whether provisioning for the claim should 54 | // be attempted. 55 | ShouldProvision(context.Context, *v1.PersistentVolumeClaim) bool 56 | } 57 | 58 | // DeletionGuard is an optional interface implemented by provisioners to determine 59 | // whether a PV should be deleted. 60 | type DeletionGuard interface { 61 | // ShouldDelete returns whether deleting the PV should be attempted. 62 | ShouldDelete(context.Context, *v1.PersistentVolume) bool 63 | } 64 | 65 | // BlockProvisioner is an optional interface implemented by provisioners to determine 66 | // whether it supports block volume. 67 | type BlockProvisioner interface { 68 | Provisioner 69 | // SupportsBlock returns whether provisioner supports block volume. 70 | SupportsBlock(context.Context) bool 71 | } 72 | 73 | // ProvisioningState is state of volume provisioning. It tells the controller if 74 | // provisioning could be in progress in the background after Provision() call 75 | // returns or the provisioning is 100% finished (either with success or error). 76 | type ProvisioningState string 77 | 78 | const ( 79 | // ProvisioningInBackground tells the controller that provisioning may be in 80 | // progress in background after Provision call finished. 81 | ProvisioningInBackground ProvisioningState = "Background" 82 | // ProvisioningFinished tells the controller that provisioning for sure does 83 | // not continue in background, error code of Provision() is final. 84 | ProvisioningFinished ProvisioningState = "Finished" 85 | // ProvisioningNoChange tells the controller that provisioning state is the same as 86 | // before the call - either ProvisioningInBackground or ProvisioningFinished from 87 | // the previous Provision(). This state is typically returned by a provisioner 88 | // before it could reach storage backend - the provisioner could not check status 89 | // of provisioning and previous state applies. If this state is returned from the 90 | // first Provision call, ProvisioningFinished is assumed (the provisioning 91 | // could not even start). 92 | ProvisioningNoChange ProvisioningState = "NoChange" 93 | // ProvisioningReschedule tells the controller that it shall stop all further 94 | // attempts to provision the volume and instead ask the Kubernetes scheduler 95 | // to pick a different node. This only makes sense for volumes with a selected 96 | // node, i.e. those with late binding, and must only be returned when it is certain 97 | // that provisioning does not continue in the background. The error returned together 98 | // with this state contains further information why rescheduling is needed. 99 | ProvisioningReschedule ProvisioningState = "Reschedule" 100 | ) 101 | 102 | // IgnoredError is the value for Delete to return to indicate that the call has 103 | // been ignored and no action taken. In case multiple provisioners are serving 104 | // the same storage class, provisioners may ignore PVs they are not responsible 105 | // for (e.g. ones they didn't create). The controller will act accordingly, 106 | // i.e. it won't emit a misleading VolumeFailedDelete event. 107 | type IgnoredError struct { 108 | Reason string 109 | } 110 | 111 | func (e *IgnoredError) Error() string { 112 | return fmt.Sprintf("ignored because %s", e.Reason) 113 | } 114 | 115 | // ProvisionOptions contains all information required to provision a volume 116 | type ProvisionOptions struct { 117 | // StorageClass is a reference to the storage class that is used for 118 | // provisioning for this volume 119 | StorageClass *storageapis.StorageClass 120 | 121 | // PV.Name of the appropriate PersistentVolume. Used to generate cloud 122 | // volume name. 123 | PVName string 124 | 125 | // PVC is reference to the claim that lead to provisioning of a new PV. 126 | // Provisioners *must* create a PV that would be matched by this PVC, 127 | // i.e. with required capacity, accessMode, labels matching PVC.Selector and 128 | // so on. 129 | PVC *v1.PersistentVolumeClaim 130 | 131 | // Node selected by the scheduler for the volume. 132 | SelectedNode *v1.Node 133 | } 134 | -------------------------------------------------------------------------------- /controller/volume_store.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controller 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "sync" 23 | "time" 24 | 25 | v1 "k8s.io/api/core/v1" 26 | apierrs "k8s.io/apimachinery/pkg/api/errors" 27 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 | utilruntime "k8s.io/apimachinery/pkg/util/runtime" 29 | "k8s.io/apimachinery/pkg/util/wait" 30 | "k8s.io/client-go/kubernetes" 31 | "k8s.io/client-go/tools/cache" 32 | "k8s.io/client-go/tools/record" 33 | "k8s.io/client-go/util/workqueue" 34 | klog "k8s.io/klog/v2" 35 | ) 36 | 37 | // VolumeStore is an interface that's used to save PersistentVolumes to API server. 38 | // Implementation of the interface add custom error recovery policy. 39 | // A volume is added via StoreVolume(). It's enough to store the volume only once. 40 | // It is not possible to remove a volume, even when corresponding PVC is deleted 41 | // and PV is not necessary any longer. PV will be always created. 42 | // If corresponding PVC is deleted, the PV will be deleted by Kubernetes using 43 | // standard deletion procedure. It saves us some code here. 44 | type VolumeStore interface { 45 | // StoreVolume makes sure a volume is saved to Kubernetes API server. 46 | // If no error is returned, caller can assume that PV was saved or 47 | // is being saved in background. 48 | // In error is returned, no PV was saved and corresponding PVC needs 49 | // to be re-queued (so whole provisioning needs to be done again). 50 | StoreVolume(logger klog.Logger, claim *v1.PersistentVolumeClaim, volume *v1.PersistentVolume) error 51 | 52 | // Runs any background goroutines for implementation of the interface. 53 | Run(ctx context.Context, threadiness int) 54 | } 55 | 56 | // queueStore is implementation of VolumeStore that re-tries saving 57 | // PVs to API server using a workqueue running in its own goroutine(s). 58 | // After failed save, volume is re-qeueued with exponential backoff. 59 | type queueStore struct { 60 | client kubernetes.Interface 61 | queue workqueue.RateLimitingInterface 62 | eventRecorder record.EventRecorder 63 | claimsIndexer cache.Indexer 64 | 65 | volumes sync.Map 66 | } 67 | 68 | var _ VolumeStore = &queueStore{} 69 | 70 | // NewVolumeStoreQueue returns VolumeStore that uses asynchronous workqueue to save PVs. 71 | func NewVolumeStoreQueue( 72 | client kubernetes.Interface, 73 | limiter workqueue.RateLimiter, 74 | claimsIndexer cache.Indexer, 75 | eventRecorder record.EventRecorder, 76 | ) VolumeStore { 77 | 78 | return &queueStore{ 79 | client: client, 80 | queue: workqueue.NewNamedRateLimitingQueue(limiter, "unsavedpvs"), 81 | claimsIndexer: claimsIndexer, 82 | eventRecorder: eventRecorder, 83 | } 84 | } 85 | 86 | func (q *queueStore) StoreVolume(logger klog.Logger, _ *v1.PersistentVolumeClaim, volume *v1.PersistentVolume) error { 87 | if err := q.doSaveVolume(logger, volume); err != nil { 88 | q.volumes.Store(volume.Name, volume) 89 | q.queue.Add(volume.Name) 90 | logger.Error(err, "Failed to save volume", "volume", volume.Name) 91 | } 92 | // Consume any error, this Store will retry in background. 93 | return nil 94 | } 95 | 96 | func (q *queueStore) Run(ctx context.Context, threadiness int) { 97 | logger := klog.FromContext(ctx) 98 | logger.Info("Starting save volume queue") 99 | defer q.queue.ShutDown() 100 | 101 | for i := 0; i < threadiness; i++ { 102 | go wait.UntilWithContext(ctx, q.saveVolumeWorker, time.Second) 103 | } 104 | <-ctx.Done() 105 | logger.Info("Stopped save volume queue") 106 | } 107 | 108 | func (q *queueStore) saveVolumeWorker(ctx context.Context) { 109 | for q.processNextWorkItem(ctx) { 110 | } 111 | } 112 | 113 | func (q *queueStore) processNextWorkItem(ctx context.Context) bool { 114 | obj, shutdown := q.queue.Get() 115 | defer q.queue.Done(obj) 116 | 117 | if shutdown { 118 | return false 119 | } 120 | 121 | var volumeName string 122 | var ok bool 123 | if volumeName, ok = obj.(string); !ok { 124 | q.queue.Forget(obj) 125 | utilruntime.HandleError(fmt.Errorf("expected string in save workqueue but got %#v", obj)) 126 | return true 127 | } 128 | 129 | volumeObj, found := q.volumes.Load(volumeName) 130 | if !found { 131 | q.queue.Forget(volumeName) 132 | utilruntime.HandleError(fmt.Errorf("did not find saved volume %s", volumeName)) 133 | return true 134 | } 135 | 136 | volume, ok := volumeObj.(*v1.PersistentVolume) 137 | if !ok { 138 | q.queue.Forget(volumeName) 139 | utilruntime.HandleError(fmt.Errorf("saved object is not volume: %+v", volumeObj)) 140 | return true 141 | } 142 | 143 | logger := klog.FromContext(ctx) 144 | if err := q.doSaveVolume(logger, volume); err != nil { 145 | q.queue.AddRateLimited(volumeName) 146 | utilruntime.HandleError(err) 147 | logger.V(5).Info("Volume enqueued", "volume", volume.Name) 148 | return true 149 | } 150 | q.volumes.Delete(volumeName) 151 | q.queue.Forget(volumeName) 152 | return true 153 | } 154 | 155 | func (q *queueStore) doSaveVolume(logger klog.Logger, volume *v1.PersistentVolume) error { 156 | logger.V(5).Info("Saving volume", "volume", volume.Name) 157 | _, err := q.client.CoreV1().PersistentVolumes().Create(context.Background(), volume, metav1.CreateOptions{}) 158 | if err == nil || apierrs.IsAlreadyExists(err) { 159 | logger.V(5).Info("Volume saved", "volume", volume.Name) 160 | q.sendSuccessEvent(logger, volume) 161 | return nil 162 | } 163 | return fmt.Errorf("error saving volume %s: %s", volume.Name, err) 164 | } 165 | 166 | func (q *queueStore) sendSuccessEvent(logger klog.Logger, volume *v1.PersistentVolume) { 167 | claimObjs, err := q.claimsIndexer.ByIndex(uidIndex, string(volume.Spec.ClaimRef.UID)) 168 | if err != nil { 169 | logger.V(2).Info("Error sending event to claim", "claimUID", volume.Spec.ClaimRef.UID, "err", err) 170 | return 171 | } 172 | if len(claimObjs) != 1 { 173 | return 174 | } 175 | claim, ok := claimObjs[0].(*v1.PersistentVolumeClaim) 176 | if !ok { 177 | return 178 | } 179 | msg := fmt.Sprintf("Successfully provisioned volume %s", volume.Name) 180 | q.eventRecorder.Event(claim, v1.EventTypeNormal, "ProvisioningSucceeded", msg) 181 | } 182 | 183 | // backoffStore is implementation of VolumeStore that blocks and tries to save 184 | // a volume to API server with configurable backoff. If saving fails, 185 | // StoreVolume() deletes the storage asset in the end and returns appropriate 186 | // error code. 187 | type backoffStore struct { 188 | client kubernetes.Interface 189 | eventRecorder record.EventRecorder 190 | backoff *wait.Backoff 191 | ctrl *ProvisionController 192 | } 193 | 194 | var _ VolumeStore = &backoffStore{} 195 | 196 | // NewBackoffStore returns VolumeStore that uses blocking exponential backoff to save PVs. 197 | func NewBackoffStore(client kubernetes.Interface, 198 | eventRecorder record.EventRecorder, 199 | backoff *wait.Backoff, 200 | ctrl *ProvisionController, 201 | ) VolumeStore { 202 | return &backoffStore{ 203 | client: client, 204 | eventRecorder: eventRecorder, 205 | backoff: backoff, 206 | ctrl: ctrl, 207 | } 208 | } 209 | 210 | func (b *backoffStore) StoreVolume(logger klog.Logger, claim *v1.PersistentVolumeClaim, volume *v1.PersistentVolume) error { 211 | // Try to create the PV object several times 212 | var lastSaveError error 213 | err := wait.ExponentialBackoff(*b.backoff, func() (bool, error) { 214 | logger.V(4).Info("Trying to save persistentvolume", "persistentvolume", volume.Name) 215 | var err error 216 | if _, err = b.client.CoreV1().PersistentVolumes().Create(context.Background(), volume, metav1.CreateOptions{}); err == nil || apierrs.IsAlreadyExists(err) { 217 | // Save succeeded. 218 | if err != nil { 219 | logger.V(2).Info("Persistentvolume already exists, reusing", "persistentvolume", volume.Name) 220 | } else { 221 | logger.V(4).Info("Persistentvolume saved", "persistentvolume", volume.Name) 222 | } 223 | return true, nil 224 | } 225 | // Save failed, try again after a while. 226 | logger.Info("Failed to save persistentvolume", "persistentvolume", volume.Name, "err", err) 227 | lastSaveError = err 228 | return false, nil 229 | }) 230 | 231 | if err == nil { 232 | // Save succeeded 233 | msg := fmt.Sprintf("Successfully provisioned volume %s", volume.Name) 234 | b.eventRecorder.Event(claim, v1.EventTypeNormal, "ProvisioningSucceeded", msg) 235 | return nil 236 | } 237 | 238 | // Save failed. Now we have a storage asset outside of Kubernetes, 239 | // but we don't have appropriate PV object for it. 240 | // Emit some event here and try to delete the storage asset several 241 | // times. 242 | logger.Error(lastSaveError, "Error creating provisioned PV object for claim. Deleting the volume.", "claim", klog.KObj(claim)) 243 | strerr := fmt.Sprintf("Error creating provisioned PV object for claim %s: %v. Deleting the volume.", klog.KObj(claim), lastSaveError) 244 | b.eventRecorder.Event(claim, v1.EventTypeWarning, "ProvisioningFailed", strerr) 245 | 246 | var lastDeleteError error 247 | err = wait.ExponentialBackoff(*b.backoff, func() (bool, error) { 248 | if err = b.ctrl.provisioner.Delete(context.Background(), volume); err == nil { 249 | // Delete succeeded 250 | logger.V(4).Info("Cleaning volume succeeded", "volume", volume.Name) 251 | return true, nil 252 | } 253 | // Delete failed, try again after a while. 254 | logger.Info("Failed to clean volume", "volume", volume.Name, "err", err) 255 | lastDeleteError = err 256 | return false, nil 257 | }) 258 | if err != nil { 259 | // Delete failed several times. There is an orphaned volume and there 260 | // is nothing we can do about it. 261 | logger.Error(lastSaveError, "Error cleaning provisioned volume for claim. Please delete manually.", "claim", klog.KObj(claim)) 262 | strerr := fmt.Sprintf("Error cleaning provisioned volume for claim %s: %v. Please delete manually.", klog.KObj(claim), lastDeleteError) 263 | b.eventRecorder.Event(claim, v1.EventTypeWarning, "ProvisioningCleanupFailed", strerr) 264 | } 265 | 266 | return lastSaveError 267 | } 268 | 269 | func (b *backoffStore) Run(ctx context.Context, threadiness int) { 270 | // There is not background processing 271 | } 272 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/.dockerignore: -------------------------------------------------------------------------------- 1 | vendor 2 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/.gitignore: -------------------------------------------------------------------------------- 1 | vendor 2 | Gopkg.lock 3 | hostpath-provisioner 4 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/Dockerfile.scratch: -------------------------------------------------------------------------------- 1 | FROM scratch 2 | COPY hostpath-provisioner / 3 | CMD ["/hostpath-provisioner"] 4 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/Makefile: -------------------------------------------------------------------------------- 1 | # Copyright 2016 The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | IMAGE?=hostpath-provisioner 16 | 17 | all: dep hostpath-provisioner image 18 | 19 | dep: 20 | go mod tidy 21 | 22 | hostpath-provisioner: 23 | CGO_ENABLED=0 go build -a -ldflags '-extldflags "-static"' -o hostpath-provisioner . 24 | 25 | image: hostpath-provisioner 26 | docker build -t $(IMAGE) -f Dockerfile.scratch . 27 | 28 | clean: 29 | rm -rf hostpath-provisioner 30 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/README.md: -------------------------------------------------------------------------------- 1 | ```bash 2 | make 3 | ``` 4 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/claim.yaml: -------------------------------------------------------------------------------- 1 | kind: PersistentVolumeClaim 2 | apiVersion: v1 3 | metadata: 4 | name: hostpath-pvc 5 | spec: 6 | storageClassName: "example-hostpath" 7 | accessModes: 8 | - ReadWriteMany 9 | resources: 10 | requests: 11 | storage: 1Mi 12 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/class.yaml: -------------------------------------------------------------------------------- 1 | kind: StorageClass 2 | apiVersion: storage.k8s.io/v1 3 | metadata: 4 | name: example-hostpath 5 | provisioner: example.com/hostpath 6 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/kubernetes-sigs/sig-storage-lib-external-provisioner/examples/hostpath-provisioner 2 | 3 | go 1.22.0 4 | 5 | toolchain go1.22.2 6 | 7 | require ( 8 | k8s.io/api v0.30.0 9 | k8s.io/apimachinery v0.30.0 10 | k8s.io/client-go v0.30.0 11 | k8s.io/klog/v2 v2.120.1 12 | sigs.k8s.io/sig-storage-lib-external-provisioner/v10 v10.0.1 13 | ) 14 | 15 | require ( 16 | github.com/beorn7/perks v1.0.1 // indirect 17 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 18 | github.com/davecgh/go-spew v1.1.1 // indirect 19 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 20 | github.com/go-logr/logr v1.4.1 // indirect 21 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 22 | github.com/go-openapi/jsonreference v0.20.2 // indirect 23 | github.com/go-openapi/swag v0.22.3 // indirect 24 | github.com/gogo/protobuf v1.3.2 // indirect 25 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 26 | github.com/golang/protobuf v1.5.4 // indirect 27 | github.com/google/gnostic-models v0.6.8 // indirect 28 | github.com/google/go-cmp v0.6.0 // indirect 29 | github.com/google/gofuzz v1.2.0 // indirect 30 | github.com/google/uuid v1.3.0 // indirect 31 | github.com/josharian/intern v1.0.0 // indirect 32 | github.com/json-iterator/go v1.1.12 // indirect 33 | github.com/mailru/easyjson v0.7.7 // indirect 34 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 35 | github.com/miekg/dns v1.1.29 // indirect 36 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 37 | github.com/modern-go/reflect2 v1.0.2 // indirect 38 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 39 | github.com/prometheus/client_golang v1.5.1 // indirect 40 | github.com/prometheus/client_model v0.2.0 // indirect 41 | github.com/prometheus/common v0.9.1 // indirect 42 | github.com/prometheus/procfs v0.0.8 // indirect 43 | golang.org/x/crypto v0.21.0 // indirect 44 | golang.org/x/net v0.23.0 // indirect 45 | golang.org/x/oauth2 v0.10.0 // indirect 46 | golang.org/x/sys v0.18.0 // indirect 47 | golang.org/x/term v0.18.0 // indirect 48 | golang.org/x/text v0.14.0 // indirect 49 | golang.org/x/time v0.3.0 // indirect 50 | google.golang.org/appengine v1.6.7 // indirect 51 | google.golang.org/protobuf v1.33.0 // indirect 52 | gopkg.in/inf.v0 v0.9.1 // indirect 53 | gopkg.in/yaml.v2 v2.4.0 // indirect 54 | gopkg.in/yaml.v3 v3.0.1 // indirect 55 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect 56 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 57 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 58 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 59 | sigs.k8s.io/yaml v1.3.0 // indirect 60 | ) 61 | 62 | replace sigs.k8s.io/sig-storage-lib-external-provisioner/v10 => ../.. 63 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 2 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 3 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 4 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 5 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 6 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 7 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 8 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 9 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 10 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 11 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 12 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 14 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 15 | github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= 16 | github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 17 | github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= 18 | github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 19 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 20 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 21 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 22 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 23 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 24 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 25 | github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= 26 | github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 27 | github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 28 | github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 29 | github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= 30 | github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 31 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 32 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 33 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 34 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 35 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 36 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 37 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 38 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 39 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 40 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 41 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 42 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 43 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 44 | github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= 45 | github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= 46 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 47 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 49 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 50 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 51 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 52 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 53 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 54 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= 55 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 56 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 57 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 58 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 59 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 60 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 61 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 62 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 63 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 64 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 65 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 66 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 67 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 68 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 69 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 70 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 71 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 72 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 73 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 74 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 75 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 76 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 77 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 78 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 79 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 80 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 81 | github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= 82 | github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 83 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 84 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 85 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 86 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 87 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 88 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 89 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 90 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 91 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 92 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 93 | github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= 94 | github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= 95 | github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= 96 | github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= 97 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 98 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 99 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 100 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 101 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 102 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 103 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 104 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 105 | github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= 106 | github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 107 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 108 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 109 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 110 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 111 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 112 | github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= 113 | github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 114 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 115 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 116 | github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= 117 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 118 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 119 | github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 120 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 121 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 122 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 123 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 124 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 125 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 126 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 127 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 128 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 129 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 130 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 131 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 132 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 133 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 134 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 135 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 136 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 137 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 138 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 139 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 140 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 141 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 142 | golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= 143 | golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= 144 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 145 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 146 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 147 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 148 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 149 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 150 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 151 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 152 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 153 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 154 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 155 | golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= 156 | golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 157 | golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= 158 | golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= 159 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 160 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 161 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 162 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 163 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 164 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= 165 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 166 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 167 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 168 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 169 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 170 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 171 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 172 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 173 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 174 | golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= 175 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 176 | golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= 177 | golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= 178 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 179 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 180 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 181 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 182 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 183 | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 184 | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 185 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 186 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 187 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 188 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 189 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 190 | golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= 191 | golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= 192 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 193 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 194 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 195 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 196 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 197 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 198 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 199 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 200 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 201 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 202 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 203 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 204 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 205 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 206 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 207 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 208 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 209 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 210 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 211 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 212 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 213 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 214 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 215 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 216 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 217 | k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= 218 | k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= 219 | k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= 220 | k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= 221 | k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= 222 | k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= 223 | k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= 224 | k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 225 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= 226 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= 227 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= 228 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 229 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= 230 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 231 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= 232 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= 233 | sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= 234 | sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 235 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/hostpath-provisioner.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "context" 21 | "errors" 22 | "flag" 23 | "os" 24 | "path" 25 | "syscall" 26 | 27 | "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/controller" 28 | 29 | v1 "k8s.io/api/core/v1" 30 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 31 | "k8s.io/client-go/kubernetes" 32 | "k8s.io/client-go/rest" 33 | klog "k8s.io/klog/v2" 34 | ) 35 | 36 | const ( 37 | provisionerName = "example.com/hostpath" 38 | ) 39 | 40 | type hostPathProvisioner struct { 41 | // The directory to create PV-backing directories in 42 | pvDir string 43 | 44 | // Identity of this hostPathProvisioner, set to node's name. Used to identify 45 | // "this" provisioner's PVs. 46 | identity string 47 | } 48 | 49 | // NewHostPathProvisioner creates a new hostpath provisioner 50 | func NewHostPathProvisioner(ctx context.Context) controller.Provisioner { 51 | nodeName := os.Getenv("NODE_NAME") 52 | if nodeName == "" { 53 | klog.FromContext(ctx).Error(nil, "env variable NODE_NAME must be set so that this provisioner can identify itself") 54 | } 55 | return &hostPathProvisioner{ 56 | pvDir: "/tmp/hostpath-provisioner", 57 | identity: nodeName, 58 | } 59 | } 60 | 61 | var _ controller.Provisioner = &hostPathProvisioner{} 62 | 63 | // Provision creates a storage asset and returns a PV object representing it. 64 | func (p *hostPathProvisioner) Provision(ctx context.Context, options controller.ProvisionOptions) (*v1.PersistentVolume, controller.ProvisioningState, error) { 65 | path := path.Join(p.pvDir, options.PVName) 66 | 67 | if err := os.MkdirAll(path, 0777); err != nil { 68 | return nil, controller.ProvisioningFinished, err 69 | } 70 | 71 | pv := &v1.PersistentVolume{ 72 | ObjectMeta: metav1.ObjectMeta{ 73 | Name: options.PVName, 74 | Annotations: map[string]string{ 75 | "hostPathProvisionerIdentity": p.identity, 76 | }, 77 | }, 78 | Spec: v1.PersistentVolumeSpec{ 79 | PersistentVolumeReclaimPolicy: *options.StorageClass.ReclaimPolicy, 80 | AccessModes: options.PVC.Spec.AccessModes, 81 | Capacity: v1.ResourceList{ 82 | v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)], 83 | }, 84 | PersistentVolumeSource: v1.PersistentVolumeSource{ 85 | HostPath: &v1.HostPathVolumeSource{ 86 | Path: path, 87 | }, 88 | }, 89 | }, 90 | } 91 | 92 | return pv, controller.ProvisioningFinished, nil 93 | } 94 | 95 | // Delete removes the storage asset that was created by Provision represented 96 | // by the given PV. 97 | func (p *hostPathProvisioner) Delete(ctx context.Context, volume *v1.PersistentVolume) error { 98 | ann, ok := volume.Annotations["hostPathProvisionerIdentity"] 99 | if !ok { 100 | return errors.New("identity annotation not found on PV") 101 | } 102 | if ann != p.identity { 103 | return &controller.IgnoredError{Reason: "identity annotation on PV does not match ours"} 104 | } 105 | 106 | path := path.Join(p.pvDir, volume.Name) 107 | if err := os.RemoveAll(path); err != nil { 108 | return err 109 | } 110 | 111 | return nil 112 | } 113 | 114 | func main() { 115 | syscall.Umask(0) 116 | 117 | flag.Parse() 118 | flag.Set("logtostderr", "true") 119 | 120 | ctx := context.Background() 121 | logger := klog.FromContext(ctx) 122 | 123 | // Create an InClusterConfig and use it to create a client for the controller 124 | // to use to communicate with Kubernetes 125 | config, err := rest.InClusterConfig() 126 | if err != nil { 127 | logger.Error(err, "Failed to create config") 128 | } 129 | clientset, err := kubernetes.NewForConfig(config) 130 | if err != nil { 131 | logger.Error(err, "Failed to create client") 132 | } 133 | 134 | // Create the provisioner: it implements the Provisioner interface expected by 135 | // the controller 136 | hostPathProvisioner := NewHostPathProvisioner(ctx) 137 | 138 | // Start the provision controller which will dynamically provision hostPath 139 | // PVs 140 | pc := controller.NewProvisionController(ctx, clientset, provisionerName, hostPathProvisioner) 141 | 142 | // Never stops. 143 | pc.Run(context.Background()) 144 | } 145 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/pod.yaml: -------------------------------------------------------------------------------- 1 | kind: Pod 2 | apiVersion: v1 3 | metadata: 4 | name: hostpath-provisioner 5 | spec: 6 | containers: 7 | - name: hostpath-provisioner 8 | image: hostpath-provisioner:latest 9 | imagePullPolicy: "IfNotPresent" 10 | env: 11 | - name: NODE_NAME 12 | valueFrom: 13 | fieldRef: 14 | fieldPath: spec.nodeName 15 | volumeMounts: 16 | - name: pv-volume 17 | mountPath: /tmp/hostpath-provisioner 18 | serviceAccountName: hostpath-provisioner 19 | volumes: 20 | - name: pv-volume 21 | hostPath: 22 | path: /tmp/hostpath-provisioner 23 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/rbac.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: hostpath-provisioner 5 | --- 6 | kind: ClusterRole 7 | apiVersion: rbac.authorization.k8s.io/v1 8 | metadata: 9 | name: hostpath-provisioner 10 | rules: 11 | - apiGroups: [""] 12 | resources: ["persistentvolumes"] 13 | verbs: ["get", "list", "watch", "create", "patch", "delete"] 14 | - apiGroups: [""] 15 | resources: ["persistentvolumeclaims"] 16 | verbs: ["get", "list", "watch"] 17 | - apiGroups: ["storage.k8s.io"] 18 | resources: ["storageclasses"] 19 | verbs: ["get", "list", "watch"] 20 | - apiGroups: [""] 21 | resources: ["events"] 22 | verbs: ["create", "update", "patch"] 23 | --- 24 | kind: ClusterRoleBinding 25 | apiVersion: rbac.authorization.k8s.io/v1 26 | metadata: 27 | name: hostpath-provisioner 28 | subjects: 29 | - kind: ServiceAccount 30 | name: hostpath-provisioner 31 | namespace: default 32 | roleRef: 33 | kind: ClusterRole 34 | name: hostpath-provisioner 35 | apiGroup: rbac.authorization.k8s.io 36 | --- 37 | kind: Role 38 | apiVersion: rbac.authorization.k8s.io/v1 39 | metadata: 40 | name: leader-locking-hostpath-provisioner 41 | rules: 42 | - apiGroups: [""] 43 | resources: ["endpoints"] 44 | verbs: ["get", "update", "patch"] 45 | - apiGroups: [""] 46 | resources: ["endpoints"] 47 | verbs: ["list", "watch", "create"] 48 | --- 49 | kind: RoleBinding 50 | apiVersion: rbac.authorization.k8s.io/v1 51 | metadata: 52 | name: leader-locking-hostpath-provisioner 53 | subjects: 54 | - kind: ServiceAccount 55 | name: hostpath-provisioner 56 | namespace: default 57 | roleRef: 58 | kind: Role 59 | name: leader-locking-hostpath-provisioner 60 | apiGroup: rbac.authorization.k8s.io 61 | -------------------------------------------------------------------------------- /examples/hostpath-provisioner/test-pod.yaml: -------------------------------------------------------------------------------- 1 | kind: Pod 2 | apiVersion: v1 3 | metadata: 4 | name: test-pod 5 | spec: 6 | containers: 7 | - name: test-pod 8 | image: gcr.io/google_containers/busybox:1.24 9 | command: 10 | - "/bin/sh" 11 | args: 12 | - "-c" 13 | - "touch /mnt/SUCCESS && exit 0 || exit 1" 14 | volumeMounts: 15 | - name: hostpath-pvc 16 | mountPath: "/mnt" 17 | restartPolicy: "Never" 18 | volumes: 19 | - name: hostpath-pvc 20 | persistentVolumeClaim: 21 | claimName: hostpath-pvc 22 | -------------------------------------------------------------------------------- /gidallocator/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package gidallocator // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/gidallocator" 18 | -------------------------------------------------------------------------------- /gidallocator/gidallocator.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package gidallocator 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "math" 23 | "strconv" 24 | "strings" 25 | "sync" 26 | 27 | v1 "k8s.io/api/core/v1" 28 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 | "k8s.io/client-go/kubernetes" 30 | klog "k8s.io/klog/v2" 31 | "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/allocator" 32 | "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/controller" 33 | "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/util" 34 | ) 35 | 36 | const ( 37 | // VolumeGidAnnotationKey is the key of the annotation on the PersistentVolume 38 | // object that specifies a supplemental GID. 39 | VolumeGidAnnotationKey = "pv.beta.kubernetes.io/gid" 40 | 41 | defaultGidMin = 2000 42 | defaultGidMax = math.MaxInt32 43 | // absoluteGidMin/Max are currently the same as the 44 | // default values, but they play a different role and 45 | // could take a different value. Only thing we need is: 46 | // absGidMin <= defGidMin <= defGidMax <= absGidMax 47 | absoluteGidMin = 2000 48 | absoluteGidMax = math.MaxInt32 49 | ) 50 | 51 | // Allocator allocates GIDs to PVs. It allocates from per-SC ranges and ensures 52 | // that no two PVs of the same SC get the same GID. 53 | type Allocator struct { 54 | client kubernetes.Interface 55 | gidTable map[string]*allocator.MinMaxAllocator 56 | gidTableLock sync.Mutex 57 | } 58 | 59 | // New creates a new GID Allocator 60 | func New(client kubernetes.Interface) Allocator { 61 | return Allocator{ 62 | client: client, 63 | gidTable: make(map[string]*allocator.MinMaxAllocator), 64 | } 65 | } 66 | 67 | // AllocateNext allocates the next available GID for the given ProvisionOptions 68 | // (claim's options for a volume it wants) from the appropriate GID table. 69 | func (a *Allocator) AllocateNext(logger klog.Logger, options controller.ProvisionOptions) (int, error) { 70 | class := util.GetPersistentVolumeClaimClass(options.PVC) 71 | gidMin, gidMax, err := parseClassParameters(options.StorageClass.Parameters) 72 | if err != nil { 73 | return 0, err 74 | } 75 | 76 | gidTable, err := a.getGidTable(logger, class, gidMin, gidMax) 77 | if err != nil { 78 | return 0, fmt.Errorf("failed to get gidTable: %v", err) 79 | } 80 | 81 | gid, _, err := gidTable.AllocateNext() 82 | if err != nil { 83 | return 0, fmt.Errorf("failed to reserve gid from table: %v", err) 84 | } 85 | 86 | return gid, nil 87 | } 88 | 89 | // Release releases the given volume's allocated GID from the appropriate GID 90 | // table. 91 | func (a *Allocator) Release(logger klog.Logger, volume *v1.PersistentVolume) error { 92 | class, err := a.client.StorageV1().StorageClasses().Get(context.Background(), util.GetPersistentVolumeClass(volume), metav1.GetOptions{}) 93 | gidMin, gidMax, err := parseClassParameters(class.Parameters) 94 | if err != nil { 95 | return err 96 | } 97 | 98 | gid, exists, err := getGid(volume) 99 | if err != nil { 100 | logger.Error(err, "Failed to get gid from volume") 101 | } else if exists { 102 | gidTable, err := a.getGidTable(logger, class.Name, gidMin, gidMax) 103 | if err != nil { 104 | return fmt.Errorf("failed to get gidTable: %v", err) 105 | } 106 | 107 | err = gidTable.Release(gid) 108 | if err != nil { 109 | return fmt.Errorf("failed to release gid %v: %v", gid, err) 110 | } 111 | } 112 | 113 | return nil 114 | } 115 | 116 | // Return the gid table for a storage class. 117 | // - If this is the first time, fill it with all the gids 118 | // used in PVs of this storage class by traversing the PVs. 119 | // - Adapt the range of the table to the current range of the SC. 120 | func (a *Allocator) getGidTable(logger klog.Logger, className string, min int, max int) (*allocator.MinMaxAllocator, error) { 121 | var err error 122 | a.gidTableLock.Lock() 123 | gidTable, ok := a.gidTable[className] 124 | a.gidTableLock.Unlock() 125 | 126 | if ok { 127 | err = gidTable.SetRange(min, max) 128 | if err != nil { 129 | return nil, err 130 | } 131 | 132 | return gidTable, nil 133 | } 134 | 135 | // create a new table and fill it 136 | newGidTable, err := allocator.NewMinMaxAllocator(0, absoluteGidMax) 137 | if err != nil { 138 | return nil, err 139 | } 140 | 141 | // collect gids with the full range 142 | err = a.collectGids(logger, className, newGidTable) 143 | if err != nil { 144 | return nil, err 145 | } 146 | 147 | // and only reduce the range afterwards 148 | err = newGidTable.SetRange(min, max) 149 | if err != nil { 150 | return nil, err 151 | } 152 | 153 | // if in the meantime a table appeared, use it 154 | 155 | a.gidTableLock.Lock() 156 | defer a.gidTableLock.Unlock() 157 | 158 | gidTable, ok = a.gidTable[className] 159 | if ok { 160 | err = gidTable.SetRange(min, max) 161 | if err != nil { 162 | return nil, err 163 | } 164 | 165 | return gidTable, nil 166 | } 167 | 168 | a.gidTable[className] = newGidTable 169 | 170 | return newGidTable, nil 171 | } 172 | 173 | // Traverse the PVs, fetching all the GIDs from those 174 | // in a given storage class, and mark them in the table. 175 | func (a *Allocator) collectGids(logger klog.Logger, className string, gidTable *allocator.MinMaxAllocator) error { 176 | pvList, err := a.client.CoreV1().PersistentVolumes().List(context.Background(), metav1.ListOptions{}) 177 | if err != nil { 178 | logger.Error(err, "Failed to get existing persistent volumes") 179 | return err 180 | } 181 | 182 | for _, pv := range pvList.Items { 183 | if util.GetPersistentVolumeClass(&pv) != className { 184 | continue 185 | } 186 | 187 | pvName := pv.ObjectMeta.Name 188 | 189 | gidStr, ok := pv.Annotations[VolumeGidAnnotationKey] 190 | 191 | if !ok { 192 | logger.Info("No gid found", "pv", pvName) 193 | continue 194 | } 195 | 196 | gid, err := convertGid(gidStr) 197 | if err != nil { 198 | logger.Error(err, "Failed to convert gid", "pv", pvName) 199 | continue 200 | } 201 | 202 | _, err = gidTable.Allocate(gid) 203 | if err == allocator.ErrConflict { 204 | logger.Info("gid was already allocated", "gid", gid, "pv", pvName) 205 | } else if err != nil { 206 | logger.Error(err, "Failed to store gid", "gid", gid, "pv", pvName) 207 | return err 208 | } 209 | } 210 | 211 | return nil 212 | } 213 | 214 | func parseClassParameters(params map[string]string) (int, int, error) { 215 | gidMin := defaultGidMin 216 | gidMax := defaultGidMax 217 | 218 | for k, v := range params { 219 | switch strings.ToLower(k) { 220 | case "gidmin": 221 | parseGidMin, err := convertGid(v) 222 | if err != nil { 223 | return 0, 0, fmt.Errorf("invalid value %s for parameter %s: %v", v, k, err) 224 | } 225 | if parseGidMin < absoluteGidMin { 226 | return 0, 0, fmt.Errorf("gidMin must be >= %v", absoluteGidMin) 227 | } 228 | if parseGidMin > absoluteGidMax { 229 | return 0, 0, fmt.Errorf("gidMin must be <= %v", absoluteGidMax) 230 | } 231 | gidMin = parseGidMin 232 | case "gidmax": 233 | parseGidMax, err := convertGid(v) 234 | if err != nil { 235 | return 0, 0, fmt.Errorf("invalid value %s for parameter %s: %v", v, k, err) 236 | } 237 | if parseGidMax < absoluteGidMin { 238 | return 0, 0, fmt.Errorf("gidMax must be >= %v", absoluteGidMin) 239 | } 240 | if parseGidMax > absoluteGidMax { 241 | return 0, 0, fmt.Errorf("gidMax must be <= %v", absoluteGidMax) 242 | } 243 | gidMax = parseGidMax 244 | } 245 | } 246 | 247 | if gidMin > gidMax { 248 | return 0, 0, fmt.Errorf("gidMax %v is not >= gidMin %v", gidMax, gidMin) 249 | } 250 | 251 | return gidMin, gidMax, nil 252 | } 253 | 254 | func getGid(volume *v1.PersistentVolume) (int, bool, error) { 255 | gidStr, ok := volume.Annotations[VolumeGidAnnotationKey] 256 | 257 | if !ok { 258 | return 0, false, nil 259 | } 260 | 261 | gid, err := convertGid(gidStr) 262 | 263 | return gid, true, err 264 | } 265 | 266 | func convertGid(gidString string) (int, error) { 267 | gid64, err := strconv.ParseInt(gidString, 10, 32) 268 | if err != nil { 269 | return 0, fmt.Errorf("failed to parse gid %v ", gidString) 270 | } 271 | 272 | if gid64 < 0 { 273 | return 0, fmt.Errorf("negative GIDs are not allowed: %v", gidString) 274 | } 275 | 276 | // ParseInt returns a int64, but since we parsed only 277 | // for 32 bit, we can cast to int without loss: 278 | gid := int(gid64) 279 | return gid, nil 280 | } 281 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module sigs.k8s.io/sig-storage-lib-external-provisioner/v11 2 | 3 | go 1.22.0 4 | 5 | toolchain go1.22.2 6 | 7 | require ( 8 | github.com/miekg/dns v1.1.29 9 | github.com/prometheus/client_golang v1.5.1 10 | github.com/prometheus/client_model v0.2.0 11 | golang.org/x/time v0.3.0 12 | k8s.io/api v0.30.0 13 | k8s.io/apimachinery v0.30.0 14 | k8s.io/client-go v0.30.0 15 | k8s.io/klog/v2 v2.120.1 16 | ) 17 | 18 | require ( 19 | github.com/beorn7/perks v1.0.1 // indirect 20 | github.com/cespare/xxhash/v2 v2.1.1 // indirect 21 | github.com/davecgh/go-spew v1.1.1 // indirect 22 | github.com/emicklei/go-restful/v3 v3.11.0 // indirect 23 | github.com/evanphx/json-patch v5.6.0+incompatible // indirect 24 | github.com/go-logr/logr v1.4.1 // indirect 25 | github.com/go-openapi/jsonpointer v0.19.6 // indirect 26 | github.com/go-openapi/jsonreference v0.20.2 // indirect 27 | github.com/go-openapi/swag v0.22.3 // indirect 28 | github.com/gogo/protobuf v1.3.2 // indirect 29 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 30 | github.com/golang/protobuf v1.5.4 // indirect 31 | github.com/google/gnostic-models v0.6.8 // indirect 32 | github.com/google/go-cmp v0.6.0 // indirect 33 | github.com/google/gofuzz v1.2.0 // indirect 34 | github.com/google/uuid v1.3.0 // indirect 35 | github.com/josharian/intern v1.0.0 // indirect 36 | github.com/json-iterator/go v1.1.12 // indirect 37 | github.com/mailru/easyjson v0.7.7 // indirect 38 | github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect 39 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect 40 | github.com/modern-go/reflect2 v1.0.2 // indirect 41 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect 42 | github.com/pkg/errors v0.9.1 // indirect 43 | github.com/prometheus/common v0.9.1 // indirect 44 | github.com/prometheus/procfs v0.0.8 // indirect 45 | golang.org/x/crypto v0.21.0 // indirect 46 | golang.org/x/net v0.23.0 // indirect 47 | golang.org/x/oauth2 v0.10.0 // indirect 48 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect 49 | golang.org/x/sys v0.18.0 // indirect 50 | golang.org/x/term v0.18.0 // indirect 51 | golang.org/x/text v0.14.0 // indirect 52 | google.golang.org/appengine v1.6.7 // indirect 53 | google.golang.org/protobuf v1.33.0 // indirect 54 | gopkg.in/inf.v0 v0.9.1 // indirect 55 | gopkg.in/yaml.v2 v2.4.0 // indirect 56 | gopkg.in/yaml.v3 v3.0.1 // indirect 57 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect 58 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect 59 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect 60 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect 61 | sigs.k8s.io/yaml v1.3.0 // indirect 62 | ) 63 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 2 | github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= 3 | github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 4 | github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= 5 | github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= 6 | github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= 7 | github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= 8 | github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= 9 | github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= 10 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 11 | github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= 12 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 13 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 14 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 15 | github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= 16 | github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= 17 | github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= 18 | github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= 19 | github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 20 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 21 | github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= 22 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 23 | github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= 24 | github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= 25 | github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= 26 | github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= 27 | github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= 28 | github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= 29 | github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= 30 | github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= 31 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 32 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 33 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 34 | github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= 35 | github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= 36 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 37 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= 38 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= 39 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 40 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 41 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 42 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 43 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 44 | github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= 45 | github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= 46 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 47 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 48 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 49 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 50 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 51 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 52 | github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= 53 | github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 54 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= 55 | github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= 56 | github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= 57 | github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 58 | github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= 59 | github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= 60 | github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= 61 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 62 | github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= 63 | github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= 64 | github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= 65 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 66 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 67 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 68 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 69 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 70 | github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= 71 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 72 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= 73 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 74 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 75 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= 76 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 77 | github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= 78 | github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= 79 | github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= 80 | github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= 81 | github.com/miekg/dns v1.1.29 h1:xHBEhR+t5RzcFJjBLJlax2daXOrTYtr9z4WdKEfWFzg= 82 | github.com/miekg/dns v1.1.29/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM= 83 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 84 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= 85 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 86 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 87 | github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 88 | github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= 89 | github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= 90 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= 91 | github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= 92 | github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= 93 | github.com/onsi/ginkgo/v2 v2.15.0 h1:79HwNRBAZHOEwrczrgSOPy+eFTTlIGELKy5as+ClttY= 94 | github.com/onsi/ginkgo/v2 v2.15.0/go.mod h1:HlxMHtYF57y6Dpf+mc5529KKmSq9h2FpCF+/ZkwUxKM= 95 | github.com/onsi/gomega v1.31.0 h1:54UJxxj6cPInHS3a35wm6BK/F9nHYueZ1NVujHDrnXE= 96 | github.com/onsi/gomega v1.31.0/go.mod h1:DW9aCi7U6Yi40wNVAvT6kzFnEVEI5n3DloYBiKiT6zk= 97 | github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 98 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 99 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 100 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 101 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 102 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 103 | github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= 104 | github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= 105 | github.com/prometheus/client_golang v1.5.1 h1:bdHYieyGlH+6OLEk2YQha8THib30KP0/yD0YH9m6xcA= 106 | github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= 107 | github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= 108 | github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 109 | github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= 110 | github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 111 | github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= 112 | github.com/prometheus/common v0.9.1 h1:KOMtN28tlbam3/7ZKEYKHhKoJZYYj3gMH4uc62x7X7U= 113 | github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= 114 | github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= 115 | github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= 116 | github.com/prometheus/procfs v0.0.8 h1:+fpWZdT24pJBiqJdAwYBjPSk+5YmQzYNPYzQsdzLkt8= 117 | github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= 118 | github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= 119 | github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= 120 | github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= 121 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 122 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= 123 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= 124 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 125 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 126 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= 127 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 128 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 129 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 130 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 131 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 132 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= 133 | github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= 134 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= 135 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= 136 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 137 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 138 | golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= 139 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 140 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 141 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 142 | golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= 143 | golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= 144 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= 145 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 146 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 147 | golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 148 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 149 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= 150 | golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 151 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 152 | golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 153 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 154 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 155 | golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= 156 | golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= 157 | golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8= 158 | golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI= 159 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 160 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 161 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 162 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 163 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 164 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= 165 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 166 | golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 167 | golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 168 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 169 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 170 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 171 | golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 172 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 173 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 174 | golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= 175 | golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 176 | golang.org/x/term v0.18.0 h1:FcHjZXDMxI8mM3nwhX9HlKop4C0YQvCVCdwYl2wOtE8= 177 | golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58= 178 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 179 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 180 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 181 | golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= 182 | golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= 183 | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 184 | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 185 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 186 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 187 | golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= 188 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 189 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 190 | golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ= 191 | golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg= 192 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 193 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 194 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 195 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 196 | google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= 197 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= 198 | google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= 199 | google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 200 | gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= 201 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 202 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 203 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= 204 | gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= 205 | gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= 206 | gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= 207 | gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 208 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 209 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 210 | gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 211 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 212 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 213 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 214 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 215 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 216 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 217 | k8s.io/api v0.30.0 h1:siWhRq7cNjy2iHssOB9SCGNCl2spiF1dO3dABqZ8niA= 218 | k8s.io/api v0.30.0/go.mod h1:OPlaYhoHs8EQ1ql0R/TsUgaRPhpKNxIMrKQfWUp8QSE= 219 | k8s.io/apimachinery v0.30.0 h1:qxVPsyDM5XS96NIh9Oj6LavoVFYff/Pon9cZeDIkHHA= 220 | k8s.io/apimachinery v0.30.0/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= 221 | k8s.io/client-go v0.30.0 h1:sB1AGGlhY/o7KCyCEQ0bPWzYDL0pwOZO4vAtTSh/gJQ= 222 | k8s.io/client-go v0.30.0/go.mod h1:g7li5O5256qe6TYdAMyX/otJqMhIiGgTapdLchhmOaY= 223 | k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw= 224 | k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= 225 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= 226 | k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= 227 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= 228 | k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= 229 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= 230 | sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= 231 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= 232 | sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= 233 | sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= 234 | sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= 235 | -------------------------------------------------------------------------------- /hack/verify-logcheck.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2024 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This script uses the logcheck tool to analyze the source code 18 | # for proper usage of klog contextual logging. 19 | 20 | set -o errexit 21 | set -o nounset 22 | set -o pipefail 23 | 24 | LOGCHECK_VERSION=${1:-0.8.2} 25 | 26 | # This will canonicalize the path 27 | SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. && pwd -P) 28 | 29 | # Create a temporary directory for installing logcheck and 30 | # set up a trap command to remove it when the script exits. 31 | SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_TEMP=$(mktemp -d 2>/dev/null || mktemp -d -t sig-storage-lib-external-provisioner.XXXXXX) 32 | trap 'rm -rf "${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_TEMP}"' EXIT 33 | 34 | echo "Installing logcheck to temp dir: sigs.k8s.io/logtools/logcheck@v${LOGCHECK_VERSION}" 35 | GOBIN="${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_TEMP}" go install "sigs.k8s.io/logtools/logcheck@v${LOGCHECK_VERSION}" 36 | echo "Verifing logcheck: ${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_TEMP}/logcheck -check-contextual ${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_ROOT}/..." 37 | "${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_TEMP}/logcheck" -check-contextual -check-with-helpers "${SIG_STORAGE_LIB_EXTERNAL_PROVISIONER_ROOT}/..." 38 | -------------------------------------------------------------------------------- /mount/LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | https://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | Copyright 2013-2017 Docker, Inc. 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | https://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. 192 | -------------------------------------------------------------------------------- /mount/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mount // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/mount" 18 | -------------------------------------------------------------------------------- /mount/mount.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mount 18 | 19 | // GetMounts retrieves a list of mounts for the current running process. 20 | func GetMounts() ([]*Info, error) { 21 | return parseMountTable() 22 | } 23 | -------------------------------------------------------------------------------- /mount/mountinfo.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package mount 18 | 19 | // Info reveals information about a particular mounted filesystem. This 20 | // struct is populated from the content in the /proc//mountinfo file. 21 | type Info struct { 22 | // ID is a unique identifier of the mount (may be reused after umount). 23 | ID int 24 | 25 | // Parent indicates the ID of the mount parent (or of self for the top of the 26 | // mount tree). 27 | Parent int 28 | 29 | // Major indicates one half of the device ID which identifies the device class. 30 | Major int 31 | 32 | // Minor indicates one half of the device ID which identifies a specific 33 | // instance of device. 34 | Minor int 35 | 36 | // Root of the mount within the filesystem. 37 | Root string 38 | 39 | // Mountpoint indicates the mount point relative to the process's root. 40 | Mountpoint string 41 | 42 | // Opts represents mount-specific options. 43 | Opts string 44 | 45 | // Optional represents optional fields. 46 | Optional string 47 | 48 | // Fstype indicates the type of filesystem, such as EXT3. 49 | Fstype string 50 | 51 | // Source indicates filesystem specific information or "none". 52 | Source string 53 | 54 | // VfsOpts represents per super block options. 55 | VfsOpts string 56 | } 57 | -------------------------------------------------------------------------------- /mount/mountinfo_linux.go: -------------------------------------------------------------------------------- 1 | //go:build linux 2 | // +build linux 3 | 4 | /* 5 | Copyright 2018 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package mount 21 | 22 | import ( 23 | "bufio" 24 | "fmt" 25 | "io" 26 | "os" 27 | "strings" 28 | ) 29 | 30 | const ( 31 | /* 36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue 32 | (1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) 33 | 34 | (1) mount ID: unique identifier of the mount (may be reused after umount) 35 | (2) parent ID: ID of parent (or of self for the top of the mount tree) 36 | (3) major:minor: value of st_dev for files on filesystem 37 | (4) root: root of the mount within the filesystem 38 | (5) mount point: mount point relative to the process's root 39 | (6) mount options: per mount options 40 | (7) optional fields: zero or more fields of the form "tag[:value]" 41 | (8) separator: marks the end of the optional fields 42 | (9) filesystem type: name of filesystem of the form "type[.subtype]" 43 | (10) mount source: filesystem specific information or "none" 44 | (11) super options: per super block options*/ 45 | mountinfoFormat = "%d %d %d:%d %s %s %s %s" 46 | ) 47 | 48 | // Parse /proc/self/mountinfo because comparing Dev and ino does not work from 49 | // bind mounts 50 | func parseMountTable() ([]*Info, error) { 51 | f, err := os.Open("/proc/self/mountinfo") 52 | if err != nil { 53 | return nil, err 54 | } 55 | defer f.Close() 56 | 57 | return parseInfoFile(f) 58 | } 59 | 60 | func parseInfoFile(r io.Reader) ([]*Info, error) { 61 | var ( 62 | s = bufio.NewScanner(r) 63 | out = []*Info{} 64 | ) 65 | 66 | for s.Scan() { 67 | if err := s.Err(); err != nil { 68 | return nil, err 69 | } 70 | 71 | var ( 72 | p = &Info{} 73 | text = s.Text() 74 | optionalFields string 75 | ) 76 | 77 | if _, err := fmt.Sscanf(text, mountinfoFormat, 78 | &p.ID, &p.Parent, &p.Major, &p.Minor, 79 | &p.Root, &p.Mountpoint, &p.Opts, &optionalFields); err != nil { 80 | return nil, fmt.Errorf("Scanning '%s' failed: %s", text, err) 81 | } 82 | // Safe as mountinfo encodes mountpoints with spaces as \040. 83 | index := strings.Index(text, " - ") 84 | postSeparatorFields := strings.Fields(text[index+3:]) 85 | if len(postSeparatorFields) < 3 { 86 | return nil, fmt.Errorf("Error found less than 3 fields post '-' in %q", text) 87 | } 88 | 89 | if optionalFields != "-" { 90 | p.Optional = optionalFields 91 | } 92 | 93 | p.Fstype = postSeparatorFields[0] 94 | p.Source = postSeparatorFields[1] 95 | p.VfsOpts = strings.Join(postSeparatorFields[2:], " ") 96 | out = append(out, p) 97 | } 98 | return out, nil 99 | } 100 | 101 | // PidMountInfo collects the mounts for a specific process ID. If the process 102 | // ID is unknown, it is better to use `GetMounts` which will inspect 103 | // "/proc/self/mountinfo" instead. 104 | func PidMountInfo(pid int) ([]*Info, error) { 105 | f, err := os.Open(fmt.Sprintf("/proc/%d/mountinfo", pid)) 106 | if err != nil { 107 | return nil, err 108 | } 109 | defer f.Close() 110 | 111 | return parseInfoFile(f) 112 | } 113 | -------------------------------------------------------------------------------- /mount/mountinfo_unsupported.go: -------------------------------------------------------------------------------- 1 | //go:build (!windows && !linux && !freebsd && !solaris) || (freebsd && !cgo) || (solaris && !cgo) 2 | // +build !windows,!linux,!freebsd,!solaris freebsd,!cgo solaris,!cgo 3 | 4 | /* 5 | Copyright 2018 The Kubernetes Authors. 6 | 7 | Licensed under the Apache License, Version 2.0 (the "License"); 8 | you may not use this file except in compliance with the License. 9 | You may obtain a copy of the License at 10 | 11 | http://www.apache.org/licenses/LICENSE-2.0 12 | 13 | Unless required by applicable law or agreed to in writing, software 14 | distributed under the License is distributed on an "AS IS" BASIS, 15 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | See the License for the specific language governing permissions and 17 | limitations under the License. 18 | */ 19 | 20 | package mount 21 | 22 | import ( 23 | "fmt" 24 | "runtime" 25 | ) 26 | 27 | func parseMountTable() ([]*Info, error) { 28 | return nil, fmt.Errorf("mount.parseMountTable is not implemented on %s/%s", runtime.GOOS, runtime.GOARCH) 29 | } 30 | -------------------------------------------------------------------------------- /repo-infra/verify/README.md: -------------------------------------------------------------------------------- 1 | # Verification scripts 2 | 3 | Collection of scripts that verifies that a project meets requirements set for kubernetes related projects. The scripts are to be invoked depending on the needs via CI tooling, such as Travis CI. See main Readme file on how to integrate the repo-infra in your project. 4 | 5 | The scripts are currently being migrated from the main kubernetes repository. If your project requires additional set of verifications, consider creating an issue/PR on repo-infra to avoid code duplication across multiple projects. 6 | 7 | If repo-infra is integrated at the root of your project as git submodule at path: `/repo-infra`, 8 | then scripts can be invoked as `repo-infra/verify/verify-*.sh` 9 | 10 | travis.yaml example: 11 | 12 | ``` 13 | dist: trusty 14 | 15 | os: 16 | - linux 17 | 18 | language: go 19 | 20 | go: 21 | - 1.22 22 | 23 | script: 24 | - repo-infra/verify/verify-go-src.sh -v 25 | - repo-infra/verify/verify-boilerplate.sh 26 | # OR with vendoring 27 | # - vendor/github.com/kubernetes/repo-infra/verify-go-src.sh --rootdir=$(pwd) -v 28 | ``` 29 | 30 | ## Verify boilerplate 31 | 32 | Verifies that the boilerplate for various formats (go files, Makefile, etc.) is included in each file: `verify-boilerplate.sh`. 33 | 34 | ## Verify go source code 35 | 36 | Runs a set of scripts on the go source code excluding vendored files: `verify-go-src.sh`. 37 | 38 | With git submodule from your repo root: `repo-infra/verify/verify-go-src.sh -v` 39 | 40 | With vendoring: `vendor/repo-infra/verify/verify-go-src.sh -v --rootdir $(pwd)` 41 | 42 | Checks include: 43 | 44 | 1. gofmt 45 | 2. govet 46 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/BUILD.bazel: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | exports_files(glob(["*.txt"])) 4 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.Dockerfile.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.Makefile.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.bzl.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright YEAR The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | from __future__ import print_function 18 | 19 | import argparse 20 | import difflib 21 | import glob 22 | import json 23 | import mmap 24 | import os 25 | import re 26 | import sys 27 | from datetime import date 28 | 29 | parser = argparse.ArgumentParser() 30 | parser.add_argument( 31 | "filenames", 32 | help="list of files to check, all files if unspecified", 33 | nargs='*') 34 | 35 | # Rootdir defaults to the directory **above** the repo-infra dir. 36 | rootdir = os.path.dirname(__file__) + "/../../../" 37 | rootdir = os.path.abspath(rootdir) 38 | parser.add_argument( 39 | "--rootdir", default=rootdir, help="root directory to examine") 40 | 41 | default_boilerplate_dir = os.path.join(rootdir, "repo-infra/verify/boilerplate") 42 | parser.add_argument( 43 | "--boilerplate-dir", default=default_boilerplate_dir) 44 | 45 | parser.add_argument( 46 | "-v", "--verbose", 47 | help="give verbose output regarding why a file does not pass", 48 | action="store_true") 49 | 50 | args = parser.parse_args() 51 | 52 | verbose_out = sys.stderr if args.verbose else open("/dev/null", "w") 53 | 54 | def get_refs(): 55 | refs = {} 56 | 57 | for path in glob.glob(os.path.join(args.boilerplate_dir, "boilerplate.*.txt")): 58 | extension = os.path.basename(path).split(".")[1] 59 | 60 | ref_file = open(path, 'r') 61 | ref = ref_file.read().splitlines() 62 | ref_file.close() 63 | refs[extension] = ref 64 | 65 | return refs 66 | 67 | def file_passes(filename, refs, regexs): 68 | try: 69 | f = open(filename, 'r') 70 | except Exception as exc: 71 | print("Unable to open %s: %s" % (filename, exc), file=verbose_out) 72 | return False 73 | 74 | data = f.read() 75 | f.close() 76 | 77 | basename = os.path.basename(filename) 78 | extension = file_extension(filename) 79 | if extension != "": 80 | ref = refs[extension] 81 | else: 82 | ref = refs[basename] 83 | 84 | # remove build tags from the top of Go files 85 | if extension == "go": 86 | p = regexs["go_build_constraints"] 87 | (data, found) = p.subn("", data, 1) 88 | 89 | # remove shebang from the top of shell files 90 | if extension == "sh" or extension == "py": 91 | p = regexs["shebang"] 92 | (data, found) = p.subn("", data, 1) 93 | 94 | data = data.splitlines() 95 | 96 | # if our test file is smaller than the reference it surely fails! 97 | if len(ref) > len(data): 98 | print('File %s smaller than reference (%d < %d)' % 99 | (filename, len(data), len(ref)), 100 | file=verbose_out) 101 | return False 102 | 103 | # trim our file to the same number of lines as the reference file 104 | data = data[:len(ref)] 105 | 106 | p = regexs["year"] 107 | for d in data: 108 | if p.search(d): 109 | print('File %s is missing the year' % filename, file=verbose_out) 110 | return False 111 | 112 | # Replace all occurrences of the regex "CURRENT_YEAR|...|2016|2015|2014" with "YEAR" 113 | p = regexs["date"] 114 | for i, d in enumerate(data): 115 | (data[i], found) = p.subn('YEAR', d) 116 | if found != 0: 117 | break 118 | 119 | # if we don't match the reference at this point, fail 120 | if ref != data: 121 | print("Header in %s does not match reference, diff:" % filename, file=verbose_out) 122 | if args.verbose: 123 | print(file=verbose_out) 124 | for line in difflib.unified_diff(ref, data, 'reference', filename, lineterm=''): 125 | print(line, file=verbose_out) 126 | print(file=verbose_out) 127 | return False 128 | 129 | return True 130 | 131 | def file_extension(filename): 132 | return os.path.splitext(filename)[1].split(".")[-1].lower() 133 | 134 | skipped_dirs = ['Godeps', 'third_party', '_gopath', '_output', '.git', 135 | 'cluster/env.sh', 'vendor', 'test/e2e/generated/bindata.go', 136 | 'repo-infra/verify/boilerplate/test', '.glide'] 137 | 138 | def normalize_files(files): 139 | newfiles = [] 140 | for pathname in files: 141 | if any(x in pathname for x in skipped_dirs): 142 | continue 143 | newfiles.append(pathname) 144 | for i, pathname in enumerate(newfiles): 145 | if not os.path.isabs(pathname): 146 | newfiles[i] = os.path.join(args.rootdir, pathname) 147 | return newfiles 148 | 149 | def get_files(extensions): 150 | files = [] 151 | if len(args.filenames) > 0: 152 | files = args.filenames 153 | else: 154 | for root, dirs, walkfiles in os.walk(args.rootdir): 155 | # don't visit certain dirs. This is just a performance improvement 156 | # as we would prune these later in normalize_files(). But doing it 157 | # cuts down the amount of filesystem walking we do and cuts down 158 | # the size of the file list 159 | for d in skipped_dirs: 160 | if d in dirs: 161 | dirs.remove(d) 162 | 163 | for name in walkfiles: 164 | pathname = os.path.join(root, name) 165 | files.append(pathname) 166 | 167 | files = normalize_files(files) 168 | 169 | outfiles = [] 170 | for pathname in files: 171 | basename = os.path.basename(pathname) 172 | extension = file_extension(pathname) 173 | if extension in extensions or basename in extensions: 174 | outfiles.append(pathname) 175 | return outfiles 176 | 177 | def get_regexs(): 178 | regexs = {} 179 | # Search for "YEAR" which exists in the boilerplate, but shouldn't in the real thing 180 | regexs["year"] = re.compile( 'YEAR' ) 181 | # dates can be 2014, 2015, 2016, ..., CURRENT_YEAR, company holder names can be anything 182 | years = range(2014, date.today().year + 1) 183 | regexs["date"] = re.compile( '(%s)' % "|".join(map(lambda l: str(l), years)) ) 184 | # strip (//go:build \n\n) and (// +build \n\n) build constraints 185 | regexs["go_build_constraints"] = re.compile(r"^(//(go:| \+)build.*\n)+\n", re.MULTILINE) 186 | # strip #!.* from shell scripts 187 | regexs["shebang"] = re.compile(r"^(#!.*\n)\n*", re.MULTILINE) 188 | return regexs 189 | 190 | def main(): 191 | regexs = get_regexs() 192 | refs = get_refs() 193 | filenames = get_files(refs.keys()) 194 | 195 | for filename in filenames: 196 | if not file_passes(filename, refs, regexs): 197 | print(filename, file=sys.stdout) 198 | 199 | return 0 200 | 201 | if __name__ == "__main__": 202 | sys.exit(main()) 203 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.py.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate.sh.txt: -------------------------------------------------------------------------------- 1 | # Copyright YEAR The Kubernetes Authors. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/boilerplate_test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2016 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import boilerplate 18 | import unittest 19 | try: 20 | import StringIO as io 21 | except: 22 | import io 23 | 24 | import os 25 | import sys 26 | 27 | class TestBoilerplate(unittest.TestCase): 28 | """ 29 | Note: run this test from the hack/boilerplate directory. 30 | 31 | $ python3 -m unittest boilerplate_test 32 | """ 33 | 34 | def test_boilerplate(self): 35 | os.chdir("test/") 36 | 37 | class Args(object): 38 | def __init__(self): 39 | self.filenames = [] 40 | self.rootdir = "." 41 | self.boilerplate_dir = "../" 42 | self.verbose = True 43 | 44 | # capture stdout 45 | old_stdout = sys.stdout 46 | sys.stdout = io.StringIO() 47 | 48 | boilerplate.args = Args() 49 | ret = boilerplate.main() 50 | 51 | output = sorted(sys.stdout.getvalue().split()) 52 | 53 | sys.stdout = old_stdout 54 | 55 | self.assertEqual( 56 | output, ['././fail.go', '././fail.py']) 57 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/test/BUILD.bazel: -------------------------------------------------------------------------------- 1 | package(default_visibility = ["//visibility:public"]) 2 | 3 | licenses(["notice"]) 4 | 5 | load( 6 | "@io_bazel_rules_go//go:def.bzl", 7 | "go_library", 8 | ) 9 | 10 | go_library( 11 | name = "go_default_library", 12 | srcs = [ 13 | "fail.go", 14 | "pass.go", 15 | ], 16 | importpath = "k8s.io/repo-infra/verify/boilerplate/test", 17 | tags = ["automanaged"], 18 | ) 19 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/test/fail.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Kubernetes Authors. 3 | 4 | fail 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); 7 | you may not use this file except in compliance with the License. 8 | You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, 14 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | See the License for the specific language governing permissions and 16 | limitations under the License. 17 | */ 18 | 19 | package test 20 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/test/fail.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # failed 6 | # 7 | # Licensed under the Apache License, Version 2.0 (the "License"); 8 | # you may not use this file except in compliance with the License. 9 | # You may obtain a copy of the License at 10 | # 11 | # http://www.apache.org/licenses/LICENSE-2.0 12 | # 13 | # Unless required by applicable law or agreed to in writing, software 14 | # distributed under the License is distributed on an "AS IS" BASIS, 15 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 | # See the License for the specific language governing permissions and 17 | # limitations under the License. 18 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/test/pass.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2014 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package test 18 | -------------------------------------------------------------------------------- /repo-infra/verify/boilerplate/test/pass.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # Copyright 2015 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | True 18 | -------------------------------------------------------------------------------- /repo-infra/verify/go-tools/verify-gofmt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | find_files() { 21 | find . -not \( \ 22 | \( \ 23 | -wholename '*/vendor/*' \ 24 | \) -prune \ 25 | \) -name '*.go' 26 | } 27 | 28 | GOFMT="gofmt -s" 29 | bad_files=$(find_files | xargs $GOFMT -l) 30 | if [[ -n "${bad_files}" ]]; then 31 | echo "!!! '$GOFMT' needs to be run on the following files: " 32 | echo "${bad_files}" 33 | exit 1 34 | fi 35 | -------------------------------------------------------------------------------- /repo-infra/verify/go-tools/verify-govet.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | go vet -v $(go list ./... | grep -v /vendor/) 21 | -------------------------------------------------------------------------------- /repo-infra/verify/go_install_from_commit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2017 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | PKG=$1 21 | COMMIT=$2 22 | export GOPATH=$3 23 | export GOBIN="$GOPATH/bin" 24 | 25 | go get -d -u "${PKG}" 26 | cd "${GOPATH}/src/${PKG}" 27 | git checkout -q "${COMMIT}" 28 | go install "${PKG}" 29 | -------------------------------------------------------------------------------- /repo-infra/verify/update-bazel.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2016 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | REPOINFRA_ROOT=$(git rev-parse --show-toplevel) 21 | # https://github.com/kubernetes/test-infra/issues/5699#issuecomment-348350792 22 | cd ${REPOINFRA_ROOT} 23 | 24 | OUTPUT_GOBIN="${REPOINFRA_ROOT}/_output/bin" 25 | GOBIN="${OUTPUT_GOBIN}" go install ./vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle 26 | GOBIN="${OUTPUT_GOBIN}" go install ./kazel 27 | 28 | touch "${REPOINFRA_ROOT}/vendor/BUILD.bazel" 29 | 30 | "${OUTPUT_GOBIN}/gazelle" fix \ 31 | -external=vendored \ 32 | -mode=fix 33 | 34 | "${OUTPUT_GOBIN}/kazel" 35 | -------------------------------------------------------------------------------- /repo-infra/verify/verify-bazel.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | # Copyright 2016 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | set -o errexit 17 | set -o nounset 18 | set -o pipefail 19 | 20 | REPOINFRA_ROOT=$(git rev-parse --show-toplevel) 21 | # https://github.com/kubernetes/test-infra/issues/5699#issuecomment-348350792 22 | cd ${REPOINFRA_ROOT} 23 | 24 | OUTPUT_GOBIN="${REPOINFRA_ROOT}/_output/bin" 25 | GOBIN="${OUTPUT_GOBIN}" go install ./vendor/github.com/bazelbuild/bazel-gazelle/cmd/gazelle 26 | GOBIN="${OUTPUT_GOBIN}" go install ./kazel 27 | 28 | touch "${REPOINFRA_ROOT}/vendor/BUILD.bazel" 29 | 30 | gazelle_diff=$("${OUTPUT_GOBIN}/gazelle" fix \ 31 | -external=vendored \ 32 | -mode=diff) 33 | 34 | kazel_diff=$("${OUTPUT_GOBIN}/kazel" \ 35 | -dry-run \ 36 | -print-diff) 37 | 38 | if [[ -n "${gazelle_diff}" || -n "${kazel_diff}" ]]; then 39 | echo "${gazelle_diff}" 40 | echo "${kazel_diff}" 41 | echo 42 | echo "Run ./verify/update-bazel.sh" 43 | exit 1 44 | fi 45 | -------------------------------------------------------------------------------- /repo-infra/verify/verify-boilerplate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2014 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # This script is intended to be used via subtree in a top-level directory: 22 | # / 23 | # repo-infra/ 24 | # verify/ 25 | 26 | REPO_ROOT=$(dirname "${BASH_SOURCE}")/../.. 27 | 28 | boilerDir="${REPO_ROOT}/repo-infra/verify/boilerplate" 29 | boiler="${boilerDir}/boilerplate.py" 30 | 31 | files_need_boilerplate=($(${boiler} "$@")) 32 | 33 | # Run boilerplate.py unit tests 34 | unitTestOut="$(mktemp)" 35 | trap cleanup EXIT 36 | cleanup() { 37 | rm "${unitTestOut}" 38 | } 39 | 40 | pushd "${boilerDir}" >/dev/null 41 | if ! python3 -m unittest boilerplate_test 2>"${unitTestOut}"; then 42 | echo "boilerplate_test.py failed" 43 | echo 44 | cat "${unitTestOut}" 45 | exit 1 46 | fi 47 | popd >/dev/null 48 | 49 | # Run boilerplate check 50 | if [[ ${#files_need_boilerplate[@]} -gt 0 ]]; then 51 | for file in "${files_need_boilerplate[@]}"; do 52 | echo "Boilerplate header is wrong for: ${file}" 53 | done 54 | 55 | exit 1 56 | fi 57 | -------------------------------------------------------------------------------- /repo-infra/verify/verify-errexit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2017 The Kubernetes Authors. 3 | # 4 | # Licensed under the Apache License, Version 2.0 (the "License"); 5 | # you may not use this file except in compliance with the License. 6 | # You may obtain a copy of the License at 7 | # 8 | # http://www.apache.org/licenses/LICENSE-2.0 9 | # 10 | # Unless required by applicable law or agreed to in writing, software 11 | # distributed under the License is distributed on an "AS IS" BASIS, 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | # See the License for the specific language governing permissions and 14 | # limitations under the License. 15 | 16 | # This script will verify that the specified script files have 17 | # "set -o errexit" turned on at some point. 18 | # 19 | # Usage: verify-errexit.sh [ dir | file ... ] 20 | # default args is the root of our source tree 21 | 22 | set -o errexit 23 | set -o nounset 24 | set -o pipefail 25 | 26 | REPO_ROOT=$(dirname "${BASH_SOURCE}")/.. 27 | 28 | if [[ "$*" != "" ]]; then 29 | args="$*" 30 | else 31 | args=$(ls "${REPO_ROOT}" | grep -v vendor | grep -v glide) 32 | fi 33 | 34 | # Gather the list of files that appear to be shell scripts. 35 | # Meaning they have some form of "#!...sh" as a line in them. 36 | shFiles=$(grep -rl '^#!.*sh$' ${args}) 37 | 38 | rc="0" 39 | for file in ${shFiles}; do 40 | grep "set -o errexit" ${file} &> /dev/null && continue 41 | grep "set -[a-z]*e" ${file} &> /dev/null && continue 42 | 43 | echo ${file}: appears to be missing \"set -o errexit\" 44 | rc="1" 45 | done 46 | 47 | exit ${rc} 48 | 49 | -------------------------------------------------------------------------------- /repo-infra/verify/verify-go-src.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2017 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -o errexit 18 | set -o nounset 19 | set -o pipefail 20 | 21 | # This script is intended to be used via subtree in a top-level directory: 22 | # / 23 | # repo-infra/ 24 | # verify/ 25 | # Or via vendoring and passing root directory as vendor/repo-infra/verify-*.sh --rootdir **full path to your repo dir** 26 | # / 27 | # vendor/ 28 | # repo-infra/ 29 | # ... 30 | # 31 | 32 | 33 | SILENT=true 34 | REPO_ROOT=$(dirname "${BASH_SOURCE}")/../.. 35 | 36 | # Convert long opts to short ones to read through getopts 37 | for arg in "$@"; do 38 | shift 39 | case "$arg" in 40 | "--rootdir") set -- "$@" "-r";; 41 | *) 42 | set -- "$@" "$arg" 43 | ;; 44 | esac 45 | done 46 | 47 | OPTIND=1 48 | while getopts "vr:" opt; do 49 | case ${opt} in 50 | v) 51 | SILENT=false 52 | ;; 53 | r) 54 | REPO_ROOT=${OPTARG} 55 | ;; 56 | \?) 57 | echo "Invalid flag: -${OPTARG}" >&2 58 | exit 1 59 | ;; 60 | esac 61 | done 62 | 63 | shift "$(($OPTIND-1))" 64 | 65 | echo "Working directory: ${REPO_ROOT}" 66 | 67 | GO_TOOLS_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/go-tools" 68 | 69 | function run-cmd { 70 | if ${SILENT}; then 71 | "$@" &> /dev/null 72 | else 73 | "$@" 74 | fi 75 | } 76 | 77 | # Some useful colors. 78 | if [[ -z "${color_start-}" ]]; then 79 | declare -r color_start="\033[" 80 | declare -r color_red="${color_start}0;31m" 81 | declare -r color_yellow="${color_start}0;33m" 82 | declare -r color_green="${color_start}0;32m" 83 | declare -r color_norm="${color_start}0m" 84 | fi 85 | 86 | function run-checks { 87 | local -r pattern=$1 88 | local -r runner=$2 89 | 90 | for t in $(ls ${pattern}) 91 | do 92 | echo -e "Verifying ${t}" 93 | local start=$(date +%s) 94 | cd $REPO_ROOT && run-cmd "${runner}" "${t}" && tr=$? || tr=$? 95 | local elapsed=$(($(date +%s) - ${start})) 96 | if [[ ${tr} -eq 0 ]]; then 97 | echo -e "${color_green}SUCCESS${color_norm} ${t}\t${elapsed}s" 98 | else 99 | echo -e "${color_red}FAILED${color_norm} ${t}\t${elapsed}s" 100 | ret=1 101 | fi 102 | done 103 | } 104 | 105 | if ${SILENT} ; then 106 | echo "Running in the silent mode, run with -v if you want to see script logs." 107 | fi 108 | 109 | ret=0 110 | run-checks "${GO_TOOLS_DIR}/*.sh" bash 111 | exit ${ret} 112 | -------------------------------------------------------------------------------- /test/e2e/.gitignore: -------------------------------------------------------------------------------- 1 | kubernetes 2 | -------------------------------------------------------------------------------- /test/e2e/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 The Kubernetes Authors. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -x 18 | PS4='+\t ' 19 | 20 | pushd $GOPATH/src/sigs.k8s.io/sig-storage-lib-external-provisioner/test/e2e 21 | if [ ! -f dind-cluster-v1.13.sh ]; then 22 | wget https://github.com/kubernetes-sigs/kubeadm-dind-cluster/releases/download/v0.1.0/dind-cluster-v1.13.sh 23 | chmod +x dind-cluster-v1.13.sh 24 | fi 25 | ./dind-cluster-v1.13.sh up 26 | 27 | export PATH="$HOME/.kubeadm-dind-cluster:$PATH" 28 | 29 | pushd $GOPATH/src/sigs.k8s.io/sig-storage-lib-external-provisioner/examples/hostpath-provisioner 30 | make image 31 | docker save hostpath-provisioner | docker exec -i kube-node-1 docker load 32 | docker save hostpath-provisioner | docker exec -i kube-node-2 docker load 33 | kubectl create -f ./rbac.yaml 34 | kubectl create -f ./pod.yaml 35 | kubectl create -f ./class.yaml 36 | kubectl create -f ./claim.yaml 37 | kubectl create -f ./test-pod.yaml 38 | timeout 30 bash -c "until kubectl get pod test-pod -o=jsonpath='{.status.phase}' | grep -E 'Succeeded|Failed'; do sleep 1; done" 39 | kubectl describe pod test-pod 40 | kubectl describe pod hostpath-provisioner 41 | kubectl logs hostpath-provisioner 42 | kubectl describe pvc 43 | kubectl describe pv 44 | if [ $? == 0 ] && kubectl get pod test-pod -o=jsonpath='{.status.phase}' | grep -q Succeeded; then 45 | #./dind-cluster-v1.13.sh down 46 | exit 0 47 | fi 48 | #./dind-cluster-v1.13.sh down 49 | exit 1 50 | -------------------------------------------------------------------------------- /util/doc.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2019 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util // import "sigs.k8s.io/sig-storage-lib-external-provisioner/v11/util" 18 | -------------------------------------------------------------------------------- /util/util.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2017 The Kubernetes Authors. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package util 18 | 19 | import ( 20 | "context" 21 | "fmt" 22 | "net" 23 | 24 | "github.com/miekg/dns" 25 | v1 "k8s.io/api/core/v1" 26 | metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 | "k8s.io/client-go/kubernetes" 28 | klog "k8s.io/klog/v2" 29 | ) 30 | 31 | // Common allocation units 32 | const ( 33 | KiB int64 = 1024 34 | MiB int64 = 1024 * KiB 35 | GiB int64 = 1024 * MiB 36 | TiB int64 = 1024 * GiB 37 | ) 38 | 39 | // RoundUpSize calculates how many allocation units are needed to accommodate 40 | // a volume of given size. E.g. when user wants 1500MiB volume, while AWS EBS 41 | // allocates volumes in gibibyte-sized chunks, 42 | // RoundUpSize(1500 * 1024*1024, 1024*1024*1024) returns '2' 43 | // (2 GiB is the smallest allocatable volume that can hold 1500MiB) 44 | func RoundUpSize(volumeSizeBytes int64, allocationUnitBytes int64) int64 { 45 | return (volumeSizeBytes + allocationUnitBytes - 1) / allocationUnitBytes 46 | } 47 | 48 | // RoundUpToGiB rounds up given quantity upto chunks of GiB 49 | func RoundUpToGiB(sizeBytes int64) int64 { 50 | return RoundUpSize(sizeBytes, GiB) 51 | } 52 | 53 | // AccessModesContains returns whether the requested mode is contained by modes 54 | func AccessModesContains(modes []v1.PersistentVolumeAccessMode, mode v1.PersistentVolumeAccessMode) bool { 55 | for _, m := range modes { 56 | if m == mode { 57 | return true 58 | } 59 | } 60 | return false 61 | } 62 | 63 | // AccessModesContainedInAll returns whether all of the requested modes are contained by modes 64 | func AccessModesContainedInAll(indexedModes []v1.PersistentVolumeAccessMode, requestedModes []v1.PersistentVolumeAccessMode) bool { 65 | for _, mode := range requestedModes { 66 | if !AccessModesContains(indexedModes, mode) { 67 | return false 68 | } 69 | } 70 | return true 71 | } 72 | 73 | // GetPersistentVolumeClass returns StorageClassName. 74 | func GetPersistentVolumeClass(volume *v1.PersistentVolume) string { 75 | // Use beta annotation first 76 | if class, found := volume.Annotations[v1.BetaStorageClassAnnotation]; found { 77 | return class 78 | } 79 | 80 | return volume.Spec.StorageClassName 81 | } 82 | 83 | // GetPersistentVolumeClaimClass returns StorageClassName. If no storage class was 84 | // requested, it returns "". 85 | func GetPersistentVolumeClaimClass(claim *v1.PersistentVolumeClaim) string { 86 | // Use beta annotation first 87 | if class, found := claim.Annotations[v1.BetaStorageClassAnnotation]; found { 88 | return class 89 | } 90 | 91 | if claim.Spec.StorageClassName != nil { 92 | return *claim.Spec.StorageClassName 93 | } 94 | 95 | return "" 96 | } 97 | 98 | // CheckPersistentVolumeClaimModeBlock checks VolumeMode. 99 | // If the mode is Block, return true otherwise return false. 100 | func CheckPersistentVolumeClaimModeBlock(pvc *v1.PersistentVolumeClaim) bool { 101 | return pvc.Spec.VolumeMode != nil && *pvc.Spec.VolumeMode == v1.PersistentVolumeBlock 102 | } 103 | 104 | // FindDNSIP looks up the cluster DNS service by label "coredns", falling back to "kube-dns" if not found 105 | func FindDNSIP(ctx context.Context, client kubernetes.Interface) (dnsip string) { 106 | logger := klog.FromContext(ctx) 107 | // find DNS server address through client API 108 | // cache result in rbdProvisioner 109 | var dnssvc *v1.Service 110 | coredns, err := client.CoreV1().Services(metav1.NamespaceSystem).Get(ctx, "coredns", metav1.GetOptions{}) 111 | if err != nil { 112 | logger.Info("Error getting coredns service. Falling back to kube-dns", "err", err) 113 | kubedns, err := client.CoreV1().Services(metav1.NamespaceSystem).Get(ctx, "kube-dns", metav1.GetOptions{}) 114 | if err != nil { 115 | logger.Error(err, "Error getting kube-dns service") 116 | return "" 117 | } 118 | dnssvc = kubedns 119 | } else { 120 | dnssvc = coredns 121 | } 122 | if len(dnssvc.Spec.ClusterIP) == 0 { 123 | logger.Error(nil, "DNS service ClusterIP bad\n") 124 | return "" 125 | } 126 | return dnssvc.Spec.ClusterIP 127 | } 128 | 129 | // LookupHost looks up IP addresses of hostname on specified DNS server 130 | func LookupHost(ctx context.Context, hostname string, serverip string) (iplist []string, err error) { 131 | logger := klog.FromContext(ctx) 132 | logger.V(4).Info("LookupHost", "hostname", hostname, "serverIP", serverip) 133 | m := new(dns.Msg) 134 | m.SetQuestion(dns.Fqdn(hostname), dns.TypeA) 135 | in, err := dns.Exchange(m, JoinHostPort(serverip, "53")) 136 | if err != nil { 137 | logger.Error(err, "DNS lookup failed", "hostname", hostname) 138 | return nil, err 139 | } 140 | for _, a := range in.Answer { 141 | logger.V(4).Info("LookupHost answer", "answer", fmt.Sprintf("%v", a)) 142 | if t, ok := a.(*dns.A); ok { 143 | iplist = append(iplist, t.A.String()) 144 | } 145 | } 146 | return iplist, nil 147 | } 148 | 149 | // SplitHostPort split a string into host and port (port is optional) 150 | func SplitHostPort(hostport string) (host, port string) { 151 | host, port, err := net.SplitHostPort(hostport) 152 | if err != nil { 153 | host, port = hostport, "" 154 | } 155 | return host, port 156 | } 157 | 158 | // JoinHostPort joins a hostname and an optional port 159 | func JoinHostPort(host, port string) (hostport string) { 160 | if port != "" { 161 | return net.JoinHostPort(host, port) 162 | } 163 | return host 164 | } 165 | --------------------------------------------------------------------------------