mirror of
https://github.com/TECHNOFAB11/zfs-localpv.git
synced 2025-12-12 14:30:12 +01:00
refact(csi): use common lib-csi imports (#263)
Signed-off-by: shubham <shubham.bajpai@mayadata.io>
This commit is contained in:
parent
48e6a19d7c
commit
2906d39d94
55 changed files with 271 additions and 611 deletions
201
vendor/github.com/openebs/lib-csi/LICENSE
generated
vendored
Normal file
201
vendor/github.com/openebs/lib-csi/LICENSE
generated
vendored
Normal file
|
|
@ -0,0 +1,201 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
43
vendor/github.com/openebs/lib-csi/pkg/btrfs/btrfs_util.go
generated
vendored
Normal file
43
vendor/github.com/openebs/lib-csi/pkg/btrfs/btrfs_util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 btrfs
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
/*
|
||||
* We have to generate a new UUID for the cloned volumes with btrfs filesystem
|
||||
* otherwise system will mount the same volume if UUID is same. Here, since cloned
|
||||
* volume refers to the same block because of the way ZFS clone works, it will
|
||||
* also have the same UUID.
|
||||
*/
|
||||
|
||||
// GenerateUUID generates a new btrfs UUID for the given device
|
||||
func GenerateUUID(device string) error {
|
||||
// for mounting the cloned volume for btrfs, a new UUID has to be generated
|
||||
cmd := exec.Command("btrfstune", "-f", "-u", device)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("btrfs: uuid generate failed for device %s error: %s", device, string(out))
|
||||
return err
|
||||
}
|
||||
klog.Infof("btrfs: generated UUID for the device %s \n %v", device, string(out))
|
||||
return nil
|
||||
}
|
||||
44
vendor/github.com/openebs/lib-csi/pkg/client/k8s/clientset.go
generated
vendored
Normal file
44
vendor/github.com/openebs/lib-csi/pkg/client/k8s/clientset.go
generated
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
// ClientsetGetter abstracts fetching of kubernetes clientset
|
||||
type ClientsetGetter interface {
|
||||
Get() (*kubernetes.Clientset, error)
|
||||
}
|
||||
|
||||
// ClientsetStruct is used to export a kuberneter Clientset
|
||||
type ClientsetStruct struct{}
|
||||
|
||||
// Clientset returns a pointer to clientset struct
|
||||
func Clientset() *ClientsetStruct {
|
||||
return &ClientsetStruct{}
|
||||
}
|
||||
|
||||
// Get returns a new instance of kubernetes clientset
|
||||
func (c *ClientsetStruct) Get() (*kubernetes.Clientset, error) {
|
||||
config, err := Config().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get kubernetes clientset")
|
||||
}
|
||||
return kubernetes.NewForConfig(config)
|
||||
}
|
||||
100
vendor/github.com/openebs/lib-csi/pkg/client/k8s/config.go
generated
vendored
Normal file
100
vendor/github.com/openebs/lib-csi/pkg/client/k8s/config.go
generated
vendored
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/openebs/lib-csi/pkg/common/env"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// ConfigGetter abstracts fetching of kubernetes client config
|
||||
type ConfigGetter interface {
|
||||
Get() (*rest.Config, error)
|
||||
Name() string
|
||||
}
|
||||
|
||||
// configFromENV is an implementation of ConfigGetter
|
||||
type configFromENV struct{}
|
||||
|
||||
// Name returns the name of this config getter instance
|
||||
func (c *configFromENV) Name() string {
|
||||
return "k8s-config-from-env"
|
||||
}
|
||||
|
||||
// Get returns kubernetes rest config based on kubernetes environment values
|
||||
func (c *configFromENV) Get() (*rest.Config, error) {
|
||||
k8sMaster := env.Get(env.KubeMaster)
|
||||
kubeConfig := env.Get(env.KubeConfig)
|
||||
|
||||
if len(strings.TrimSpace(k8sMaster)) == 0 && len(strings.TrimSpace(kubeConfig)) == 0 {
|
||||
return nil, errors.New("missing kubernetes master as well as kubeconfig: failed to get kubernetes client config")
|
||||
}
|
||||
|
||||
return clientcmd.BuildConfigFromFlags(k8sMaster, kubeConfig)
|
||||
}
|
||||
|
||||
// configFromREST is an implementation of ConfigGetter
|
||||
type configFromREST struct{}
|
||||
|
||||
// Name returns the name of this config getter instance
|
||||
func (c *configFromREST) Name() string {
|
||||
return "k8s-config-from-rest"
|
||||
}
|
||||
|
||||
// Get returns kubernetes rest config based on in-cluster config implementation
|
||||
func (c *configFromREST) Get() (*rest.Config, error) {
|
||||
return rest.InClusterConfig()
|
||||
}
|
||||
|
||||
// ConfigGetters holds a list of ConfigGetter instances
|
||||
//
|
||||
// NOTE:
|
||||
// This is an implementation of ConfigGetter
|
||||
type ConfigGetters []ConfigGetter
|
||||
|
||||
// Name returns the name of this config getter instance
|
||||
func (c ConfigGetters) Name() string {
|
||||
return "list-of-k8s-config-getter"
|
||||
}
|
||||
|
||||
// Get fetches the kubernetes client config that is used to make kubernetes API
|
||||
// calls. It makes use of its list of getter instances to fetch kubernetes
|
||||
// config.
|
||||
func (c ConfigGetters) Get() (config *rest.Config, err error) {
|
||||
var errs []error
|
||||
for _, g := range c {
|
||||
config, err = g.Get()
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
errs = append(errs, errors.Wrapf(err, "failed to get kubernetes client config via %s", g.Name()))
|
||||
}
|
||||
// at this point; all getters have failed
|
||||
err = errors.Errorf("%+v", errs)
|
||||
err = errors.Wrap(err, "failed to get kubernetes client config")
|
||||
return
|
||||
}
|
||||
|
||||
// Config provides appropriate config getter instances that help in fetching
|
||||
// kubernetes client config to invoke kubernetes API calls
|
||||
func Config() ConfigGetter {
|
||||
return ConfigGetters{&configFromENV{}, &configFromREST{}}
|
||||
}
|
||||
54
vendor/github.com/openebs/lib-csi/pkg/client/k8s/configmap.go
generated
vendored
Normal file
54
vendor/github.com/openebs/lib-csi/pkg/client/k8s/configmap.go
generated
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// ConfigMapGetter abstracts fetching of ConfigMap instance from kubernetes
|
||||
// cluster
|
||||
type ConfigMapGetter interface {
|
||||
Get(options metav1.GetOptions) (*corev1.ConfigMap, error)
|
||||
}
|
||||
|
||||
// Configmap is used to initialise a kubernetes Configmap struct
|
||||
type Configmap struct {
|
||||
namespace string // namespace where this configmap exists
|
||||
name string // name of this configmap
|
||||
}
|
||||
|
||||
// ConfigMap returns a new instance of configmap
|
||||
func ConfigMap(namespace, name string) *Configmap {
|
||||
return &Configmap{namespace: namespace, name: name}
|
||||
}
|
||||
|
||||
// Get returns configmap instance from kubernetes cluster
|
||||
func (c *Configmap) Get(options metav1.GetOptions) (cm *corev1.ConfigMap, err error) {
|
||||
if len(strings.TrimSpace(c.name)) == 0 {
|
||||
return nil, errors.Errorf("missing config map name: failed to get config map from namespace %s", c.namespace)
|
||||
}
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get config map %s %s", c.namespace, c.name)
|
||||
}
|
||||
return cs.CoreV1().ConfigMaps(c.namespace).Get(c.name, options)
|
||||
}
|
||||
45
vendor/github.com/openebs/lib-csi/pkg/client/k8s/dynamic.go
generated
vendored
Normal file
45
vendor/github.com/openebs/lib-csi/pkg/client/k8s/dynamic.go
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
k8sdynamic "k8s.io/client-go/dynamic"
|
||||
)
|
||||
|
||||
// DynamicProvider abstracts providing kubernetes dynamic client interface
|
||||
type DynamicProvider interface {
|
||||
Provide() (k8sdynamic.Interface, error)
|
||||
}
|
||||
|
||||
//DynamicStruct is used to initialise a kuberenets dynamic interface
|
||||
type DynamicStruct struct{}
|
||||
|
||||
// Dynamic returns a new instance of dynamic
|
||||
func Dynamic() *DynamicStruct {
|
||||
return &DynamicStruct{}
|
||||
}
|
||||
|
||||
// Provide provides a kubernetes dynamic client capable of invoking operations
|
||||
// against kubernetes resources
|
||||
func (d *DynamicStruct) Provide() (k8sdynamic.Interface, error) {
|
||||
config, err := Config().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to provide dynamic client")
|
||||
}
|
||||
return k8sdynamic.NewForConfig(config)
|
||||
}
|
||||
32
vendor/github.com/openebs/lib-csi/pkg/client/k8s/k8s.go
generated
vendored
Normal file
32
vendor/github.com/openebs/lib-csi/pkg/client/k8s/k8s.go
generated
vendored
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
// GetServerVersion uses the client-go Discovery client to get the
|
||||
// kubernetes version struct
|
||||
func GetServerVersion() (*version.Info, error) {
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get apiserver version")
|
||||
}
|
||||
return cs.Discovery().ServerVersion()
|
||||
}
|
||||
59
vendor/github.com/openebs/lib-csi/pkg/client/k8s/namespace.go
generated
vendored
Normal file
59
vendor/github.com/openebs/lib-csi/pkg/client/k8s/namespace.go
generated
vendored
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// NamespaceGetter abstracts fetching of Namespace from kubernetes cluster
|
||||
type NamespaceGetter interface {
|
||||
Get(name string, options metav1.GetOptions) (*corev1.Namespace, error)
|
||||
}
|
||||
|
||||
// NamespaceLister abstracts fetching of a list of namespaces from kubernetes cluster
|
||||
type NamespaceLister interface {
|
||||
List(options metav1.ListOptions) (*corev1.NamespaceList, error)
|
||||
}
|
||||
|
||||
// NamespaceStruct is used to initialise kubernetes namespace instnaces
|
||||
type NamespaceStruct struct{}
|
||||
|
||||
// Namespace returns a pointer to the namespace struct
|
||||
func Namespace() *NamespaceStruct {
|
||||
return &NamespaceStruct{}
|
||||
}
|
||||
|
||||
// Get returns a namespace instance from kubernetes cluster
|
||||
func (ns *NamespaceStruct) Get(name string, options metav1.GetOptions) (*corev1.Namespace, error) {
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get namespace: %s", name)
|
||||
}
|
||||
return cs.CoreV1().Namespaces().Get(name, options)
|
||||
}
|
||||
|
||||
// List returns a slice of namespaces defined in a Kubernetes cluster
|
||||
func (ns *NamespaceStruct) List(options metav1.ListOptions) (*corev1.NamespaceList, error) {
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get namespaces")
|
||||
}
|
||||
return cs.CoreV1().Namespaces().List(options)
|
||||
}
|
||||
101
vendor/github.com/openebs/lib-csi/pkg/client/k8s/node.go
generated
vendored
Normal file
101
vendor/github.com/openebs/lib-csi/pkg/client/k8s/node.go
generated
vendored
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 k8s
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
// NodeGetter abstracts fetching of Node details from kubernetes cluster
|
||||
type NodeGetter interface {
|
||||
Get(name string, options metav1.GetOptions) (*corev1.Node, error)
|
||||
}
|
||||
|
||||
// NodeLister abstracts fetching of Nodes from kubernetes cluster
|
||||
type NodeLister interface {
|
||||
List(options metav1.ListOptions) (*corev1.NodeList, error)
|
||||
}
|
||||
|
||||
//NodeStruct returns a struct used to instantiate a kubernetes Node
|
||||
type NodeStruct struct{}
|
||||
|
||||
// Node returnd a pointer to the node struct
|
||||
func Node() *NodeStruct {
|
||||
return &NodeStruct{}
|
||||
}
|
||||
|
||||
// Get returns a node instance from kubernetes cluster
|
||||
func (n *NodeStruct) Get(name string, options metav1.GetOptions) (*corev1.Node, error) {
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get node: %s", name)
|
||||
}
|
||||
return cs.CoreV1().Nodes().Get(name, options)
|
||||
}
|
||||
|
||||
// List returns a slice of Nodes registered in a Kubernetes cluster
|
||||
func (n *NodeStruct) List(options metav1.ListOptions) (*corev1.NodeList, error) {
|
||||
cs, err := Clientset().Get()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get nodes")
|
||||
}
|
||||
return cs.CoreV1().Nodes().List(options)
|
||||
}
|
||||
|
||||
// NumberOfNodes returns the number of nodes registered in a Kubernetes cluster
|
||||
func NumberOfNodes() (int, error) {
|
||||
n := Node()
|
||||
nodes, err := n.List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return 0, errors.Wrapf(err, "failed to get the number of nodes")
|
||||
}
|
||||
return len(nodes.Items), nil
|
||||
}
|
||||
|
||||
// GetNode returns a node instance from kubernetes cluster
|
||||
func GetNode(name string) (*corev1.Node, error) {
|
||||
n := Node()
|
||||
node, err := n.Get(name, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get node")
|
||||
}
|
||||
return node, nil
|
||||
}
|
||||
|
||||
// ListNodes returns list of node instance from kubernetes cluster
|
||||
func ListNodes(options metav1.ListOptions) (*corev1.NodeList, error) {
|
||||
n := Node()
|
||||
nodelist, err := n.List(options)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to list node")
|
||||
}
|
||||
return nodelist, nil
|
||||
}
|
||||
|
||||
// GetOSAndKernelVersion gets us the OS,Kernel version
|
||||
func GetOSAndKernelVersion() (string, error) {
|
||||
nodes := Node()
|
||||
// get a single node
|
||||
firstNode, err := nodes.List(metav1.ListOptions{Limit: 1})
|
||||
if err != nil {
|
||||
return "unknown, unknown", errors.Wrapf(err, "failed to get the os kernel/arch")
|
||||
}
|
||||
nodedetails := firstNode.Items[0].Status.NodeInfo
|
||||
return nodedetails.OSImage + ", " + nodedetails.KernelVersion, nil
|
||||
}
|
||||
362
vendor/github.com/openebs/lib-csi/pkg/client/k8s/resource.go
generated
vendored
Normal file
362
vendor/github.com/openebs/lib-csi/pkg/client/k8s/resource.go
generated
vendored
Normal file
|
|
@ -0,0 +1,362 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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.
|
||||
*/
|
||||
|
||||
// TODO
|
||||
// Move this file to pkg/k8sresource/v1alpha1
|
||||
|
||||
package k8s
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// ResourceCreator abstracts creating an unstructured instance in kubernetes
|
||||
// cluster
|
||||
type ResourceCreator interface {
|
||||
Create(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
// ResourceGetter abstracts fetching an unstructured instance from kubernetes
|
||||
// cluster
|
||||
type ResourceGetter interface {
|
||||
Get(name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
// ResourceLister abstracts fetching an unstructured list of instance from kubernetes
|
||||
// cluster
|
||||
type ResourceLister interface {
|
||||
List(options metav1.ListOptions) (*unstructured.UnstructuredList, error)
|
||||
}
|
||||
|
||||
// ResourceUpdater abstracts updating an unstructured instance found in
|
||||
// kubernetes cluster
|
||||
type ResourceUpdater interface {
|
||||
Update(oldobj, newobj *unstructured.Unstructured, subresources ...string) (u *unstructured.Unstructured, err error)
|
||||
}
|
||||
|
||||
// ResourceApplier abstracts applying an unstructured instance that may or may
|
||||
// not be available in kubernetes cluster
|
||||
type ResourceApplier interface {
|
||||
Apply(obj *unstructured.Unstructured, subresources ...string) (*unstructured.Unstructured, error)
|
||||
}
|
||||
|
||||
// ResourceDeleter abstracts deletes an unstructured instance that is available in kubernetes cluster
|
||||
type ResourceDeleter interface {
|
||||
Delete(obj *unstructured.Unstructured, subresources ...string) error
|
||||
}
|
||||
|
||||
// ResourceStruct is used to abstract a kubernetes struct
|
||||
type ResourceStruct struct {
|
||||
gvr schema.GroupVersionResource // identify a resource
|
||||
namespace string // namespace where this resource is to be operated at
|
||||
}
|
||||
|
||||
// String implements Stringer interface
|
||||
func (r *ResourceStruct) String() string {
|
||||
return r.gvr.String()
|
||||
}
|
||||
|
||||
// Resource returns a new resource instance
|
||||
func Resource(gvr schema.GroupVersionResource, namespace string) *ResourceStruct {
|
||||
return &ResourceStruct{gvr: gvr, namespace: namespace}
|
||||
}
|
||||
|
||||
// Create creates a new resource in kubernetes cluster
|
||||
func (r *ResourceStruct) Create(obj *unstructured.Unstructured, subresources ...string) (u *unstructured.Unstructured, err error) {
|
||||
if obj == nil {
|
||||
err = errors.Errorf("nil resource instance: failed to create resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
dynamic, err := Dynamic().Provide()
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to create resource '%s' '%s' at '%s'", r.gvr, obj.GetName(), r.namespace)
|
||||
return
|
||||
}
|
||||
u, err = dynamic.Resource(r.gvr).Namespace(r.namespace).Create(obj, metav1.CreateOptions{}, subresources...)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to create resource '%s' '%s' at '%s'", r.gvr, obj.GetName(), r.namespace)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Delete deletes a existing resource in kubernetes cluster
|
||||
func (r *ResourceStruct) Delete(obj *unstructured.Unstructured, subresources ...string) error {
|
||||
if obj == nil {
|
||||
return errors.Errorf("nil resource instance: failed to delete resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
}
|
||||
dynamic, err := Dynamic().Provide()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to delete resource '%s' '%s' at '%s'", r.gvr, obj.GetName(), r.namespace)
|
||||
}
|
||||
err = dynamic.Resource(r.gvr).Namespace(r.namespace).Delete(obj.GetName(), &metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to delete resource '%s' '%s' at '%s'", r.gvr, obj.GetName(), r.namespace)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get returns a specific resource from kubernetes cluster
|
||||
func (r *ResourceStruct) Get(name string, opts metav1.GetOptions, subresources ...string) (u *unstructured.Unstructured, err error) {
|
||||
if len(strings.TrimSpace(name)) == 0 {
|
||||
err = errors.Errorf("missing resource name: failed to get resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
dynamic, err := Dynamic().Provide()
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to get resource '%s' '%s' at '%s'", r.gvr, name, r.namespace)
|
||||
return
|
||||
}
|
||||
u, err = dynamic.Resource(r.gvr).Namespace(r.namespace).Get(name, opts, subresources...)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to get resource '%s' '%s' at '%s'", r.gvr, name, r.namespace)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Update updates the resource at kubernetes cluster
|
||||
func (r *ResourceStruct) Update(oldobj, newobj *unstructured.Unstructured, subresources ...string) (u *unstructured.Unstructured, err error) {
|
||||
if oldobj == nil {
|
||||
err = errors.Errorf("nil old resource instance: failed to update resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
if newobj == nil {
|
||||
err = errors.Errorf("nil new resource instance: failed to update resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
dynamic, err := Dynamic().Provide()
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to update resource '%s' '%s' at '%s'", r.gvr, oldobj.GetName(), r.namespace)
|
||||
return
|
||||
}
|
||||
|
||||
resourceVersion := oldobj.GetResourceVersion()
|
||||
newobj.SetResourceVersion(resourceVersion)
|
||||
|
||||
u, err = dynamic.Resource(r.gvr).Namespace(r.namespace).Update(newobj, metav1.UpdateOptions{}, subresources...)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to update resource '%s' '%s' at '%s'", r.gvr, oldobj.GetName(), r.namespace)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// List returns a list of specific resource at kubernetes cluster
|
||||
func (r *ResourceStruct) List(opts metav1.ListOptions) (u *unstructured.UnstructuredList, err error) {
|
||||
dynamic, err := Dynamic().Provide()
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to list resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
u, err = dynamic.Resource(r.gvr).Namespace(r.namespace).List(opts)
|
||||
if err != nil {
|
||||
err = errors.Wrapf(err, "failed to list resource '%s' at '%s'", r.gvr, r.namespace)
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// ResourceCreateOrUpdater as the name suggests manages to either
|
||||
// create or update a given resource. It does so by implementing
|
||||
// ResourceApplier interface
|
||||
type ResourceCreateOrUpdater struct {
|
||||
*ResourceStruct
|
||||
|
||||
// Various executors required to perform Apply
|
||||
// This is how this instance decouples its dependencies
|
||||
Getter ResourceGetter
|
||||
Creator ResourceCreator
|
||||
Updater ResourceUpdater
|
||||
|
||||
// IsSkipUpdate will not update this resource if set to true.
|
||||
// In other words, enabling this flag can only create the
|
||||
// resource in the cluster if not created previously
|
||||
IsSkipUpdate bool
|
||||
}
|
||||
|
||||
// ResourceCreateOrUpdaterOption is a typed function used to
|
||||
// build an instance of ResourceCreateOrUpdater
|
||||
//
|
||||
// NOTE:
|
||||
// This follows the pattern known as "functional options". It
|
||||
// is a function that operates on a given structure as a value
|
||||
// to build (initialise, configure, sensible defaults, etc) this
|
||||
// same structure.
|
||||
type ResourceCreateOrUpdaterOption func(*ResourceCreateOrUpdater)
|
||||
|
||||
// ResourceCreateOrUpdaterSkipUpdate sets IsSkipUpdate based
|
||||
// on the provided flag
|
||||
func ResourceCreateOrUpdaterSkipUpdate(skip bool) ResourceCreateOrUpdaterOption {
|
||||
return func(r *ResourceCreateOrUpdater) {
|
||||
r.IsSkipUpdate = skip
|
||||
}
|
||||
}
|
||||
|
||||
// NewResourceCreateOrUpdater returns a new instance of
|
||||
// ResourceCreateOrUpdater
|
||||
func NewResourceCreateOrUpdater(
|
||||
gvr schema.GroupVersionResource,
|
||||
namespace string,
|
||||
options ...ResourceCreateOrUpdaterOption,
|
||||
) *ResourceCreateOrUpdater {
|
||||
resource := Resource(gvr, namespace)
|
||||
t := &ResourceCreateOrUpdater{
|
||||
ResourceStruct: resource,
|
||||
Getter: resource,
|
||||
Creator: resource,
|
||||
Updater: resource,
|
||||
}
|
||||
for _, o := range options {
|
||||
o(t)
|
||||
}
|
||||
return t
|
||||
}
|
||||
|
||||
// String implements Stringer interface
|
||||
func (r *ResourceCreateOrUpdater) String() string {
|
||||
if r.ResourceStruct == nil {
|
||||
return "ResourceCreateOrUpdater"
|
||||
}
|
||||
return fmt.Sprintf("ResourceCreateOrUpdater %s", r.ResourceStruct)
|
||||
}
|
||||
|
||||
// Apply applies a resource to the kubernetes cluster. In other words, it
|
||||
// creates a new resource if it does not exist or updates the existing
|
||||
// resource.
|
||||
func (r *ResourceCreateOrUpdater) Apply(
|
||||
obj *unstructured.Unstructured,
|
||||
subresources ...string,
|
||||
) (resource *unstructured.Unstructured, err error) {
|
||||
if r.Getter == nil {
|
||||
err = errors.Errorf("%s: Apply failed: Nil getter", r)
|
||||
return
|
||||
}
|
||||
if r.Creator == nil {
|
||||
err = errors.Errorf("%s: Apply failed: Nil creator", r)
|
||||
return
|
||||
}
|
||||
if r.Updater == nil {
|
||||
err = errors.Errorf("%s: Apply failed: Nil updater", r)
|
||||
return
|
||||
}
|
||||
if obj == nil {
|
||||
err = errors.Errorf("%s: Apply failed: Nil resource", r)
|
||||
return
|
||||
}
|
||||
resource, err = r.Getter.Get(obj.GetName(), metav1.GetOptions{})
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(errors.Cause(err)) {
|
||||
return r.Creator.Create(obj, subresources...)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if r.IsSkipUpdate {
|
||||
klog.V(2).Infof("%s: Skipping update", r)
|
||||
return resource, nil
|
||||
}
|
||||
return r.Updater.Update(resource, obj, subresources...)
|
||||
}
|
||||
|
||||
// ResourceDeleteOptions is a utility instance used during the resource's delete operations
|
||||
type ResourceDeleteOptions struct {
|
||||
Deleter ResourceDeleter
|
||||
}
|
||||
|
||||
// Delete is a resource that is suitable to be executed as a Delete operation
|
||||
type Delete struct {
|
||||
*ResourceStruct
|
||||
options ResourceDeleteOptions
|
||||
}
|
||||
|
||||
// DeleteResource returns a new instance of delete resource
|
||||
func DeleteResource(gvr schema.GroupVersionResource, namespace string) *Delete {
|
||||
resource := Resource(gvr, namespace)
|
||||
options := ResourceDeleteOptions{Deleter: resource}
|
||||
return &Delete{ResourceStruct: resource, options: options}
|
||||
}
|
||||
|
||||
// Delete deletes a resource from a kubernetes cluster
|
||||
func (d *Delete) Delete(obj *unstructured.Unstructured, subresources ...string) error {
|
||||
if d.options.Deleter == nil {
|
||||
return errors.New("nil resource deleter instance: failed to delete resource")
|
||||
} else if obj == nil {
|
||||
return errors.New("nil resource instance: failed to delete resource")
|
||||
}
|
||||
return d.options.Deleter.Delete(obj, subresources...)
|
||||
}
|
||||
|
||||
// ResourceListOptions is a utility instance used during the resource's list operations
|
||||
type ResourceListOptions struct {
|
||||
Lister ResourceLister
|
||||
}
|
||||
|
||||
// List is a resource resource that is suitable to be executed as a List operation
|
||||
type List struct {
|
||||
*ResourceStruct
|
||||
options ResourceListOptions
|
||||
}
|
||||
|
||||
// ListResource returns a new instance of list resource
|
||||
func ListResource(gvr schema.GroupVersionResource, namespace string) *List {
|
||||
resource := Resource(gvr, namespace)
|
||||
options := ResourceListOptions{Lister: resource}
|
||||
return &List{ResourceStruct: resource, options: options}
|
||||
}
|
||||
|
||||
// List lists a resource from a kubernetes cluster
|
||||
func (l *List) List(options metav1.ListOptions) (u *unstructured.UnstructuredList, err error) {
|
||||
if l.options.Lister == nil {
|
||||
err = errors.New("nil resource lister instance: failed to list resource")
|
||||
return
|
||||
}
|
||||
return l.options.Lister.List(options)
|
||||
}
|
||||
|
||||
// ResourceGetOptions is a utility instance used during the resource's get operations
|
||||
type ResourceGetOptions struct {
|
||||
Getter ResourceGetter
|
||||
}
|
||||
|
||||
// Get is resource that is suitable to be executed as Get operation
|
||||
type Get struct {
|
||||
*ResourceStruct
|
||||
options ResourceGetOptions
|
||||
}
|
||||
|
||||
// GetResource returns a new instance of get resource
|
||||
func GetResource(gvr schema.GroupVersionResource, namespace string) *Get {
|
||||
resource := Resource(gvr, namespace)
|
||||
options := ResourceGetOptions{Getter: resource}
|
||||
return &Get{ResourceStruct: resource, options: options}
|
||||
}
|
||||
|
||||
// Get gets a resource from a kubernetes cluster
|
||||
func (g *Get) Get(name string, opts metav1.GetOptions, subresources ...string) (u *unstructured.Unstructured, err error) {
|
||||
if g.options.Getter == nil {
|
||||
err = errors.New("nil resource getter instance: failed to get resource")
|
||||
return
|
||||
}
|
||||
return g.options.Getter.Get(name, opts, subresources...)
|
||||
}
|
||||
113
vendor/github.com/openebs/lib-csi/pkg/common/env/env.go
generated
vendored
Normal file
113
vendor/github.com/openebs/lib-csi/pkg/common/env/env.go
generated
vendored
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
Copyright 2019 The OpenEBS 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 env
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// KubeConfig is the ENV variable to fetch kubernetes kubeconfig
|
||||
KubeConfig = "OPENEBS_IO_KUBE_CONFIG"
|
||||
|
||||
// KubeMaster is the ENV variable to fetch kubernetes master's address
|
||||
KubeMaster = "OPENEBS_IO_K8S_MASTER"
|
||||
)
|
||||
|
||||
// EnvironmentSetter abstracts setting of environment variable
|
||||
type EnvironmentSetter func(envKey string, value string) (err error)
|
||||
|
||||
// EnvironmentGetter abstracts fetching value from an environment variable
|
||||
type EnvironmentGetter func(envKey string) (value string)
|
||||
|
||||
// EnvironmentLookup abstracts looking up an environment variable
|
||||
type EnvironmentLookup func(envKey string) (value string, present bool)
|
||||
|
||||
// Set sets the provided environment variable
|
||||
//
|
||||
// NOTE:
|
||||
// This is an implementation of EnvironmentSetter
|
||||
func Set(envKey string, value string) (err error) {
|
||||
return os.Setenv(string(envKey), value)
|
||||
}
|
||||
|
||||
// Get fetches value from the provided environment variable
|
||||
//
|
||||
// NOTE:
|
||||
// This is an implementation of EnvironmentGetter
|
||||
func Get(envKey string) (value string) {
|
||||
return getEnv(string(envKey))
|
||||
}
|
||||
|
||||
// GetOrDefault fetches value from the provided environment variable
|
||||
// which on empty returns the defaultValue
|
||||
// NOTE: os.Getenv is used here instead of os.LookupEnv because it is
|
||||
// not required to know if the environment variable is defined on the system
|
||||
func GetOrDefault(e string, defaultValue string) (value string) {
|
||||
envValue := Get(e)
|
||||
if len(envValue) == 0 {
|
||||
// ENV not defined or set to ""
|
||||
return defaultValue
|
||||
}
|
||||
return envValue
|
||||
}
|
||||
|
||||
// Lookup looks up an environment variable
|
||||
//
|
||||
// NOTE:
|
||||
// This is an implementation of EnvironmentLookup
|
||||
func Lookup(envKey string) (value string, present bool) {
|
||||
return lookupEnv(string(envKey))
|
||||
}
|
||||
|
||||
// Truthy returns boolean based on the environment variable's value
|
||||
//
|
||||
// The lookup value can be truthy (i.e. 1, t, TRUE, true) or falsy (0, false,
|
||||
// etc) based on strconv.ParseBool logic
|
||||
func Truthy(envKey string) (truth bool) {
|
||||
v, found := Lookup(envKey)
|
||||
if !found {
|
||||
return
|
||||
}
|
||||
truth, _ = strconv.ParseBool(v)
|
||||
return
|
||||
}
|
||||
|
||||
// LookupOrFalse looks up an environment variable and returns a string "false"
|
||||
// if environment variable is not present. It returns appropriate values for
|
||||
// other cases.
|
||||
func LookupOrFalse(envKey string) string {
|
||||
val, present := Lookup(envKey)
|
||||
if !present {
|
||||
return "false"
|
||||
}
|
||||
return strings.TrimSpace(val)
|
||||
}
|
||||
|
||||
// getEnv fetches the provided environment variable's value
|
||||
func getEnv(envKey string) (value string) {
|
||||
return strings.TrimSpace(os.Getenv(envKey))
|
||||
}
|
||||
|
||||
// lookupEnv looks up the provided environment variable
|
||||
func lookupEnv(envKey string) (value string, present bool) {
|
||||
value, present = os.LookupEnv(envKey)
|
||||
value = strings.TrimSpace(value)
|
||||
return
|
||||
}
|
||||
99
vendor/github.com/openebs/lib-csi/pkg/common/errors/errors.go
generated
vendored
Normal file
99
vendor/github.com/openebs/lib-csi/pkg/common/errors/errors.go
generated
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright 2019 The OpenEBS 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 errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// New returns an error with the supplied message.
|
||||
// New also records the stack trace at the point it was called.
|
||||
func New(message string) error {
|
||||
return &err{
|
||||
prefix: stackTraceMessagePrefix,
|
||||
msg: message,
|
||||
stack: callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// Errorf formats according to a format specifier and returns the string
|
||||
// as a value that satisfies error.
|
||||
// Errorf also records the stack trace at the point it was called.
|
||||
func Errorf(format string, args ...interface{}) error {
|
||||
return &err{
|
||||
prefix: stackTraceMessagePrefix,
|
||||
msg: fmt.Sprintf(format, args...),
|
||||
stack: callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap annotates err with a new message.
|
||||
// If err is nil, Wrap returns nil.
|
||||
func Wrap(err error, message string) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &wrapper{wrapErrorMessagePrefix, message, err}
|
||||
}
|
||||
|
||||
// Wrapf annotates err with the format specifier.
|
||||
// If err is nil, Wrapf returns nil.
|
||||
func Wrapf(err error, format string, args ...interface{}) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &wrapper{wrapErrorMessagePrefix, fmt.Sprintf(format, args...), err}
|
||||
}
|
||||
|
||||
// WithStack annotates err with a stack trace at the
|
||||
// point WithStack was called. If err is nil, WithStack returns nil.
|
||||
func WithStack(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
return &withStack{
|
||||
stackTraceMessagePrefix,
|
||||
err,
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// Cause returns the underlying cause of the error, if possible.
|
||||
// An error value has a cause if it implements the following
|
||||
// interface:
|
||||
//
|
||||
// type causer interface {
|
||||
// Cause() error
|
||||
// }
|
||||
//
|
||||
// If the error does not implement Cause, the original error will
|
||||
// be returned. If the error is nil, nil will be returned without further
|
||||
// investigation.
|
||||
func Cause(err error) error {
|
||||
type causer interface {
|
||||
Cause() error
|
||||
}
|
||||
|
||||
for err != nil {
|
||||
cause, ok := err.(causer)
|
||||
if !ok {
|
||||
break
|
||||
}
|
||||
err = cause.Cause()
|
||||
}
|
||||
return err
|
||||
}
|
||||
188
vendor/github.com/openebs/lib-csi/pkg/common/errors/types.go
generated
vendored
Normal file
188
vendor/github.com/openebs/lib-csi/pkg/common/errors/types.go
generated
vendored
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
Copyright 2019 The OpenEBS 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 errors
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
wrapErrorMessagePrefix string = " -- "
|
||||
listErrorMessagePrefix string = " - "
|
||||
stackTraceMessagePrefix string = " "
|
||||
)
|
||||
|
||||
// stack represents a stack of program counters.
|
||||
type stack []uintptr
|
||||
|
||||
// callers returns stack of caller function
|
||||
func callers() *stack {
|
||||
const depth = 32
|
||||
var pcs [depth]uintptr
|
||||
n := runtime.Callers(3, pcs[:])
|
||||
var st stack = pcs[0:n]
|
||||
return &st
|
||||
}
|
||||
|
||||
// err implements error interface that has a message and stack
|
||||
type err struct {
|
||||
prefix string
|
||||
msg string
|
||||
*stack
|
||||
}
|
||||
|
||||
// Error is implementation of error interface
|
||||
func (e *err) Error() string { return e.msg }
|
||||
|
||||
// Format is implementation of Formater interface
|
||||
func (e *err) Format(s fmt.State, verb rune) {
|
||||
message := wrapErrorMessagePrefix + e.msg
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprint(s, message)
|
||||
for i, pc := range *e.stack {
|
||||
if i > 0 {
|
||||
return
|
||||
}
|
||||
f := errors.Frame(pc)
|
||||
fmt.Fprintf(s, "\n%s%+v", e.prefix, f)
|
||||
}
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
fmt.Fprint(s, message)
|
||||
}
|
||||
}
|
||||
|
||||
// wrapper implements error interface that has a message and error
|
||||
type wrapper struct {
|
||||
prefix string
|
||||
msg string
|
||||
error
|
||||
}
|
||||
|
||||
// Error is implementation of error interface
|
||||
func (w *wrapper) Error() string { return w.msg }
|
||||
|
||||
// Cause is implementation of causer interface
|
||||
func (w *wrapper) Cause() error { return w.error }
|
||||
|
||||
// Format is implementation of Formater interface
|
||||
func (w *wrapper) Format(s fmt.State, verb rune) {
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprintf(s, "%+v\n", w.error)
|
||||
fmt.Fprint(s, w.prefix+w.msg)
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
fmt.Fprintf(s, "%s\n", w.error)
|
||||
fmt.Fprint(s, w.prefix+w.msg)
|
||||
}
|
||||
}
|
||||
|
||||
// withStack implements error interface that has a stack and error
|
||||
type withStack struct {
|
||||
prefix string
|
||||
error
|
||||
*stack
|
||||
}
|
||||
|
||||
// Format is implementation of Formater interface
|
||||
func (ws *withStack) Format(s fmt.State, verb rune) {
|
||||
message := wrapErrorMessagePrefix + fmt.Sprintf("%s", ws.error)
|
||||
switch verb {
|
||||
case 'v':
|
||||
if s.Flag('+') {
|
||||
fmt.Fprint(s, message)
|
||||
for i, pc := range *ws.stack {
|
||||
if i > 0 {
|
||||
return
|
||||
}
|
||||
f := errors.Frame(pc)
|
||||
fmt.Fprintf(s, "\n%s%+v", ws.prefix, f)
|
||||
}
|
||||
return
|
||||
}
|
||||
fallthrough
|
||||
case 's', 'q':
|
||||
fmt.Fprint(s, message)
|
||||
}
|
||||
}
|
||||
|
||||
// Cause is implementation of causer interface
|
||||
func (ws *withStack) Cause() error { return ws.error }
|
||||
|
||||
// ErrorList is a wrapper over list of errors
|
||||
// It implements error interface
|
||||
type ErrorList struct {
|
||||
Errors []error
|
||||
msg string
|
||||
}
|
||||
|
||||
// Error is implementation of error interface
|
||||
func (el *ErrorList) Error() string {
|
||||
message := ""
|
||||
for _, err := range el.Errors {
|
||||
message += err.Error() + ":"
|
||||
}
|
||||
el.msg = message
|
||||
return message
|
||||
}
|
||||
|
||||
// Format is implementation of Formater interface
|
||||
func (el *ErrorList) Format(s fmt.State, verb rune) {
|
||||
message := ""
|
||||
for _, err := range el.Errors {
|
||||
message += "\n" + listErrorMessagePrefix + err.Error()
|
||||
}
|
||||
fmt.Fprint(s, message)
|
||||
|
||||
}
|
||||
|
||||
// WithStack annotates ErrorList with a new message and
|
||||
// stack trace of caller.
|
||||
func (el *ErrorList) WithStack(message string) error {
|
||||
if el == nil {
|
||||
return nil
|
||||
}
|
||||
return &withStack{
|
||||
stackTraceMessagePrefix,
|
||||
Wrap(el, message),
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
|
||||
// WithStackf annotates ErrorList with the format specifier
|
||||
// and stack trace of caller.
|
||||
func (el *ErrorList) WithStackf(format string, args ...interface{}) error {
|
||||
if el == nil {
|
||||
return nil
|
||||
}
|
||||
return &withStack{
|
||||
stackTraceMessagePrefix,
|
||||
Wrapf(el, format, args...),
|
||||
callers(),
|
||||
}
|
||||
}
|
||||
45
vendor/github.com/openebs/lib-csi/pkg/common/helpers/helpers.go
generated
vendored
Normal file
45
vendor/github.com/openebs/lib-csi/pkg/common/helpers/helpers.go
generated
vendored
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 helpers
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetCaseInsensitiveMap coercs the map's keys to lower case, which only works
|
||||
// when unicode char is in ASCII subset. May overwrite key-value pairs on
|
||||
// different permutations of key case as in Key and key. DON'T force values to the
|
||||
// lower case unconditionally, because values for keys such as mountpoint or
|
||||
// keylocation are case-sensitive.
|
||||
// Note that although keys such as 'comPREssion' are accepted and processed,
|
||||
// even if they are technically invalid, updates to rectify such typing will be
|
||||
// prohibited as a forbidden update.
|
||||
func GetCaseInsensitiveMap(dict *map[string]string) map[string]string {
|
||||
insensitiveDict := map[string]string{}
|
||||
|
||||
for k, v := range *dict {
|
||||
insensitiveDict[strings.ToLower(k)] = v
|
||||
}
|
||||
return insensitiveDict
|
||||
}
|
||||
|
||||
// GetInsensitiveParameter handles special case ofGetCaseInsensitiveMap looking up one
|
||||
// key-value pair only
|
||||
func GetInsensitiveParameter(dict *map[string]string, key string) string {
|
||||
insensitiveDict := GetCaseInsensitiveMap(dict)
|
||||
return insensitiveDict[strings.ToLower(key)]
|
||||
}
|
||||
250
vendor/github.com/openebs/lib-csi/pkg/common/kubernetes/client/client.go
generated
vendored
Normal file
250
vendor/github.com/openebs/lib-csi/pkg/common/kubernetes/client/client.go
generated
vendored
Normal file
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
Copyright 2019 The OpenEBS 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 client
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
env "github.com/openebs/lib-csi/pkg/common/env"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
)
|
||||
|
||||
// getInClusterConfigFunc abstracts the logic to get
|
||||
// kubernetes incluster config
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type getInClusterConfigFunc func() (*rest.Config, error)
|
||||
|
||||
// buildConfigFromFlagsFunc provides the abstraction to get
|
||||
// kubernetes config from provided flags
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type buildConfigFromFlagsFunc func(string, string) (*rest.Config, error)
|
||||
|
||||
// GetConfigFunc provides the abstraction to get
|
||||
// kubernetes config from provided client instance
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type GetConfigFunc func(*Client) (*rest.Config, error)
|
||||
|
||||
// GetConfig returns kubernetes config instance
|
||||
//
|
||||
// NOTE:
|
||||
// This is an implementation of GetConfigFunc
|
||||
func GetConfig(c *Client) (*rest.Config, error) {
|
||||
if c == nil {
|
||||
return nil, errors.New("failed to get kubernetes config: nil client was provided")
|
||||
}
|
||||
return c.GetConfigForPathOrDirect()
|
||||
}
|
||||
|
||||
// getKubeMasterIPFunc provides the abstraction to get
|
||||
// kubernetes master IP address
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type getKubeMasterIPFunc func(string) string
|
||||
|
||||
// getKubeConfigPathFunc provides the abstraction to get
|
||||
// kubernetes config path
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type getKubeConfigPathFunc func(string) string
|
||||
|
||||
// getKubernetesDynamicClientFunc provides the abstraction to get
|
||||
// dynamic kubernetes clientset
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type getKubernetesDynamicClientFunc func(*rest.Config) (dynamic.Interface, error)
|
||||
|
||||
// getKubernetesClientsetFunc provides the abstraction to get
|
||||
// kubernetes clientset
|
||||
//
|
||||
// NOTE:
|
||||
// typed function makes it simple to mock
|
||||
type getKubernetesClientsetFunc func(*rest.Config) (*kubernetes.Clientset, error)
|
||||
|
||||
// Client provides common kuberenetes client operations
|
||||
type Client struct {
|
||||
IsInCluster bool // flag to let client point to its own cluster
|
||||
KubeConfigPath string // kubeconfig path to get kubernetes clientset
|
||||
|
||||
// Below functions are useful during mock
|
||||
|
||||
// handle to get in cluster config
|
||||
getInClusterConfig getInClusterConfigFunc
|
||||
|
||||
// handle to get desired kubernetes config
|
||||
buildConfigFromFlags buildConfigFromFlagsFunc
|
||||
|
||||
// handle to get kubernetes clienset
|
||||
getKubernetesClientset getKubernetesClientsetFunc
|
||||
|
||||
// handle to get dynamic kubernetes clientset
|
||||
getKubernetesDynamicClient getKubernetesDynamicClientFunc
|
||||
|
||||
// handle to get kubernetes master IP
|
||||
getKubeMasterIP getKubeMasterIPFunc
|
||||
|
||||
// handle to get kubernetes config path
|
||||
getKubeConfigPath getKubeConfigPathFunc
|
||||
}
|
||||
|
||||
// OptionFunc is a typed function that abstracts any kind of operation
|
||||
// against the provided client instance
|
||||
//
|
||||
// This is the basic building block to create functional operations
|
||||
// against the client instance
|
||||
type OptionFunc func(*Client)
|
||||
|
||||
// New returns a new instance of client
|
||||
func New(opts ...OptionFunc) *Client {
|
||||
c := &Client{}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
withDefaults(c)
|
||||
return c
|
||||
}
|
||||
|
||||
var (
|
||||
instance *Client
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// Instance returns a singleton instance of
|
||||
// this client
|
||||
func Instance(opts ...OptionFunc) *Client {
|
||||
once.Do(func() {
|
||||
instance = New(opts...)
|
||||
})
|
||||
|
||||
return instance
|
||||
}
|
||||
|
||||
func withDefaults(c *Client) {
|
||||
if c.getInClusterConfig == nil {
|
||||
c.getInClusterConfig = rest.InClusterConfig
|
||||
}
|
||||
if c.buildConfigFromFlags == nil {
|
||||
c.buildConfigFromFlags = clientcmd.BuildConfigFromFlags
|
||||
}
|
||||
if c.getKubernetesClientset == nil {
|
||||
c.getKubernetesClientset = kubernetes.NewForConfig
|
||||
}
|
||||
if c.getKubernetesDynamicClient == nil {
|
||||
c.getKubernetesDynamicClient = dynamic.NewForConfig
|
||||
}
|
||||
if c.getKubeMasterIP == nil {
|
||||
c.getKubeMasterIP = env.Get
|
||||
}
|
||||
if c.getKubeConfigPath == nil {
|
||||
c.getKubeConfigPath = env.Get
|
||||
}
|
||||
}
|
||||
|
||||
// InCluster enables IsInCluster flag
|
||||
func InCluster() OptionFunc {
|
||||
return func(c *Client) {
|
||||
c.IsInCluster = true
|
||||
}
|
||||
}
|
||||
|
||||
// WithKubeConfigPath sets kubeconfig path
|
||||
// against this client instance
|
||||
func WithKubeConfigPath(kubeConfigPath string) OptionFunc {
|
||||
return func(c *Client) {
|
||||
c.KubeConfigPath = kubeConfigPath
|
||||
}
|
||||
}
|
||||
|
||||
// Clientset returns a new instance of kubernetes clientset
|
||||
func (c *Client) Clientset() (*kubernetes.Clientset, error) {
|
||||
config, err := c.GetConfigForPathOrDirect()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err,
|
||||
"failed to get kubernetes clientset: failed to get kubernetes config: IsInCluster {%t}: KubeConfigPath {%s}",
|
||||
c.IsInCluster,
|
||||
c.KubeConfigPath,
|
||||
)
|
||||
}
|
||||
return c.getKubernetesClientset(config)
|
||||
}
|
||||
|
||||
// Config returns the kubernetes config instance based on available criteria
|
||||
func (c *Client) Config() (config *rest.Config, err error) {
|
||||
// IsInCluster flag holds the top most priority
|
||||
if c.IsInCluster {
|
||||
return c.getInClusterConfig()
|
||||
}
|
||||
|
||||
// ENV holds second priority
|
||||
if strings.TrimSpace(c.getKubeMasterIP(env.KubeMaster)) != "" ||
|
||||
strings.TrimSpace(c.getKubeConfigPath(env.KubeConfig)) != "" {
|
||||
return c.getConfigFromENV()
|
||||
}
|
||||
|
||||
// Defaults to InClusterConfig
|
||||
return c.getInClusterConfig()
|
||||
}
|
||||
|
||||
// ConfigForPath returns the kubernetes config instance based on KubeConfig path
|
||||
func (c *Client) ConfigForPath(kubeConfigPath string) (config *rest.Config, err error) {
|
||||
return c.buildConfigFromFlags("", kubeConfigPath)
|
||||
}
|
||||
|
||||
// GetConfigForPathOrDirect returns the kubernetes config instance based on direct KubeConfig
|
||||
func (c *Client) GetConfigForPathOrDirect() (config *rest.Config, err error) {
|
||||
if c.KubeConfigPath != "" {
|
||||
return c.ConfigForPath(c.KubeConfigPath)
|
||||
}
|
||||
return c.Config()
|
||||
}
|
||||
|
||||
func (c *Client) getConfigFromENV() (config *rest.Config, err error) {
|
||||
k8sMaster := c.getKubeMasterIP(env.KubeMaster)
|
||||
kubeConfig := c.getKubeConfigPath(env.KubeConfig)
|
||||
if strings.TrimSpace(k8sMaster) == "" &&
|
||||
strings.TrimSpace(kubeConfig) == "" {
|
||||
return nil, errors.Errorf(
|
||||
"failed to get kubernetes config: missing ENV: atleast one should be set: {%s} or {%s}",
|
||||
env.KubeMaster,
|
||||
env.KubeConfig,
|
||||
)
|
||||
}
|
||||
return c.buildConfigFromFlags(k8sMaster, kubeConfig)
|
||||
}
|
||||
|
||||
// Dynamic returns a kubernetes dynamic client capable of invoking operations
|
||||
// against kubernetes resources
|
||||
func (c *Client) Dynamic() (dynamic.Interface, error) {
|
||||
config, err := c.GetConfigForPathOrDirect()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get dynamic client")
|
||||
}
|
||||
return c.getKubernetesDynamicClient(config)
|
||||
}
|
||||
64
vendor/github.com/openebs/lib-csi/pkg/mount/mount_utils.go
generated
vendored
Normal file
64
vendor/github.com/openebs/lib-csi/pkg/mount/mount_utils.go
generated
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 mount
|
||||
|
||||
import (
|
||||
"k8s.io/kubernetes/pkg/util/mount"
|
||||
)
|
||||
|
||||
// GetMounts gets mountpoints for the specified volume
|
||||
func GetMounts(dev string) ([]string, error) {
|
||||
|
||||
var (
|
||||
currentMounts []string
|
||||
err error
|
||||
mountList []mount.MountPoint
|
||||
)
|
||||
|
||||
mounter := mount.New("")
|
||||
// Get list of mounted paths present with the node
|
||||
if mountList, err = mounter.List(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for _, mntInfo := range mountList {
|
||||
if mntInfo.Device == dev {
|
||||
currentMounts = append(currentMounts, mntInfo.Path)
|
||||
}
|
||||
}
|
||||
return currentMounts, nil
|
||||
}
|
||||
|
||||
// IsMountPath returns true if path is a mount path
|
||||
func IsMountPath(path string) bool {
|
||||
|
||||
var (
|
||||
err error
|
||||
mountList []mount.MountPoint
|
||||
)
|
||||
|
||||
mounter := mount.New("")
|
||||
// Get list of mounted paths present with the node
|
||||
if mountList, err = mounter.List(); err != nil {
|
||||
return false
|
||||
}
|
||||
for _, mntInfo := range mountList {
|
||||
if mntInfo.Path == path {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
99
vendor/github.com/openebs/lib-csi/pkg/scheduler/scheduler.go
generated
vendored
Normal file
99
vendor/github.com/openebs/lib-csi/pkg/scheduler/scheduler.go
generated
vendored
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
Copyright © 2019 The OpenEBS 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 scheduler
|
||||
|
||||
import (
|
||||
"math"
|
||||
|
||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||
k8sapi "github.com/openebs/lib-csi/pkg/client/k8s"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
// getNodeList gets the nodelist which satisfies the topology info
|
||||
func getNodeList(topo *csi.TopologyRequirement) ([]string, error) {
|
||||
|
||||
var nodelist []string
|
||||
|
||||
list, err := k8sapi.ListNodes(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for _, node := range list.Items {
|
||||
for _, prf := range topo.Preferred {
|
||||
nodeFiltered := false
|
||||
for key, value := range prf.Segments {
|
||||
if node.Labels[key] != value {
|
||||
nodeFiltered = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !nodeFiltered {
|
||||
nodelist = append(nodelist, node.Name)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nodelist, nil
|
||||
}
|
||||
|
||||
// runScheduler goes through the node mapping
|
||||
// in the topology and picks the node which is less weighted
|
||||
func runScheduler(nodelist []string, nmap map[string]int64) string {
|
||||
var selected string
|
||||
|
||||
var weight int64 = math.MaxInt64
|
||||
|
||||
// schedule it on the node which has less weight
|
||||
for _, node := range nodelist {
|
||||
if nmap[node] < weight {
|
||||
selected = node
|
||||
weight = nmap[node]
|
||||
}
|
||||
}
|
||||
return selected
|
||||
}
|
||||
|
||||
// Scheduler schedules the PV as per topology constraints for
|
||||
// the given node weight.
|
||||
func Scheduler(req *csi.CreateVolumeRequest, nmap map[string]int64) string {
|
||||
topo := req.AccessibilityRequirements
|
||||
if topo == nil ||
|
||||
len(topo.Preferred) == 0 {
|
||||
klog.Errorf("scheduler: topology information not provided")
|
||||
return ""
|
||||
}
|
||||
|
||||
nodelist, err := getNodeList(topo)
|
||||
if err != nil {
|
||||
klog.Errorf("scheduler: can not get the nodelist err : %v", err.Error())
|
||||
return ""
|
||||
} else if len(nodelist) == 0 {
|
||||
klog.Errorf("scheduler: nodelist is empty")
|
||||
return ""
|
||||
}
|
||||
|
||||
// if there is a single node, schedule it on that
|
||||
if len(nodelist) == 1 {
|
||||
return nodelist[0]
|
||||
}
|
||||
|
||||
return runScheduler(nodelist, nmap)
|
||||
}
|
||||
112
vendor/github.com/openebs/lib-csi/pkg/xfs/xfs_util.go
generated
vendored
Normal file
112
vendor/github.com/openebs/lib-csi/pkg/xfs/xfs_util.go
generated
vendored
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
Copyright 2020 The OpenEBS 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 xfs
|
||||
|
||||
import (
|
||||
"github.com/openebs/lib-csi/pkg/mount"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
|
||||
"strings"
|
||||
|
||||
"k8s.io/klog"
|
||||
)
|
||||
|
||||
func xfsTempMount(device string) error {
|
||||
pvol := strings.Split(device, "/")
|
||||
volname := pvol[len(pvol)-1]
|
||||
|
||||
// evaluate the symlink to get the dev path for volume
|
||||
dev, err := filepath.EvalSymlinks(device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create a temporary directory to mount the xfs file system
|
||||
tmpdir := "/tmp/" + volname
|
||||
err = os.Mkdir(tmpdir, 0755)
|
||||
if os.IsNotExist(err) {
|
||||
klog.Errorf("xfs: failed to create tmpdir %s error: %s", tmpdir, err.Error())
|
||||
return err
|
||||
}
|
||||
|
||||
/*
|
||||
* Device might have already mounted at the tmp path but umount might have failed
|
||||
* in previous attempt. Checking here if device is not mounted then only attempt
|
||||
* to mount it, otherwise proceed with the umount.
|
||||
*/
|
||||
curMounts, err := mount.GetMounts(dev)
|
||||
if err != nil {
|
||||
klog.Errorf("xfs: get mounts failed dev: %s err: %v", device, err.Error())
|
||||
return err
|
||||
} else if len(curMounts) == 0 {
|
||||
// mount with nouuid, so that it can play the log
|
||||
cmd := exec.Command("mount", "-o", "nouuid", device, tmpdir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("xfs: failed to mount device %s => %s error: %s", device, tmpdir, string(out))
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
klog.Infof("xfs: device already mounted %s => [%v]", device, curMounts)
|
||||
}
|
||||
|
||||
// log has been replayed, unmount the volume
|
||||
cmd := exec.Command("umount", tmpdir)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("xfs: failed to umount tmpdir %s error: %s", tmpdir, string(out))
|
||||
return err
|
||||
}
|
||||
|
||||
// remove the tmp directory
|
||||
err = os.Remove(tmpdir)
|
||||
if err != nil {
|
||||
// don't return error, reconciliation is not needed as umount is done
|
||||
klog.Errorf("xfs: failed to remove tmpdir %s error: %s", tmpdir, err.Error())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
* We have to generate a new UUID for the cloned volumes with xfs filesystem
|
||||
* otherwise system won't let anyone mount it if UUID is same. Here, since cloned
|
||||
* volume refers to the same block because of the way ZFS clone works, it will
|
||||
* also have the same UUID.
|
||||
* There might be something there in the xfs log, we have to clear them
|
||||
* so that filesystem is clean and we can generate the UUID for it.
|
||||
*/
|
||||
|
||||
// GenerateUUID generates a new UUID for the given device
|
||||
func GenerateUUID(device string) error {
|
||||
// temporary mount the volume with nouuid to replay the logs
|
||||
err := xfsTempMount(device)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// for mounting the cloned volume for xfs, a new UUID has to be generated
|
||||
cmd := exec.Command("xfs_admin", "-U", "generate", device)
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
klog.Errorf("xfs: uuid generate failed for device %s error: %s", device, string(out))
|
||||
return err
|
||||
}
|
||||
klog.Infof("xfs: generated UUID for the device %s \n %v", device, string(out))
|
||||
return nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue