mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-24 04:06:03 +00:00
Merge pull request #91785 from mattcary/filtereddial
Specify a DialContext in storage plugin clients
This commit is contained in:
commit
b86e725694
@ -370,6 +370,7 @@ API rule violation: list_type_missing,k8s.io/apiserver/pkg/apis/audit/v1beta1,Po
|
||||
API rule violation: list_type_missing,k8s.io/apiserver/pkg/apis/audit/v1beta1,PolicyRule,Verbs
|
||||
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GarbageCollectorControllerConfiguration,GCIgnoredResources
|
||||
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,GenericControllerManagerConfiguration,Controllers
|
||||
API rule violation: list_type_missing,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostCIDRDenylist
|
||||
API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyConfiguration,NodePortAddresses
|
||||
API rule violation: list_type_missing,k8s.io/kube-proxy/config/v1alpha1,KubeProxyIPVSConfiguration,ExcludeCIDRs
|
||||
API rule violation: list_type_missing,k8s.io/kube-scheduler/config/v1,ExtenderTLSConfig,CAData
|
||||
@ -569,6 +570,8 @@ API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,N
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,NodeLifecycleControllerConfiguration,UnhealthyZoneThreshold
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,PVClaimBinderSyncPeriod
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeConfiguration
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostAllowLocalLoopback
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeBinderControllerConfiguration,VolumeHostCIDRDenylist
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutHostPath
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,IncrementTimeoutNFS
|
||||
API rule violation: names_match,k8s.io/kube-controller-manager/config/v1alpha1,PersistentVolumeRecyclerConfiguration,MaximumRetry
|
||||
|
@ -43,6 +43,7 @@ import (
|
||||
servicecontroller "k8s.io/cloud-provider/controllers/service"
|
||||
"k8s.io/component-base/metrics/prometheus/ratelimiter"
|
||||
csitrans "k8s.io/csi-translation-lib"
|
||||
"k8s.io/kubernetes/cmd/kube-controller-manager/app/options"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
endpointcontroller "k8s.io/kubernetes/pkg/controller/endpoint"
|
||||
"k8s.io/kubernetes/pkg/controller/garbagecollector"
|
||||
@ -285,6 +286,12 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (http.Handler,
|
||||
if err != nil {
|
||||
return nil, true, fmt.Errorf("failed to probe volume plugins when starting persistentvolume controller: %v", err)
|
||||
}
|
||||
filteredDialOptions, err := options.ParseVolumeHostFilters(
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
params := persistentvolumecontroller.ControllerParameters{
|
||||
KubeClient: ctx.ClientBuilder.ClientOrDie("persistent-volume-binder"),
|
||||
SyncPeriod: ctx.ComponentConfig.PersistentVolumeBinderController.PVClaimBinderSyncPeriod.Duration,
|
||||
@ -297,6 +304,7 @@ func startPersistentVolumeBinderController(ctx ControllerContext) (http.Handler,
|
||||
PodInformer: ctx.InformerFactory.Core().V1().Pods(),
|
||||
NodeInformer: ctx.InformerFactory.Core().V1().Nodes(),
|
||||
EnableDynamicProvisioning: ctx.ComponentConfig.PersistentVolumeBinderController.VolumeConfiguration.EnableDynamicProvisioning,
|
||||
FilteredDialOptions: filteredDialOptions,
|
||||
}
|
||||
volumeController, volumeControllerErr := persistentvolumecontroller.NewController(params)
|
||||
if volumeControllerErr != nil {
|
||||
@ -324,6 +332,13 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
|
||||
return nil, true, fmt.Errorf("failed to probe volume plugins when starting attach/detach controller: %v", err)
|
||||
}
|
||||
|
||||
filteredDialOptions, err := options.ParseVolumeHostFilters(
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
|
||||
attachDetachController, attachDetachControllerErr :=
|
||||
attachdetach.NewAttachDetachController(
|
||||
ctx.ClientBuilder.ClientOrDie("attachdetach-controller"),
|
||||
@ -340,6 +355,7 @@ func startAttachDetachController(ctx ControllerContext) (http.Handler, bool, err
|
||||
ctx.ComponentConfig.AttachDetachController.DisableAttachDetachReconcilerSync,
|
||||
ctx.ComponentConfig.AttachDetachController.ReconcilerSyncLoopPeriod.Duration,
|
||||
attachdetach.DefaultTimerConfig,
|
||||
filteredDialOptions,
|
||||
)
|
||||
if attachDetachControllerErr != nil {
|
||||
return nil, true, fmt.Errorf("failed to start attach/detach controller: %v", attachDetachControllerErr)
|
||||
@ -355,6 +371,12 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
|
||||
return nil, true, fmt.Errorf("failed to probe volume plugins when starting volume expand controller: %v", err)
|
||||
}
|
||||
csiTranslator := csitrans.New()
|
||||
filteredDialOptions, err := options.ParseVolumeHostFilters(
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostCIDRDenylist,
|
||||
ctx.ComponentConfig.PersistentVolumeBinderController.VolumeHostAllowLocalLoopback)
|
||||
if err != nil {
|
||||
return nil, true, err
|
||||
}
|
||||
expandController, expandControllerErr := expand.NewExpandController(
|
||||
ctx.ClientBuilder.ClientOrDie("expand-controller"),
|
||||
ctx.InformerFactory.Core().V1().PersistentVolumeClaims(),
|
||||
@ -363,7 +385,9 @@ func startVolumeExpandController(ctx ControllerContext) (http.Handler, bool, err
|
||||
ctx.Cloud,
|
||||
plugins,
|
||||
csiTranslator,
|
||||
csimigration.NewPluginManager(csiTranslator))
|
||||
csimigration.NewPluginManager(csiTranslator),
|
||||
filteredDialOptions,
|
||||
)
|
||||
|
||||
if expandControllerErr != nil {
|
||||
return nil, true, fmt.Errorf("failed to start volume expand controller: %v", expandControllerErr)
|
||||
|
@ -63,6 +63,7 @@ go_library(
|
||||
"//pkg/controller/volume/attachdetach/config:go_default_library",
|
||||
"//pkg/controller/volume/persistentvolume/config:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||
"//staging/src/k8s.io/apiserver/pkg/server/options:go_default_library",
|
||||
@ -78,6 +79,7 @@ go_library(
|
||||
"//staging/src/k8s.io/component-base/metrics:go_default_library",
|
||||
"//staging/src/k8s.io/kube-controller-manager/config/v1alpha1:go_default_library",
|
||||
"//vendor/github.com/spf13/pflag:go_default_library",
|
||||
"//vendor/k8s.io/utils/net:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
|
@ -100,6 +100,8 @@ var args = []string{
|
||||
"--enable-taint-manager=false",
|
||||
"--cluster-signing-duration=10h",
|
||||
"--flex-volume-plugin-dir=/flex-volume-plugin",
|
||||
"--volume-host-cidr-denylist=127.0.0.1/28,feed::/16",
|
||||
"--volume-host-allow-local-loopback=false",
|
||||
"--horizontal-pod-autoscaler-downscale-delay=2m",
|
||||
"--horizontal-pod-autoscaler-sync-period=45s",
|
||||
"--horizontal-pod-autoscaler-upscale-delay=1m",
|
||||
@ -350,6 +352,8 @@ func TestAddFlags(t *testing.T) {
|
||||
IncrementTimeoutHostPath: 45,
|
||||
},
|
||||
},
|
||||
VolumeHostCIDRDenylist: []string{"127.0.0.1/28", "feed::/16"},
|
||||
VolumeHostAllowLocalLoopback: false,
|
||||
},
|
||||
},
|
||||
PodGCController: &PodGCControllerOptions{
|
||||
@ -589,6 +593,8 @@ func TestApplyTo(t *testing.T) {
|
||||
IncrementTimeoutHostPath: 45,
|
||||
},
|
||||
},
|
||||
VolumeHostCIDRDenylist: []string{"127.0.0.1/28", "feed::/16"},
|
||||
VolumeHostAllowLocalLoopback: false,
|
||||
},
|
||||
PodGCController: podgcconfig.PodGCControllerConfiguration{
|
||||
TerminatedPodGCThreshold: 12000,
|
||||
|
@ -17,9 +17,13 @@ limitations under the License.
|
||||
package options
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
persistentvolumeconfig "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/config"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
netutils "k8s.io/utils/net"
|
||||
)
|
||||
|
||||
// PersistentVolumeBinderControllerOptions holds the PersistentVolumeBinderController options.
|
||||
@ -43,6 +47,8 @@ func (o *PersistentVolumeBinderControllerOptions) AddFlags(fs *pflag.FlagSet) {
|
||||
fs.BoolVar(&o.VolumeConfiguration.EnableHostPathProvisioning, "enable-hostpath-provisioner", o.VolumeConfiguration.EnableHostPathProvisioning, "Enable HostPath PV provisioning when running without a cloud provider. This allows testing and development of provisioning features. HostPath provisioning is not supported in any way, won't work in a multi-node cluster, and should not be used for anything other than testing or development.")
|
||||
fs.BoolVar(&o.VolumeConfiguration.EnableDynamicProvisioning, "enable-dynamic-provisioning", o.VolumeConfiguration.EnableDynamicProvisioning, "Enable dynamic provisioning for environments that support it.")
|
||||
fs.StringVar(&o.VolumeConfiguration.FlexVolumePluginDir, "flex-volume-plugin-dir", o.VolumeConfiguration.FlexVolumePluginDir, "Full path of the directory in which the flex volume plugin should search for additional third party volume plugins.")
|
||||
fs.StringSliceVar(&o.VolumeHostCIDRDenylist, "volume-host-cidr-denylist", o.VolumeHostCIDRDenylist, "A comma-separated list of CIDR ranges to avoid from volume plugins.")
|
||||
fs.BoolVar(&o.VolumeHostAllowLocalLoopback, "volume-host-allow-local-loopback", o.VolumeHostAllowLocalLoopback, "If false, deny local loopback IPs in addition to any CIDR ranges in --volume-host-cidr-denylist")
|
||||
}
|
||||
|
||||
// ApplyTo fills up PersistentVolumeBinderController config with options.
|
||||
@ -53,6 +59,8 @@ func (o *PersistentVolumeBinderControllerOptions) ApplyTo(cfg *persistentvolumec
|
||||
|
||||
cfg.PVClaimBinderSyncPeriod = o.PVClaimBinderSyncPeriod
|
||||
cfg.VolumeConfiguration = o.VolumeConfiguration
|
||||
cfg.VolumeHostCIDRDenylist = o.VolumeHostCIDRDenylist
|
||||
cfg.VolumeHostAllowLocalLoopback = o.VolumeHostAllowLocalLoopback
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -64,5 +72,17 @@ func (o *PersistentVolumeBinderControllerOptions) Validate() []error {
|
||||
}
|
||||
|
||||
errs := []error{}
|
||||
if _, err := ParseVolumeHostFilters(o.VolumeHostCIDRDenylist, o.VolumeHostAllowLocalLoopback); err != nil {
|
||||
errs = append(errs, fmt.Errorf("Bad --volume-host-ip-denylist/--volume-host-allow-local-loopback %w", err))
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// ParseVolumeHostFilters process the --volume-host-ip-denylist and --volume-host-allow-local-loopback flags.
|
||||
func ParseVolumeHostFilters(denylist []string, allowLocalLoopback bool) (*proxyutil.FilteredDialOptions, error) {
|
||||
denyCIDRs, err := netutils.ParseCIDRs(denylist)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &proxyutil.FilteredDialOptions{DialHostCIDRDenylist: denyCIDRs, AllowLocalLoopback: allowLocalLoopback}, nil
|
||||
}
|
||||
|
4
go.mod
4
go.mod
@ -91,7 +91,7 @@ require (
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.4.0
|
||||
github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc
|
||||
github.com/storageos/go-api v2.2.0+incompatible
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/thecodeteam/goscaleio v0.1.0
|
||||
github.com/urfave/negroni v1.0.0 // indirect
|
||||
@ -397,7 +397,7 @@ replace (
|
||||
github.com/spf13/jwalterweatherman => github.com/spf13/jwalterweatherman v1.1.0
|
||||
github.com/spf13/pflag => github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper => github.com/spf13/viper v1.4.0
|
||||
github.com/storageos/go-api => github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc
|
||||
github.com/storageos/go-api => github.com/storageos/go-api v2.2.0+incompatible
|
||||
github.com/stretchr/objx => github.com/stretchr/objx v0.2.0
|
||||
github.com/stretchr/testify => github.com/stretchr/testify v1.4.0
|
||||
github.com/syndtr/gocapability => github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2
|
||||
|
4
go.sum
4
go.sum
@ -436,8 +436,8 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
|
||||
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
|
||||
github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc h1:n+WYaU0kQ6WIiuEyWSgbXqkBx16irO69kYCtwVYoO5s=
|
||||
github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
|
||||
github.com/storageos/go-api v2.2.0+incompatible h1:U0SablXoZIg06gvSlg8BCdzq1C/SkHVygOVX95Z2MU0=
|
||||
github.com/storageos/go-api v2.2.0+incompatible/go.mod h1:ZrLn+e0ZuF3Y65PNF6dIwbJPZqfmtCXxFm9ckv0agOY=
|
||||
github.com/stretchr/objx v0.2.0 h1:Hbg2NidpLE8veEBkEZTL3CvlkUIVzuU9jDplZO54c48=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
|
@ -123,7 +123,7 @@ func (in *KubeControllerManagerConfiguration) DeepCopyInto(out *KubeControllerMa
|
||||
out.NamespaceController = in.NamespaceController
|
||||
out.NodeIPAMController = in.NodeIPAMController
|
||||
out.NodeLifecycleController = in.NodeLifecycleController
|
||||
out.PersistentVolumeBinderController = in.PersistentVolumeBinderController
|
||||
in.PersistentVolumeBinderController.DeepCopyInto(&out.PersistentVolumeBinderController)
|
||||
out.PodGCController = in.PodGCController
|
||||
out.ReplicaSetController = in.ReplicaSetController
|
||||
out.ReplicationController = in.ReplicationController
|
||||
|
@ -19,6 +19,7 @@ go_library(
|
||||
"//pkg/controller/volume/attachdetach/util:go_default_library",
|
||||
"//pkg/controller/volume/common:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/csimigration:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
|
@ -55,6 +55,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/controller/volume/attachdetach/util"
|
||||
"k8s.io/kubernetes/pkg/controller/volume/common"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csimigration"
|
||||
volumeutil "k8s.io/kubernetes/pkg/volume/util"
|
||||
@ -117,21 +118,23 @@ func NewAttachDetachController(
|
||||
prober volume.DynamicPluginProber,
|
||||
disableReconciliationSync bool,
|
||||
reconcilerSyncDuration time.Duration,
|
||||
timerConfig TimerConfig) (AttachDetachController, error) {
|
||||
timerConfig TimerConfig,
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions) (AttachDetachController, error) {
|
||||
|
||||
adc := &attachDetachController{
|
||||
kubeClient: kubeClient,
|
||||
pvcLister: pvcInformer.Lister(),
|
||||
pvcsSynced: pvcInformer.Informer().HasSynced,
|
||||
pvLister: pvInformer.Lister(),
|
||||
pvsSynced: pvInformer.Informer().HasSynced,
|
||||
podLister: podInformer.Lister(),
|
||||
podsSynced: podInformer.Informer().HasSynced,
|
||||
podIndexer: podInformer.Informer().GetIndexer(),
|
||||
nodeLister: nodeInformer.Lister(),
|
||||
nodesSynced: nodeInformer.Informer().HasSynced,
|
||||
cloud: cloud,
|
||||
pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"),
|
||||
kubeClient: kubeClient,
|
||||
pvcLister: pvcInformer.Lister(),
|
||||
pvcsSynced: pvcInformer.Informer().HasSynced,
|
||||
pvLister: pvInformer.Lister(),
|
||||
pvsSynced: pvInformer.Informer().HasSynced,
|
||||
podLister: podInformer.Lister(),
|
||||
podsSynced: podInformer.Informer().HasSynced,
|
||||
podIndexer: podInformer.Informer().GetIndexer(),
|
||||
nodeLister: nodeInformer.Lister(),
|
||||
nodesSynced: nodeInformer.Informer().HasSynced,
|
||||
cloud: cloud,
|
||||
pvcQueue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "pvcs"),
|
||||
filteredDialOptions: filteredDialOptions,
|
||||
}
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIMigration) &&
|
||||
@ -313,6 +316,9 @@ type attachDetachController struct {
|
||||
|
||||
// intreeToCSITranslator translates from in-tree volume specs to CSI
|
||||
intreeToCSITranslator csimigration.InTreeToCSITranslator
|
||||
|
||||
// filteredDialOptions configures any dialing done by the controller.
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
func (adc *attachDetachController) Run(stopCh <-chan struct{}) {
|
||||
@ -813,6 +819,10 @@ func (adc *attachDetachController) GetSubpather() subpath.Interface {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (adc *attachDetachController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
|
||||
return adc.filteredDialOptions
|
||||
}
|
||||
|
||||
func (adc *attachDetachController) GetCSIDriverLister() storagelistersv1.CSIDriverLister {
|
||||
return adc.csiDriverLister
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ func Test_NewAttachDetachController_Positive(t *testing.T) {
|
||||
false,
|
||||
5*time.Second,
|
||||
DefaultTimerConfig,
|
||||
nil, /* filteredDialOptions */
|
||||
)
|
||||
|
||||
// Assert
|
||||
@ -175,7 +176,9 @@ func attachDetachRecoveryTestCase(t *testing.T, extraPods1 []*v1.Pod, extraPods2
|
||||
prober,
|
||||
false,
|
||||
1*time.Second,
|
||||
DefaultTimerConfig)
|
||||
DefaultTimerConfig,
|
||||
nil, /* filteredDialOptions */
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Run failed with error. Expected: <no error> Actual: <%v>", err)
|
||||
|
@ -9,6 +9,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/apis/core/v1/helper:go_default_library",
|
||||
"//pkg/controller/volume/events:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/csimigration:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
|
@ -47,6 +47,7 @@ import (
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
v1helper "k8s.io/kubernetes/pkg/apis/core/v1/helper"
|
||||
"k8s.io/kubernetes/pkg/controller/volume/events"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csimigration"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
@ -104,6 +105,8 @@ type expandController struct {
|
||||
translator CSINameTranslator
|
||||
|
||||
csiMigratedPluginManager csimigration.PluginManager
|
||||
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
// NewExpandController expands the pvs
|
||||
@ -115,7 +118,8 @@ func NewExpandController(
|
||||
cloud cloudprovider.Interface,
|
||||
plugins []volume.VolumePlugin,
|
||||
translator CSINameTranslator,
|
||||
csiMigratedPluginManager csimigration.PluginManager) (ExpandController, error) {
|
||||
csiMigratedPluginManager csimigration.PluginManager,
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions) (ExpandController, error) {
|
||||
|
||||
expc := &expandController{
|
||||
kubeClient: kubeClient,
|
||||
@ -129,6 +133,7 @@ func NewExpandController(
|
||||
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "volume_expand"),
|
||||
translator: translator,
|
||||
csiMigratedPluginManager: csiMigratedPluginManager,
|
||||
filteredDialOptions: filteredDialOptions,
|
||||
}
|
||||
|
||||
if err := expc.volumePluginMgr.InitPlugins(plugins, nil, expc); err != nil {
|
||||
@ -449,3 +454,7 @@ func (expc *expandController) GetSubpather() subpath.Interface {
|
||||
// not needed for expand controller
|
||||
return nil
|
||||
}
|
||||
|
||||
func (expc *expandController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
|
||||
return expc.filteredDialOptions
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ func TestSyncHandler(t *testing.T) {
|
||||
informerFactory.Storage().V1().StorageClasses().Informer().GetIndexer().Add(tc.storageClass)
|
||||
}
|
||||
translator := csitrans.New()
|
||||
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator))
|
||||
expc, err := NewExpandController(fakeKubeClient, pvcInformer, pvInformer, storageClassInformer, nil, allPlugins, translator, csimigration.NewPluginManager(translator), nil)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating expand controller : %v", err)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ go_library(
|
||||
"//pkg/controller/volume/persistentvolume/metrics:go_default_library",
|
||||
"//pkg/controller/volume/persistentvolume/util:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/util/goroutinemap:go_default_library",
|
||||
"//pkg/util/goroutinemap/exponentialbackoff:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
|
@ -28,6 +28,12 @@ type PersistentVolumeBinderControllerConfiguration struct {
|
||||
PVClaimBinderSyncPeriod metav1.Duration
|
||||
// volumeConfiguration holds configuration for volume related features.
|
||||
VolumeConfiguration VolumeConfiguration
|
||||
// VolumeHostCIDRDenylist is a list of CIDRs that should not be reachable by the
|
||||
// controller from plugins.
|
||||
VolumeHostCIDRDenylist []string
|
||||
// VolumeHostAllowLocalLoopback indicates if local loopback hosts (127.0.0.1, etc)
|
||||
// should be allowed from plugins.
|
||||
VolumeHostAllowLocalLoopback bool
|
||||
}
|
||||
|
||||
// VolumeConfiguration contains *all* enumerated flags meant to configure all volume
|
||||
|
@ -39,6 +39,11 @@ func RecommendedDefaultPersistentVolumeBinderControllerConfiguration(obj *kubect
|
||||
obj.PVClaimBinderSyncPeriod = metav1.Duration{Duration: 15 * time.Second}
|
||||
}
|
||||
|
||||
if obj.VolumeHostAllowLocalLoopback == nil {
|
||||
trueValue := true
|
||||
obj.VolumeHostAllowLocalLoopback = &trueValue
|
||||
}
|
||||
|
||||
// Use the default VolumeConfiguration options.
|
||||
RecommendedDefaultVolumeConfiguration(&obj.VolumeConfiguration)
|
||||
}
|
||||
|
@ -21,6 +21,8 @@ limitations under the License.
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
@ -105,6 +107,10 @@ func autoConvert_v1alpha1_PersistentVolumeBinderControllerConfiguration_To_confi
|
||||
if err := Convert_v1alpha1_VolumeConfiguration_To_config_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.VolumeHostCIDRDenylist = *(*[]string)(unsafe.Pointer(&in.VolumeHostCIDRDenylist))
|
||||
if err := v1.Convert_Pointer_bool_To_bool(&in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -113,6 +119,10 @@ func autoConvert_config_PersistentVolumeBinderControllerConfiguration_To_v1alpha
|
||||
if err := Convert_config_VolumeConfiguration_To_v1alpha1_VolumeConfiguration(&in.VolumeConfiguration, &out.VolumeConfiguration, s); err != nil {
|
||||
return err
|
||||
}
|
||||
out.VolumeHostCIDRDenylist = *(*[]string)(unsafe.Pointer(&in.VolumeHostCIDRDenylist))
|
||||
if err := v1.Convert_bool_To_Pointer_bool(&in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback, s); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,11 @@ func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *Persi
|
||||
*out = *in
|
||||
out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod
|
||||
out.VolumeConfiguration = in.VolumeConfiguration
|
||||
if in.VolumeHostCIDRDenylist != nil {
|
||||
in, out := &in.VolumeHostCIDRDenylist, &out.VolumeHostCIDRDenylist
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/util/goroutinemap"
|
||||
"k8s.io/kubernetes/pkg/util/goroutinemap/exponentialbackoff"
|
||||
vol "k8s.io/kubernetes/pkg/volume"
|
||||
@ -235,6 +236,9 @@ type PersistentVolumeController struct {
|
||||
|
||||
translator CSINameTranslator
|
||||
csiMigratedPluginManager CSIMigratedPluginManager
|
||||
|
||||
// filteredDialOptions configures any dialing done by the controller.
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
// syncClaim is the main controller method to decide what to do with a claim.
|
||||
|
@ -44,6 +44,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/controller/volume/common"
|
||||
"k8s.io/kubernetes/pkg/controller/volume/persistentvolume/metrics"
|
||||
pvutil "k8s.io/kubernetes/pkg/controller/volume/persistentvolume/util"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/util/goroutinemap"
|
||||
vol "k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/csimigration"
|
||||
@ -70,6 +71,7 @@ type ControllerParameters struct {
|
||||
NodeInformer coreinformers.NodeInformer
|
||||
EventRecorder record.EventRecorder
|
||||
EnableDynamicProvisioning bool
|
||||
FilteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
// NewController creates a new PersistentVolume controller
|
||||
@ -142,6 +144,8 @@ func NewController(p ControllerParameters) (*PersistentVolumeController, error)
|
||||
controller.translator = csiTranslator
|
||||
controller.csiMigratedPluginManager = csimigration.NewPluginManager(csiTranslator)
|
||||
|
||||
controller.filteredDialOptions = p.FilteredDialOptions
|
||||
|
||||
return controller, nil
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ import (
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/record"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
vol "k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util/subpath"
|
||||
)
|
||||
@ -138,3 +139,7 @@ func (ctrl *PersistentVolumeController) GetSubpather() subpath.Interface {
|
||||
// No volume plugin needs Subpaths in PV controller.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctrl *PersistentVolumeController) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
|
||||
return ctrl.filteredDialOptions
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ go_library(
|
||||
"//pkg/kubelet/util/queue:go_default_library",
|
||||
"//pkg/kubelet/util/sliceutils:go_default_library",
|
||||
"//pkg/kubelet/volumemanager:go_default_library",
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/security/apparmor:go_default_library",
|
||||
"//pkg/security/podsecuritypolicy/sysctl:go_default_library",
|
||||
"//pkg/util/iptables:go_default_library",
|
||||
|
@ -38,6 +38,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/kubelet/configmap"
|
||||
"k8s.io/kubernetes/pkg/kubelet/secret"
|
||||
"k8s.io/kubernetes/pkg/kubelet/token"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||
@ -151,6 +152,11 @@ func (kvh *kubeletVolumeHost) GetSubpather() subpath.Interface {
|
||||
return kvh.kubelet.subpather
|
||||
}
|
||||
|
||||
func (kvh *kubeletVolumeHost) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
|
||||
// FilteredDial is not needed in the kubelet.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (kvh *kubeletVolumeHost) GetHostUtil() hostutil.HostUtils {
|
||||
return kvh.kubelet.hostutil
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
v1 "k8s.io/api/core/v1"
|
||||
@ -124,6 +125,16 @@ func IsProxyableHostname(ctx context.Context, resolv Resolver, hostname string)
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsAllowedHost checks if the given IP host address is in a network in the denied list.
|
||||
func IsAllowedHost(host net.IP, denied []*net.IPNet) error {
|
||||
for _, ipNet := range denied {
|
||||
if ipNet.Contains(host) {
|
||||
return ErrAddressNotAllowed
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetLocalAddrs returns a list of all network addresses on the local system
|
||||
func GetLocalAddrs() ([]net.IP, error) {
|
||||
var localAddrs []net.IP
|
||||
@ -311,3 +322,57 @@ func EnsureSysctl(sysctl utilsysctl.Interface, name string, newVal int) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DialContext is a dial function matching the signature of net.Dialer.DialContext.
|
||||
type DialContext = func(context.Context, string, string) (net.Conn, error)
|
||||
|
||||
// FilteredDialOptions configures how a DialContext is wrapped by NewFilteredDialContext.
|
||||
type FilteredDialOptions struct {
|
||||
// DialHostIPDenylist restricts hosts from being dialed.
|
||||
DialHostCIDRDenylist []*net.IPNet
|
||||
// AllowLocalLoopback controls connections to local loopback hosts (as defined by
|
||||
// IsProxyableIP).
|
||||
AllowLocalLoopback bool
|
||||
}
|
||||
|
||||
// NewFilteredDialContext returns a DialContext function that filters connections based on a FilteredDialOptions.
|
||||
func NewFilteredDialContext(wrapped DialContext, resolv Resolver, opts *FilteredDialOptions) DialContext {
|
||||
if wrapped == nil {
|
||||
wrapped = http.DefaultTransport.(*http.Transport).DialContext
|
||||
}
|
||||
if opts == nil {
|
||||
// Do no filtering
|
||||
return wrapped
|
||||
}
|
||||
if resolv == nil {
|
||||
resolv = net.DefaultResolver
|
||||
}
|
||||
if len(opts.DialHostCIDRDenylist) == 0 && opts.AllowLocalLoopback {
|
||||
// Do no filtering.
|
||||
return wrapped
|
||||
}
|
||||
return func(ctx context.Context, network, address string) (net.Conn, error) {
|
||||
resp, err := resolv.LookupIPAddr(ctx, address)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(resp) == 0 {
|
||||
return nil, ErrNoAddresses
|
||||
}
|
||||
|
||||
for _, host := range resp {
|
||||
if !opts.AllowLocalLoopback {
|
||||
if err := isProxyableIP(host.IP); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
if opts.DialHostCIDRDenylist != nil {
|
||||
if err := IsAllowedHost(host.IP, opts.DialHostCIDRDenylist); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return wrapped(ctx, network, address)
|
||||
}
|
||||
}
|
||||
|
@ -163,6 +163,39 @@ func TestIsProxyableHostname(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsAllowedHost(t *testing.T) {
|
||||
testCases := []struct {
|
||||
ip string
|
||||
denied []string
|
||||
want error
|
||||
}{
|
||||
{"8.8.8.8", []string{}, nil},
|
||||
{"169.254.169.254", []string{"169.0.0.0/8"}, ErrAddressNotAllowed},
|
||||
{"169.254.169.254", []string{"fce8::/15", "169.254.169.0/24"}, ErrAddressNotAllowed},
|
||||
{"fce9:beef::", []string{"fce8::/15", "169.254.169.0/24"}, ErrAddressNotAllowed},
|
||||
{"127.0.0.1", []string{"127.0.0.1/32"}, ErrAddressNotAllowed},
|
||||
{"34.107.204.206", []string{"fce8::/15"}, nil},
|
||||
{"fce9:beef::", []string{"127.0.0.1/32"}, nil},
|
||||
{"34.107.204.206", []string{"127.0.0.1/32"}, nil},
|
||||
{"127.0.0.1", []string{}, nil},
|
||||
}
|
||||
|
||||
for i := range testCases {
|
||||
var denyList []*net.IPNet
|
||||
for _, cidrStr := range testCases[i].denied {
|
||||
_, ipNet, err := net.ParseCIDR(cidrStr)
|
||||
if err != nil {
|
||||
t.Fatalf("bad IP for test case: %v: %v", cidrStr, err)
|
||||
}
|
||||
denyList = append(denyList, ipNet)
|
||||
}
|
||||
got := IsAllowedHost(net.ParseIP(testCases[i].ip), denyList)
|
||||
if testCases[i].want != got {
|
||||
t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestShouldSkipService(t *testing.T) {
|
||||
testCases := []struct {
|
||||
service *v1.Service
|
||||
|
@ -18,6 +18,7 @@ go_library(
|
||||
importpath = "k8s.io/kubernetes/pkg/volume",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume/util/fs:go_default_library",
|
||||
"//pkg/volume/util/hostutil:go_default_library",
|
||||
"//pkg/volume/util/recyclerclient:go_default_library",
|
||||
|
@ -39,6 +39,7 @@ import (
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/record"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||
"k8s.io/kubernetes/pkg/volume/util/recyclerclient"
|
||||
"k8s.io/kubernetes/pkg/volume/util/subpath"
|
||||
@ -450,6 +451,9 @@ type VolumeHost interface {
|
||||
|
||||
// Returns an interface that should be used to execute subpath operations
|
||||
GetSubpather() subpath.Interface
|
||||
|
||||
// Returns options to pass for proxyutil filtered dialers.
|
||||
GetFilteredDialOptions() *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
// VolumePluginMgr tracks registered plugins.
|
||||
|
@ -41,6 +41,7 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/scaleio",
|
||||
deps = [
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
@ -33,6 +34,7 @@ import (
|
||||
sio "github.com/thecodeteam/goscaleio"
|
||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||
"k8s.io/klog/v2"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -56,37 +58,39 @@ type sioInterface interface {
|
||||
}
|
||||
|
||||
type sioClient struct {
|
||||
client *sio.Client
|
||||
gateway string
|
||||
username string
|
||||
password string
|
||||
insecure bool
|
||||
certsEnabled bool
|
||||
system *siotypes.System
|
||||
sysName string
|
||||
sysClient *sio.System
|
||||
protectionDomain *siotypes.ProtectionDomain
|
||||
pdName string
|
||||
pdClient *sio.ProtectionDomain
|
||||
storagePool *siotypes.StoragePool
|
||||
spName string
|
||||
spClient *sio.StoragePool
|
||||
provisionMode string
|
||||
sdcPath string
|
||||
sdcGUID string
|
||||
instanceID string
|
||||
inited bool
|
||||
diskRegex *regexp.Regexp
|
||||
mtx sync.Mutex
|
||||
exec utilexec.Interface
|
||||
client *sio.Client
|
||||
gateway string
|
||||
username string
|
||||
password string
|
||||
insecure bool
|
||||
certsEnabled bool
|
||||
system *siotypes.System
|
||||
sysName string
|
||||
sysClient *sio.System
|
||||
protectionDomain *siotypes.ProtectionDomain
|
||||
pdName string
|
||||
pdClient *sio.ProtectionDomain
|
||||
storagePool *siotypes.StoragePool
|
||||
spName string
|
||||
spClient *sio.StoragePool
|
||||
provisionMode string
|
||||
sdcPath string
|
||||
sdcGUID string
|
||||
instanceID string
|
||||
inited bool
|
||||
diskRegex *regexp.Regexp
|
||||
mtx sync.Mutex
|
||||
exec utilexec.Interface
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
func newSioClient(gateway, username, password string, sslEnabled bool, exec utilexec.Interface) (*sioClient, error) {
|
||||
func newSioClient(gateway, username, password string, sslEnabled bool, exec utilexec.Interface, filteredDialOptions *proxyutil.FilteredDialOptions) (*sioClient, error) {
|
||||
client := new(sioClient)
|
||||
client.gateway = gateway
|
||||
client.username = username
|
||||
client.password = password
|
||||
client.exec = exec
|
||||
client.filteredDialOptions = filteredDialOptions
|
||||
if sslEnabled {
|
||||
client.insecure = false
|
||||
client.certsEnabled = true
|
||||
@ -118,6 +122,15 @@ func (c *sioClient) init() error {
|
||||
klog.Error(log("failed to create client: %v", err))
|
||||
return err
|
||||
}
|
||||
transport, ok := client.Http.Transport.(*http.Transport)
|
||||
if !ok {
|
||||
return errors.New("could not set http.Transport options for scaleio client")
|
||||
}
|
||||
//lint:ignore SA1019 DialTLS must be used to support legacy clients.
|
||||
if transport.DialTLS != nil {
|
||||
return errors.New("DialTLS will be used instead of DialContext")
|
||||
}
|
||||
transport.DialContext = proxyutil.NewFilteredDialContext(transport.DialContext, nil, c.filteredDialOptions)
|
||||
c.client = client
|
||||
if _, err = c.client.Authenticate(
|
||||
&sio.ConfigConnect{
|
||||
|
@ -21,6 +21,7 @@ import (
|
||||
"strconv"
|
||||
|
||||
"k8s.io/klog/v2"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
|
||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||
@ -30,9 +31,10 @@ type sioMgr struct {
|
||||
client sioInterface
|
||||
configData map[string]string
|
||||
exec utilexec.Interface
|
||||
host volume.VolumeHost
|
||||
}
|
||||
|
||||
func newSioMgr(configs map[string]string, exec utilexec.Interface) (*sioMgr, error) {
|
||||
func newSioMgr(configs map[string]string, host volume.VolumeHost, exec utilexec.Interface) (*sioMgr, error) {
|
||||
if configs == nil {
|
||||
return nil, errors.New("missing configuration data")
|
||||
}
|
||||
@ -41,7 +43,7 @@ func newSioMgr(configs map[string]string, exec utilexec.Interface) (*sioMgr, err
|
||||
configs[confKey.sdcRootPath] = defaultString(configs[confKey.sdcRootPath], sdcRootPath)
|
||||
configs[confKey.storageMode] = defaultString(configs[confKey.storageMode], "ThinProvisioned")
|
||||
|
||||
mgr := &sioMgr{configData: configs, exec: exec}
|
||||
mgr := &sioMgr{configData: configs, host: host, exec: exec}
|
||||
return mgr, nil
|
||||
}
|
||||
|
||||
@ -61,7 +63,7 @@ func (m *sioMgr) getClient() (sioInterface, error) {
|
||||
certsEnabled := b
|
||||
|
||||
klog.V(4).Info(log("creating new client for gateway %s", gateway))
|
||||
client, err := newSioClient(gateway, username, password, certsEnabled, m.exec)
|
||||
client, err := newSioClient(gateway, username, password, certsEnabled, m.exec, m.host.GetFilteredDialOptions())
|
||||
if err != nil {
|
||||
klog.Error(log("failed to create scaleio client: %v", err))
|
||||
return nil, err
|
||||
|
@ -22,6 +22,7 @@ import (
|
||||
"time"
|
||||
|
||||
siotypes "github.com/thecodeteam/goscaleio/types/v1"
|
||||
volumetesting "k8s.io/kubernetes/pkg/volume/testing"
|
||||
"k8s.io/utils/exec/testing"
|
||||
)
|
||||
|
||||
@ -42,7 +43,8 @@ var (
|
||||
)
|
||||
|
||||
func newTestMgr(t *testing.T) *sioMgr {
|
||||
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{})
|
||||
host := volumetesting.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
|
||||
mgr, err := newSioMgr(fakeConfig, host, &testingexec.FakeExec{})
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -51,7 +53,8 @@ func newTestMgr(t *testing.T) *sioMgr {
|
||||
}
|
||||
|
||||
func TestMgrNew(t *testing.T) {
|
||||
mgr, err := newSioMgr(fakeConfig, &testingexec.FakeExec{})
|
||||
host := volumetesting.NewFakeVolumeHost(t, "/tmp/fake", nil, nil)
|
||||
mgr, err := newSioMgr(fakeConfig, host, &testingexec.FakeExec{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -405,7 +405,7 @@ func (v *sioVolume) setSioMgr() error {
|
||||
klog.Error(log("failed to retrieve sdc guid: %v", err))
|
||||
return err
|
||||
}
|
||||
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
|
||||
if err != nil {
|
||||
klog.Error(log("failed to reset sio manager: %v", err))
|
||||
@ -444,8 +444,7 @@ func (v *sioVolume) resetSioMgr() error {
|
||||
klog.Error(log("failed to retrieve sdc guid: %v", err))
|
||||
return err
|
||||
}
|
||||
|
||||
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
|
||||
if err != nil {
|
||||
klog.Error(log("failed to reset scaleio mgr: %v", err))
|
||||
@ -480,8 +479,7 @@ func (v *sioVolume) setSioMgrFromConfig() error {
|
||||
klog.Error(log("failed to load secret: %v", err))
|
||||
return err
|
||||
}
|
||||
|
||||
mgr, err := newSioMgr(data, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
mgr, err := newSioMgr(data, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
|
||||
if err != nil {
|
||||
klog.Error(log("failed while setting scaleio mgr from config: %v", err))
|
||||
@ -516,8 +514,7 @@ func (v *sioVolume) setSioMgrFromSpec() error {
|
||||
klog.Error(log("failed to load secret: %v", err))
|
||||
return err
|
||||
}
|
||||
|
||||
mgr, err := newSioMgr(configData, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
mgr, err := newSioMgr(configData, v.plugin.host, v.plugin.host.GetExec(v.plugin.GetPluginName()))
|
||||
|
||||
if err != nil {
|
||||
klog.Error(log("failed to reset sio manager: %v", err))
|
||||
|
@ -15,6 +15,7 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/storageos",
|
||||
deps = [
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//staging/src/k8s.io/api/core/v1:go_default_library",
|
||||
|
@ -110,7 +110,7 @@ func (plugin *storageosPlugin) NewMounter(spec *volume.Spec, pod *v1.Pod, _ volu
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||
return plugin.newMounterInternal(spec, pod, apiCfg, &storageosUtil{host: plugin.host}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod, apiCfg *storageosAPIConfig, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Mounter, error) {
|
||||
@ -142,7 +142,7 @@ func (plugin *storageosPlugin) newMounterInternal(spec *volume.Spec, pod *v1.Pod
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) NewUnmounter(pvName string, podUID types.UID) (volume.Unmounter, error) {
|
||||
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||
return plugin.newUnmounterInternal(pvName, podUID, &storageosUtil{host: plugin.host}, plugin.host.GetMounter(plugin.GetPluginName()), plugin.host.GetExec(plugin.GetPluginName()))
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) newUnmounterInternal(pvName string, podUID types.UID, manager storageosManager, mounter mount.Interface, exec utilexec.Interface) (volume.Unmounter, error) {
|
||||
@ -194,7 +194,7 @@ func (plugin *storageosPlugin) NewDeleter(spec *volume.Spec) (volume.Deleter, er
|
||||
return nil, fmt.Errorf("failed to get admin secret from [%q/%q]: %v", adminSecretNamespace, adminSecretName, err)
|
||||
}
|
||||
|
||||
return plugin.newDeleterInternal(spec, apiCfg, &storageosUtil{})
|
||||
return plugin.newDeleterInternal(spec, apiCfg, &storageosUtil{host: plugin.host})
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) newDeleterInternal(spec *volume.Spec, apiCfg *storageosAPIConfig, manager storageosManager) (volume.Deleter, error) {
|
||||
@ -215,7 +215,7 @@ func (plugin *storageosPlugin) newDeleterInternal(spec *volume.Spec, apiCfg *sto
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) NewProvisioner(options volume.VolumeOptions) (volume.Provisioner, error) {
|
||||
return plugin.newProvisionerInternal(options, &storageosUtil{})
|
||||
return plugin.newProvisionerInternal(options, &storageosUtil{host: plugin.host})
|
||||
}
|
||||
|
||||
func (plugin *storageosPlugin) newProvisionerInternal(options volume.VolumeOptions, manager storageosManager) (volume.Provisioner, error) {
|
||||
|
@ -26,6 +26,8 @@ import (
|
||||
storageosapi "github.com/storageos/go-api"
|
||||
storageostypes "github.com/storageos/go-api/types"
|
||||
"k8s.io/klog/v2"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
"k8s.io/kubernetes/pkg/volume"
|
||||
utilexec "k8s.io/utils/exec"
|
||||
)
|
||||
|
||||
@ -76,13 +78,17 @@ type apiImplementer interface {
|
||||
|
||||
// storageosUtil is the utility structure to interact with the StorageOS API.
|
||||
type storageosUtil struct {
|
||||
api apiImplementer
|
||||
api apiImplementer
|
||||
host volume.VolumeHost
|
||||
}
|
||||
|
||||
func (u *storageosUtil) NewAPI(apiCfg *storageosAPIConfig) error {
|
||||
if u.api != nil {
|
||||
return nil
|
||||
}
|
||||
if u.host == nil {
|
||||
return errors.New("host must not be nil")
|
||||
}
|
||||
if apiCfg == nil {
|
||||
apiCfg = &storageosAPIConfig{
|
||||
apiAddr: defaultAPIAddress,
|
||||
@ -98,6 +104,9 @@ func (u *storageosUtil) NewAPI(apiCfg *storageosAPIConfig) error {
|
||||
return err
|
||||
}
|
||||
api.SetAuth(apiCfg.apiUser, apiCfg.apiPass)
|
||||
if err := api.SetDialContext(proxyutil.NewFilteredDialContext(api.GetDialContext(), nil, u.host.GetFilteredDialOptions())); err != nil {
|
||||
return fmt.Errorf("failed to set DialContext in storageos client: %v", err)
|
||||
}
|
||||
u.api = api
|
||||
return nil
|
||||
}
|
||||
|
@ -49,8 +49,12 @@ func GetAPIConfig() *storageosAPIConfig {
|
||||
}
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
util := storageosUtil{}
|
||||
err := util.NewAPI(GetAPIConfig())
|
||||
tmpDir, err := utiltesting.MkTmpdir("storageos_test")
|
||||
if err != nil {
|
||||
t.Fatalf("error creating tmpdir: %v", err)
|
||||
}
|
||||
util := storageosUtil{host: volumetest.NewFakeVolumeHost(t, tmpDir, nil, nil)}
|
||||
err = util.NewAPI(GetAPIConfig())
|
||||
if err != nil {
|
||||
t.Fatalf("error getting api config: %v", err)
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ go_library(
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/volume/testing",
|
||||
deps = [
|
||||
"//pkg/proxy/util:go_default_library",
|
||||
"//pkg/volume:go_default_library",
|
||||
"//pkg/volume/util:go_default_library",
|
||||
"//pkg/volume/util/hostutil:go_default_library",
|
||||
|
@ -46,6 +46,7 @@ import (
|
||||
"k8s.io/client-go/tools/record"
|
||||
utiltesting "k8s.io/client-go/util/testing"
|
||||
cloudprovider "k8s.io/cloud-provider"
|
||||
proxyutil "k8s.io/kubernetes/pkg/proxy/util"
|
||||
. "k8s.io/kubernetes/pkg/volume"
|
||||
"k8s.io/kubernetes/pkg/volume/util"
|
||||
"k8s.io/kubernetes/pkg/volume/util/hostutil"
|
||||
@ -118,6 +119,7 @@ type fakeVolumeHost struct {
|
||||
informerFactory informers.SharedInformerFactory
|
||||
kubeletErr error
|
||||
mux sync.Mutex
|
||||
filteredDialOptions *proxyutil.FilteredDialOptions
|
||||
}
|
||||
|
||||
var _ VolumeHost = &fakeVolumeHost{}
|
||||
@ -207,6 +209,10 @@ func (f *fakeVolumeHost) GetSubpather() subpath.Interface {
|
||||
return f.subpather
|
||||
}
|
||||
|
||||
func (f *fakeVolumeHost) GetFilteredDialOptions() *proxyutil.FilteredDialOptions {
|
||||
return f.filteredDialOptions
|
||||
}
|
||||
|
||||
func (f *fakeVolumeHost) GetPluginMgr() *VolumePluginMgr {
|
||||
return f.pluginMgr
|
||||
}
|
||||
|
@ -471,6 +471,12 @@ type PersistentVolumeBinderControllerConfiguration struct {
|
||||
PVClaimBinderSyncPeriod metav1.Duration
|
||||
// volumeConfiguration holds configuration for volume related features.
|
||||
VolumeConfiguration VolumeConfiguration
|
||||
// VolumeHostCIDRDenylist is a list of CIDRs that should not be reachable by the
|
||||
// controller from plugins.
|
||||
VolumeHostCIDRDenylist []string
|
||||
// VolumeHostAllowLocalLoopback indicates if local loopback hosts (127.0.0.1, etc)
|
||||
// should be allowed from plugins.
|
||||
VolumeHostAllowLocalLoopback *bool
|
||||
}
|
||||
|
||||
// PodGCControllerConfiguration contains elements describing PodGCController.
|
||||
|
@ -442,6 +442,16 @@ func (in *PersistentVolumeBinderControllerConfiguration) DeepCopyInto(out *Persi
|
||||
*out = *in
|
||||
out.PVClaimBinderSyncPeriod = in.PVClaimBinderSyncPeriod
|
||||
in.VolumeConfiguration.DeepCopyInto(&out.VolumeConfiguration)
|
||||
if in.VolumeHostCIDRDenylist != nil {
|
||||
in, out := &in.VolumeHostCIDRDenylist, &out.VolumeHostCIDRDenylist
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.VolumeHostAllowLocalLoopback != nil {
|
||||
in, out := &in.VolumeHostAllowLocalLoopback, &out.VolumeHostAllowLocalLoopback
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -438,7 +438,9 @@ func createAdClients(ns *v1.Namespace, t *testing.T, server *httptest.Server, sy
|
||||
nil, /* prober */
|
||||
false,
|
||||
5*time.Second,
|
||||
timers)
|
||||
timers,
|
||||
nil, /* filteredDialOptions */
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error creating AttachDetach : %v", err)
|
||||
|
2
vendor/github.com/storageos/go-api/BUILD
generated
vendored
2
vendor/github.com/storageos/go-api/BUILD
generated
vendored
@ -4,7 +4,9 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"cluster.go",
|
||||
"health.go",
|
||||
"licence.go",
|
||||
"logger.go",
|
||||
"login.go",
|
||||
"namespace.go",
|
||||
|
53
vendor/github.com/storageos/go-api/client.go
generated
vendored
53
vendor/github.com/storageos/go-api/client.go
generated
vendored
@ -44,6 +44,9 @@ var (
|
||||
// ErrProxyNotSupported is returned when a client is unable to set a proxy for http requests.
|
||||
ErrProxyNotSupported = errors.New("client does not support http proxy")
|
||||
|
||||
// ErrDialerNotSupported is returned when a client is unable to set a DialContext for http requests.
|
||||
ErrDialerNotSupported = errors.New("client does not support setting DialContext")
|
||||
|
||||
// DefaultPort is the default API port.
|
||||
DefaultPort = "5705"
|
||||
|
||||
@ -107,6 +110,8 @@ type Dialer interface {
|
||||
Dial(network, address string) (net.Conn, error)
|
||||
}
|
||||
|
||||
type dialContext = func(ctx context.Context, network, address string) (net.Conn, error)
|
||||
|
||||
// NewClient returns a Client instance ready for communication with the given
|
||||
// server endpoint. It will use the latest remote API version available in the
|
||||
// server.
|
||||
@ -203,6 +208,36 @@ func (c *Client) SetTimeout(t time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
// GetDialContext returns the current DialContext function, or nil if there is none.
|
||||
func (c *Client) GetDialContext() dialContext {
|
||||
c.configLock.RLock()
|
||||
defer c.configLock.RUnlock()
|
||||
|
||||
if c.httpClient == nil {
|
||||
return nil
|
||||
}
|
||||
transport, supported := c.httpClient.Transport.(*http.Transport)
|
||||
if !supported {
|
||||
return nil
|
||||
}
|
||||
return transport.DialContext
|
||||
}
|
||||
|
||||
// SetDialContext uses the given dial function to establish TCP connections in the HTTPClient.
|
||||
func (c *Client) SetDialContext(dial dialContext) error {
|
||||
c.configLock.Lock()
|
||||
defer c.configLock.Unlock()
|
||||
|
||||
if client := c.httpClient; client != nil {
|
||||
transport, supported := client.Transport.(*http.Transport)
|
||||
if !supported {
|
||||
return ErrDialerNotSupported
|
||||
}
|
||||
transport.DialContext = dial
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Client) checkAPIVersion() error {
|
||||
serverAPIVersionString, err := c.getServerAPIVersionString()
|
||||
if err != nil {
|
||||
@ -259,6 +294,8 @@ type doOptions struct {
|
||||
forceJSON bool
|
||||
force bool
|
||||
unversioned bool
|
||||
|
||||
retryOn []int // http.status codes
|
||||
}
|
||||
|
||||
func (c *Client) do(method, urlpath string, doOptions doOptions) (*http.Response, error) {
|
||||
@ -338,6 +375,7 @@ func (c *Client) do(method, urlpath string, doOptions doOptions) (*http.Response
|
||||
|
||||
resp, err := httpClient.Do(req.WithContext(ctx))
|
||||
if err != nil {
|
||||
|
||||
// If it is a custom error, return it. It probably knows more than us
|
||||
if serror.IsStorageOSError(err) {
|
||||
switch serror.ErrorKind(err) {
|
||||
@ -366,6 +404,17 @@ func (c *Client) do(method, urlpath string, doOptions doOptions) (*http.Response
|
||||
}
|
||||
}
|
||||
|
||||
var shouldretry bool
|
||||
if doOptions.retryOn != nil {
|
||||
for _, code := range doOptions.retryOn {
|
||||
if resp.StatusCode == code {
|
||||
failedAddresses[address] = struct{}{}
|
||||
shouldretry = true
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// If we get to the point of response, we should move any failed
|
||||
// addresses to the back.
|
||||
failed := len(failedAddresses)
|
||||
@ -388,6 +437,10 @@ func (c *Client) do(method, urlpath string, doOptions doOptions) (*http.Response
|
||||
c.addressLock.Unlock()
|
||||
}
|
||||
|
||||
if shouldretry {
|
||||
continue
|
||||
}
|
||||
|
||||
if resp.StatusCode < 200 || resp.StatusCode >= 400 {
|
||||
return nil, newError(resp) // These status codes are likely to be fatal
|
||||
}
|
||||
|
48
vendor/github.com/storageos/go-api/cluster.go
generated
vendored
Normal file
48
vendor/github.com/storageos/go-api/cluster.go
generated
vendored
Normal file
@ -0,0 +1,48 @@
|
||||
package storageos
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/storageos/go-api/types"
|
||||
)
|
||||
|
||||
var (
|
||||
// ClusterMaintenanceAPIPrefix is a path to the HTTP endpoint for managing
|
||||
// the cluster maintenance mode.
|
||||
ClusterMaintenanceAPIPrefix = "cluster/maintenance"
|
||||
)
|
||||
|
||||
// Maintenance returns the maintenance status of the cluster
|
||||
func (c *Client) Maintenance() (*types.Maintenance, error) {
|
||||
resp, err := c.do("GET", ClusterMaintenanceAPIPrefix, doOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
res := &types.Maintenance{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
// EnableMaintenance enables maintenance mode in the cluster
|
||||
func (c *Client) EnableMaintenance() error {
|
||||
resp, err := c.do("POST", ClusterMaintenanceAPIPrefix, doOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
// DisableMaintenance disables maintenance mode in the cluster
|
||||
func (c *Client) DisableMaintenance() error {
|
||||
resp, err := c.do("DELETE", ClusterMaintenanceAPIPrefix, doOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
}
|
16
vendor/github.com/storageos/go-api/health.go
generated
vendored
16
vendor/github.com/storageos/go-api/health.go
generated
vendored
@ -14,6 +14,22 @@ var (
|
||||
HealthAPIPrefix = "health"
|
||||
)
|
||||
|
||||
func (c *Client) ClusterHealth(ctx context.Context) ([]*types.ClusterHealthNode, error) {
|
||||
status := []*types.ClusterHealthNode{}
|
||||
url := fmt.Sprintf("/cluster/%s", HealthAPIPrefix)
|
||||
|
||||
resp, err := c.do("GET", url, doOptions{context: ctx, retryOn: []int{http.StatusNotFound}})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if err := json.NewDecoder(resp.Body).Decode(&status); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return status, nil
|
||||
}
|
||||
|
||||
// CPHealth returns the health of the control plane server at a given url.
|
||||
func (c *Client) CPHealth(ctx context.Context, hostname string) (*types.CPHealthStatus, error) {
|
||||
|
||||
|
43
vendor/github.com/storageos/go-api/licence.go
generated
vendored
Normal file
43
vendor/github.com/storageos/go-api/licence.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package storageos
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/storageos/go-api/types"
|
||||
)
|
||||
|
||||
const (
|
||||
// licenceAPIPrefix is a partial path to the HTTP endpoint.
|
||||
licenceAPIPrefix = "licencing"
|
||||
)
|
||||
|
||||
// Licence returns the current licence on the server.
|
||||
func (c *Client) Licence() (*types.Licence, error) {
|
||||
resp, err := c.do("GET", licenceAPIPrefix, doOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
licence := &types.Licence{}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&licence); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return licence, nil
|
||||
}
|
||||
|
||||
// LicenceApply applies a licence on the server.
|
||||
func (c *Client) LicenceApply(licenceKey string) error {
|
||||
_, err := c.do("POST", licenceAPIPrefix, doOptions{
|
||||
data: &types.LicenceKeyContainer{Key: licenceKey},
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
// LicenceDelete removes the current licence.
|
||||
func (c *Client) LicenceDelete() error {
|
||||
resp, err := c.do("DELETE", licenceAPIPrefix, doOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return resp.Body.Close()
|
||||
}
|
6
vendor/github.com/storageos/go-api/netutil/parsers.go
generated
vendored
6
vendor/github.com/storageos/go-api/netutil/parsers.go
generated
vendored
@ -55,6 +55,12 @@ func AddressesFromNodes(nodes []string) ([]string, error) {
|
||||
return nil, newInvalidNodeError(errInvalidHostName)
|
||||
}
|
||||
|
||||
// Given input like "http://localhost:8080:8383", url.Parse() will
|
||||
// return host as "localhost:8000", which isn't a vaild DNS name.
|
||||
if strings.Contains(host, ":") {
|
||||
return nil, newInvalidNodeError(errInvalidHostName)
|
||||
}
|
||||
|
||||
port := url.Port()
|
||||
if port == "" {
|
||||
port = DefaultDialPort
|
||||
|
2
vendor/github.com/storageos/go-api/policy.go
generated
vendored
2
vendor/github.com/storageos/go-api/policy.go
generated
vendored
@ -29,7 +29,7 @@ func (n *nopMarshaler) MarshalJSON() ([]byte, error) {
|
||||
}
|
||||
|
||||
// PolicyCreate creates a policy on the server.
|
||||
func (c *Client) PolicyCreate(jsonl []byte, ctx context.Context) error {
|
||||
func (c *Client) PolicyCreate(ctx context.Context, jsonl []byte) error {
|
||||
nopm := nopMarshaler(jsonl)
|
||||
_, err := c.do("POST", PolicyAPIPrefix, doOptions{
|
||||
data: &nopm,
|
||||
|
2
vendor/github.com/storageos/go-api/pool.go
generated
vendored
2
vendor/github.com/storageos/go-api/pool.go
generated
vendored
@ -110,7 +110,7 @@ func (c *Client) PoolDelete(opts types.DeleteOptions) error {
|
||||
return ErrPoolInUse
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
|
2
vendor/github.com/storageos/go-api/rule.go
generated
vendored
2
vendor/github.com/storageos/go-api/rule.go
generated
vendored
@ -134,7 +134,7 @@ func (c *Client) RuleDelete(opts types.DeleteOptions) error {
|
||||
return ErrRuleInUse
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
return nil
|
||||
|
2
vendor/github.com/storageos/go-api/types/BUILD
generated
vendored
2
vendor/github.com/storageos/go-api/types/BUILD
generated
vendored
@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"auth.go",
|
||||
"capacity_stats.go",
|
||||
"cluster.go",
|
||||
"connectivity.go",
|
||||
"delete_options.go",
|
||||
"deployment.go",
|
||||
@ -12,6 +13,7 @@ go_library(
|
||||
"error_response.go",
|
||||
"events.go",
|
||||
"health.go",
|
||||
"licence.go",
|
||||
"list_options.go",
|
||||
"logger.go",
|
||||
"namespace.go",
|
||||
|
10
vendor/github.com/storageos/go-api/types/cluster.go
generated
vendored
Normal file
10
vendor/github.com/storageos/go-api/types/cluster.go
generated
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
// Maintenance is used to place the cluster in maintenance mode.
|
||||
type Maintenance struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
UpdatedBy string `json:"updatedBy"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
}
|
14
vendor/github.com/storageos/go-api/types/health.go
generated
vendored
14
vendor/github.com/storageos/go-api/types/health.go
generated
vendored
@ -14,6 +14,20 @@ type NamedSubModuleStatus struct {
|
||||
SubModuleStatus
|
||||
}
|
||||
|
||||
type ClusterHealthNode struct {
|
||||
NodeID string `json:"nodeID"`
|
||||
NodeName string `json:"nodeName"`
|
||||
Submodules struct {
|
||||
DirectFSInitiator SubModuleStatus `json:"directfs_initiator"`
|
||||
Director SubModuleStatus `json:"director"`
|
||||
KV SubModuleStatus `json:"kv"`
|
||||
KVWrite SubModuleStatus `json:"kv_write"`
|
||||
NATS SubModuleStatus `json:"nats"`
|
||||
Presentation SubModuleStatus `json:"presentation"`
|
||||
RDB SubModuleStatus `json:"rdb"`
|
||||
} `json:"submodules"`
|
||||
}
|
||||
|
||||
type CPHealthStatus struct {
|
||||
KV SubModuleStatus
|
||||
KVWrite SubModuleStatus
|
||||
|
35
vendor/github.com/storageos/go-api/types/licence.go
generated
vendored
Normal file
35
vendor/github.com/storageos/go-api/types/licence.go
generated
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
package types
|
||||
|
||||
import "time"
|
||||
|
||||
// FeatureType store features types
|
||||
type FeatureType string
|
||||
|
||||
const (
|
||||
// HA means High Availability
|
||||
HA = FeatureType("HA")
|
||||
// DEV means developer licence
|
||||
DEV = FeatureType("DEV")
|
||||
// TRIAL means trial licence
|
||||
TRIAL = FeatureType("TRIAL")
|
||||
)
|
||||
|
||||
// Licence holds the information to be encoded in the licence key. It needs to be synced across
|
||||
// the django server running on portal-API as well as the corresponding decoding package on the
|
||||
// storageOS control plane
|
||||
type Licence struct {
|
||||
ArrayUUID string `json:"arrayUUID,omitempty"`
|
||||
ClusterID string `json:"clusterID,omitempty"`
|
||||
CustomerID string `json:"customerID"`
|
||||
CustomerName string `json:"customerName"`
|
||||
Storage int `json:"storage"`
|
||||
ValidUntil time.Time `json:"validUntil"`
|
||||
LicenceType string `json:"licenceType"`
|
||||
Features map[FeatureType]bool `json:"features"`
|
||||
Unregistered bool `json:"unregistered"`
|
||||
}
|
||||
|
||||
// LicenceKeyContainer - stores a licence key
|
||||
type LicenceKeyContainer struct {
|
||||
Key string `json:"key"`
|
||||
}
|
3
vendor/github.com/storageos/go-api/user.go
generated
vendored
3
vendor/github.com/storageos/go-api/user.go
generated
vendored
@ -12,7 +12,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
// UserAPIPrefix is a partial path to the HTTP endpoint.
|
||||
UserAPIPrefix = "users"
|
||||
|
||||
@ -77,7 +76,7 @@ func (c *Client) UserCreate(opts types.UserCreateOptions) error {
|
||||
}
|
||||
|
||||
// UserUpdate updates a user on the server.
|
||||
func (c *Client) UserUpdate(user *types.User, ctx context.Context) error {
|
||||
func (c *Client) UserUpdate(ctx context.Context, user *types.User) error {
|
||||
var ref string
|
||||
switch {
|
||||
case user.UUID != "":
|
||||
|
4
vendor/modules.txt
vendored
4
vendor/modules.txt
vendored
@ -1010,10 +1010,10 @@ github.com/spf13/pflag
|
||||
## explicit
|
||||
github.com/spf13/viper
|
||||
# github.com/spf13/viper => github.com/spf13/viper v1.4.0
|
||||
# github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc => github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc
|
||||
# github.com/storageos/go-api v2.2.0+incompatible => github.com/storageos/go-api v2.2.0+incompatible
|
||||
## explicit
|
||||
github.com/storageos/go-api
|
||||
# github.com/storageos/go-api => github.com/storageos/go-api v0.0.0-20180912212459-343b3eff91fc
|
||||
# github.com/storageos/go-api => github.com/storageos/go-api v2.2.0+incompatible
|
||||
github.com/storageos/go-api/netutil
|
||||
github.com/storageos/go-api/serror
|
||||
github.com/storageos/go-api/types
|
||||
|
Loading…
Reference in New Issue
Block a user