// SetUpAt creates new directory and clones a git repo. func (gr *gitRepo) SetUpAt(dir string) error { if volumeutil.IsReady(gr.getMetaDir()) { return nil } if gr.legacyMode { return fmt.Errorf("legacy mode: can not create new instances") } // Wrap EmptyDir, let it do the setup. wrapped, err := gr.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &gr.pod, gr.opts, gr.mounter) if err != nil { return err } if err := wrapped.SetUpAt(dir); err != nil { return err } if output, err := gr.execCommand("git", []string{"clone", gr.source}, dir); err != nil { return fmt.Errorf("failed to exec 'git clone %s': %s: %v", gr.source, output, err) } files, err := ioutil.ReadDir(dir) if err != nil { return err } if len(files) != 1 { return fmt.Errorf("unexpected directory contents: %v", files) } if len(gr.revision) == 0 { // Done! volumeutil.SetReady(gr.getMetaDir()) return nil } subdir := path.Join(dir, files[0].Name()) if output, err := gr.execCommand("git", []string{"checkout", gr.revision}, subdir); err != nil { return fmt.Errorf("failed to exec 'git checkout %s': %s: %v", gr.revision, output, err) } if output, err := gr.execCommand("git", []string{"reset", "--hard"}, subdir); err != nil { return fmt.Errorf("failed to exec 'git reset --hard': %s: %v", output, err) } volumeutil.SetReady(gr.getMetaDir()) return nil }
func (sv *secretVolume) SetUpAt(dir string) error { isMnt, err := sv.mounter.IsMountPoint(dir) // Getting an os.IsNotExist err from is a contingency; the directory // may not exist yet, in which case, setup should run. if err != nil && !os.IsNotExist(err) { return err } // If the plugin readiness file is present for this volume and // the setup dir is a mountpoint, this volume is already ready. if volumeutil.IsReady(sv.getMetaDir()) && isMnt { return nil } glog.V(3).Infof("Setting up volume %v for pod %v at %v", sv.volName, sv.pod.UID, dir) // Wrap EmptyDir, let it do the setup. wrapped, err := sv.plugin.host.NewWrapperBuilder(wrappedVolumeSpec, &sv.pod, *sv.opts, sv.mounter) if err != nil { return err } if err := wrapped.SetUpAt(dir); err != nil { return err } qingClient := sv.plugin.host.GetQingClient() if qingClient == nil { return fmt.Errorf("Cannot setup secret volume %v because qing client is not configured", sv) } secret, err := qingClient.Secrets(sv.pod.Namespace).Get(sv.secretName) if err != nil { glog.Errorf("Couldn't get secret %v/%v", sv.pod.Namespace, sv.secretName) return err } else { totalBytes := totalSecretBytes(secret) glog.V(3).Infof("Received secret %v/%v containing (%v) pieces of data, %v total bytes", sv.pod.Namespace, sv.secretName, len(secret.Data), totalBytes) } for name, data := range secret.Data { hostFilePath := path.Join(dir, name) glog.V(3).Infof("Writing secret data %v/%v/%v (%v bytes) to host file %v", sv.pod.Namespace, sv.secretName, name, len(data), hostFilePath) err := ioutil.WriteFile(hostFilePath, data, 0444) if err != nil { glog.Errorf("Error writing secret data to host path: %v, %v", hostFilePath, err) return err } } volumeutil.SetReady(sv.getMetaDir()) return nil }
// Test the case where the 'ready' file has been created and the pod volume dir // is a mountpoint. Mount should not be called. func TestPluginIdempotent(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid2") testVolumeName = "test_volume_name" testNamespace = "test_secret_namespace" testName = "test_secret_name" volumeSpec = volumeSpec(testVolumeName, testName) secret = secret(testNamespace, testName) client = testclient.NewSimpleFake(&secret) pluginMgr = volume.VolumePluginMgr{} rootDir, host = newTestHost(t, client) ) pluginMgr.InitPlugins(ProbeVolumePlugins(), host) plugin, err := pluginMgr.FindPluginByName(secretPluginName) if err != nil { t.Errorf("Can't find the plugin by name") } podVolumeDir := fmt.Sprintf("%v/pods/test_pod_uid2/volumes/qingyuan~secret/test_volume_name", rootDir) podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid2/plugins/qingyuan~secret/test_volume_name", rootDir) pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} mounter := &mount.FakeMounter{} mounter.MountPoints = []mount.MountPoint{ { Path: podVolumeDir, }, } util.SetReady(podMetadataDir) builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, mounter) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } volumePath := builder.GetPath() err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } if len(mounter.Log) != 0 { t.Errorf("Unexpected calls made to mounter: %v", mounter.Log) } if _, err := os.Stat(volumePath); err != nil { if !os.IsNotExist(err) { t.Errorf("SetUp() failed unexpectedly: %v", err) } } else { t.Errorf("volume path should not exist: %v", volumePath) } }
// Test the case where the plugin's ready file exists, but the volume dir is not a // mountpoint, which is the state the system will be in after reboot. The dir // should be mounter and the secret data written to it. func TestPluginReboot(t *testing.T) { var ( testPodUID = types.UID("test_pod_uid3") testVolumeName = "test_volume_name" testNamespace = "test_secret_namespace" testName = "test_secret_name" volumeSpec = volumeSpec(testVolumeName, testName) secret = secret(testNamespace, testName) client = testclient.NewSimpleFake(&secret) pluginMgr = volume.VolumePluginMgr{} rootDir, host = newTestHost(t, client) ) pluginMgr.InitPlugins(ProbeVolumePlugins(), host) plugin, err := pluginMgr.FindPluginByName(secretPluginName) if err != nil { t.Errorf("Can't find the plugin by name") } pod := &api.Pod{ObjectMeta: api.ObjectMeta{UID: testPodUID}} builder, err := plugin.NewBuilder(volume.NewSpecFromVolume(volumeSpec), pod, volume.VolumeOptions{}, &mount.FakeMounter{}) if err != nil { t.Errorf("Failed to make a new Builder: %v", err) } if builder == nil { t.Errorf("Got a nil Builder") } podMetadataDir := fmt.Sprintf("%v/pods/test_pod_uid3/plugins/qingyuan~secret/test_volume_name", rootDir) util.SetReady(podMetadataDir) volumePath := builder.GetPath() if !strings.HasSuffix(volumePath, fmt.Sprintf("pods/test_pod_uid3/volumes/qingyuan~secret/test_volume_name")) { t.Errorf("Got unexpected path: %s", volumePath) } err = builder.SetUp() if err != nil { t.Errorf("Failed to setup volume: %v", err) } if _, err := os.Stat(volumePath); err != nil { if os.IsNotExist(err) { t.Errorf("SetUp() failed, volume path not created: %s", volumePath) } else { t.Errorf("SetUp() failed: %v", err) } } doTestSecretDataInVolume(volumePath, secret, t) doTestCleanAndTeardown(plugin, testPodUID, testVolumeName, volumePath, t) }