func OnlyAllowNodeZones(f *framework.Framework, zoneCount int, image string) {
	gceCloud, err := gce.GetGCECloud()
	framework.ExpectNoError(err)

	// Get all the zones that the nodes are in
	expectedZones, err := gceCloud.GetAllZonesFromCloudProvider()
	framework.ExpectNoError(err)
	framework.Logf("Expected zones: %v", expectedZones)

	// Get all the zones in this current region
	region := gceCloud.Region()
	allZonesInRegion, err := gceCloud.ListZonesInRegion(region)
	framework.ExpectNoError(err)

	var extraZone string
	for _, zone := range allZonesInRegion {
		if !expectedZones.Has(zone.Name) {
			extraZone = zone.Name
			break
		}
	}
	framework.ExpectNotEqual(extraZone, "", fmt.Sprintf("No extra zones available in region %s", region))

	ginkgo.By(fmt.Sprintf("starting a compute instance in unused zone: %v\n", extraZone))
	project := framework.TestContext.CloudConfig.ProjectID
	zone := extraZone
	myuuid := string(uuid.NewUUID())
	name := "compute-" + myuuid
	imageURL := "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140606"

	rb := &compute.Instance{
		MachineType: "zones/" + zone + "/machineTypes/f1-micro",
		Disks: []*compute.AttachedDisk{
			{
				AutoDelete: true,
				Boot:       true,
				Type:       "PERSISTENT",
				InitializeParams: &compute.AttachedDiskInitializeParams{
					DiskName:    "my-root-pd-" + myuuid,
					SourceImage: imageURL,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			{
				AccessConfigs: []*compute.AccessConfig{
					{
						Type: "ONE_TO_ONE_NAT",
						Name: "External NAT",
					},
				},
				Network: "/global/networks/default",
			},
		},
		Name: name,
	}

	err = gceCloud.InsertInstance(project, zone, rb)
	framework.ExpectNoError(err)

	defer func() {
		// Teardown of the compute instance
		framework.Logf("Deleting compute resource: %v", name)
		err := gceCloud.DeleteInstance(project, zone, name)
		framework.ExpectNoError(err)
	}()

	ginkgo.By("Creating zoneCount+1 PVCs and making sure PDs are only provisioned in zones with nodes")
	// Create some (zoneCount+1) PVCs with names of form "pvc-x" where x is 1...zoneCount+1
	// This will exploit ChooseZoneForVolume in pkg/volume/util.go to provision them in all the zones it "sees"
	var pvcList []*v1.PersistentVolumeClaim
	c := f.ClientSet
	ns := f.Namespace.Name

	for index := 1; index <= zoneCount+1; index++ {
		pvc := newNamedDefaultClaim(ns, index)
		pvc, err = e2epv.CreatePVC(c, ns, pvc)
		framework.ExpectNoError(err)
		pvcList = append(pvcList, pvc)

		// Defer the cleanup
		defer func() {
			framework.Logf("deleting claim %q/%q", pvc.Namespace, pvc.Name)
			err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{})
			if err != nil {
				framework.Failf("Error deleting claim %q. Error: %v", pvc.Name, err)
			}
		}()
	}

	// Wait for all claims bound
	for _, claim := range pvcList {
		err = e2epv.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, claim.Namespace, claim.Name, framework.Poll, framework.ClaimProvisionTimeout)
		framework.ExpectNoError(err)
	}

	pvZones := sets.NewString()
	ginkgo.By("Checking that PDs have been provisioned in only the expected zones")
	for _, claim := range pvcList {
		// Get a new copy of the claim to have all fields populated
		claim, err = c.CoreV1().PersistentVolumeClaims(claim.Namespace).Get(context.TODO(), claim.Name, metav1.GetOptions{})
		framework.ExpectNoError(err)

		// Get the related PV
		pv, err := c.CoreV1().PersistentVolumes().Get(context.TODO(), claim.Spec.VolumeName, metav1.GetOptions{})
		framework.ExpectNoError(err)

		pvZone, ok := pv.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
		framework.ExpectEqual(ok, true, "PV has no LabelZone to be found")
		pvZones.Insert(pvZone)
	}
	framework.ExpectEqual(pvZones.Equal(expectedZones), true, fmt.Sprintf("PDs provisioned in unwanted zones. We want zones: %v, got: %v", expectedZones, pvZones))
}
// OnlyAllowNodeZones tests that GetAllCurrentZones returns only zones with Nodes
OnlyAllowNodeZones tests that GetAllCurrentZones returns only zones with Nodes
// OnlyAllowNodeZones tests that GetAllCurrentZones returns only zones with Nodes
func OnlyAllowNodeZones(f *framework.Framework, zoneCount int, image string) {
	gceCloud, err := gce.GetGCECloud()
	framework.ExpectNoError(err)
	expectedZones, err := gceCloud.GetAllZonesFromCloudProvider()
	framework.ExpectNoError(err)
	framework.Logf("Expected zones: %v", expectedZones)
	region := gceCloud.Region()
	allZonesInRegion, err := gceCloud.ListZonesInRegion(region)
	framework.ExpectNoError(err)
	var extraZone string
	for _, zone := range allZonesInRegion {
		if !expectedZones.Has(zone.Name) {
			extraZone = zone.Name
			break
		}
	}
	framework.ExpectNotEqual(extraZone, "", fmt.Sprintf("No extra zones available in region %s", region))
	ginkgo.By(fmt.Sprintf("starting a compute instance in unused zone: %v\n", extraZone))
	project := framework.TestContext.CloudConfig.ProjectID
	zone := extraZone
	myuuid := string(uuid.NewUUID())
	name := "compute-" + myuuid
	imageURL := "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20140606"
	rb := &compute.Instance{
		MachineType: "zones/" + zone + "/machineTypes/f1-micro",
		Disks: []*compute.AttachedDisk{
			{
				AutoDelete: true,
				Boot:       true,
				Type:       "PERSISTENT",
				InitializeParams: &compute.AttachedDiskInitializeParams{
					DiskName:    "my-root-pd-" + myuuid,
					SourceImage: imageURL,
				},
			},
		},
		NetworkInterfaces: []*compute.NetworkInterface{
			{
				AccessConfigs: []*compute.AccessConfig{
					{
						Type: "ONE_TO_ONE_NAT",
						Name: "External NAT",
					},
				},
				Network: "/global/networks/default",
			},
		},
		Name: name,
	}
	err = gceCloud.InsertInstance(project, zone, rb)
	framework.ExpectNoError(err)
	defer func() {
		framework.Logf("Deleting compute resource: %v", name)
		err := gceCloud.DeleteInstance(project, zone, name)
		framework.ExpectNoError(err)
	}()
	ginkgo.By("Creating zoneCount+1 PVCs and making sure PDs are only provisioned in zones with nodes")
	var pvcList []*v1.PersistentVolumeClaim
	c := f.ClientSet
	ns := f.Namespace.Name
	for index := 1; index <= zoneCount+1; index++ {
		pvc := newNamedDefaultClaim(ns, index)
		pvc, err = e2epv.CreatePVC(c, ns, pvc)
		framework.ExpectNoError(err)
		pvcList = append(pvcList, pvc)
		defer func() {
			framework.Logf("deleting claim %q/%q", pvc.Namespace, pvc.Name)
			err = c.CoreV1().PersistentVolumeClaims(pvc.Namespace).Delete(context.TODO(), pvc.Name, metav1.DeleteOptions{})
			if err != nil {
				framework.Failf("Error deleting claim %q. Error: %v", pvc.Name, err)
			}
		}()
	}
	for _, claim := range pvcList {
		err = e2epv.WaitForPersistentVolumeClaimPhase(v1.ClaimBound, c, claim.Namespace, claim.Name, framework.Poll, framework.ClaimProvisionTimeout)
		framework.ExpectNoError(err)
	}
	pvZones := sets.NewString()
	ginkgo.By("Checking that PDs have been provisioned in only the expected zones")
	for _, claim := range pvcList {
		claim, err = c.CoreV1().PersistentVolumeClaims(claim.Namespace).Get(context.TODO(), claim.Name, metav1.GetOptions{})
		framework.ExpectNoError(err)
		pv, err := c.CoreV1().PersistentVolumes().Get(context.TODO(), claim.Spec.VolumeName, metav1.GetOptions{})
		framework.ExpectNoError(err)
		pvZone, ok := pv.ObjectMeta.Labels[v1.LabelZoneFailureDomain]
		framework.ExpectEqual(ok, true, "PV has no LabelZone to be found")
		pvZones.Insert(pvZone)
	}
	framework.ExpectEqual(pvZones.Equal(expectedZones), true, fmt.Sprintf("PDs provisioned in unwanted zones. We want zones: %v, got: %v", expectedZones, pvZones))
}
func OnlyAllowNodeZones ( f * framework . Framework , zoneCount int , image string ) { gceCloud , err := gce . GetGCECloud ( ) framework . ExpectNoError ( err ) expectedZones , err := gceCloud . GetAllZonesFromCloudProvider ( ) framework . ExpectNoError ( err ) framework . Logf ( " " , expectedZones ) region := gceCloud . Region ( ) allZonesInRegion , err := gceCloud . ListZonesInRegion ( region ) framework . ExpectNoError ( err ) var extraZone string for _ , zone := range allZonesInRegion { if ! expectedZones . Has ( zone . Name ) { extraZone = zone . Name break } } framework . ExpectNotEqual ( extraZone , " " , fmt . Sprintf ( " " , region ) ) ginkgo . By ( fmt . Sprintf ( " \n " , extraZone ) ) project := framework . TestContext . CloudConfig . ProjectID zone := extraZone myuuid := string ( uuid . NewUUID ( ) ) name := " " + myuuid imageURL := " " rb := & compute . Instance { MachineType : " " + zone + " " , Disks : [ ] * compute . AttachedDisk { { AutoDelete : true , Boot : true , Type : " " , InitializeParams : & compute . AttachedDiskInitializeParams { DiskName : " " + myuuid , SourceImage : imageURL , } , } , } , NetworkInterfaces : [ ] * compute . NetworkInterface { { AccessConfigs : [ ] * compute . AccessConfig { { Type : " " , Name : " " , } , } , Network : " " , } , } , Name : name , } err = gceCloud . InsertInstance ( project , zone , rb ) framework . ExpectNoError ( err ) defer func ( ) { framework . Logf ( " " , name ) err := gceCloud . DeleteInstance ( project , zone , name ) framework . ExpectNoError ( err ) } ( ) ginkgo . By ( " " ) var pvcList [ ] * v1 . PersistentVolumeClaim c := f . ClientSet ns := f . Namespace . Name for index := 1 ; index <= zoneCount + 1 ; index ++ { pvc := newNamedDefaultClaim ( ns , index ) pvc , err = e2epv . CreatePVC ( c , ns , pvc ) framework . ExpectNoError ( err ) pvcList = append ( pvcList , pvc ) defer func ( ) { framework . Logf ( " " , pvc . Namespace , pvc . Name ) err = c . CoreV1 ( ) . PersistentVolumeClaims ( pvc . Namespace ) . Delete ( context . TODO ( ) , pvc . Name , metav1 . DeleteOptions { } ) if err != nil { framework . Failf ( " " , pvc . Name , err ) } } ( ) } for _ , claim := range pvcList { err = e2epv . WaitForPersistentVolumeClaimPhase ( v1 . ClaimBound , c , claim . Namespace , claim . Name , framework . Poll , framework . ClaimProvisionTimeout ) framework . ExpectNoError ( err ) } pvZones := sets . NewString ( ) ginkgo . By ( " " ) for _ , claim := range pvcList { claim , err = c . CoreV1 ( ) . PersistentVolumeClaims ( claim . Namespace ) . Get ( context . TODO ( ) , claim . Name , metav1 . GetOptions { } ) framework . ExpectNoError ( err ) pv , err := c . CoreV1 ( ) . PersistentVolumes ( ) . Get ( context . TODO ( ) , claim . Spec . VolumeName , metav1 . GetOptions { } ) framework . ExpectNoError ( err ) pvZone , ok := pv . ObjectMeta . Labels [ v1 . LabelZoneFailureDomain ] framework . ExpectEqual ( ok , true , " " ) pvZones . Insert ( pvZone ) } framework . ExpectEqual ( pvZones . Equal ( expectedZones ) , true , fmt . Sprintf ( " " , expectedZones , pvZones ) ) }
OnlyAllowNodeZones tests that GetAllCurrentZones returns only zones with Nodes
OnlyAllowNodeZones tests that GetAllCurrentZones returns only zones with Nodes
// Get all the zones that the nodes are in // Get all the zones in this current region // Teardown of the compute instance // Create some (zoneCount+1) PVCs with names of form "pvc-x" where x is 1...zoneCount+1 // This will exploit ChooseZoneForVolume in pkg/volume/util.go to provision them in all the zones it "sees" // Defer the cleanup // Wait for all claims bound // Get a new copy of the claim to have all fields populated // Get the related PV