diff --git a/Godeps/Godeps.json b/Godeps/Godeps.json deleted file mode 100644 index 5b834b574..000000000 --- a/Godeps/Godeps.json +++ /dev/null @@ -1,626 +0,0 @@ -{ - "ImportPath": "k8s.io/client-go", - "GoVersion": "go1.11", - "GodepVersion": "v80", - "Packages": [ - "./..." - ], - "Deps": [ - { - "ImportPath": "cloud.google.com/go/compute/metadata", - "Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821" - }, - { - "ImportPath": "cloud.google.com/go/internal", - "Rev": "3b1ae45394a234c385be014e9a488f2bb6eef821" - }, - { - "ImportPath": "github.com/Azure/go-autorest/autorest", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/Azure/go-autorest/autorest/adal", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/Azure/go-autorest/autorest/azure", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/Azure/go-autorest/autorest/date", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/Azure/go-autorest/logger", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/Azure/go-autorest/version", - "Rev": "ea233b6412b0421a65dc6160e16c893364664a95" - }, - { - "ImportPath": "github.com/davecgh/go-spew/spew", - "Rev": "782f4967f2dc4564575ca782fe2d04090b5faca8" - }, - { - "ImportPath": "github.com/dgrijalva/jwt-go", - "Rev": "01aeca54ebda6e0fbfafd0a524d234159c05ec20" - }, - { - "ImportPath": "github.com/docker/spdystream", - "Rev": "449fdfce4d962303d702fec724ef0ad181c92528" - }, - { - "ImportPath": "github.com/docker/spdystream/spdy", - "Rev": "449fdfce4d962303d702fec724ef0ad181c92528" - }, - { - "ImportPath": "github.com/evanphx/json-patch", - "Rev": "36442dbdb585210f8d5a1b45e67aa323c197d5c4" - }, - { - "ImportPath": "github.com/gogo/protobuf/proto", - "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" - }, - { - "ImportPath": "github.com/gogo/protobuf/sortkeys", - "Rev": "342cbe0a04158f6dcb03ca0079991a51a4248c02" - }, - { - "ImportPath": "github.com/golang/groupcache/lru", - "Rev": "02826c3e79038b59d737d3b1c0a1d937f71a4433" - }, - { - "ImportPath": "github.com/golang/protobuf/proto", - "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes", - "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes/any", - "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes/duration", - "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" - }, - { - "ImportPath": "github.com/golang/protobuf/ptypes/timestamp", - "Rev": "b4deda0973fb4c70b50d226b1af49f3da59f5265" - }, - { - "ImportPath": "github.com/google/btree", - "Rev": "7d79101e329e5a3adf994758c578dab82b90c017" - }, - { - "ImportPath": "github.com/google/gofuzz", - "Rev": "44d81051d367757e1c7c6a5a86423ece9afcf63c" - }, - { - "ImportPath": "github.com/googleapis/gnostic/OpenAPIv2", - "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" - }, - { - "ImportPath": "github.com/googleapis/gnostic/compiler", - "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" - }, - { - "ImportPath": "github.com/googleapis/gnostic/extensions", - "Rev": "0c5108395e2debce0d731cf0287ddf7242066aba" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/openstack", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tenants", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v2/tokens", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/openstack/identity/v3/tokens", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/openstack/utils", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gophercloud/gophercloud/pagination", - "Rev": "781450b3c4fcb4f5182bcc5133adb4b2e4a09d1d" - }, - { - "ImportPath": "github.com/gregjones/httpcache", - "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" - }, - { - "ImportPath": "github.com/gregjones/httpcache/diskcache", - "Rev": "787624de3eb7bd915c329cba748687a3b22666a6" - }, - { - "ImportPath": "github.com/hashicorp/golang-lru", - "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" - }, - { - "ImportPath": "github.com/hashicorp/golang-lru/simplelru", - "Rev": "a0d98a5f288019575c6d1f4bb1573fef2d1fcdc4" - }, - { - "ImportPath": "github.com/imdario/mergo", - "Rev": "9316a62528ac99aaecb4e47eadd6dc8aa6533d58" - }, - { - "ImportPath": "github.com/json-iterator/go", - "Rev": "ab8a2e0c74be9d3be70b3184d9acc634935ded82" - }, - { - "ImportPath": "github.com/modern-go/concurrent", - "Rev": "bacd9c7ef1dd9b15be4a9909b8ac7a4e313eec94" - }, - { - "ImportPath": "github.com/modern-go/reflect2", - "Rev": "94122c33edd36123c84d5368cfb2b69df93a0ec8" - }, - { - "ImportPath": "github.com/peterbourgon/diskv", - "Rev": "5f041e8faa004a95c88a202771f4cc3e991971e6" - }, - { - "ImportPath": "github.com/pmezard/go-difflib/difflib", - "Rev": "d8ed2627bdf02c080bf22230dbb337003b7aba2d" - }, - { - "ImportPath": "github.com/spf13/pflag", - "Rev": "583c0c0531f06d5278b7d917446061adc344b5cd" - }, - { - "ImportPath": "github.com/stretchr/testify/assert", - "Rev": "c679ae2cc0cb27ec3293fea7e254e47386f05d69" - }, - { - "ImportPath": "golang.org/x/crypto/ssh/terminal", - "Rev": "de0752318171da717af4ce24d0a2e8626afaeb11" - }, - { - "ImportPath": "golang.org/x/net/context", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/net/context/ctxhttp", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/net/http2", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/net/http2/hpack", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/net/idna", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/net/lex/httplex", - "Rev": "0ed95abb35c445290478a5348a7b38bb154135fd" - }, - { - "ImportPath": "golang.org/x/oauth2", - "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" - }, - { - "ImportPath": "golang.org/x/oauth2/google", - "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" - }, - { - "ImportPath": "golang.org/x/oauth2/internal", - "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" - }, - { - "ImportPath": "golang.org/x/oauth2/jws", - "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" - }, - { - "ImportPath": "golang.org/x/oauth2/jwt", - "Rev": "a6bd8cefa1811bd24b86f8902872e4e8225f74c4" - }, - { - "ImportPath": "golang.org/x/sys/unix", - "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" - }, - { - "ImportPath": "golang.org/x/sys/windows", - "Rev": "95c6576299259db960f6c5b9b69ea52422860fce" - }, - { - "ImportPath": "golang.org/x/text/secure/bidirule", - "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" - }, - { - "ImportPath": "golang.org/x/text/transform", - "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" - }, - { - "ImportPath": "golang.org/x/text/unicode/bidi", - "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" - }, - { - "ImportPath": "golang.org/x/text/unicode/norm", - "Rev": "b19bf474d317b857955b12035d2c5acb57ce8b01" - }, - { - "ImportPath": "golang.org/x/time/rate", - "Rev": "f51c12702a4d776e4c1fa9b0fabab841babae631" - }, - { - "ImportPath": "gopkg.in/inf.v0", - "Rev": "3887ee99ecf07df5b447e9b00d9c0b2adaa9f3e4" - }, - { - "ImportPath": "gopkg.in/yaml.v2", - "Rev": "5420a8b6744d3b0345ab293f6fcba19c978f1183" - }, - { - "ImportPath": "k8s.io/api/admissionregistration/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/admissionregistration/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/apps/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/apps/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/apps/v1beta2", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/auditregistration/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/authentication/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/authentication/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/authorization/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/authorization/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/autoscaling/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/autoscaling/v2beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/autoscaling/v2beta2", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/batch/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/batch/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/batch/v2alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/certificates/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/coordination/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/coordination/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/core/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/events/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/extensions/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/imagepolicy/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/networking/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/policy/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/rbac/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/rbac/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/rbac/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/scheduling/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/scheduling/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/settings/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/storage/v1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/storage/v1alpha1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/api/storage/v1beta1", - "Rev": "173ce66c1e39d1d0f56e0b3347ff2988068aecd0" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/fuzzer", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/apitesting/roundtrip", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/equality", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/errors", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/meta", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/api/resource", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/conversion", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/fields", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/labels", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/schema", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/selection", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/types", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/cache", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/clock", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/diff", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/errors", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/framer", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/intstr", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/json", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/naming", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/net", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/runtime", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/sets", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/validation", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/validation/field", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/wait", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/util/yaml", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/version", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/pkg/watch", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect", - "Rev": "fa6ddc151d63306b3540a37d910a07b181e4a474" - }, - { - "ImportPath": "k8s.io/klog", - "Rev": "8139d8cb77af419532b33dfa7dd09fbc5f1d344f" - }, - { - "ImportPath": "k8s.io/kube-openapi/pkg/util/proto", - "Rev": "c59034cc13d587f5ef4e85ca0ade0c1866ae8e1d" - }, - { - "ImportPath": "sigs.k8s.io/yaml", - "Rev": "fd68e9863619f6ec2fdd8625fe1f02e7c877e480" - } - ] -} diff --git a/Godeps/OWNERS b/Godeps/OWNERS deleted file mode 100644 index 3d49f3060..000000000 --- a/Godeps/OWNERS +++ /dev/null @@ -1,2 +0,0 @@ -approvers: -- dep-approvers diff --git a/Godeps/Readme b/Godeps/Readme deleted file mode 100644 index 4cdaa53d5..000000000 --- a/Godeps/Readme +++ /dev/null @@ -1,5 +0,0 @@ -This directory tree is generated automatically by godep. - -Please do not edit. - -See https://github.com/tools/godep for more information. diff --git a/tools/leaderelection/example/main.go b/tools/leaderelection/example/main.go new file mode 100644 index 000000000..91511e5b1 --- /dev/null +++ b/tools/leaderelection/example/main.go @@ -0,0 +1,122 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "context" + "flag" + "log" + "os" + "os/signal" + "syscall" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/client-go/tools/leaderelection" + "k8s.io/client-go/tools/leaderelection/resourcelock" + "k8s.io/klog" +) + +// main demonstrates a leader elected process that will step down if interrupted. +func main() { + klog.InitFlags(nil) + flag.Parse() + args := flag.Args() + if len(args) != 3 { + log.Fatalf("requires three arguments: ID NAMESPACE CONFIG_MAP_NAME (%d)", len(args)) + } + + // leader election uses the Kubernetes API by writing to a ConfigMap or Endpoints + // object. Conflicting writes are detected and each client handles those actions + // independently. + var config *rest.Config + var err error + if kubeconfig := os.Getenv("KUBECONFIG"); len(kubeconfig) > 0 { + config, err = clientcmd.BuildConfigFromFlags("", kubeconfig) + } else { + config, err = rest.InClusterConfig() + } + if err != nil { + log.Fatalf("failed to create client: %v", err) + } + + // we use the ConfigMap lock type since edits to ConfigMaps are less common + // and fewer objects in the cluster watch "all ConfigMaps" (unlike the older + // Endpoints lock type, where quite a few system agents like the kube-proxy + // and ingress controllers must watch endpoints). + id := args[0] + lock := &resourcelock.ConfigMapLock{ + ConfigMapMeta: metav1.ObjectMeta{ + Namespace: args[1], + Name: args[2], + }, + Client: kubernetes.NewForConfigOrDie(config).CoreV1(), + LockConfig: resourcelock.ResourceLockConfig{ + Identity: id, + }, + } + + // use a Go context so we can tell the leaderelection code when we + // want to step down + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + // listen for interrupts or the Linux SIGTERM signal and cancel + // our context, which the leader election code will observe and + // step down + ch := make(chan os.Signal, 1) + signal.Notify(ch, os.Interrupt, syscall.SIGTERM) + go func() { + <-ch + log.Printf("Received termination, signaling shutdown") + cancel() + }() + + // start the leader election code loop + leaderelection.RunOrDie(ctx, leaderelection.LeaderElectionConfig{ + Lock: lock, + // IMPORTANT: you MUST ensure that any code you have that + // is protected by the lease must terminate **before** + // you call cancel. Otherwise, you could have a background + // loop still running and another process could + // get elected before your background loop finished, violating + // the stated goal of the lease. + ReleaseOnCancel: true, + LeaseDuration: 60 * time.Second, + RenewDeadline: 15 * time.Second, + RetryPeriod: 5 * time.Second, + Callbacks: leaderelection.LeaderCallbacks{ + OnStartedLeading: func(ctx context.Context) { + // we're notified when we start - this is where you would + // usually put your code + log.Printf("%s: leading", id) + }, + OnStoppedLeading: func() { + // we can do cleanup here, or after the RunOrDie method + // returns + log.Printf("%s: lost", id) + }, + }, + }) + + // we no longer hold the lease, so perform any cleanup and then + // exit + log.Printf("%s: done", id) +} diff --git a/tools/leaderelection/leaderelection.go b/tools/leaderelection/leaderelection.go index 19c57f316..02bdebd1d 100644 --- a/tools/leaderelection/leaderelection.go +++ b/tools/leaderelection/leaderelection.go @@ -121,6 +121,13 @@ type LeaderElectionConfig struct { // WatchDog may be null if its not needed/configured. WatchDog *HealthzAdaptor + // ReleaseOnCancel should be set true if the lock should be released + // when the run context is cancelled. If you set this to true, you must + // ensure all code guarded by this lease has successfully completed + // prior to cancelling the context, or you may have two processes + // simultaneously acting on the critical path. + ReleaseOnCancel bool + // Name is the name of the resource lock for debugging Name string } @@ -256,6 +263,28 @@ func (le *LeaderElector) renew(ctx context.Context) { klog.Infof("failed to renew lease %v: %v", desc, err) cancel() }, le.config.RetryPeriod, ctx.Done()) + + // if we hold the lease, give it up + if le.config.ReleaseOnCancel { + le.release() + } +} + +// release attempts to release the leader lease if we have acquired it. +func (le *LeaderElector) release() bool { + if !le.IsLeader() { + return true + } + leaderElectionRecord := rl.LeaderElectionRecord{ + LeaderTransitions: le.observedRecord.LeaderTransitions, + } + if err := le.config.Lock.Update(leaderElectionRecord); err != nil { + klog.Errorf("Failed to release lock: %v", err) + return false + } + le.observedRecord = leaderElectionRecord + le.observedTime = le.clock.Now() + return true } // tryAcquireOrRenew tries to acquire a leader lease if it is not already acquired, @@ -291,7 +320,8 @@ func (le *LeaderElector) tryAcquireOrRenew() bool { le.observedRecord = *oldLeaderElectionRecord le.observedTime = le.clock.Now() } - if le.observedTime.Add(le.config.LeaseDuration).After(now.Time) && + if len(oldLeaderElectionRecord.HolderIdentity) > 0 && + le.observedTime.Add(le.config.LeaseDuration).After(now.Time) && !le.IsLeader() { klog.V(4).Infof("lock is held by %v and has not yet expired", oldLeaderElectionRecord.HolderIdentity) return false diff --git a/tools/leaderelection/leaderelection_test.go b/tools/leaderelection/leaderelection_test.go index 842aebdab..c286b2579 100644 --- a/tools/leaderelection/leaderelection_test.go +++ b/tools/leaderelection/leaderelection_test.go @@ -55,6 +55,7 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { past := time.Now().Add(-1000 * time.Hour) tests := []struct { + name string observedRecord rl.LeaderElectionRecord observedTime time.Time reactors []struct { @@ -66,8 +67,8 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { transitionLeader bool outHolder string }{ - // acquire from no object { + name: "acquire from no object", reactors: []struct { verb string reaction core.ReactionFunc @@ -88,8 +89,8 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { expectSuccess: true, outHolder: "baz", }, - // acquire from unled object { + name: "acquire from unled object", reactors: []struct { verb string reaction core.ReactionFunc @@ -116,8 +117,8 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { transitionLeader: true, outHolder: "baz", }, - // acquire from led, unacked object { + name: "acquire from led, unacked object", reactors: []struct { verb string reaction core.ReactionFunc @@ -149,8 +150,40 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { transitionLeader: true, outHolder: "baz", }, - // don't acquire from led, acked object { + name: "acquire from empty led, acked object", + reactors: []struct { + verb string + reaction core.ReactionFunc + }{ + { + verb: "get", + reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) { + objectMeta := metav1.ObjectMeta{ + Namespace: action.GetNamespace(), + Name: action.(core.GetAction).GetName(), + Annotations: map[string]string{ + rl.LeaderElectionRecordAnnotationKey: `{"holderIdentity":""}`, + }, + } + return true, createLockObject(objectType, objectMeta), nil + }, + }, + { + verb: "update", + reaction: func(action core.Action) (handled bool, ret runtime.Object, err error) { + return true, action.(core.CreateAction).GetObject(), nil + }, + }, + }, + observedTime: future, + + expectSuccess: true, + transitionLeader: true, + outHolder: "baz", + }, + { + name: "don't acquire from led, acked object", reactors: []struct { verb string reaction core.ReactionFunc @@ -174,8 +207,8 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { expectSuccess: false, outHolder: "bing", }, - // renew already acquired object { + name: "renew already acquired object", reactors: []struct { verb string reaction core.ReactionFunc @@ -208,83 +241,86 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) { }, } - for i, test := range tests { - // OnNewLeader is called async so we have to wait for it. - var wg sync.WaitGroup - wg.Add(1) - var reportedLeader string - var lock rl.Interface + for i := range tests { + test := &tests[i] + t.Run(test.name, func(t *testing.T) { + // OnNewLeader is called async so we have to wait for it. + var wg sync.WaitGroup + wg.Add(1) + var reportedLeader string + var lock rl.Interface - objectMeta := metav1.ObjectMeta{Namespace: "foo", Name: "bar"} - resourceLockConfig := rl.ResourceLockConfig{ - Identity: "baz", - EventRecorder: &record.FakeRecorder{}, - } - c := &fakecorev1.FakeCoreV1{Fake: &core.Fake{}} - for _, reactor := range test.reactors { - c.AddReactor(reactor.verb, objectType, reactor.reaction) - } - c.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { - t.Errorf("[%v] unreachable action. testclient called too many times: %+v", i, action) - return true, nil, fmt.Errorf("unreachable action") - }) - - switch objectType { - case "endpoints": - lock = &rl.EndpointsLock{ - EndpointsMeta: objectMeta, - LockConfig: resourceLockConfig, - Client: c, + objectMeta := metav1.ObjectMeta{Namespace: "foo", Name: "bar"} + resourceLockConfig := rl.ResourceLockConfig{ + Identity: "baz", + EventRecorder: &record.FakeRecorder{}, } - case "configmaps": - lock = &rl.ConfigMapLock{ - ConfigMapMeta: objectMeta, - LockConfig: resourceLockConfig, - Client: c, + c := &fakecorev1.FakeCoreV1{Fake: &core.Fake{}} + for _, reactor := range test.reactors { + c.AddReactor(reactor.verb, objectType, reactor.reaction) } - } + c.AddReactor("*", "*", func(action core.Action) (bool, runtime.Object, error) { + t.Errorf("unreachable action. testclient called too many times: %+v", action) + return true, nil, fmt.Errorf("unreachable action") + }) - lec := LeaderElectionConfig{ - Lock: lock, - LeaseDuration: 10 * time.Second, - Callbacks: LeaderCallbacks{ - OnNewLeader: func(l string) { - defer wg.Done() - reportedLeader = l + switch objectType { + case "endpoints": + lock = &rl.EndpointsLock{ + EndpointsMeta: objectMeta, + LockConfig: resourceLockConfig, + Client: c, + } + case "configmaps": + lock = &rl.ConfigMapLock{ + ConfigMapMeta: objectMeta, + LockConfig: resourceLockConfig, + Client: c, + } + } + + lec := LeaderElectionConfig{ + Lock: lock, + LeaseDuration: 10 * time.Second, + Callbacks: LeaderCallbacks{ + OnNewLeader: func(l string) { + defer wg.Done() + reportedLeader = l + }, }, - }, - } - le := &LeaderElector{ - config: lec, - observedRecord: test.observedRecord, - observedTime: test.observedTime, - clock: clock.RealClock{}, - } + } + le := &LeaderElector{ + config: lec, + observedRecord: test.observedRecord, + observedTime: test.observedTime, + clock: clock.RealClock{}, + } - if test.expectSuccess != le.tryAcquireOrRenew() { - t.Errorf("[%v]unexpected result of tryAcquireOrRenew: [succeeded=%v]", i, !test.expectSuccess) - } + if test.expectSuccess != le.tryAcquireOrRenew() { + t.Errorf("unexpected result of tryAcquireOrRenew: [succeeded=%v]", !test.expectSuccess) + } - le.observedRecord.AcquireTime = metav1.Time{} - le.observedRecord.RenewTime = metav1.Time{} - if le.observedRecord.HolderIdentity != test.outHolder { - t.Errorf("[%v]expected holder:\n\t%+v\ngot:\n\t%+v", i, test.outHolder, le.observedRecord.HolderIdentity) - } - if len(test.reactors) != len(c.Actions()) { - t.Errorf("[%v]wrong number of api interactions", i) - } - if test.transitionLeader && le.observedRecord.LeaderTransitions != 1 { - t.Errorf("[%v]leader should have transitioned but did not", i) - } - if !test.transitionLeader && le.observedRecord.LeaderTransitions != 0 { - t.Errorf("[%v]leader should not have transitioned but did", i) - } + le.observedRecord.AcquireTime = metav1.Time{} + le.observedRecord.RenewTime = metav1.Time{} + if le.observedRecord.HolderIdentity != test.outHolder { + t.Errorf("expected holder:\n\t%+v\ngot:\n\t%+v", test.outHolder, le.observedRecord.HolderIdentity) + } + if len(test.reactors) != len(c.Actions()) { + t.Errorf("wrong number of api interactions") + } + if test.transitionLeader && le.observedRecord.LeaderTransitions != 1 { + t.Errorf("leader should have transitioned but did not") + } + if !test.transitionLeader && le.observedRecord.LeaderTransitions != 0 { + t.Errorf("leader should not have transitioned but did") + } - le.maybeReportTransition() - wg.Wait() - if reportedLeader != test.outHolder { - t.Errorf("[%v]reported leader was not the new leader. expected %q, got %q", i, test.outHolder, reportedLeader) - } + le.maybeReportTransition() + wg.Wait() + if reportedLeader != test.outHolder { + t.Errorf("reported leader was not the new leader. expected %q, got %q", test.outHolder, reportedLeader) + } + }) } } diff --git a/tools/leaderelection/resourcelock/configmaplock.go b/tools/leaderelection/resourcelock/configmaplock.go index c12daad02..785356894 100644 --- a/tools/leaderelection/resourcelock/configmaplock.go +++ b/tools/leaderelection/resourcelock/configmaplock.go @@ -93,6 +93,9 @@ func (cml *ConfigMapLock) Update(ler LeaderElectionRecord) error { // RecordEvent in leader election while adding meta-data func (cml *ConfigMapLock) RecordEvent(s string) { + if cml.LockConfig.EventRecorder == nil { + return + } events := fmt.Sprintf("%v %v", cml.LockConfig.Identity, s) cml.LockConfig.EventRecorder.Eventf(&v1.ConfigMap{ObjectMeta: cml.cm.ObjectMeta}, v1.EventTypeNormal, "LeaderElection", events) } diff --git a/tools/leaderelection/resourcelock/endpointslock.go b/tools/leaderelection/resourcelock/endpointslock.go index 6f7dcfb0c..bfe5e8b1b 100644 --- a/tools/leaderelection/resourcelock/endpointslock.go +++ b/tools/leaderelection/resourcelock/endpointslock.go @@ -88,6 +88,9 @@ func (el *EndpointsLock) Update(ler LeaderElectionRecord) error { // RecordEvent in leader election while adding meta-data func (el *EndpointsLock) RecordEvent(s string) { + if el.LockConfig.EventRecorder == nil { + return + } events := fmt.Sprintf("%v %v", el.LockConfig.Identity, s) el.LockConfig.EventRecorder.Eventf(&v1.Endpoints{ObjectMeta: el.e.ObjectMeta}, v1.EventTypeNormal, "LeaderElection", events) } diff --git a/tools/leaderelection/resourcelock/interface.go b/tools/leaderelection/resourcelock/interface.go index 676fd1d7d..0bf8e9cd6 100644 --- a/tools/leaderelection/resourcelock/interface.go +++ b/tools/leaderelection/resourcelock/interface.go @@ -20,8 +20,8 @@ import ( "fmt" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" corev1 "k8s.io/client-go/kubernetes/typed/core/v1" - "k8s.io/client-go/tools/record" ) const ( @@ -35,6 +35,11 @@ const ( // with a random string (e.g. UUID) with only slight modification of this code. // TODO(mikedanese): this should potentially be versioned type LeaderElectionRecord struct { + // HolderIdentity is the ID that owns the lease. If empty, no one owns this lease and + // all callers may acquire. Versions of this library prior to Kubernetes 1.14 will not + // attempt to acquire leases with empty identities and will wait for the full lease + // interval to expire before attempting to reacquire. This value is set to empty when + // a client voluntarily steps down. HolderIdentity string `json:"holderIdentity"` LeaseDurationSeconds int `json:"leaseDurationSeconds"` AcquireTime metav1.Time `json:"acquireTime"` @@ -42,11 +47,19 @@ type LeaderElectionRecord struct { LeaderTransitions int `json:"leaderTransitions"` } +// EventRecorder records a change in the ResourceLock. +type EventRecorder interface { + Eventf(obj runtime.Object, eventType, reason, message string, args ...interface{}) +} + // ResourceLockConfig common data that exists across different // resource locks type ResourceLockConfig struct { - Identity string - EventRecorder record.EventRecorder + // Identity is the unique string identifying a lease holder across + // all participants in an election. + Identity string + // EventRecorder is optional. + EventRecorder EventRecorder } // Interface offers a common interface for locking on arbitrary