提交 e969ebe8 编写于 作者: D dlorenc

Add an external hostpath provisioner to localkube.

上级 0c616a6b
......@@ -124,4 +124,7 @@ func SetupServer(s *localkube.LocalkubeServer) {
// setup proxy
proxy := s.NewProxyServer()
s.AddServer(proxy)
storageProvisioner := s.NewStorageProvisionerServer()
s.AddServer(storageProvisioner)
}
/*
Copyright 2016 The Kubernetes Authors All rights reserved.
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 localkube
import (
"errors"
"fmt"
"os"
"path"
"time"
"github.com/golang/glog"
"github.com/kubernetes-incubator/external-storage/lib/controller"
"github.com/kubernetes-incubator/external-storage/lib/leaderelection"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/pkg/types"
"k8s.io/client-go/pkg/util/uuid"
"k8s.io/client-go/pkg/util/wait"
"k8s.io/client-go/rest"
)
const (
resyncPeriod = 15 * time.Second
provisionerName = "k8s.io/minikube-hostpath"
exponentialBackOffOnError = false
failedRetryThreshold = 5
leasePeriod = leaderelection.DefaultLeaseDuration
retryPeriod = leaderelection.DefaultRetryPeriod
renewDeadline = leaderelection.DefaultRenewDeadline
termLimit = leaderelection.DefaultTermLimit
)
type hostPathProvisioner struct {
// The directory to create PV-backing directories in
pvDir string
// Identity of this hostPathProvisioner, generated. Used to identify "this"
// provisioner's PVs.
identity types.UID
}
func NewHostPathProvisioner() controller.Provisioner {
return &hostPathProvisioner{
pvDir: "/tmp/hostpath-provisioner",
identity: uuid.NewUUID(),
}
}
var _ controller.Provisioner = &hostPathProvisioner{}
// Provision creates a storage asset and returns a PV object representing it.
func (p *hostPathProvisioner) Provision(options controller.VolumeOptions) (*v1.PersistentVolume, error) {
path := path.Join(p.pvDir, options.PVName)
if err := os.MkdirAll(path, 0777); err != nil {
return nil, err
}
pv := &v1.PersistentVolume{
ObjectMeta: v1.ObjectMeta{
Name: options.PVName,
Annotations: map[string]string{
"hostPathProvisionerIdentity": string(p.identity),
},
},
Spec: v1.PersistentVolumeSpec{
PersistentVolumeReclaimPolicy: options.PersistentVolumeReclaimPolicy,
AccessModes: options.PVC.Spec.AccessModes,
Capacity: v1.ResourceList{
v1.ResourceName(v1.ResourceStorage): options.PVC.Spec.Resources.Requests[v1.ResourceName(v1.ResourceStorage)],
},
PersistentVolumeSource: v1.PersistentVolumeSource{
HostPath: &v1.HostPathVolumeSource{
Path: path,
},
},
},
}
return pv, nil
}
// Delete removes the storage asset that was created by Provision represented
// by the given PV.
func (p *hostPathProvisioner) Delete(volume *v1.PersistentVolume) error {
ann, ok := volume.Annotations["hostPathProvisionerIdentity"]
if !ok {
return errors.New("identity annotation not found on PV")
}
if ann != string(p.identity) {
return &controller.IgnoredError{"identity annotation on PV does not match ours"}
}
path := path.Join(p.pvDir, volume.Name)
if err := os.RemoveAll(path); err != nil {
return err
}
return nil
}
func (lk LocalkubeServer) NewStorageProvisionerServer() Server {
return NewSimpleServer("storage-provisioner", serverInterval, StartStorageProvisioner(lk))
}
func StartStorageProvisioner(lk LocalkubeServer) func() error {
// Create an InClusterConfig and use it to create a client for the controller
// to use to communicate with Kubernetes
config := rest.Config{Host: "http://localhost:8080"}
return func() error {
clientset, err := kubernetes.NewForConfig(&config)
if err != nil {
glog.Fatalf("Failed to create client: %v", err)
}
// The controller needs to know what the server version is because out-of-tree
// provisioners aren't officially supported until 1.5
serverVersion, err := clientset.Discovery().ServerVersion()
if err != nil {
return fmt.Errorf("Error getting server version: %v", err)
}
// Create the provisioner: it implements the Provisioner interface expected by
// the controller
hostPathProvisioner := NewHostPathProvisioner()
// Start the provision controller which will dynamically provision hostPath
// PVs
pc := controller.NewProvisionController(clientset, resyncPeriod, provisionerName, hostPathProvisioner, serverVersion.GitVersion, exponentialBackOffOnError, failedRetryThreshold, leasePeriod, renewDeadline, retryPeriod, termLimit)
pc.Run(wait.NeverStop)
return nil
}
}
......@@ -27,21 +27,20 @@ import (
"github.com/docker/machine/libmachine"
"github.com/pkg/browser"
"github.com/pkg/errors"
"k8s.io/client-go/1.5/kubernetes"
corev1 "k8s.io/client-go/1.5/kubernetes/typed/core/v1"
kubeapi "k8s.io/client-go/1.5/pkg/api"
"k8s.io/client-go/1.5/pkg/api/v1"
"k8s.io/client-go/1.5/tools/clientcmd"
"k8s.io/client-go/kubernetes"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/client-go/tools/clientcmd"
"text/template"
"k8s.io/client-go/1.5/pkg/labels"
"k8s.io/client-go/pkg/labels"
"k8s.io/minikube/pkg/minikube/cluster"
"k8s.io/minikube/pkg/util"
)
type K8sClient interface {
GetCoreClient() (corev1.CoreInterface, error)
GetCoreClient() (corev1.CoreV1Interface, error)
}
type K8sClientGetter struct{}
......@@ -52,7 +51,7 @@ func init() {
k8s = &K8sClientGetter{}
}
func (*K8sClientGetter) GetCoreClient() (corev1.CoreInterface, error) {
func (*K8sClientGetter) GetCoreClient() (corev1.CoreV1Interface, error) {
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
configOverrides := &clientcmd.ConfigOverrides{}
kubeConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loadingRules, configOverrides)
......@@ -95,7 +94,7 @@ func GetServiceURLs(api libmachine.API, namespace string, t *template.Template)
serviceInterface := client.Services(namespace)
svcs, err := serviceInterface.List(kubeapi.ListOptions{})
svcs, err := serviceInterface.List(v1.ListOptions{})
if err != nil {
return nil, err
}
......@@ -133,7 +132,7 @@ func GetServiceURLsForService(api libmachine.API, namespace, service string, t *
return printURLsForService(client, ip, service, namespace, t)
}
func printURLsForService(c corev1.CoreInterface, ip, service, namespace string, t *template.Template) ([]string, error) {
func printURLsForService(c corev1.CoreV1Interface, ip, service, namespace string, t *template.Template) ([]string, error) {
if t == nil {
return nil, errors.New("Error, attempted to generate service url with nil --format template")
}
......@@ -254,7 +253,7 @@ func GetServiceListByLabel(namespace string, key string, value string) (*v1.Serv
func getServiceListFromServicesByLabel(services corev1.ServiceInterface, key string, value string) (*v1.ServiceList, error) {
selector := labels.SelectorFromSet(labels.Set(map[string]string{key: value}))
serviceList, err := services.List(kubeapi.ListOptions{LabelSelector: selector})
serviceList, err := services.List(v1.ListOptions{LabelSelector: selector.String()})
if err != nil {
return &v1.ServiceList{}, &util.RetriableError{Err: err}
}
......@@ -320,7 +319,7 @@ func DeleteSecret(namespace, name string) error {
return &util.RetriableError{Err: err}
}
err = secrets.Delete(name, &kubeapi.DeleteOptions{})
err = secrets.Delete(name, &v1.DeleteOptions{})
if err != nil {
return &util.RetriableError{Err: err}
}
......
......@@ -25,10 +25,9 @@ import (
"github.com/docker/machine/libmachine"
"github.com/docker/machine/libmachine/host"
"github.com/pkg/errors"
corev1 "k8s.io/client-go/1.5/kubernetes/typed/core/v1"
"k8s.io/client-go/1.5/kubernetes/typed/core/v1/fake"
"k8s.io/client-go/1.5/pkg/api"
"k8s.io/client-go/1.5/pkg/api/v1"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/kubernetes/typed/core/v1/fake"
"k8s.io/client-go/pkg/api/v1"
"k8s.io/minikube/pkg/minikube/constants"
"k8s.io/minikube/pkg/minikube/tests"
)
......@@ -37,14 +36,14 @@ type MockClientGetter struct {
servicesMap map[string]corev1.ServiceInterface
}
func (m *MockClientGetter) GetCoreClient() (corev1.CoreInterface, error) {
func (m *MockClientGetter) GetCoreClient() (corev1.CoreV1Interface, error) {
return &MockCoreClient{
servicesMap: m.servicesMap,
}, nil
}
type MockCoreClient struct {
fake.FakeCore
fake.FakeCoreV1
servicesMap map[string]corev1.ServiceInterface
}
......@@ -171,12 +170,12 @@ type MockServiceInterface struct {
ServiceList *v1.ServiceList
}
func (s MockServiceInterface) List(opts api.ListOptions) (*v1.ServiceList, error) {
func (s MockServiceInterface) List(opts v1.ListOptions) (*v1.ServiceList, error) {
serviceList := &v1.ServiceList{
Items: []v1.Service{},
}
if opts.LabelSelector != nil {
keyValArr := strings.Split(opts.LabelSelector.String(), "=")
if opts.LabelSelector != "" {
keyValArr := strings.Split(opts.LabelSelector, "=")
for _, service := range s.ServiceList.Items {
if service.Spec.Selector[keyValArr[0]] == keyValArr[1] {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册