123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344 |
- package metadata
- import (
- "errors"
- "fmt"
- "github.com/denverdino/aliyungo/util"
- "io"
- "io/ioutil"
- "net"
- "net/http"
- "net/url"
- "strings"
- "time"
- )
- type Request struct {
- }
- const (
- ENDPOINT = "http://100.100.100.200"
- META_VERSION_LATEST = "latest"
- RS_TYPE_META_DATA = "meta-data"
- RS_TYPE_USER_DATA = "user-data"
- DNS_NAMESERVERS = "dns-conf/nameservers"
- EIPV4 = "eipv4"
- HOSTNAME = "hostname"
- IMAGE_ID = "image-id"
- INSTANCE_ID = "instance-id"
- MAC = "mac"
- NETWORK_TYPE = "network-type"
- NTP_CONF_SERVERS = "ntp-conf/ntp-servers"
- OWNER_ACCOUNT_ID = "owner-account-id"
- PRIVATE_IPV4 = "private-ipv4"
- REGION = "region-id"
- SERIAL_NUMBER = "serial-number"
- SOURCE_ADDRESS = "source-address"
- VPC_CIDR_BLOCK = "vpc-cidr-block"
- VPC_ID = "vpc-id"
- VSWITCH_CIDR_BLOCK = "vswitch-cidr-block"
- VSWITCH_ID = "vswitch-id"
- )
- type IMetaDataClient interface {
- Version(version string) IMetaDataClient
- ResourceType(rtype string) IMetaDataClient
- Resource(resource string) IMetaDataClient
- Go() ([]string, error)
- Url() (string, error)
- }
- type MetaData struct {
- c IMetaDataClient
- }
- func NewMetaData(client *http.Client) *MetaData {
- if client == nil {
- client = &http.Client{}
- }
- return &MetaData{
- c: &MetaDataClient{client: client},
- }
- }
- func (m *MetaData) HostName() (string, error) {
- hostname, err := m.c.Resource(HOSTNAME).Go()
- if err != nil {
- return "", err
- }
- return hostname[0], nil
- }
- func (m *MetaData) ImageID() (string, error) {
- image, err := m.c.Resource(IMAGE_ID).Go()
- if err != nil {
- return "", err
- }
- return image[0], err
- }
- func (m *MetaData) InstanceID() (string, error) {
- instanceid, err := m.c.Resource(INSTANCE_ID).Go()
- if err != nil {
- return "", err
- }
- return instanceid[0], err
- }
- func (m *MetaData) Mac() (string, error) {
- mac, err := m.c.Resource(MAC).Go()
- if err != nil {
- return "", err
- }
- return mac[0], nil
- }
- func (m *MetaData) NetworkType() (string, error) {
- network, err := m.c.Resource(NETWORK_TYPE).Go()
- if err != nil {
- return "", err
- }
- return network[0], nil
- }
- func (m *MetaData) OwnerAccountID() (string, error) {
- owner, err := m.c.Resource(OWNER_ACCOUNT_ID).Go()
- if err != nil {
- return "", err
- }
- return owner[0], nil
- }
- func (m *MetaData) PrivateIPv4() (string, error) {
- private, err := m.c.Resource(PRIVATE_IPV4).Go()
- if err != nil {
- return "", err
- }
- return private[0], nil
- }
- func (m *MetaData) Region() (string, error) {
- region, err := m.c.Resource(REGION).Go()
- if err != nil {
- return "", err
- }
- return region[0], nil
- }
- func (m *MetaData) SerialNumber() (string, error) {
- serial, err := m.c.Resource(SERIAL_NUMBER).Go()
- if err != nil {
- return "", err
- }
- return serial[0], nil
- }
- func (m *MetaData) SourceAddress() (string, error) {
- source, err := m.c.Resource(SOURCE_ADDRESS).Go()
- if err != nil {
- return "", err
- }
- return source[0], nil
- }
- func (m *MetaData) VpcCIDRBlock() (string, error) {
- vpcCIDR, err := m.c.Resource(VPC_CIDR_BLOCK).Go()
- if err != nil {
- return "", err
- }
- return vpcCIDR[0], err
- }
- func (m *MetaData) VpcID() (string, error) {
- vpcId, err := m.c.Resource(VPC_ID).Go()
- if err != nil {
- return "", err
- }
- return vpcId[0], err
- }
- func (m *MetaData) VswitchCIDRBlock() (string, error) {
- cidr, err := m.c.Resource(VSWITCH_CIDR_BLOCK).Go()
- if err != nil {
- return "", err
- }
- return cidr[0], err
- }
- func (m *MetaData) VswitchID() (string, error) {
- vswithcid, err := m.c.Resource(VSWITCH_ID).Go()
- if err != nil {
- return "", err
- }
- return vswithcid[0], err
- }
- func (m *MetaData) EIPv4() (string, error) {
- eip, err := m.c.Resource(EIPV4).Go()
- if err != nil {
- return "", err
- }
- return eip[0], nil
- }
- func (m *MetaData) DNSNameServers() ([]string, error) {
- data, err := m.c.Resource(DNS_NAMESERVERS).Go()
- if err != nil {
- return []string{}, err
- }
- return data, nil
- }
- func (m *MetaData) NTPConfigServers() ([]string, error) {
- data, err := m.c.Resource(NTP_CONF_SERVERS).Go()
- if err != nil {
- return []string{}, err
- }
- return data, nil
- }
- type MetaDataClient struct {
- version string
- resourceType string
- resource string
- client *http.Client
- }
- func (vpc *MetaDataClient) Version(version string) IMetaDataClient {
- vpc.version = version
- return vpc
- }
- func (vpc *MetaDataClient) ResourceType(rtype string) IMetaDataClient {
- vpc.resourceType = rtype
- return vpc
- }
- func (vpc *MetaDataClient) Resource(resource string) IMetaDataClient {
- vpc.resource = resource
- return vpc
- }
- var retry = util.AttemptStrategy{
- Min: 5,
- Total: 5 * time.Second,
- Delay: 200 * time.Millisecond,
- }
- func (vpc *MetaDataClient) Url() (string, error) {
- if vpc.version == "" {
- vpc.version = "latest"
- }
- if vpc.resourceType == "" {
- vpc.resourceType = "meta-data"
- }
- if vpc.resource == "" {
- return "", errors.New("the resource you want to visit must not be nil!")
- }
- return fmt.Sprintf("%s/%s/%s/%s", ENDPOINT, vpc.version, vpc.resourceType, vpc.resource), nil
- }
- func (vpc *MetaDataClient) Go() (resu []string, err error) {
- for r := retry.Start(); r.Next(); {
- resu, err = vpc.send()
- if !shouldRetry(err) {
- break
- }
- }
- return resu, err
- }
- func (vpc *MetaDataClient) send() ([]string, error) {
- url, err := vpc.Url()
- if err != nil {
- return []string{}, err
- }
- requ, err := http.NewRequest(http.MethodGet, url, nil)
- if err != nil {
- return []string{}, err
- }
- resp, err := vpc.client.Do(requ)
- if err != nil {
- return nil, err
- }
- if resp.StatusCode != 200 {
- return nil, err
- }
- defer resp.Body.Close()
- data, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- return []string{}, err
- }
- if string(data) == "" {
- return []string{""}, nil
- }
- return strings.Split(string(data), "\n"), nil
- }
- type TimeoutError interface {
- error
- Timeout() bool
- }
- func shouldRetry(err error) bool {
- if err == nil {
- return false
- }
- _, ok := err.(TimeoutError)
- if ok {
- return true
- }
- switch err {
- case io.ErrUnexpectedEOF, io.EOF:
- return true
- }
- switch e := err.(type) {
- case *net.DNSError:
- return true
- case *net.OpError:
- switch e.Op {
- case "read", "write":
- return true
- }
- case *url.Error:
-
-
-
-
-
-
- switch e.Op {
- case "Get", "Put", "Delete", "Head":
- return shouldRetry(e.Err)
- default:
- return false
- }
- }
- return false
- }
|