func TestTargetShow(t *testing.T) {
	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	configRead, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	set := flag.NewFlagSet("test", 0)
	cxt := cli.NewContext(nil, set, nil)
	err = showEndpoint(cxt)
	if err != nil {
		t.Error("Not expecting error showing endpoint")
	}

	if configRead.CloudTarget != configOri.CloudTarget {
		t.Error("Endpoint should not have changed from show endpoint")
	}

	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
func TestGet(t *testing.T) {
	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	// test Get when config file doesn't exist
	err = cf.RemoveConfigFile()
	if err != nil {
		t.Error("Not expecting error removing config file")
	}
	_, err = get()
	if err == nil {
		t.Error("Expected to receive error trying to get client when config file does not exist")
	}

	// test GetClient with valid endpoint in config file
	endpoint := "http://localhost:9080"
	testGetEndpoint(t, endpoint, false, true)

	endpoint = "https://172.31.253.66:443"
	//test Get for a https endpoint with secure endpoint = true & skipping verify = true
	testGetEndpoint(t, endpoint, true, true)

	//test Get for a https endpoint with secure endpoint = true & skipping verify = false
	testGetEndpoint(t, endpoint, true, false)

	//Restore the original configuration
	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
// Read config from config file, change target and then write back to file
// Also check if the target is reachable securely
func setEndpoint(c *cli.Context) error {
	err := checkArgNum(c.Args(), 1, "target set <url>")
	if err != nil {
		return err
	}
	endpoint := c.Args()[0]
	noCertCheck := c.Bool("nocertcheck")

	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	config.CloudTarget = endpoint
	config.IgnoreCertificate = noCertCheck

	err = cf.SaveConfig(config)
	if err != nil {
		return err
	}

	err = configureServerCerts(endpoint, noCertCheck, c.GlobalIsSet("non-interactive"))
	if err != nil {
		return err
	}

	fmt.Printf("API target set to '%s'\n", endpoint)

	err = clearConfigTenant("")
	if err != nil {
		return err
	}

	return err
}
// Clears the project in the config if it has a matching id
func clearConfigProject(id string) error {
	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	if config == nil || config.Project == nil {
		return nil
	}

	if len(id) == 0 || config.Project.ID == id {
		config.Project = nil
		err = cf.SaveConfig(config)
		if err != nil {
			return err
		}
	}
	return nil
}
// Remove token from the config file
func logout(c *cli.Context) error {
	err := checkArgNum(c.Args(), 0, "target logout")
	if err != nil {
		return err
	}
	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	config.Token = ""

	err = cf.SaveConfig(config)
	if err != nil {
		return err
	}

	fmt.Println("Token removed from config file")

	return nil
}
// Overwrites the tenant in the config file
func setTenant(c *cli.Context) error {
	err := checkArgNum(c.Args(), 1, "tenant set <name>")
	if err != nil {
		return err
	}
	name := c.Args().First()

	client.Esxclient, err = client.GetClient(utils.IsNonInteractive(c))
	if err != nil {
		return err
	}

	// Ensure tenant exists
	id, err := findTenantID(name)
	if len(id) == 0 || err != nil {
		return err
	}

	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	config.Tenant = &cf.TenantConfiguration{Name: name, ID: id}
	err = cf.SaveConfig(config)
	if err != nil {
		return err
	}

	err = clearConfigProject("")
	if err != nil {
		return err
	}

	if !utils.IsNonInteractive(c) {
		fmt.Printf("Tenant set to '%s'\n", name)
	}
	return nil
}
// Set project name and id to config file
// Returns an error if one occurred
func setProject(c *cli.Context) error {
	err := checkArgNum(c.Args(), 1, "project set <project name>")
	if err != nil {
		return err
	}
	name := c.Args().First()

	client.Esxclient, err = client.GetClient(utils.IsNonInteractive(c))
	if err != nil {
		return err
	}

	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	if config == nil || config.Tenant == nil {
		return fmt.Errorf("Error: Set tenant first using 'tenant set <name>' or '-t <name>' option")
	}

	project, err := findProject(config.Tenant.ID, name)
	if err != nil {
		return err
	}

	config.Project = &cf.ProjectConfiguration{Name: project.Name, ID: project.ID}
	err = cf.SaveConfig(config)
	if err != nil {
		return err
	}

	if !utils.IsNonInteractive(c) {
		fmt.Printf("Project set to '%s'\n", name)
	}

	return nil
}
func testGetEndpoint(t *testing.T, endpoint string, ephttps bool, skipVerify bool) {
	token := "fake-token"
	var configExpected *cf.Configuration
	if ephttps == false {
		//this is http case
		configExpected = &cf.Configuration{
			CloudTarget: endpoint,
			Token:       token,
		}
	} else if skipVerify == true {
		configExpected = &cf.Configuration{
			CloudTarget:       endpoint,
			Token:             token,
			IgnoreCertificate: true,
		}
	} else {
		configExpected = &cf.Configuration{
			CloudTarget:       endpoint,
			Token:             token,
			IgnoreCertificate: false,
		}
	}
	err := cf.SaveConfig(configExpected)
	if err != nil {
		t.Error("Not expecting error saving config file")
	}

	Esxclient, err = get()
	if err != nil {
		t.Error("Not expecting error trying to get client when config file has valid endpoint")
	}

	if Esxclient.Endpoint != endpoint {
		t.Error("Endpoint of client not match endpoint in config file")
	}
}
func TestSetGetProject(t *testing.T) {
	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	projectListStruct := photon.ProjectList{
		Items: []photon.ProjectCompact{
			{
				Name: "fake_project_name",
				ID:   "fake_project_ID",
				ResourceTicket: photon.ProjectTicket{
					Limits: []photon.QuotaLineItem{{Key: "vm.test1", Value: 1, Unit: "B"}},
					Usage:  []photon.QuotaLineItem{{Key: "vm.test1", Value: 0, Unit: "B"}},
				},
			},
		},
	}
	listResponse, err := json.Marshal(projectListStruct)
	if err != nil {
		t.Error("Not expecting error serializaing expected projectLists")
	}

	mocks.RegisterResponder(
		"GET",
		server.URL+"/tenants/"+"fake_tenant_ID"+"/projects",
		mocks.CreateResponder(200, string(listResponse[:])))
	mocks.RegisterResponder(
		"GET",
		server.URL+"/tenants/"+"fake_tenant_ID"+"/projects?name="+"fake_project_name",
		mocks.CreateResponder(200, string(listResponse[:])))

	config := &cf.Configuration{
		Tenant: &cf.TenantConfiguration{Name: "fake_tenant_name", ID: "fake_tenant_ID"},
	}
	err = cf.SaveConfig(config)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}

	set := flag.NewFlagSet("test", 0)
	err = set.Parse([]string{"fake_project_name"})
	if err != nil {
		t.Error("Not expecting arguments parsing to fail")
	}
	cxt := cli.NewContext(nil, set, nil)

	err = setProject(cxt)
	if err != nil {
		t.Error("Not expecting error setting project: " + err.Error())
	}

	set = flag.NewFlagSet("test", 0)
	cxt = cli.NewContext(nil, set, nil)

	err = getProject(cxt, os.Stdout)
	if err != nil {
		t.Error("Not expecting error showing project: " + err.Error())
	}

	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
func TestSetEndpoint(t *testing.T) {
	var endpoint string

	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	// test SetEndpoint when config file does not exist
	err = cf.RemoveConfigFile()
	if err != nil {
		t.Error("Not expecting error removing config file")
	}

	endpoint = "endpoint"
	set := flag.NewFlagSet("test", 0)
	err = set.Parse([]string{"endpoint"})
	if err != nil {
		t.Error("Not expecting arguments parsing to fail")
	}
	set.Bool("nocertcheck", true, "")
	cxt := cli.NewContext(nil, set, nil)
	err = setEndpoint(cxt)
	if err != nil {
		t.Error("Not expecting error when setting endpoint")
	}

	configRead, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.CloudTarget != endpoint {
		t.Error("Endpoint read from file not match what's written to file")
	}

	// test SetEndpoint when overwriting existing endpoint
	configExpected := &cf.Configuration{
		CloudTarget:       "test-setendpoint",
		Token:             "test-setendpoint",
		IgnoreCertificate: true,
	}
	err = cf.SaveConfig(configExpected)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}

	endpoint = "endpoint-overwrite"
	set = flag.NewFlagSet("test", 0)
	err = set.Parse([]string{"endpoint-overwrite"})
	if err != nil {
		t.Error("Not expecting arguments parsign to fail")
	}
	set.Bool("nocertcheck", true, "")
	cxt = cli.NewContext(nil, set, nil)
	err = setEndpoint(cxt)
	if err != nil {
		t.Error("Not expecting error when overwritting endpoint in file")
	}

	configRead, err = cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.CloudTarget != endpoint {
		t.Error("Endpoint read from file not match what's written to file")
	}

	configRead.CloudTarget = configExpected.CloudTarget
	if *configRead != *configExpected {
		t.Error("Other configurations changed when setting only cloudtarget")
	}

	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
func TestLogout(t *testing.T) {
	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	// test Logout when config file does not exist
	err = cf.RemoveConfigFile()
	if err != nil {
		t.Error("Not expecting error removing config file")
	}
	set := flag.NewFlagSet("test", 0)
	cxt := cli.NewContext(nil, set, nil)
	err = logout(cxt)
	if err != nil {
		t.Error("Not expecting error when logging out")
	}

	configRead, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.Token != "" {
		t.Error("Token expected to be empty after logout")
	}

	// test Logout when config file exists
	configExpected := &cf.Configuration{
		CloudTarget: "test-logout",
		Token:       "test-logout",
	}
	err = cf.SaveConfig(configExpected)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}

	err = logout(cxt)
	if err != nil {
		t.Error("Not expecting error when logging out")
	}

	configRead, err = cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.Token != "" {
		t.Error("Token expected to be empty after logout")
	}

	configRead.Token = configExpected.Token
	if *configRead != *configExpected {
		t.Error("Other configurations changed when removing only token")
	}

	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
func TestLogin(t *testing.T) {
	var token string

	configOri, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	// test Login when config file does not exist
	err = cf.RemoveConfigFile()
	if err != nil {
		t.Error("Not expecting error removing config file")
	}

	token = "token"
	set := flag.NewFlagSet("test", 0)
	set.String("access_token", token, "")
	cxt := cli.NewContext(nil, set, nil)
	err = login(cxt)
	if err != nil {
		t.Error("Not expecting error when logging in")
	}

	configRead, err := cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.Token != token {
		t.Error("Token read from file not match what's written to file")
	}

	// test Login when overwriting existing endpoint
	configExpected := &cf.Configuration{
		CloudTarget: "test-login",
		Token:       "test-login",
	}
	err = cf.SaveConfig(configExpected)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}

	token = "token-overwrite"
	set = flag.NewFlagSet("test", 0)
	set.String("access_token", token, "")
	cxt = cli.NewContext(nil, set, nil)
	err = login(cxt)
	if err != nil {
		t.Error("Not expecting error when overwritting token in file")
	}

	configRead, err = cf.LoadConfig()
	if err != nil {
		t.Error("Not expecting error loading config file")
	}

	if configRead.Token != token {
		t.Error("Token read from file not match what's written to file")
	}

	configRead.Token = configExpected.Token
	if *configRead != *configExpected {
		t.Error("Other configurations changed when setting only token")
	}

	err = cf.SaveConfig(configOri)
	if err != nil {
		t.Error("Not expecting error when saving config file")
	}
}
// Store token in the config file
func login(c *cli.Context) error {
	err := checkArgNum(c.Args(), 0, "target login")
	if err != nil {
		return err
	}

	username := c.String("username")
	password := c.String("password")
	token := c.String("access_token")

	if !c.GlobalIsSet("non-interactive") && len(token) == 0 {
		username, err = askForInput("User name (username@tenant): ", username)
		if err != nil {
			return err
		}
		if len(password) == 0 {
			fmt.Printf("Password:"******"\n")
		}
	}

	if len(token) == 0 && (len(username) == 0 || len(password) == 0) {
		return fmt.Errorf("Please provide either a token or username/password")
	}

	config, err := cf.LoadConfig()
	if err != nil {
		return err
	}

	if len(token) > 0 {
		config.Token = token

	} else {
		client.Esxclient, err = client.GetClient(c.GlobalIsSet("non-interactive"))
		if err != nil {
			return err
		}

		options, err := client.Esxclient.Auth.GetTokensByPassword(username, password)
		if err != nil {
			return err
		}

		config.Token = options.AccessToken
	}

	err = cf.SaveConfig(config)
	if err != nil {
		return err
	}

	fmt.Println("Token stored in config file")

	return nil
}