func handleListAutoscaleMembers(c *cli.Context) {
	name := c.String("name")
	//prefix := c.String("prefix")
	//suffix := c.String("suffix")
	format := c.String("format")
	chomp := c.String("chomp")
	//joinSeparator := c.String("join-separator")
	outputFilePath := c.String("out")

	// sanitize everything
	format = sanitize(format)
	chomp = sanitize(chomp)

	// parse format as golang template
	tmpl, err := template.New("format").Parse(format)
	if err != nil {
		log.Fatal(err)
	}

	// for now, just AWS provider
	var provider providers.Provider = aws.New()

	// retrieve cluster members
	var clusterMembersByName map[string]string = nil
	if name == "" {
		clusterMembersByName, err = provider.GetClusterMembers()
		if err != nil {
			log.Fatal(err)
		}
	} else {
		clusterMembersByName, err = provider.GetClusterMembersByName(name)
		if err != nil {
			log.Fatal(err)
		}
	}

	// create intermediate key map
	sortedNames := make([]string, 0)
	for name := range clusterMembersByName {
		sortedNames = append(sortedNames, name)
	}

	// do string sorting
	sort.Strings(sortedNames)

	// create final sorted array of Name & Addresses
	sortedNameAndAddresses := make([]NameAndAddress, 0)
	for _, name := range sortedNames {
		nameAndAddress := NameAndAddress{name, clusterMembersByName[name]}
		sortedNameAndAddresses = append(sortedNameAndAddresses, nameAndAddress)
	}

	// loop over sorted name (which are the keys in the map)
	data, err := executeTemplate(tmpl, sortedNameAndAddresses)
	if err != nil {
		log.Fatal(err)
	}

	// chomp if necessary
	if chomp != "" {
		if last := len(data) - 1; last >= 0 && strings.Contains(chomp, string([]rune(data)[last])) {
			data = string([]rune(data)[:last])
		}
	}

	if outputFilePath == "" {
		printToStdout(data)
	} else {
		printToFile(outputFilePath, data)
	}
}
func writeEnvironment(w io.Writer) error {
	var buffer bytes.Buffer
	var err error
	var provider providers.Provider = aws.New()

	instanceId, err := provider.GetInstanceId()
	if err != nil {
		return err
	}

	instanceIp, err := provider.GetInstancePrivateAddress()
	if err != nil {
		return err
	}

	clusterMembersByName, err := provider.GetClusterMembers()
	if err != nil {
		return err
	}

	// retrieve current cluster members
	var etcdMembers []client.Member
	var goodEtcdClientURL string = ""
	for _, memberIp := range clusterMembersByName {
		if memberIp == instanceIp {
			continue
		}

		etcdClientURL := util.EtcdClientURLFromIP(memberIp)
		etcdMembers, err = util.EtcdListMembers(etcdClientURL)
		if err == nil {
			goodEtcdClientURL = etcdClientURL
			break
		}
	}

	// etcd parameters
	var initialClusterState string
	var initialCluster string

	// check if instanceId is already member of cluster
	var isMember bool = false
	for _, member := range etcdMembers {
		if member.Name == instanceId {
			isMember = true
			break
		}
	}

	// if i am not already listed as a member of the cluster assume that this is a new cluster
	if etcdMembers != nil && !isMember {
		log.Printf("joining to an existing cluster, using this client url: %s\n", goodEtcdClientURL)

		//
		// detect and remove bad peers
		//

		// create a reverse cluster members map
		clusterMembersByIp := make(map[string]string)
		for memberName, memberIp := range clusterMembersByName {
			clusterMembersByIp[memberIp] = memberName
		}

		for _, etcdMember := range etcdMembers {
			peerURL, err := url.Parse(etcdMember.PeerURLs[0])
			if err != nil {
				return err
			}

			peerHost, _, err := net.SplitHostPort(peerURL.Host)
			if err != nil {
				return err
			}

			if _, ok := clusterMembersByIp[peerHost]; !ok {
				log.Printf("removing etcd member: %s...", etcdMember.ID)
				err = util.EtcdRemoveMember(goodEtcdClientURL, etcdMember.ID)
				if err != nil {
					return err
				}
				log.Printf("done\n")
			}
		}

		//
		// list current etcd members (after removing spurious ones)
		//

		etcdMembers, err = util.EtcdListMembers(goodEtcdClientURL)
		if err != nil {
			return err
		}

		kvs := make([]string, 0)
		for _, etcdMember := range etcdMembers {
			// ignore unstarted peers
			if len(etcdMember.Name) == 0 {
				continue
			}
			kvs = append(kvs, fmt.Sprintf("%s=%s", etcdMember.Name, etcdMember.PeerURLs[0]))
		}
		kvs = append(kvs, fmt.Sprintf("%s=%s", instanceId, util.EtcdPeerURLFromIP(instanceIp)))

		initialClusterState = "existing"
		initialCluster = strings.Join(kvs, ",")

		//
		// join an existing cluster
		//

		instancePeerURL := util.EtcdPeerURLFromIP(instanceIp)
		log.Printf("adding etcd member: %s...", instancePeerURL)
		member, err := util.EtcdAddMember(goodEtcdClientURL, instancePeerURL)
		if member == nil {
			return err
		}
		log.Printf("done\n")
	} else {
		log.Printf("creating new cluster\n")

		// initial cluster
		kvs := make([]string, 0)
		for memberName, memberIp := range clusterMembersByName {
			kvs = append(kvs, fmt.Sprintf("%s=%s", memberName, util.EtcdPeerURLFromIP(memberIp)))
		}

		initialClusterState = "new"
		initialCluster = strings.Join(kvs, ",")
	}

	// indicate it's going to write envvars
	log.Printf("writing environment variables...")

	// create environment variables
	buffer.WriteString(fmt.Sprintf("ETCD_NAME=%s\n", instanceId))
	buffer.WriteString(fmt.Sprintf("ETCD_INITIAL_CLUSTER_STATE=%s\n", initialClusterState))
	buffer.WriteString(fmt.Sprintf("ETCD_INITIAL_CLUSTER=%s\n", initialCluster))

	if _, err := buffer.WriteTo(w); err != nil {
		return err
	}

	// write done
	log.Printf("done\n")

	return nil
}