From ff063889a72e25db2ae51a9fdbd6e5d629995eb4 Mon Sep 17 00:00:00 2001 From: Jiawei Wang Date: Tue, 2 Aug 2022 00:22:04 +0000 Subject: [PATCH] cleanup: Remove flocker volume plugins from k8s codebase Flocker storage plugin removed from k8s codebase. Flocker, an early external storage plugin in k8s, has not been in maintenance and their business is down. As far as I know, the plugin is not being used anymore. This PR removes the whole flocker dependency and codebase from core k8s to reduce potential security risks and reduce maintenance work from the sig-storage community. --- .../github.com/clusterhq/flocker-go/LICENSE | 194 -------- cmd/kube-controller-manager/app/plugins.go | 2 - cmd/kubelet/app/plugins.go | 2 - go.mod | 2 - go.sum | 2 - pkg/kubemark/hollow_kubelet.go | 2 - pkg/volume/flocker/OWNERS | 11 - pkg/volume/flocker/doc.go | 18 - pkg/volume/flocker/flocker.go | 457 ------------------ pkg/volume/flocker/flocker_test.go | 304 ------------ pkg/volume/flocker/flocker_util.go | 98 ---- pkg/volume/flocker/flocker_util_test.go | 58 --- pkg/volume/flocker/flocker_volume.go | 114 ----- pkg/volume/flocker/flocker_volume_test.go | 102 ---- .../github.com/clusterhq/flocker-go/LICENSE | 190 -------- .../github.com/clusterhq/flocker-go/README.md | 18 - .../clusterhq/flocker-go/circle.yml | 16 - .../github.com/clusterhq/flocker-go/client.go | 376 -------------- vendor/github.com/clusterhq/flocker-go/doc.go | 2 - .../github.com/clusterhq/flocker-go/util.go | 34 -- vendor/modules.txt | 4 - 21 files changed, 2006 deletions(-) delete mode 100644 LICENSES/vendor/github.com/clusterhq/flocker-go/LICENSE delete mode 100644 pkg/volume/flocker/OWNERS delete mode 100644 pkg/volume/flocker/doc.go delete mode 100644 pkg/volume/flocker/flocker.go delete mode 100644 pkg/volume/flocker/flocker_test.go delete mode 100644 pkg/volume/flocker/flocker_util.go delete mode 100644 pkg/volume/flocker/flocker_util_test.go delete mode 100644 pkg/volume/flocker/flocker_volume.go delete mode 100644 pkg/volume/flocker/flocker_volume_test.go delete mode 100644 vendor/github.com/clusterhq/flocker-go/LICENSE delete mode 100644 vendor/github.com/clusterhq/flocker-go/README.md delete mode 100644 vendor/github.com/clusterhq/flocker-go/circle.yml delete mode 100644 vendor/github.com/clusterhq/flocker-go/client.go delete mode 100644 vendor/github.com/clusterhq/flocker-go/doc.go delete mode 100644 vendor/github.com/clusterhq/flocker-go/util.go diff --git a/LICENSES/vendor/github.com/clusterhq/flocker-go/LICENSE b/LICENSES/vendor/github.com/clusterhq/flocker-go/LICENSE deleted file mode 100644 index e3368fa4fa5..00000000000 --- a/LICENSES/vendor/github.com/clusterhq/flocker-go/LICENSE +++ /dev/null @@ -1,194 +0,0 @@ -= vendor/github.com/clusterhq/flocker-go licensed under: = - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014-2016 ClusterHQ - - 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. - -= vendor/github.com/clusterhq/flocker-go/LICENSE d8103d9796cd0e951379d0834edad066 diff --git a/cmd/kube-controller-manager/app/plugins.go b/cmd/kube-controller-manager/app/plugins.go index 69daea0bb5c..78255d901b4 100644 --- a/cmd/kube-controller-manager/app/plugins.go +++ b/cmd/kube-controller-manager/app/plugins.go @@ -34,7 +34,6 @@ import ( "k8s.io/kubernetes/pkg/volume/csi" "k8s.io/kubernetes/pkg/volume/fc" "k8s.io/kubernetes/pkg/volume/flexvolume" - "k8s.io/kubernetes/pkg/volume/flocker" "k8s.io/kubernetes/pkg/volume/glusterfs" "k8s.io/kubernetes/pkg/volume/hostpath" "k8s.io/kubernetes/pkg/volume/iscsi" @@ -133,7 +132,6 @@ func ProbeControllerVolumePlugins(cloud cloudprovider.Interface, config persiste return allPlugins, err } - allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...) allPlugins = append(allPlugins, local.ProbeVolumePlugins()...) allPlugins = append(allPlugins, storageos.ProbeVolumePlugins()...) diff --git a/cmd/kubelet/app/plugins.go b/cmd/kubelet/app/plugins.go index e13d1bc7173..52ba75cc669 100644 --- a/cmd/kubelet/app/plugins.go +++ b/cmd/kubelet/app/plugins.go @@ -30,7 +30,6 @@ import ( "k8s.io/kubernetes/pkg/volume/emptydir" "k8s.io/kubernetes/pkg/volume/fc" "k8s.io/kubernetes/pkg/volume/flexvolume" - "k8s.io/kubernetes/pkg/volume/flocker" "k8s.io/kubernetes/pkg/volume/git_repo" "k8s.io/kubernetes/pkg/volume/glusterfs" "k8s.io/kubernetes/pkg/volume/hostpath" @@ -72,7 +71,6 @@ func ProbeVolumePlugins(featureGate featuregate.FeatureGate) ([]volume.VolumePlu allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...) allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...) allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...) - allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...) allPlugins = append(allPlugins, configmap.ProbeVolumePlugins()...) allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...) allPlugins = append(allPlugins, local.ProbeVolumePlugins()...) diff --git a/go.mod b/go.mod index 035c40eacc1..22459e4bddf 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,6 @@ require ( github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 github.com/aws/aws-sdk-go v1.38.49 github.com/blang/semver/v4 v4.0.0 - github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/container-storage-interface/spec v1.6.0 github.com/coredns/corefile-migration v1.0.17 github.com/coreos/go-oidc v2.1.0+incompatible @@ -312,7 +311,6 @@ replace ( github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 github.com/cilium/ebpf => github.com/cilium/ebpf v0.7.0 - github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 github.com/cncf/xds/go => github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 diff --git a/go.sum b/go.sum index 93a3ee70138..bd7ac7ad1c9 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,6 @@ github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5P github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.7.0 h1:1k/q3ATgxSXRdrmPfH8d7YK0GfqVsEKZAX9dQZvs56k= github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= -github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 h1:eIHD9GNM3Hp7kcRW5mvcz7WTR3ETeoYYKwpgA04kaXE= -github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313/go.mod h1:P1wt9Z3DP8O6W3rvwCt0REIlshg1InHImaLW0t3ObY0= github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5 h1:xD/lrqdvwsc+O2bjSSi3YqY73Ke3LAiSCx49aCesA0E= diff --git a/pkg/kubemark/hollow_kubelet.go b/pkg/kubemark/hollow_kubelet.go index 8c0e5e0d414..62cc751c9e6 100644 --- a/pkg/kubemark/hollow_kubelet.go +++ b/pkg/kubemark/hollow_kubelet.go @@ -44,7 +44,6 @@ import ( "k8s.io/kubernetes/pkg/volume/downwardapi" "k8s.io/kubernetes/pkg/volume/emptydir" "k8s.io/kubernetes/pkg/volume/fc" - "k8s.io/kubernetes/pkg/volume/flocker" "k8s.io/kubernetes/pkg/volume/git_repo" "k8s.io/kubernetes/pkg/volume/glusterfs" "k8s.io/kubernetes/pkg/volume/hostpath" @@ -82,7 +81,6 @@ func volumePlugins() []volume.VolumePlugin { allPlugins = append(allPlugins, cephfs.ProbeVolumePlugins()...) allPlugins = append(allPlugins, downwardapi.ProbeVolumePlugins()...) allPlugins = append(allPlugins, fc.ProbeVolumePlugins()...) - allPlugins = append(allPlugins, flocker.ProbeVolumePlugins()...) allPlugins = append(allPlugins, configmap.ProbeVolumePlugins()...) allPlugins = append(allPlugins, projected.ProbeVolumePlugins()...) allPlugins = append(allPlugins, portworx.ProbeVolumePlugins()...) diff --git a/pkg/volume/flocker/OWNERS b/pkg/volume/flocker/OWNERS deleted file mode 100644 index 4e2f2d2a690..00000000000 --- a/pkg/volume/flocker/OWNERS +++ /dev/null @@ -1,11 +0,0 @@ -# See the OWNERS docs at https://go.k8s.io/owners - -approvers: - - saad-ali -reviewers: - - saad-ali - - jsafrane - - jingxu97 - - msau42 -emeritus_approvers: - - rootfs diff --git a/pkg/volume/flocker/doc.go b/pkg/volume/flocker/doc.go deleted file mode 100644 index e93a7489c13..00000000000 --- a/pkg/volume/flocker/doc.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2015 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 flocker contains the internal representation of Flocker volumes -package flocker // import "k8s.io/kubernetes/pkg/volume/flocker" diff --git a/pkg/volume/flocker/flocker.go b/pkg/volume/flocker/flocker.go deleted file mode 100644 index dcf94a361ba..00000000000 --- a/pkg/volume/flocker/flocker.go +++ /dev/null @@ -1,457 +0,0 @@ -/* -Copyright 2015 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 flocker - -import ( - "fmt" - "os" - "path/filepath" - "time" - - flockerapi "github.com/clusterhq/flocker-go" - "k8s.io/klog/v2" - "k8s.io/mount-utils" - utilstrings "k8s.io/utils/strings" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - "k8s.io/kubernetes/pkg/util/env" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/util" -) - -// ProbeVolumePlugins is the primary entrypoint for volume plugins. -func ProbeVolumePlugins() []volume.VolumePlugin { - return []volume.VolumePlugin{&flockerPlugin{nil}} -} - -type flockerPlugin struct { - host volume.VolumeHost -} - -type flockerVolume struct { - volName string - podUID types.UID - // dataset metadata name deprecated - datasetName string - // dataset uuid - datasetUUID string - //pod *v1.Pod - flockerClient flockerapi.Clientable - manager volumeManager - plugin *flockerPlugin - mounter mount.Interface - volume.MetricsProvider -} - -var _ volume.VolumePlugin = &flockerPlugin{} -var _ volume.PersistentVolumePlugin = &flockerPlugin{} -var _ volume.DeletableVolumePlugin = &flockerPlugin{} -var _ volume.ProvisionableVolumePlugin = &flockerPlugin{} - -const ( - flockerPluginName = "kubernetes.io/flocker" - - defaultHost = "localhost" - defaultPort = 4523 - defaultCACertFile = "/etc/flocker/cluster.crt" - defaultClientKeyFile = "/etc/flocker/apiuser.key" - defaultClientCertFile = "/etc/flocker/apiuser.crt" - defaultMountPath = "/flocker" - - timeoutWaitingForVolume = 2 * time.Minute - tickerWaitingForVolume = 5 * time.Second -) - -func getPath(uid types.UID, volName string, host volume.VolumeHost) string { - return host.GetPodVolumeDir(uid, utilstrings.EscapeQualifiedName(flockerPluginName), volName) -} - -func makeGlobalFlockerPath(datasetUUID string) string { - return filepath.Join(defaultMountPath, datasetUUID) -} - -func (p *flockerPlugin) Init(host volume.VolumeHost) error { - p.host = host - return nil -} - -func (p *flockerPlugin) GetPluginName() string { - return flockerPluginName -} - -func (p *flockerPlugin) GetVolumeName(spec *volume.Spec) (string, error) { - volumeSource, _, err := getVolumeSource(spec) - if err != nil { - return "", err - } - - return volumeSource.DatasetName, nil -} - -func (p *flockerPlugin) CanSupport(spec *volume.Spec) bool { - return (spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Flocker != nil) || - (spec.Volume != nil && spec.Volume.Flocker != nil) -} - -func (p *flockerPlugin) RequiresRemount(spec *volume.Spec) bool { - return false -} - -func (p *flockerPlugin) SupportsMountOption() bool { - return false -} - -func (p *flockerPlugin) SupportsBulkVolumeVerification() bool { - return false -} - -func (p *flockerPlugin) GetAccessModes() []v1.PersistentVolumeAccessMode { - return []v1.PersistentVolumeAccessMode{ - v1.ReadWriteOnce, - } -} - -func (p *flockerPlugin) getFlockerVolumeSource(spec *volume.Spec) (*v1.FlockerVolumeSource, bool) { - // AFAIK this will always be r/w, but perhaps for the future it will be needed - readOnly := false - - if spec.Volume != nil && spec.Volume.Flocker != nil { - return spec.Volume.Flocker, readOnly - } - return spec.PersistentVolume.Spec.Flocker, readOnly -} - -func (p *flockerPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volume.VolumeOptions) (volume.Mounter, error) { - // Inject real implementations here, test through the internal function. - return p.newMounterInternal(spec, pod.UID, &flockerUtil{}, p.host.GetMounter(p.GetPluginName())) -} - -func (p *flockerPlugin) newMounterInternal(spec *volume.Spec, podUID types.UID, manager volumeManager, mounter mount.Interface) (volume.Mounter, error) { - volumeSource, readOnly, err := getVolumeSource(spec) - if err != nil { - return nil, err - } - - datasetName := volumeSource.DatasetName - datasetUUID := volumeSource.DatasetUUID - - return &flockerVolumeMounter{ - flockerVolume: &flockerVolume{ - podUID: podUID, - volName: spec.Name(), - datasetName: datasetName, - datasetUUID: datasetUUID, - mounter: mounter, - manager: manager, - plugin: p, - MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, spec.Name(), p.host)), - }, - readOnly: readOnly}, nil -} - -func (p *flockerPlugin) NewUnmounter(volName string, podUID types.UID) (volume.Unmounter, error) { - // Inject real implementations here, test through the internal function. - return p.newUnmounterInternal(volName, podUID, &flockerUtil{}, p.host.GetMounter(p.GetPluginName())) -} - -func (p *flockerPlugin) newUnmounterInternal(volName string, podUID types.UID, manager volumeManager, mounter mount.Interface) (volume.Unmounter, error) { - return &flockerVolumeUnmounter{&flockerVolume{ - podUID: podUID, - volName: volName, - manager: manager, - mounter: mounter, - plugin: p, - MetricsProvider: volume.NewMetricsStatFS(getPath(podUID, volName, p.host)), - }}, nil -} - -func (p *flockerPlugin) ConstructVolumeSpec(volumeName, mountPath string) (*volume.Spec, error) { - flockerVolume := &v1.Volume{ - Name: volumeName, - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{ - DatasetName: volumeName, - }, - }, - } - return volume.NewSpecFromVolume(flockerVolume), nil -} - -func (b *flockerVolume) GetDatasetUUID() (datasetUUID string, err error) { - - // return UUID if set - if len(b.datasetUUID) > 0 { - return b.datasetUUID, nil - } - - if b.flockerClient == nil { - return "", fmt.Errorf("flocker client is not initialized") - } - - // lookup in flocker API otherwise - return b.flockerClient.GetDatasetID(b.datasetName) -} - -type flockerVolumeMounter struct { - *flockerVolume - readOnly bool -} - -func (b *flockerVolumeMounter) GetAttributes() volume.Attributes { - return volume.Attributes{ - ReadOnly: b.readOnly, - Managed: false, - SELinuxRelabel: false, - } -} - -func (b *flockerVolumeMounter) GetPath() string { - return getPath(b.podUID, b.volName, b.plugin.host) -} - -// SetUp bind mounts the disk global mount to the volume path. -func (b *flockerVolumeMounter) SetUp(mounterArgs volume.MounterArgs) error { - return b.SetUpAt(b.GetPath(), mounterArgs) -} - -// newFlockerClient uses environment variables and pod attributes to return a -// flocker client capable of talking with the Flocker control service. -func (p *flockerPlugin) newFlockerClient(hostIP string) (*flockerapi.Client, error) { - host := env.GetEnvAsStringOrFallback("FLOCKER_CONTROL_SERVICE_HOST", defaultHost) - port, err := env.GetEnvAsIntOrFallback("FLOCKER_CONTROL_SERVICE_PORT", defaultPort) - - if err != nil { - return nil, err - } - caCertPath := env.GetEnvAsStringOrFallback("FLOCKER_CONTROL_SERVICE_CA_FILE", defaultCACertFile) - keyPath := env.GetEnvAsStringOrFallback("FLOCKER_CONTROL_SERVICE_CLIENT_KEY_FILE", defaultClientKeyFile) - certPath := env.GetEnvAsStringOrFallback("FLOCKER_CONTROL_SERVICE_CLIENT_CERT_FILE", defaultClientCertFile) - - c, err := flockerapi.NewClient(host, port, hostIP, caCertPath, keyPath, certPath) - return c, err -} - -func (b *flockerVolumeMounter) newFlockerClient() (*flockerapi.Client, error) { - - hostIP, err := b.plugin.host.GetHostIP() - if err != nil { - return nil, err - } - - return b.plugin.newFlockerClient(hostIP.String()) -} - -/* -SetUpAt will setup a Flocker volume following this flow of calls to the Flocker -control service: - - 1. Get the dataset id for the given volume name/dir - 2. It should already be there, if it's not the user needs to manually create it - 3. Check the current Primary UUID - 4. If it doesn't match with the Primary UUID that we got on 2, then we will - need to update the Primary UUID for this volume. - 5. Wait until the Primary UUID was updated or timeout. -*/ -func (b *flockerVolumeMounter) SetUpAt(dir string, mounterArgs volume.MounterArgs) error { - var err error - if b.flockerClient == nil { - b.flockerClient, err = b.newFlockerClient() - if err != nil { - return err - } - } - - datasetUUID, err := b.GetDatasetUUID() - if err != nil { - return fmt.Errorf("the datasetUUID for volume with datasetName='%s' can not be found using flocker: %s", b.datasetName, err) - } - - datasetState, err := b.flockerClient.GetDatasetState(datasetUUID) - if err != nil { - return fmt.Errorf("the datasetState for volume with datasetUUID='%s' could not determinted uusing flocker: %s", datasetUUID, err) - } - - primaryUUID, err := b.flockerClient.GetPrimaryUUID() - if err != nil { - return err - } - - if datasetState.Primary != primaryUUID { - if err := b.updateDatasetPrimary(datasetUUID, primaryUUID); err != nil { - return err - } - _, err := b.flockerClient.GetDatasetState(datasetUUID) - if err != nil { - return fmt.Errorf("the volume with datasetUUID='%s' migrated unsuccessfully", datasetUUID) - } - } - - // TODO: handle failed mounts here. - notMnt, err := b.mounter.IsLikelyNotMountPoint(dir) - klog.V(4).Infof("flockerVolume set up: %s %v %v, datasetUUID %v readOnly %v", dir, !notMnt, err, datasetUUID, b.readOnly) - if err != nil && !os.IsNotExist(err) { - klog.Errorf("cannot validate mount point: %s %v", dir, err) - return err - } - if !notMnt { - return nil - } - - if err := os.MkdirAll(dir, 0750); err != nil { - klog.Errorf("mkdir failed on disk %s (%v)", dir, err) - return err - } - - // Perform a bind mount to the full path to allow duplicate mounts of the same PD. - options := []string{"bind"} - if b.readOnly { - options = append(options, "ro") - } - - globalFlockerPath := makeGlobalFlockerPath(datasetUUID) - klog.V(4).Infof("attempting to mount %s", dir) - - err = b.mounter.MountSensitiveWithoutSystemd(globalFlockerPath, dir, "", options, nil) - if err != nil { - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) - if mntErr != nil { - klog.Errorf("isLikelyNotMountPoint check failed: %v", mntErr) - return err - } - if !notMnt { - if mntErr = b.mounter.Unmount(dir); mntErr != nil { - klog.Errorf("failed to unmount: %v", mntErr) - return err - } - notMnt, mntErr := b.mounter.IsLikelyNotMountPoint(dir) - if mntErr != nil { - klog.Errorf("isLikelyNotMountPoint check failed: %v", mntErr) - return err - } - if !notMnt { - // This is very odd, we don't expect it. We'll try again next sync loop. - klog.Errorf("%s is still mounted, despite call to unmount(). Will try again next sync loop.", dir) - return err - } - } - os.Remove(dir) - klog.Errorf("mount of disk %s failed: %v", dir, err) - return err - } - - if !b.readOnly { - volume.SetVolumeOwnership(b, mounterArgs.FsGroup, mounterArgs.FSGroupChangePolicy, util.FSGroupCompleteHook(b.plugin, nil)) - } - - klog.V(4).Infof("successfully mounted %s", dir) - return nil -} - -// updateDatasetPrimary will update the primary in Flocker and wait for it to -// be ready. If it never gets to ready state it will timeout and error. -func (b *flockerVolumeMounter) updateDatasetPrimary(datasetUUID string, primaryUUID string) error { - // We need to update the primary and wait for it to be ready - _, err := b.flockerClient.UpdatePrimaryForDataset(primaryUUID, datasetUUID) - if err != nil { - return err - } - - timeoutChan := time.NewTimer(timeoutWaitingForVolume) - defer timeoutChan.Stop() - tickChan := time.NewTicker(tickerWaitingForVolume) - defer tickChan.Stop() - - for { - if s, err := b.flockerClient.GetDatasetState(datasetUUID); err == nil && s.Primary == primaryUUID { - return nil - } - - select { - case <-timeoutChan.C: - return fmt.Errorf( - "Timed out waiting for the datasetUUID: '%s' to be moved to the primary: '%s'\n%v", - datasetUUID, primaryUUID, err, - ) - case <-tickChan.C: - } - } - -} - -func getVolumeSource(spec *volume.Spec) (*v1.FlockerVolumeSource, bool, error) { - if spec.Volume != nil && spec.Volume.Flocker != nil { - return spec.Volume.Flocker, spec.ReadOnly, nil - } else if spec.PersistentVolume != nil && - spec.PersistentVolume.Spec.Flocker != nil { - return spec.PersistentVolume.Spec.Flocker, spec.ReadOnly, nil - } - - return nil, false, fmt.Errorf("Spec does not reference a Flocker volume type") -} - -type flockerVolumeUnmounter struct { - *flockerVolume -} - -var _ volume.Unmounter = &flockerVolumeUnmounter{} - -func (c *flockerVolumeUnmounter) GetPath() string { - return getPath(c.podUID, c.volName, c.plugin.host) -} - -// Unmounts the bind mount, and detaches the disk only if the PD -// resource was the last reference to that disk on the kubelet. -func (c *flockerVolumeUnmounter) TearDown() error { - return c.TearDownAt(c.GetPath()) -} - -// TearDownAt unmounts the bind mount -func (c *flockerVolumeUnmounter) TearDownAt(dir string) error { - return mount.CleanupMountPoint(dir, c.mounter, false) -} - -func (p *flockerPlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, error) { - return p.newDeleterInternal(spec, &flockerUtil{}) -} - -func (p *flockerPlugin) newDeleterInternal(spec *volume.Spec, manager volumeManager) (volume.Deleter, error) { - if spec.PersistentVolume != nil && spec.PersistentVolume.Spec.Flocker == nil { - return nil, fmt.Errorf("spec.PersistentVolumeSource.Flocker is nil") - } - return &flockerVolumeDeleter{ - flockerVolume: &flockerVolume{ - volName: spec.Name(), - datasetName: spec.PersistentVolume.Spec.Flocker.DatasetName, - datasetUUID: spec.PersistentVolume.Spec.Flocker.DatasetUUID, - manager: manager, - }}, nil -} - -func (p *flockerPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) { - return p.newProvisionerInternal(options, &flockerUtil{}) -} - -func (p *flockerPlugin) newProvisionerInternal(options volume.VolumeOptions, manager volumeManager) (volume.Provisioner, error) { - return &flockerVolumeProvisioner{ - flockerVolume: &flockerVolume{ - manager: manager, - plugin: p, - }, - options: options, - }, nil -} diff --git a/pkg/volume/flocker/flocker_test.go b/pkg/volume/flocker/flocker_test.go deleted file mode 100644 index 847bab087dc..00000000000 --- a/pkg/volume/flocker/flocker_test.go +++ /dev/null @@ -1,304 +0,0 @@ -/* -Copyright 2015 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 flocker - -import ( - "fmt" - "os" - "testing" - - flockerapi "github.com/clusterhq/flocker-go" - "github.com/stretchr/testify/assert" - "k8s.io/mount-utils" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/types" - utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/volume" - volumetest "k8s.io/kubernetes/pkg/volume/testing" -) - -const pluginName = "kubernetes.io/flocker" -const datasetOneID = "11111111-1111-1111-1111-111111111100" -const nodeOneID = "11111111-1111-1111-1111-111111111111" -const nodeTwoID = "22222222-2222-2222-2222-222222222222" - -var _ flockerapi.Clientable = &fakeFlockerClient{} - -type fakeFlockerClient struct { - DatasetID string - Primary string - Deleted bool - Metadata map[string]string - Nodes []flockerapi.NodeState - Error error -} - -func newFakeFlockerClient() *fakeFlockerClient { - return &fakeFlockerClient{ - DatasetID: datasetOneID, - Primary: nodeOneID, - Deleted: false, - Metadata: map[string]string{"Name": "dataset-one"}, - Nodes: []flockerapi.NodeState{ - { - Host: "1.2.3.4", - UUID: nodeOneID, - }, - { - Host: "4.5.6.7", - UUID: nodeTwoID, - }, - }, - } -} - -func (c *fakeFlockerClient) CreateDataset(options *flockerapi.CreateDatasetOptions) (*flockerapi.DatasetState, error) { - - if c.Error != nil { - return nil, c.Error - } - - return &flockerapi.DatasetState{ - DatasetID: c.DatasetID, - }, nil -} - -func (c *fakeFlockerClient) DeleteDataset(datasetID string) error { - c.DatasetID = datasetID - c.Deleted = true - return nil -} - -func (c *fakeFlockerClient) GetDatasetState(datasetID string) (*flockerapi.DatasetState, error) { - return &flockerapi.DatasetState{}, nil -} - -func (c *fakeFlockerClient) GetDatasetID(metaName string) (datasetID string, err error) { - if val, ok := c.Metadata["Name"]; !ok { - return val, nil - } - return "", fmt.Errorf("no dataset with metadata X found") -} - -func (c *fakeFlockerClient) GetPrimaryUUID() (primaryUUID string, err error) { - return -} - -func (c *fakeFlockerClient) ListNodes() (nodes []flockerapi.NodeState, err error) { - return c.Nodes, nil -} - -func (c *fakeFlockerClient) UpdatePrimaryForDataset(primaryUUID, datasetID string) (*flockerapi.DatasetState, error) { - return &flockerapi.DatasetState{}, nil -} - -type fakeFlockerUtil struct { -} - -func (fake *fakeFlockerUtil) CreateVolume(c *flockerVolumeProvisioner) (datasetUUID string, volumeSizeGB int, labels map[string]string, err error) { - labels = make(map[string]string) - labels["fakeflockerutil"] = "yes" - return "test-flocker-volume-uuid", 3, labels, nil -} - -func (fake *fakeFlockerUtil) DeleteVolume(cd *flockerVolumeDeleter) error { - if cd.datasetUUID != "test-flocker-volume-uuid" { - return fmt.Errorf("Deleter got unexpected datasetUUID: %s", cd.datasetUUID) - } - return nil -} - -func newInitializedVolumePlugMgr(t *testing.T) (*volume.VolumePluginMgr, string) { - plugMgr := &volume.VolumePluginMgr{} - dir, err := utiltesting.MkTmpdir("flocker") - assert.NoError(t, err) - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, dir, nil, nil)) - return plugMgr, dir -} - -func TestPlugin(t *testing.T) { - tmpDir, err := utiltesting.MkTmpdir("flockerTest") - if err != nil { - t.Fatalf("can't make a temp dir: %v", err) - } - defer os.RemoveAll(tmpDir) - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) - - plug, err := plugMgr.FindPluginByName("kubernetes.io/flocker") - if err != nil { - t.Errorf("Can't find the plugin by name") - } - spec := &v1.Volume{ - Name: "vol1", - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{ - DatasetUUID: "uuid1", - }, - }, - } - fakeManager := &fakeFlockerUtil{} - fakeMounter := mount.NewFakeMounter(nil) - mounter, err := plug.(*flockerPlugin).newMounterInternal(volume.NewSpecFromVolume(spec), types.UID("poduid"), fakeManager, fakeMounter) - if err != nil { - t.Errorf("Failed to make a new Mounter: %v", err) - } - if mounter == nil { - t.Errorf("Got a nil Mounter") - } -} - -func TestGetByName(t *testing.T) { - assert := assert.New(t) - plugMgr, dir := newInitializedVolumePlugMgr(t) - defer os.RemoveAll(dir) - - plug, err := plugMgr.FindPluginByName(pluginName) - assert.NotNil(plug, "Can't find the plugin by name") - assert.NoError(err) -} - -func TestCanSupport(t *testing.T) { - assert := assert.New(t) - plugMgr, dir := newInitializedVolumePlugMgr(t) - defer os.RemoveAll(dir) - - plug, err := plugMgr.FindPluginByName(pluginName) - assert.NoError(err) - - specs := map[*volume.Spec]bool{ - { - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{}, - }, - }, - }: true, - { - PersistentVolume: &v1.PersistentVolume{ - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - Flocker: &v1.FlockerVolumeSource{}, - }, - }, - }, - }: true, - { - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{}, - }, - }: false, - } - - for spec, expected := range specs { - actual := plug.CanSupport(spec) - assert.Equal(expected, actual) - } -} - -func TestGetFlockerVolumeSource(t *testing.T) { - assert := assert.New(t) - - p := flockerPlugin{} - - spec := &volume.Spec{ - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{}, - }, - }, - } - vs, ro := p.getFlockerVolumeSource(spec) - assert.False(ro) - assert.Equal(spec.Volume.Flocker, vs) - - spec = &volume.Spec{ - PersistentVolume: &v1.PersistentVolume{ - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeSource: v1.PersistentVolumeSource{ - Flocker: &v1.FlockerVolumeSource{}, - }, - }, - }, - } - vs, ro = p.getFlockerVolumeSource(spec) - assert.False(ro) - assert.Equal(spec.PersistentVolume.Spec.Flocker, vs) -} - -func TestNewMounterDatasetName(t *testing.T) { - assert := assert.New(t) - - plugMgr, dir := newInitializedVolumePlugMgr(t) - defer os.RemoveAll(dir) - plug, err := plugMgr.FindPluginByName(pluginName) - assert.NoError(err) - - spec := &volume.Spec{ - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{ - DatasetName: "something", - }, - }, - }, - } - - _, err = plug.NewMounter(spec, &v1.Pod{}, volume.VolumeOptions{}) - assert.NoError(err) -} - -func TestNewMounterDatasetUUID(t *testing.T) { - assert := assert.New(t) - - plugMgr, dir := newInitializedVolumePlugMgr(t) - defer os.RemoveAll(dir) - plug, err := plugMgr.FindPluginByName(pluginName) - assert.NoError(err) - - spec := &volume.Spec{ - Volume: &v1.Volume{ - VolumeSource: v1.VolumeSource{ - Flocker: &v1.FlockerVolumeSource{ - DatasetUUID: "uuid1", - }, - }, - }, - } - - mounter, err := plug.NewMounter(spec, &v1.Pod{}, volume.VolumeOptions{}) - assert.NoError(err) - assert.NotNil(mounter, "got a nil mounter") - -} - -func TestNewUnmounter(t *testing.T) { - t.Skip("broken") - assert := assert.New(t) - - p := flockerPlugin{} - - unmounter, err := p.NewUnmounter("", types.UID("")) - assert.Nil(unmounter) - assert.NoError(err) -} - -func TestIsReadOnly(t *testing.T) { - b := &flockerVolumeMounter{readOnly: true} - assert.True(t, b.GetAttributes().ReadOnly) -} diff --git a/pkg/volume/flocker/flocker_util.go b/pkg/volume/flocker/flocker_util.go deleted file mode 100644 index 75b1a3b56ef..00000000000 --- a/pkg/volume/flocker/flocker_util.go +++ /dev/null @@ -1,98 +0,0 @@ -/* -Copyright 2016 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 flocker - -import ( - "fmt" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/util/rand" - - volumehelpers "k8s.io/cloud-provider/volume/helpers" - - flockerapi "github.com/clusterhq/flocker-go" - "k8s.io/klog/v2" -) - -type flockerUtil struct{} - -func (util *flockerUtil) DeleteVolume(d *flockerVolumeDeleter) error { - var err error - - if d.flockerClient == nil { - d.flockerClient, err = d.plugin.newFlockerClient("") - if err != nil { - return err - } - } - - datasetUUID, err := d.GetDatasetUUID() - if err != nil { - return err - } - - return d.flockerClient.DeleteDataset(datasetUUID) -} - -func (util *flockerUtil) CreateVolume(c *flockerVolumeProvisioner) (datasetUUID string, volumeSizeGiB int, labels map[string]string, err error) { - - if c.flockerClient == nil { - c.flockerClient, err = c.plugin.newFlockerClient("") - if err != nil { - return - } - } - - nodes, err := c.flockerClient.ListNodes() - if err != nil { - return - } - if len(nodes) < 1 { - err = fmt.Errorf("no nodes found inside the flocker cluster to provision a dataset") - return - } - - // select random node - node := nodes[rand.Intn(len(nodes))] - klog.V(2).Infof("selected flocker node with UUID '%s' to provision dataset", node.UUID) - - capacity := c.options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)] - requestBytes := capacity.Value() - volumeSizeGiB, err = volumehelpers.RoundUpToGiBInt(capacity) - if err != nil { - return - } - - createOptions := &flockerapi.CreateDatasetOptions{ - MaximumSize: requestBytes, - Metadata: map[string]string{ - "type": "k8s-dynamic-prov", - "pvc": c.options.PVC.Name, - }, - Primary: node.UUID, - } - - datasetState, err := c.flockerClient.CreateDataset(createOptions) - if err != nil { - return - } - datasetUUID = datasetState.DatasetID - - klog.V(2).Infof("successfully created Flocker dataset with UUID '%s'", datasetUUID) - - return -} diff --git a/pkg/volume/flocker/flocker_util_test.go b/pkg/volume/flocker/flocker_util_test.go deleted file mode 100644 index 4453816998f..00000000000 --- a/pkg/volume/flocker/flocker_util_test.go +++ /dev/null @@ -1,58 +0,0 @@ -/* -Copyright 2015 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 flocker - -import ( - "fmt" - "os" - "testing" - - v1 "k8s.io/api/core/v1" - "k8s.io/kubernetes/pkg/volume" - volumetest "k8s.io/kubernetes/pkg/volume/testing" - - "github.com/stretchr/testify/assert" -) - -func TestFlockerUtil_CreateVolume(t *testing.T) { - assert := assert.New(t) - - // test CreateVolume happy path - pvc := volumetest.CreateTestPVC("3Gi", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}) - options := volume.VolumeOptions{ - PVC: pvc, - PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, - } - - fakeFlockerClient := newFakeFlockerClient() - dir, p := newTestableProvisioner(t, assert, options) - provisioner := p.(*flockerVolumeProvisioner) - defer os.RemoveAll(dir) - provisioner.flockerClient = fakeFlockerClient - - flockerUtil := &flockerUtil{} - - datasetID, size, _, err := flockerUtil.CreateVolume(provisioner) - assert.NoError(err) - assert.Equal(datasetOneID, datasetID) - assert.Equal(3, size) - - // test error during CreateVolume - fakeFlockerClient.Error = fmt.Errorf("do not feel like provisioning") - _, _, _, err = flockerUtil.CreateVolume(provisioner) - assert.Equal(fakeFlockerClient.Error.Error(), err.Error()) -} diff --git a/pkg/volume/flocker/flocker_volume.go b/pkg/volume/flocker/flocker_volume.go deleted file mode 100644 index 68a03bd41d3..00000000000 --- a/pkg/volume/flocker/flocker_volume.go +++ /dev/null @@ -1,114 +0,0 @@ -/* -Copyright 2015 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 flocker - -import ( - "fmt" - - "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/resource" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/kubernetes/pkg/volume" - "k8s.io/kubernetes/pkg/volume/util" -) - -type volumeManager interface { - // Creates a volume - CreateVolume(provisioner *flockerVolumeProvisioner) (datasetUUID string, volumeSizeGB int, labels map[string]string, err error) - // Deletes a volume - DeleteVolume(deleter *flockerVolumeDeleter) error -} - -type flockerVolumeDeleter struct { - *flockerVolume -} - -var _ volume.Deleter = &flockerVolumeDeleter{} - -func (b *flockerVolumeDeleter) GetPath() string { - return getPath(b.podUID, b.volName, b.plugin.host) -} - -func (b *flockerVolumeDeleter) Delete() error { - return b.manager.DeleteVolume(b) -} - -type flockerVolumeProvisioner struct { - *flockerVolume - options volume.VolumeOptions -} - -var _ volume.Provisioner = &flockerVolumeProvisioner{} - -func (c *flockerVolumeProvisioner) Provision(selectedNode *v1.Node, allowedTopologies []v1.TopologySelectorTerm) (*v1.PersistentVolume, error) { - if !util.ContainsAllAccessModes(c.plugin.GetAccessModes(), c.options.PVC.Spec.AccessModes) { - return nil, fmt.Errorf("invalid AccessModes %v: only AccessModes %v are supported", c.options.PVC.Spec.AccessModes, c.plugin.GetAccessModes()) - } - - if len(c.options.Parameters) > 0 { - return nil, fmt.Errorf("provisioning failed: Specified at least one unsupported parameter") - } - - if c.options.PVC.Spec.Selector != nil { - return nil, fmt.Errorf("provisioning failed: Specified unsupported selector") - } - - if util.CheckPersistentVolumeClaimModeBlock(c.options.PVC) { - return nil, fmt.Errorf("%s does not support block volume provisioning", c.plugin.GetPluginName()) - } - - datasetUUID, sizeGB, labels, err := c.manager.CreateVolume(c) - if err != nil { - return nil, err - } - - pv := &v1.PersistentVolume{ - ObjectMeta: metav1.ObjectMeta{ - Name: c.options.PVName, - Labels: map[string]string{}, - Annotations: map[string]string{ - util.VolumeDynamicallyCreatedByKey: "flocker-dynamic-provisioner", - }, - }, - Spec: v1.PersistentVolumeSpec{ - PersistentVolumeReclaimPolicy: c.options.PersistentVolumeReclaimPolicy, - AccessModes: c.options.PVC.Spec.AccessModes, - Capacity: v1.ResourceList{ - v1.ResourceName(v1.ResourceStorage): resource.MustParse(fmt.Sprintf("%dGi", sizeGB)), - }, - PersistentVolumeSource: v1.PersistentVolumeSource{ - Flocker: &v1.FlockerVolumeSource{ - DatasetUUID: datasetUUID, - }, - }, - }, - } - if len(c.options.PVC.Spec.AccessModes) == 0 { - pv.Spec.AccessModes = c.plugin.GetAccessModes() - } - - if len(labels) != 0 { - if pv.Labels == nil { - pv.Labels = make(map[string]string) - } - for k, v := range labels { - pv.Labels[k] = v - } - } - - return pv, nil -} diff --git a/pkg/volume/flocker/flocker_volume_test.go b/pkg/volume/flocker/flocker_volume_test.go deleted file mode 100644 index 9964f1ed143..00000000000 --- a/pkg/volume/flocker/flocker_volume_test.go +++ /dev/null @@ -1,102 +0,0 @@ -/* -Copyright 2015 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 flocker - -import ( - "fmt" - "os" - "testing" - - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - utiltesting "k8s.io/client-go/util/testing" - "k8s.io/kubernetes/pkg/volume" - volumetest "k8s.io/kubernetes/pkg/volume/testing" - - "github.com/stretchr/testify/assert" -) - -func newTestableProvisioner(t *testing.T, assert *assert.Assertions, options volume.VolumeOptions) (string, volume.Provisioner) { - tmpDir, err := utiltesting.MkTmpdir("flockervolumeTest") - assert.NoError(err, fmt.Sprintf("can't make a temp dir: %v", err)) - - plugMgr := volume.VolumePluginMgr{} - plugMgr.InitPlugins(ProbeVolumePlugins(), nil /* prober */, volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)) - - plug, err := plugMgr.FindPluginByName(pluginName) - assert.NoError(err, "Can't find the plugin by name") - - provisioner, err := plug.(*flockerPlugin).newProvisionerInternal(options, &fakeFlockerUtil{}) - assert.NoError(err, fmt.Sprintf("Can't create new provisioner:%v", err)) - return tmpDir, provisioner -} - -func TestProvision(t *testing.T) { - assert := assert.New(t) - - pvc := volumetest.CreateTestPVC("3Gi", []v1.PersistentVolumeAccessMode{v1.ReadWriteOnce}) - options := volume.VolumeOptions{ - PVC: pvc, - PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, - } - - dir, provisioner := newTestableProvisioner(t, assert, options) - defer os.RemoveAll(dir) - - persistentSpec, err := provisioner.Provision(nil, nil) - assert.NoError(err, "Provision() failed: ", err) - - cap := persistentSpec.Spec.Capacity[v1.ResourceStorage] - - assert.Equal(int64(3*1024*1024*1024), cap.Value()) - - assert.Equal( - "test-flocker-volume-uuid", - persistentSpec.Spec.PersistentVolumeSource.Flocker.DatasetUUID, - ) - - assert.Equal( - map[string]string{"fakeflockerutil": "yes"}, - persistentSpec.Labels, - ) - - // parameters are not supported - options = volume.VolumeOptions{ - PVC: pvc, - PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, - Parameters: map[string]string{ - "not-supported-params": "test123", - }, - } - - dir, provisioner = newTestableProvisioner(t, assert, options) - defer os.RemoveAll(dir) - _, err = provisioner.Provision(nil, nil) - assert.Error(err, "Provision() did not fail with Parameters specified") - - // selectors are not supported - pvc.Spec.Selector = &metav1.LabelSelector{MatchLabels: map[string]string{"key": "value"}} - options = volume.VolumeOptions{ - PVC: pvc, - PersistentVolumeReclaimPolicy: v1.PersistentVolumeReclaimDelete, - } - - dir, provisioner = newTestableProvisioner(t, assert, options) - defer os.RemoveAll(dir) - _, err = provisioner.Provision(nil, nil) - assert.Error(err, "Provision() did not fail with Selector specified") -} diff --git a/vendor/github.com/clusterhq/flocker-go/LICENSE b/vendor/github.com/clusterhq/flocker-go/LICENSE deleted file mode 100644 index 9b72e90b75d..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/LICENSE +++ /dev/null @@ -1,190 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - Copyright 2014-2016 ClusterHQ - - 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. diff --git a/vendor/github.com/clusterhq/flocker-go/README.md b/vendor/github.com/clusterhq/flocker-go/README.md deleted file mode 100644 index 7c57e11295e..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/README.md +++ /dev/null @@ -1,18 +0,0 @@ -flocker-go -========== - -[![circleci](https://circleci.com/gh/ClusterHQ/flocker-go.svg)](https://circleci.com/gh/ClusterHQ/flocker-go) - -flocker-go implements the package `flocker` that will let you easily interact -with a Flocker Control Service. - -What can it do? ---------------- - -You can check the package documentation here: https://godoc.org/github.com/ClusterHQ/flocker-go - -TODO ----- - -- Define a proper interface `flockerClientable` with all the needed methods for - wrapping the Flocker API. diff --git a/vendor/github.com/clusterhq/flocker-go/circle.yml b/vendor/github.com/clusterhq/flocker-go/circle.yml deleted file mode 100644 index 81b56c8f27f..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/circle.yml +++ /dev/null @@ -1,16 +0,0 @@ -machine: - timezone: - America/Los_Angeles - -# Output the test output to circle. -test: - pre: - - go get -u github.com/jstemmer/go-junit-report - override: - - go test -coverprofile=coverage.out -v -race ./... > test.out - - cat test.out | go-junit-report > report.xml - - go tool cover -func=coverage.out - post: - - mv test.out $CIRCLE_ARTIFACTS/ - - mv report.xml $CIRCLE_TEST_REPORTS/ - diff --git a/vendor/github.com/clusterhq/flocker-go/client.go b/vendor/github.com/clusterhq/flocker-go/client.go deleted file mode 100644 index 7cdd71054cb..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/client.go +++ /dev/null @@ -1,376 +0,0 @@ -package flocker - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "net/http" - "time" -) - -// From https://github.com/ClusterHQ/flocker-docker-plugin/blob/master/flockerdockerplugin/adapter.py#L18 -const defaultVolumeSize = json.Number("107374182400") - -var ( - // A volume can take a long time to be available, if we don't want - // Kubernetes to wait forever we need to stop trying after some time, that - // time is defined here - timeoutWaitingForVolume = 2 * time.Minute - tickerWaitingForVolume = 5 * time.Second - - errStateNotFound = errors.New("State not found by Dataset ID") - errConfigurationNotFound = errors.New("Configuration not found by Name") - - errFlockerControlServiceHost = errors.New("The volume config must have a key CONTROL_SERVICE_HOST defined in the OtherAttributes field") - errFlockerControlServicePort = errors.New("The volume config must have a key CONTROL_SERVICE_PORT defined in the OtherAttributes field") - - errVolumeAlreadyExists = errors.New("The volume already exists") - errVolumeDoesNotExist = errors.New("The volume does not exist") - - errUpdatingDataset = errors.New("It was impossible to update the dataset") -) - -// Clientable exposes the needed methods to implement your own Flocker Client. -type Clientable interface { - CreateDataset(options *CreateDatasetOptions) (*DatasetState, error) - DeleteDataset(datasetID string) error - - GetDatasetState(datasetID string) (*DatasetState, error) - GetDatasetID(metaName string) (datasetID string, err error) - GetPrimaryUUID() (primaryUUID string, err error) - - ListNodes() (nodes []NodeState, err error) - - UpdatePrimaryForDataset(primaryUUID, datasetID string) (*DatasetState, error) -} - -// Client is a default Flocker Client. -type Client struct { - *http.Client - - schema string - host string - port int - version string - - clientIP string - - maximumSize json.Number -} - -var _ Clientable = &Client{} - -// NewClient creates a wrapper over http.Client to communicate with the flocker control service. -func NewClient(host string, port int, clientIP string, caCertPath, keyPath, certPath string) (*Client, error) { - client, err := newTLSClient(caCertPath, keyPath, certPath) - if err != nil { - return nil, err - } - - return &Client{ - Client: client, - schema: "https", - host: host, - port: port, - version: "v1", - maximumSize: defaultVolumeSize, - clientIP: clientIP, - }, nil -} - -/* -request do a request using the http.Client embedded to the control service -and returns the response or an error in case it happens. - -Note: you will need to deal with the response body call to Close if you -don't want to deal with problems later. -*/ -func (c Client) request(method, url string, payload interface{}) (*http.Response, error) { - var ( - b []byte - err error - ) - - if method == "POST" { // Just allow payload on POST - b, err = json.Marshal(payload) - if err != nil { - return nil, err - } - } - - req, err := http.NewRequest(method, url, bytes.NewBuffer(b)) - if err != nil { - return nil, err - } - req.Header.Set("Content-Type", "application/json") - - // REMEMBER TO CLOSE THE BODY IN THE OUTSIDE FUNCTION - return c.Do(req) -} - -// post performs a post request with the indicated payload -func (c Client) post(url string, payload interface{}) (*http.Response, error) { - return c.request("POST", url, payload) -} - -// delete performs a delete request with the indicated payload -func (c Client) delete(url string, payload interface{}) (*http.Response, error) { - return c.request("DELETE", url, payload) -} - -// get performs a get request -func (c Client) get(url string) (*http.Response, error) { - return c.request("GET", url, nil) -} - -// getURL returns a full URI to the control service -func (c Client) getURL(path string) string { - return fmt.Sprintf("%s://%s:%d/%s/%s", c.schema, c.host, c.port, c.version, path) -} - -type configurationPayload struct { - Deleted bool `json:"deleted"` - Primary string `json:"primary"` - DatasetID string `json:"dataset_id,omitempty"` - MaximumSize json.Number `json:"maximum_size,omitempty"` - Metadata metadataPayload `json:"metadata,omitempty"` -} - -type CreateDatasetOptions struct { - Primary string `json:"primary"` - DatasetID string `json:"dataset_id,omitempty"` - MaximumSize int64 `json:"maximum_size,omitempty"` - Metadata map[string]string `json:"metadata,omitempty"` -} - -type metadataPayload struct { - Name string `json:"name,omitempty"` -} - -type DatasetState struct { - Path string `json:"path"` - DatasetID string `json:"dataset_id"` - Primary string `json:"primary,omitempty"` - MaximumSize json.Number `json:"maximum_size,omitempty"` -} - -type datasetStatePayload struct { - *DatasetState -} - -type NodeState struct { - UUID string `json:"uuid"` - Host string `json:"host"` -} - -// findIDInConfigurationsPayload returns the datasetID if it was found in the -// configurations payload, otherwise it will return an error. -func (c Client) findIDInConfigurationsPayload(body io.ReadCloser, name string) (datasetID string, err error) { - var configurations []configurationPayload - if err = json.NewDecoder(body).Decode(&configurations); err == nil { - for _, r := range configurations { - if r.Metadata.Name == name { - return r.DatasetID, nil - } - } - return "", errConfigurationNotFound - } - return "", err -} - -// ListNodes returns a list of dataset agent nodes from Flocker Control Service -func (c *Client) ListNodes() (nodes []NodeState, err error) { - resp, err := c.get(c.getURL("state/nodes")) - if err != nil { - return []NodeState{}, err - } - defer resp.Body.Close() - if resp.StatusCode >= 300 { - return []NodeState{}, fmt.Errorf("Expected: {1,2}xx listing nodes, got: %d", resp.StatusCode) - } - - err = json.NewDecoder(resp.Body).Decode(&nodes) - if err != nil { - return []NodeState{}, err - } - return nodes, err -} - -// GetPrimaryUUID returns the UUID of the primary Flocker Control Service for -// the given host. -func (c Client) GetPrimaryUUID() (uuid string, err error) { - states, err := c.ListNodes() - if err != nil { - return "", err - } - - for _, s := range states { - if s.Host == c.clientIP { - return s.UUID, nil - } - } - return "", fmt.Errorf("No node found with IP '%s', available nodes %+v", c.clientIP, states) -} - -// DeleteDataset performs a delete request to the given datasetID -func (c *Client) DeleteDataset(datasetID string) error { - url := c.getURL(fmt.Sprintf("configuration/datasets/%s", datasetID)) - resp, err := c.delete(url, nil) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode >= 300 { - return fmt.Errorf("Expected: {1,2}xx deleting the dataset %s, got: %d", datasetID, resp.StatusCode) - } - - return nil -} - -// GetDatasetState performs a get request to get the state of the given datasetID, if -// something goes wrong or the datasetID was not found it returns an error. -func (c Client) GetDatasetState(datasetID string) (*DatasetState, error) { - resp, err := c.get(c.getURL("state/datasets")) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var states []datasetStatePayload - if err = json.NewDecoder(resp.Body).Decode(&states); err == nil { - for _, s := range states { - if s.DatasetID == datasetID { - return s.DatasetState, nil - } - } - return nil, errStateNotFound - } - - return nil, err -} - -/* -CreateDataset creates a volume in Flocker, waits for it to be ready and -returns the dataset id. - -This process is a little bit complex but follows this flow: - -1. Find the Flocker Control Service UUID -2. If it already exists an error is returned -3. If it didn't previously exist, wait for it to be ready -*/ -func (c *Client) CreateDataset(options *CreateDatasetOptions) (datasetState *DatasetState, err error) { - // 1) Find the primary Flocker UUID - // Note: it could be cached, but doing this query we health check it - if options.Primary == "" { - options.Primary, err = c.GetPrimaryUUID() - if err != nil { - return nil, err - } - } - - if options.MaximumSize == 0 { - options.MaximumSize, _ = c.maximumSize.Int64() - } - - resp, err := c.post(c.getURL("configuration/datasets"), options) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - // 2) Return if the dataset was previously created - if resp.StatusCode == http.StatusConflict { - return nil, errVolumeAlreadyExists - } - - if resp.StatusCode >= 300 { - return nil, fmt.Errorf("Expected: {1,2}xx creating the volume, got: %d", resp.StatusCode) - } - - var p configurationPayload - if err := json.NewDecoder(resp.Body).Decode(&p); err != nil { - return nil, err - } - - // 3) Wait until the dataset is ready for usage. In case it never gets - // ready there is a timeoutChan that will return an error - timeoutChan := time.NewTimer(timeoutWaitingForVolume).C - tickChan := time.NewTicker(tickerWaitingForVolume).C - - for { - var strErrDel string - s, err := c.GetDatasetState(p.DatasetID) - if err == nil { - return s, nil - } else if err != errStateNotFound { - errDel := c.DeleteDataset(p.DatasetID) - if errDel != nil { - strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel) - } - return nil, fmt.Errorf("Flocker API error during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel) - } - - select { - case <-timeoutChan: - errDel := c.DeleteDataset(p.DatasetID) - if errDel != nil { - strErrDel = fmt.Sprintf(", deletion of dataset failed with %s", errDel) - } - return nil, fmt.Errorf("Flocker API timeout during dataset creation (datasetID %s): %s%s", p.DatasetID, err, strErrDel) - case <-tickChan: - break - } - } -} - -// UpdatePrimaryForDataset will update the Primary for the given dataset -// returning the current DatasetState. -func (c Client) UpdatePrimaryForDataset(newPrimaryUUID, datasetID string) (*DatasetState, error) { - payload := struct { - Primary string `json:"primary"` - }{ - Primary: newPrimaryUUID, - } - - url := c.getURL(fmt.Sprintf("configuration/datasets/%s", datasetID)) - resp, err := c.post(url, payload) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if resp.StatusCode >= 300 { - return nil, errUpdatingDataset - } - - var s DatasetState - if err := json.NewDecoder(resp.Body).Decode(&s); err != nil { - return nil, err - } - - return &s, nil -} - -// GetDatasetID will return the DatasetID found for the given metadata name. -func (c Client) GetDatasetID(metaName string) (datasetID string, err error) { - resp, err := c.get(c.getURL("configuration/datasets")) - if err != nil { - return "", err - } - defer resp.Body.Close() - - var configurations []configurationPayload - if err = json.NewDecoder(resp.Body).Decode(&configurations); err == nil { - for _, c := range configurations { - if c.Metadata.Name == metaName && c.Deleted == false { - return c.DatasetID, nil - } - } - return "", errConfigurationNotFound - } - return "", err -} diff --git a/vendor/github.com/clusterhq/flocker-go/doc.go b/vendor/github.com/clusterhq/flocker-go/doc.go deleted file mode 100644 index f3cd05b0196..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// flocker package allows you to easily interact with a Flocker Control Service. -package flocker diff --git a/vendor/github.com/clusterhq/flocker-go/util.go b/vendor/github.com/clusterhq/flocker-go/util.go deleted file mode 100644 index 8322ea8cd78..00000000000 --- a/vendor/github.com/clusterhq/flocker-go/util.go +++ /dev/null @@ -1,34 +0,0 @@ -package flocker - -import ( - "crypto/tls" - "crypto/x509" - "io/ioutil" - "net/http" -) - -// newTLSClient returns a new TLS http client -func newTLSClient(caCertPath, keyPath, certPath string) (*http.Client, error) { - // Client certificate - cert, err := tls.LoadX509KeyPair(certPath, keyPath) - if err != nil { - return nil, err - } - - // CA certificate - caCert, err := ioutil.ReadFile(caCertPath) - if err != nil { - return nil, err - } - caCertPool := x509.NewCertPool() - caCertPool.AppendCertsFromPEM(caCert) - - tlsConfig := &tls.Config{ - Certificates: []tls.Certificate{cert}, - RootCAs: caCertPool, - } - tlsConfig.BuildNameToCertificate() - transport := &http.Transport{TLSClientConfig: tlsConfig} - - return &http.Client{Transport: transport}, nil -} diff --git a/vendor/modules.txt b/vendor/modules.txt index 81bdcda4c2b..a17fd4604e1 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -191,9 +191,6 @@ github.com/cilium/ebpf/internal github.com/cilium/ebpf/internal/btf github.com/cilium/ebpf/internal/unix github.com/cilium/ebpf/link -# github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 -## explicit -github.com/clusterhq/flocker-go # github.com/container-storage-interface/spec v1.6.0 => github.com/container-storage-interface/spec v1.6.0 ## explicit; go 1.16 github.com/container-storage-interface/spec/lib/go/csi @@ -2602,7 +2599,6 @@ sigs.k8s.io/yaml # github.com/chzyer/readline => github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e # github.com/chzyer/test => github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 # github.com/cilium/ebpf => github.com/cilium/ebpf v0.7.0 -# github.com/clusterhq/flocker-go => github.com/clusterhq/flocker-go v0.0.0-20160920122132-2b8b7259d313 # github.com/cncf/udpa/go => github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4 # github.com/cncf/xds/go => github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1 # github.com/cockroachdb/datadriven => github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5