func (c *interfaceClient) NewInterfaceOnSubnetAtIndex(index int, secGrps []string, subnet Subnet) (*Interface, error) {
	client, err := c.aws.newEC2()
	if err != nil {
		return nil, err
	}

	idDoc, err := c.aws.getIDDoc()
	if err != nil {
		return nil, err
	}

	createReq := &ec2.CreateNetworkInterfaceInput{}
	createReq.SetDescription(fmt.Sprintf("CNI-ENI %v", idDoc.InstanceID))
	secGrpsPtr := []*string{}
	for _, grp := range secGrps {
		newgrp := grp // Need to copy
		secGrpsPtr = append(secGrpsPtr, &newgrp)
	}

	createReq.SetGroups(secGrpsPtr)
	createReq.SetSubnetId(subnet.ID)

	resp, err := client.CreateNetworkInterface(createReq)
	if err != nil {
		return nil, err
	}

	// resp.NetworkInterface.NetworkInterfaceId
	attachReq := &ec2.AttachNetworkInterfaceInput{}
	attachReq.SetDeviceIndex(int64(index))
	attachReq.SetInstanceId(idDoc.InstanceID)
	attachReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)

	attachResp, err := client.AttachNetworkInterface(attachReq)
	if err != nil {
		// We attempt to remove the interface we just made due to attachment failure
		delReq := &ec2.DeleteNetworkInterfaceInput{}
		delReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)

		_, delErr := client.DeleteNetworkInterface(delReq)
		if delErr != nil {
			return nil, delErr
		}
		return nil, err
	}

	// We have an attachment ID from the last API, which lets us mark the
	// interface as delete on termination
	changes := &ec2.NetworkInterfaceAttachmentChanges{}
	changes.SetAttachmentId(*attachResp.AttachmentId)
	changes.SetDeleteOnTermination(true)
	modifyReq := &ec2.ModifyNetworkInterfaceAttributeInput{}
	modifyReq.SetAttachment(changes)
	modifyReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)

	_, err = client.ModifyNetworkInterfaceAttribute(modifyReq)
	if err != nil {
		// Continue anyway
		fmt.Fprintf(os.Stderr,
			"Unable to mark interface for deletion due to %v",
			err)
	}

	for start := time.Now(); time.Since(start) <= interfaceSettleTime; time.Sleep(interfacePollWaitTime) {
		newInterfaces, err := c.aws.GetInterfaces()
		if err != nil {
			// The metadata server is inconsistent - for example, not
			// all of the nodes under the interface will populate at once
			// and instead return a 404 error. We just swallow this error here and
			// continue on.
			continue
		}
		for _, intf := range newInterfaces {
			if intf.Mac == *resp.NetworkInterface.MacAddress {
				if privateIPAddr := net.ParseIP(*resp.NetworkInterface.PrivateIpAddress); privateIPAddr != nil {
					// New IP. Timestamp the addition as a free IP.
					registry := &Registry{}
					registry.TrackIP(privateIPAddr)
				}
				configureInterface(&intf)
				return &intf, nil
			}
		}

	}

	return nil, fmt.Errorf("interface did not attach in time")
}
// NewInterfaceOnSubnetAtIndex creates a new Interface with a specified subnet and index
NewInterfaceOnSubnetAtIndex creates a new Interface with a specified subnet and index
// NewInterfaceOnSubnetAtIndex creates a new Interface with a specified subnet and index
func (c *interfaceClient) NewInterfaceOnSubnetAtIndex(index int, secGrps []string, subnet Subnet) (*Interface, error) {
	client, err := c.aws.newEC2()
	if err != nil {
		return nil, err
	}
	idDoc, err := c.aws.getIDDoc()
	if err != nil {
		return nil, err
	}
	createReq := &ec2.CreateNetworkInterfaceInput{}
	createReq.SetDescription(fmt.Sprintf("CNI-ENI %v", idDoc.InstanceID))
	secGrpsPtr := []*string{}
	for _, grp := range secGrps {
		newgrp := grp 
		secGrpsPtr = append(secGrpsPtr, &newgrp)
	}
	createReq.SetGroups(secGrpsPtr)
	createReq.SetSubnetId(subnet.ID)
	resp, err := client.CreateNetworkInterface(createReq)
	if err != nil {
		return nil, err
	}
	attachReq := &ec2.AttachNetworkInterfaceInput{}
	attachReq.SetDeviceIndex(int64(index))
	attachReq.SetInstanceId(idDoc.InstanceID)
	attachReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)
	attachResp, err := client.AttachNetworkInterface(attachReq)
	if err != nil {
		delReq := &ec2.DeleteNetworkInterfaceInput{}
		delReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)
		_, delErr := client.DeleteNetworkInterface(delReq)
		if delErr != nil {
			return nil, delErr
		}
		return nil, err
	}
	changes := &ec2.NetworkInterfaceAttachmentChanges{}
	changes.SetAttachmentId(*attachResp.AttachmentId)
	changes.SetDeleteOnTermination(true)
	modifyReq := &ec2.ModifyNetworkInterfaceAttributeInput{}
	modifyReq.SetAttachment(changes)
	modifyReq.SetNetworkInterfaceId(*resp.NetworkInterface.NetworkInterfaceId)
	_, err = client.ModifyNetworkInterfaceAttribute(modifyReq)
	if err != nil {
		fmt.Fprintf(os.Stderr,
			"Unable to mark interface for deletion due to %v",
			err)
	}
	for start := time.Now(); time.Since(start) <= interfaceSettleTime; time.Sleep(interfacePollWaitTime) {
		newInterfaces, err := c.aws.GetInterfaces()
		if err != nil {
			continue
		}
		for _, intf := range newInterfaces {
			if intf.Mac == *resp.NetworkInterface.MacAddress {
				if privateIPAddr := net.ParseIP(*resp.NetworkInterface.PrivateIpAddress); privateIPAddr != nil {
					registry := &Registry{}
					registry.TrackIP(privateIPAddr)
				}
				configureInterface(&intf)
				return &intf, nil
			}
		}
	}
	return nil, fmt.Errorf("interface did not attach in time")
}
func ( c * interfaceClient ) NewInterfaceOnSubnetAtIndex ( index int , secGrps [ ] string , subnet Subnet ) ( * Interface , error ) { client , err := c . aws . newEC2 ( ) if err != nil { return nil , err } idDoc , err := c . aws . getIDDoc ( ) if err != nil { return nil , err } createReq := & ec2 . CreateNetworkInterfaceInput { } createReq . SetDescription ( fmt . Sprintf ( " " , idDoc . InstanceID ) ) secGrpsPtr := [ ] * string { } for _ , grp := range secGrps { newgrp := grp secGrpsPtr = append ( secGrpsPtr , & newgrp ) } createReq . SetGroups ( secGrpsPtr ) createReq . SetSubnetId ( subnet . ID ) resp , err := client . CreateNetworkInterface ( createReq ) if err != nil { return nil , err } attachReq := & ec2 . AttachNetworkInterfaceInput { } attachReq . SetDeviceIndex ( int64 ( index ) ) attachReq . SetInstanceId ( idDoc . InstanceID ) attachReq . SetNetworkInterfaceId ( * resp . NetworkInterface . NetworkInterfaceId ) attachResp , err := client . AttachNetworkInterface ( attachReq ) if err != nil { delReq := & ec2 . DeleteNetworkInterfaceInput { } delReq . SetNetworkInterfaceId ( * resp . NetworkInterface . NetworkInterfaceId ) _ , delErr := client . DeleteNetworkInterface ( delReq ) if delErr != nil { return nil , delErr } return nil , err } changes := & ec2 . NetworkInterfaceAttachmentChanges { } changes . SetAttachmentId ( * attachResp . AttachmentId ) changes . SetDeleteOnTermination ( true ) modifyReq := & ec2 . ModifyNetworkInterfaceAttributeInput { } modifyReq . SetAttachment ( changes ) modifyReq . SetNetworkInterfaceId ( * resp . NetworkInterface . NetworkInterfaceId ) _ , err = client . ModifyNetworkInterfaceAttribute ( modifyReq ) if err != nil { fmt . Fprintf ( os . Stderr , " " , err ) } for start := time . Now ( ) ; time . Since ( start ) <= interfaceSettleTime ; time . Sleep ( interfacePollWaitTime ) { newInterfaces , err := c . aws . GetInterfaces ( ) if err != nil { continue } for _ , intf := range newInterfaces { if intf . Mac == * resp . NetworkInterface . MacAddress { if privateIPAddr := net . ParseIP ( * resp . NetworkInterface . PrivateIpAddress ) ; privateIPAddr != nil { registry := & Registry { } registry . TrackIP ( privateIPAddr ) } configureInterface ( & intf ) return & intf , nil } } } return nil , fmt . Errorf ( " " ) }
NewInterfaceOnSubnetAtIndex creates a new Interface with a specified subnet and index
NewInterfaceOnSubnetAtIndex creates a new Interface with a specified subnet and index
// Need to copy // resp.NetworkInterface.NetworkInterfaceId // We attempt to remove the interface we just made due to attachment failure // We have an attachment ID from the last API, which lets us mark the // interface as delete on termination // Continue anyway // The metadata server is inconsistent - for example, not // all of the nodes under the interface will populate at once // and instead return a 404 error. We just swallow this error here and // continue on. // New IP. Timestamp the addition as a free IP.