// Image examples.
func TestImageServiceScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	imageService := image.NewService(authenticator)
	imagesDetails, err := imageService.ImagesDetail()
	if err != nil {
		t.Fatal("Cannot access images:", err)
	}

	var imageIDs = make([]string, 0)
	for _, element := range imagesDetails {
		imageIDs = append(imageIDs, element.ID)
	}

	if len(imageIDs) == 0 {
		t.Fatal("No images found, check to make sure access is correct")
	}
}
func TestVolumeFromImageScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	imageID := os.Getenv("VATestImageID")

	if imageID == "" {
		t.Skip("Skipping test as not all env variables are set: 'VATestImageID'")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	blockstorageService := blockstorage.NewService(authenticator)

	volumeTypes, err := blockstorageService.VolumeTypes()
	if err != nil {
		t.Fatal("Cannot access volumeTypes:", err)
	}

	volumes, err := blockstorageService.Volumes()
	if err != nil {
		t.Fatal("Cannot access volumes:", err)
	}

	if len(volumes) > 0 {
		_, err := blockstorageService.Volume(volumes[0].ID)
		if err != nil {
			t.Fatal("Cannot requery volume:", err)
		}
	}

	createVolumeParameters := blockstorage.CreateVolumeParameters{
		DisplayName: "TestVolumeDisplayNameFromImage",
		Desciption:  "test description",
		VolumeType:  volumeTypes[0].ID,
		Size:        5,
		ImageRef:    imageID,
	}

	createdVolume, err := blockstorageService.CreateVolume(createVolumeParameters)
	if err != nil {
		t.Fatal("Cannot create volume:", err)
	}

	queriedVolume, err := blockstorageService.Volume(createdVolume.ID)
	if err != nil {
		t.Fatal("Cannot requery volume:", err)
	}

	err = blockstorageService.DeleteVolume(queriedVolume.ID)
	if err != nil {
		t.Fatal("Cannot delete volume:", err)
	}
}
func TestSecurityGroupScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	computeService := compute.NewService(authenticator)

	sampleSecurityGroup := compute.CreateSecurityGroupParameters{
		Description: "Description",
		Name:        "NewCustomSecurityGroup",
	}

	securityGroup, err := computeService.CreateSecurityGroup(sampleSecurityGroup)
	if err != nil {
		t.Fatal("Cannot create security group:", err)
	}

	tcp := compute.TCP
	cidr := "0.0.0.0/0"
	sampleRule := compute.CreateSecurityGroupRuleParameters{
		FromPort:      80,
		ToPort:        80,
		IPProtocol:    tcp,
		CIDR:          &cidr,
		ParentGroupID: securityGroup.ID,
	}

	securityGroupRule, err := computeService.CreateSecurityGroupRule(sampleRule)
	if err != nil {
		t.Fatal("Cannot create security group rule:", err)
	}

	queriedSecurityGroup, err := computeService.SecurityGroup(securityGroup.ID)
	if err != nil {
		t.Fatal("Cannot requery security group:", err)
	}

	testUtil.Assert(t, len(queriedSecurityGroup.Rules) > 0, "Expected Security group to have a rule")

	err = computeService.DeleteSecurityGroupRule(securityGroupRule.ID)
	if err != nil {
		t.Fatal("Cannot delete security group rule:", err)
	}

	err = computeService.DeleteSecurityGroup(queriedSecurityGroup.ID)
	if err != nil {
		t.Fatal("Cannot delete security group:", err)
	}
}
func TestVolumeTypeScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	blockstorageService := blockstorage.NewService(authenticator)

	volumeTypes, err := blockstorageService.VolumeTypes()
	if err != nil {
		t.Fatal("Cannot access volumeTypes:", err)
	}

	if len(volumeTypes) > 0 {
		_, err := blockstorageService.VolumeType(volumeTypes[0].ID)
		if err != nil {
			t.Fatal("Cannot requery volume type:", err)
		}
	}

	createVolumeParameters := blockstorage.CreateVolumeTypeParameters{Name: "nonstandard"}

	createdVolumeType, err := blockstorageService.CreateVolumeType(createVolumeParameters)

	skipRestOfTest := false
	if err != nil {
		status, ok := err.(misc.HTTPStatus)

		if ok && status.StatusCode == 404 || status.StatusCode == 403 {
			t.Log("Cannot test volume type create, so not attempting to delete.")
			skipRestOfTest = true
		} else {
			t.Fatal("Cannot create volume type:", err)
		}
	}

	if !skipRestOfTest {
		queriedVolumeType, err := blockstorageService.VolumeType(createdVolumeType.ID)
		if err != nil {
			t.Fatal("Cannot requery volume type:", err)
		}

		err = blockstorageService.DeleteVolumeType(queriedVolumeType.ID)
		if err != nil {
			t.Fatal("Cannot delete volume type:", err)
		}
	}
}
func TestKeyPairScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	computeService := compute.NewService(authenticator)

	createdKeypair, err := computeService.CreateKeyPair("testkeyPairName", "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDx8nkQv/zgGgB4rMYmIf+6A4l6Rr+o/6lHBQdW5aYd44bd8JttDCE/F/pNRr0lRE+PiqSPO8nDPHw0010JeMH9gYgnnFlyY3/OcJ02RhIPyyxYpv9FhY+2YiUkpwFOcLImyrxEsYXpD/0d3ac30bNH6Sw9JD9UZHYcpSxsIbECHw== Generated by Nova")
	if err != nil {
		t.Fatal("Cannot create keypair:", err)
	}

	queriedKeyPair, err := computeService.KeyPair(createdKeypair.Name)
	if err != nil {
		t.Fatal("Cannot requery keypair:", err)
	}

	keyPairs, err := computeService.KeyPairs()
	if err != nil {
		t.Fatal("Cannot access keypairs:", err)
	}

	foundKeyPair := false
	for _, keyPairValue := range keyPairs {
		if queriedKeyPair.Name == keyPairValue.Name {
			foundKeyPair = true
			break
		}
	}

	if !foundKeyPair {
		t.Fatal("Cannot find keypair that was created.")
	}

	err = computeService.DeleteKeyPair(queriedKeyPair.Name)
	if err != nil {
		t.Fatal("Cannot delete keypair:", err)
	}
}
func TestFlavorScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	computeService := compute.NewService(authenticator)

	flavors, err := computeService.Flavors()
	if err != nil {
		t.Fatalf("Cannot get flavors: %v", err)
	}

	flavorsDetail, err := computeService.FlavorsDetail()
	if err != nil {
		t.Fatalf("Cannot query FlavorsDetail: %v", err)
	}

	testUtil.Equals(t, len(flavorsDetail), len(flavors))

	if len(flavors) > 0 {
		fmt.Println("FlavorID to query:", flavors[0].ID)
		queriedItem, err := computeService.FlavorDetail(flavors[0].ID)
		fmt.Println("Results1:", queriedItem, "Error:", err)
		fmt.Println("Expected:", flavors[0])
		if err != nil {
			t.Fatalf("Cannot requery single flavor: %v", err)
		}

		testUtil.Equals(t, flavorsDetail[0], queriedItem)
	}

}
func TestServerScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	imageID := os.Getenv("TEST_IMAGEID")
	if imageID == "" {
		t.Skip("Cannot run test because Env Var 'TEST_IMAGEID' is not set")
	}

	keyPairName := os.Getenv("TEST_KEYPAIR_NAME")
	if keyPairName == "" {
		t.Skip("Cannot run test because Env Var 'TEST_KEYPAIR_NAME' is not set")
	}

	flavorRef := os.Getenv("TEST_FLAVOR")
	if flavorRef == "" {
		t.Skip("Cannot run test because Env Var 'TEST_FLAVOR' is not set")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	computeService := compute.NewService(authenticator)

	// Create a server with the min required parameters
	minParametersServer := compute.ServerCreationParameters{
		Name:        "testName",
		ImageRef:    imageID,
		KeyPairName: keyPairName,
		FlavorRef:   flavorRef,
	}

	createQueryDeleteServer(t, computeService, minParametersServer)
}
// Image examples.
func TestDatabaseServiceScenarios(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	if os.Getenv("OS_AUTH_URL") == "" {
		t.Skip("Cannot run integration test as the Openstack env vars aren't set.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	authenticator.(requester.Manager).SetFunction(requester.DebugRequestMakerGenerator(nil, nil, testing.Verbose()))
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	databaseService := database.NewService(authenticator)

	user := database.UserParameter{Name: "User1", Password: "******"}
	db := database.CreateDatabaseParameters{Name: "newDb"}
	createInstanceParams := database.CreateInstanceParameters{
		Databases: []database.CreateDatabaseParameters{db},
		FlavorRef: "1001",
		Name:      "Instance1",
		Users:     []database.UserParameter{user},
	}

	instance, err := databaseService.CreateInstance(createInstanceParams)
	if err != nil {
		t.Fatal("Cannot create instance:", err)
	}

	WaitUntilActiveOrError(t, databaseService, instance.ID)

	foundInstance := false
	instances, err := databaseService.Instances()
	if err != nil {
		t.Fatal("Cannot query Instances:", err)
	}

	for _, i := range instances {
		if i.ID == instance.ID {
			foundInstance = true
			break
		}
	}

	if !foundInstance {
		t.Fatal("Cannot find new instance")
	}

	err = databaseService.CreateUser(instance.ID, database.UserParameter{Name: "username", Password: "******"})
	if err != nil {
		t.Fatal("Cannot create user", err)
	}

	err = databaseService.DeleteUser(instance.ID, "username")
	if err != nil {
		t.Fatal("Cannot delete user", err)
	}

	pwd, err := databaseService.EnableRoot(instance.ID)
	if err != nil {
		t.Fatal("Cannot enable root", err)
	}
	testUtil.Assert(t, pwd.Name != "", "No Name")

	backup, err := databaseService.CreateBackup(database.CreateBackupParameters{Name: "NewBackup", InstanceID: instance.ID, Description: "Test Description"})
	if err != nil {
		t.Fatal("Cannot make backup", err)
	}
	WaitUntilActiveOrError(t, databaseService, instance.ID)

	err = databaseService.DeleteInstance(instance.ID)
	if err != nil {
		t.Fatal("Delete instance didn't work:", err)
	}

	newInstance, err := databaseService.RestoreBackupInstance(database.RestoreBackupParameters{Name: "Instance1", RestorePoint: database.RestorePoint{BackupRef: backup.ID}, FlavorRef: "1001"})
	if err != nil {
		t.Fatal("Cannot restore a backup", err)
	}

	WaitUntilActiveOrError(t, databaseService, newInstance.ID)

	err = databaseService.DeleteBackup(backup.ID)
	if err != nil {
		t.Fatal("Cannot delete backup", err)
	}

	err = databaseService.DeleteInstance(newInstance.ID)
	if err != nil {
		t.Fatal("Delete instance didn't work:", err)
	}
}
// TestObjectStorageAPI needs to be broken up into individual tests.
func TestObjectStorageAPI(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping test in short mode.")
	}

	container := os.Getenv("TEST_OBJECTSTORAGE_CONTAINERNAME")
	if container == "" {
		t.Skip("No container specified for integration test in TEST_OBJECTSTORAGE_CONTAINERNAME env variable.")
	}

	authenticator, err := identity.AuthenticateFromEnvVars()
	if err != nil {
		t.Fatal("Cannot authenticate from env vars:", err)
	}

	tokenID, err := authenticator.GetToken()
	if err != nil {
		t.Fatal("There was an error authenticating:", err)
	}

	url, err := authenticator.GetServiceURL("object-store", "1.0")
	if err != nil {
		t.Fatal("There was an error determining the object-store service url:", err)
	}

	hdr, err := objectstorage.GetAccountMeta(url, tokenID)
	if err != nil {
		t.Fatal("There was an error getting account metadata:", err)
	}

	// Create a new container.
	if err = objectstorage.PutContainer(url+container, tokenID,
		"X-Log-Retention", "true"); err != nil {
		t.Fatal("PutContainer Error:", err)
	}

	// Get a list of all the containers at the selected endoint.
	containersJSON, err := objectstorage.ListContainers(0, "", url, tokenID)
	if err != nil {
		t.Fatal(err)
	}

	type containerType struct {
		Name         string
		Bytes, Count int
	}
	containersList := []containerType{}

	if err = json.Unmarshal(containersJSON, &containersList); err != nil {
		t.Fatal(err)
	}

	found := false
	for i := 0; i < len(containersList); i++ {
		if containersList[i].Name == container {
			found = true
		}
	}
	if !found {
		t.Fatal("Created container is missing from downloaded containersList")
	}

	// Set and Get container metadata.
	if err = objectstorage.SetContainerMeta(url+container, tokenID,
		"X-Container-Meta-fubar", "false"); err != nil {
		t.Fatal(err)
	}

	hdr, err = objectstorage.GetContainerMeta(url+container, tokenID)
	if err != nil {
		t.Fatal(fmt.Sprint("GetContainerMeta Error:", err))
	}
	if hdr.Get("X-Container-Meta-fubar") != "false" {
		t.Fatal("container meta does not match")
	}

	// Create an object in a container.
	var fContent []byte
	srcFile := "10-objectstore.go"
	fContent, err = ioutil.ReadFile(srcFile)
	if err != nil {
		t.Fatal(err)
	}

	object := container + "/" + srcFile
	if err = objectstorage.PutObject(&fContent, url+object, tokenID,
		"X-Object-Meta-fubar", "false"); err != nil {
		t.Fatal(err)
	}
	objectsJSON, err := objectstorage.ListObjects(0, "", "", "", "",
		url+container, tokenID)

	type objectType struct {
		Name, Hash, Content_type, Last_modified string
		Bytes                                   int
	}
	objectsList := []objectType{}

	if err = json.Unmarshal(objectsJSON, &objectsList); err != nil {
		t.Fatal(err)
	}
	found = false
	for i := 0; i < len(objectsList); i++ {
		if objectsList[i].Name == srcFile {
			found = true
		}
	}
	if !found {
		t.Fatal("created object is missing from the objectsList")
	}

	// Manage object metadata
	if err = objectstorage.SetObjectMeta(url+object, tokenID,
		"X-Object-Meta-fubar", "true"); err != nil {
		t.Fatal("SetObjectMeta Error:", err)
	}
	hdr, err = objectstorage.GetObjectMeta(url+object, tokenID)
	if err != nil {
		t.Fatal("GetObjectMeta Error:", err)
	}
	if hdr.Get("X-Object-Meta-fubar") != "true" {
		t.Fatal("SetObjectMeta Error:", err)
	}

	// Retrieve an object and check that it is the same as what as uploaded.
	_, body, err := objectstorage.GetObject(url+object, tokenID)
	if err != nil {
		t.Fatal("GetObject Error:", err)
	}
	if !bytes.Equal(fContent, body) {
		t.Fatal("GetObject Error:", "byte comparison of uploaded != downloaded")
	}

	// Duplication (Copy) an existing object.
	if err = objectstorage.CopyObject(url+object, "/"+object+".dup", tokenID); err != nil {
		t.Fatal("CopyObject Error:", err)
	}

	// Delete the objects.
	if err = objectstorage.DeleteObject(url+object, tokenID); err != nil {
		t.Fatal("DeleteObject Error:", err)
	}
	if err = objectstorage.DeleteObject(url+object+".dup", tokenID); err != nil {
		t.Fatal("DeleteObject Error:", err)
	}

	// Delete the container that was previously created.
	if err = objectstorage.DeleteContainer(url+container, tokenID); err != nil {
		t.Fatal("DeleteContainer Error:", err)
	}
}