예제 #1
0
// 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
}
예제 #2
0
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
}
예제 #3
0
// 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)
	}
}
예제 #4
0
// 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)
}