From fb6e4f54489b4ea33e289f97654700e039683b71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20Mass=C3=A9?= Date: Thu, 18 May 2017 15:34:26 +0100 Subject: [PATCH] add missing piece of code ;) --- .../hostpath-provisioner.go | 152 ++++++++++++++++++ 1 file changed, 152 insertions(+) create mode 100644 src/hostpath-provisioner/hostpath-provisioner.go diff --git a/src/hostpath-provisioner/hostpath-provisioner.go b/src/hostpath-provisioner/hostpath-provisioner.go new file mode 100644 index 0000000..49cb21f --- /dev/null +++ b/src/hostpath-provisioner/hostpath-provisioner.go @@ -0,0 +1,152 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "errors" + "flag" + "os" + "path" + "time" + + "github.com/golang/glog" + "github.com/kubernetes-incubator/external-storage/lib/controller" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/util/wait" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/pkg/api/v1" + "k8s.io/client-go/rest" + "syscall" +) + +const ( + resyncPeriod = 15 * time.Second + provisionerName = "example.com/hostpath" + exponentialBackOffOnError = false + failedRetryThreshold = 5 + leasePeriod = controller.DefaultLeaseDuration + retryPeriod = controller.DefaultRetryPeriod + renewDeadline = controller.DefaultRenewDeadline + termLimit = controller.DefaultTermLimit +) + +type hostPathProvisioner struct { + // The directory to create PV-backing directories in + pvDir string + + // Identity of this hostPathProvisioner, set to node's name. Used to identify + // "this" provisioner's PVs. + identity string +} + +func NewHostPathProvisioner() controller.Provisioner { + nodeName := os.Getenv("NODE_NAME") + if nodeName == "" { + glog.Fatal("env variable NODE_NAME must be set so that this provisioner can identify itself") + } + return &hostPathProvisioner{ + pvDir: "/tmp/hostpath-provisioner", + identity: nodeName, + } +} + +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: metav1.ObjectMeta{ + Name: options.PVName, + Annotations: map[string]string{ + "hostPathProvisionerIdentity": 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 != 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 main() { + syscall.Umask(0) + + flag.Parse() + flag.Set("logtostderr", "true") + + // Create an InClusterConfig and use it to create a client for the controller + // to use to communicate with Kubernetes + config, err := rest.InClusterConfig() + if err != nil { + glog.Fatalf("Failed to create config: %v", err) + } + 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 { + glog.Fatalf("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) +}