func (clc *CenturyLink) addPublicIP(s clcgo.Server) error {

	var ps []clcgo.Port
	for _, p := range clc.TCPOpenPorts {
		ps = append(ps, clcgo.Port{Protocol: "TCP", Port: p})
	}
	ps = append(ps, clcgo.Port{Protocol: "TCP", Port: 22})

	priIP := clc.privateIPFromServer(s)

	a := clcgo.PublicIPAddress{Server: s, Ports: ps, InternalIPAddress: priIP}
	st, e := clc.clcClient.SaveEntity(&a)
	if e != nil {
		return e
	}

	utils.LogInfo("Adding public IP...")
	e = clc.waitForJob(st)
	if e != nil {
		return e
	}

	utils.LogInfo("Public IP is added!")
	return nil
}
func main() {

	defer func() {
		if r := recover(); r != nil {
			fmt.Println(r)
			os.Exit(1)
		}
	}()

	utils.LogInfo("\nDeploying Agent Server...")

	var ln string
	var e error
	rd := bufio.NewReader(os.Stdin)

	for {
		ln, e = rd.ReadString('\n')
		println(ln)
		if e != nil {
			panic(e)
		} else if strings.ContainsAny(ln, "AGENT_KUBER_API") {
			break
		}
	}

	if !strings.ContainsAny(ln, "AGENT_KUBER_API") {
		panic("Missing Key, AGENT_KUBER_API. Cannot proceed.")
	}

	kv := strings.Split(ln, "=")
	utils.SetKey("AGENT_KUBER_API", kv[1])

	pk, puk, _ := utils.CreateSSHKey()

	c := deploy.CenturyLink{
		PublicSSHKey:   puk,
		APIUsername:    os.Getenv("USERNAME"),
		APIPassword:    os.Getenv("PASSWORD"),
		GroupID:        os.Getenv("GROUP_ID"),
		CPU:            1,
		MemoryGB:       1,
		TCPOpenPorts:   []int{3001},
		ServerName:     "AGENT",
		ServerTemplate: "UBUNTU-14-64-TEMPLATE",
	}

	utils.LogInfo("\nWaiting for server creation...")
	s, e := c.DeployVM()

	if e != nil {
		panic(e)
	}

	utils.SetKey("AGENT_PRIVATE_KEY", base64.StdEncoding.EncodeToString([]byte(pk)))
	utils.SetKey("AGENT_PUBLIC_IP", s.PublicIP)

	utils.LogInfo("\nAgent server deployment complete!!")
}
func (clc *CenturyLink) createServer() (CloudServer, error) {

	utils.LogInfo("\nDeploying Server")

	s := clcgo.Server{
		Name:           clc.ServerName,
		GroupID:        clc.GroupID,
		SourceServerID: clc.ServerTemplate,
		CPU:            clc.CPU,
		MemoryGB:       clc.MemoryGB,
		Type:           "standard",
	}

	st, e := clc.clcClient.SaveEntity(&s)
	if e != nil {
		return CloudServer{}, e
	}

	utils.LogInfo("\nWaiting for server to provision...")
	e = clc.waitForJob(st)
	if e != nil {
		return CloudServer{}, e
	}
	clc.clcClient.GetEntity(&s)

	e = clc.addPublicIP(s)
	if e != nil {
		return CloudServer{}, e
	}
	clc.clcClient.GetEntity(&s)

	utils.LogInfo("\nServer is provisioned: " + s.Name)

	cr := clcgo.Credentials{Server: s}
	clc.clcClient.GetEntity(&cr)

	pubIP := clc.publicIPFromServer(s)
	priIP := clc.privateIPFromServer(s)

	priKey := clc.PrivateSSHKey
	utils.LogInfo(fmt.Sprintf("\nPublicIP: %s, PrivateIP: %s", pubIP, priIP))

	clc.addSSHKey(pubIP, cr.Password, clc.PublicSSHKey, priKey)

	pmxS := CloudServer{
		Name:          s.Name,
		PublicIP:      pubIP,
		PrivateIP:     priIP,
		PublicSSHKey:  clc.PublicSSHKey,
		PrivateSSHKey: priKey,
	}

	utils.LogInfo("Server deployment complete!!")

	return pmxS, nil
}
func (clc *CenturyLink) addSSHKey(publicIp string, password string, pubKey string, privateKey string) {

	utils.LogInfo("\nWaiting for server to start before adding ssh keys...")
	clc.WaitForTCP(publicIp)

	utils.LogInfo("\nServer Up....Adding SSH keys")
	config := &ssh.ClientConfig{
		User: "******",
		Auth: []ssh.AuthMethod{ssh.Password(password)},
	}

	cmd := fmt.Sprintf("echo -e \"%s\" >> ~/.ssh/authorized_keys", pubKey)
	clc.executeCmd(cmd, publicIp, config)

	if privateKey != "" {
		pKCmd := fmt.Sprintf("echo -e \"%s\" >> ~/.ssh/id_rsa && chmod 400 ~/.ssh/id_rsa", privateKey)
		clc.executeCmd(pKCmd, publicIp, config)
	}
	utils.LogInfo("\nSSH Keys added!")
}
// ProvisionCluster is used to provision a cluster of RHEL7 VMs (1 Master +
// n Minions).
func (clc CenturyLink) ProvisionCluster(params Params) ([]Server, error) {
	utils.LogInfo("\nProvisioning Server Cluster into Centurylink Cloud...")
	utils.LogInfo("\nMinion Count: " + strconv.Itoa(params.MinionCount))

	e := clc.initProvider()
	if e != nil {
		return nil, e
	}

	var servers []Server
	for i := 0; i < params.MinionCount+1; i++ {
		pk := ""
		if i == 0 {
			utils.LogInfo("\nDeploying Kubernetes Master...")
			pk = clc.masterPK
		} else {
			utils.LogInfo("\nDeploying Kubernetes Minion... " + strconv.Itoa(i))
		}

		c := deploy.CenturyLink{
			PrivateSSHKey: pk,
			PublicSSHKey:  clc.masterPuK,
			APIUsername:   clc.uname,
			APIPassword:   clc.password,
			GroupID:       clc.groupID,
			CPU:           clc.cpu,
			MemoryGB:      clc.memGb,
			ServerName:    "KUBE",
			TCPOpenPorts:  clc.minionPorts,
		}

		s, e := c.DeployVM()
		if e != nil {
			return nil, e
		}

		servers = append(servers, Server{Name: s.Name, PublicIP: s.PublicIP, PrivateIP: s.PrivateIP, PublicSSHKey: s.PublicSSHKey, PrivateSSHKey: pk})
	}
	return servers, nil
}
func (clc *CenturyLink) WaitForTCP(addr string) error {
	utils.LogInfo("\nWaiting for server to start...")
	for {
		conn, err := net.Dial("tcp", addr+":22")
		if err != nil {
			continue
		}
		defer conn.Close()
		if _, err = conn.Read(make([]byte, 1)); err != nil {
			continue
		}
		break
	}
	return nil
}