-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add metadata providers for azure, alicloud and oracle cloud infrastru…
…cture Signed-off-by: Steve Fan <29133953+stevefan1999-personal@users.noreply.github.com>
- Loading branch information
1 parent
a2869a3
commit 50ba9cb
Showing
6 changed files
with
511 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"path" | ||
|
||
"github.com/sl1pm4t/snooze" | ||
) | ||
|
||
const ( | ||
aliCloudMetadataBaseUrl = "http://100.100.100.200/latest/" | ||
) | ||
|
||
type AliCloudMetadataAPI struct { | ||
Region func() (string, error) `method:"GET" path:"/meta-data/region-id"` | ||
Zone func() (string, error) `method:"GET" path:"/meta-data/zone-id"` | ||
ImageID func() (string, error) `method:"GET" path:"/meta-data/image-id"` | ||
InstanceID func() (string, error) `method:"GET" path:"/meta-data/instance-id"` | ||
InstanceType func() (string, error) `method:"GET" path:"/meta-data/instance/instance-type"` | ||
InstanceMaxEgress func() (string, error) `method:"GET" path:"/meta-data/instance/max-netbw-egress"` | ||
InstanceMaxIngress func() (string, error) `method:"GET" path:"/meta-data/instance/max-netbw-ingerss"` | ||
ElasticPublicIP func() (string, error) `method:"GET" path:"/meta-data/eipv4"` | ||
PublicIP func() (string, error) `method:"GET" path:"/meta-data/public-ipv4"` | ||
PrivateIP func() (string, error) `method:"GET" path:"/meta-data/private-ipv4"` | ||
PublicKeys func() (string, error) `method:"GET" path:"/meta-data/public-keys"` | ||
Hostname func() (string, error) `method:"GET" path:"/meta-data/hostname"` | ||
Userdata func() (string, error) `method:"GET" path:"/user-data"` | ||
} | ||
|
||
type ProviderAliCloud struct { | ||
DefaultProviderUtil | ||
*AliCloudMetadataAPI | ||
} | ||
|
||
func NewAliCloud() (provider *ProviderAliCloud) { | ||
client := snooze.Client{Root: aliCloudMetadataBaseUrl} | ||
api := &AliCloudMetadataAPI{} | ||
client.Create(api) | ||
return &ProviderAliCloud{AliCloudMetadataAPI: api} | ||
} | ||
|
||
func (p *ProviderAliCloud) String() string { | ||
return "Alibaba Cloud" | ||
} | ||
|
||
func (p *ProviderAliCloud) ShortName() string { | ||
return "alicloud" | ||
} | ||
|
||
func (p *ProviderAliCloud) Probe() bool { | ||
res, err := p.Hostname() | ||
return err == nil && res != "" | ||
} | ||
|
||
func (p *ProviderAliCloud) Extract() ([]byte, error) { | ||
var ret string | ||
var err error | ||
|
||
if ret, err = p.InstanceID(); err == nil { | ||
if err := p.WriteDataToFile("instance id", 0644, ret, path.Join(ConfigPath, "instance_id")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get instance id: %s", err) | ||
} | ||
|
||
if ret, err = p.InstanceType(); err == nil { | ||
if err := p.WriteDataToFile("instance type", 0644, ret, path.Join(ConfigPath, "instance_type")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get instance type: %s", err) | ||
} | ||
|
||
if ret, err = p.Region(); err == nil { | ||
if err := p.WriteDataToFile("region", 0644, ret, path.Join(ConfigPath, "region")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get region: %s", err) | ||
} | ||
|
||
if ret, err = p.Zone(); err == nil { | ||
if err := p.WriteDataToFile("zone", 0644, ret, path.Join(ConfigPath, "zone")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get zone: %s", err) | ||
} | ||
|
||
if ret, err = p.ImageID(); err == nil { | ||
if err := p.WriteDataToFile("instance image", 0644, ret, path.Join(ConfigPath, "image")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get instance image: %s", err) | ||
} | ||
|
||
if ret, err = p.Hostname(); err == nil { | ||
if err := p.WriteDataToFile("host name", 0644, ret, path.Join(ConfigPath, Hostname)); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get host name: %s", err) | ||
} | ||
|
||
if ret, err = p.PublicIP(); err != nil { | ||
ret, err = p.ElasticPublicIP() | ||
} | ||
|
||
if err == nil { | ||
if err := p.WriteDataToFile("public ipv4", 0644, ret, path.Join(ConfigPath, "public_ipv4")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get public ipv4: %s", err) | ||
} | ||
|
||
if ret, err = p.PrivateIP(); err == nil { | ||
if err := p.WriteDataToFile("private ipv4", 0644, ret, path.Join(ConfigPath, "private_ipv4")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get private ipv4: %s", err) | ||
} | ||
|
||
if ret, err = p.PublicKeys(); err == nil { | ||
if err = p.MakeFolder("ssh public keys", 0755, path.Join(ConfigPath, SSH)); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err = p.WriteDataToFile("ssh public keys", 0600, ret, path.Join(ConfigPath, SSH, "authorized_keys")); err != nil { | ||
return nil, err | ||
} | ||
} else { | ||
fmt.Errorf("failed to get public keys: %s", err) | ||
} | ||
|
||
ret, err = p.Userdata() | ||
return []byte(ret), err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,208 @@ | ||
package main | ||
|
||
import ( | ||
"path" | ||
"strings" | ||
|
||
"github.com/hashicorp/go-retryablehttp" | ||
"github.com/sl1pm4t/snooze" | ||
"github.com/thoas/go-funk" | ||
) | ||
|
||
const ( | ||
azureAPIBaseUrl = "http://169.254.169.254/metadata/instance" | ||
azureAPIVersion = "2020-06-01" | ||
) | ||
|
||
type AzurePublicKeyEntry struct { | ||
KeyData string `json:"keyData"` | ||
Path string `json:"path"` | ||
} | ||
|
||
type AzureInstanceComputeMetadata struct { | ||
AzEnvironment string `json:"azEnvironment"` | ||
CustomData string `json:"customData"` | ||
IsHostCompatibilityLayerVM string `json:"isHostCompatibilityLayerVm"` | ||
Location string `json:"location"` | ||
Name string `json:"name"` | ||
Offer string `json:"offer"` | ||
OsType string `json:"osType"` | ||
PlacementGroupID string `json:"placementGroupId"` | ||
Plan struct { | ||
Name string `json:"name"` | ||
Product string `json:"product"` | ||
Publisher string `json:"publisher"` | ||
} `json:"plan"` | ||
PlatformFaultDomain string `json:"platformFaultDomain"` | ||
PlatformUpdateDomain string `json:"platformUpdateDomain"` | ||
Provider string `json:"provider"` | ||
PublicKeys *[]AzurePublicKeyEntry `json:"publicKeys,omitempty"` | ||
Publisher string `json:"publisher"` | ||
ResourceGroupName string `json:"resourceGroupName"` | ||
ResourceID string `json:"resourceId"` | ||
SecurityProfile struct { | ||
SecureBootEnabled string `json:"secureBootEnabled"` | ||
VirtualTpmEnabled string `json:"virtualTpmEnabled"` | ||
} `json:"securityProfile"` | ||
Sku string `json:"sku"` | ||
StorageProfile struct { | ||
DataDisks []interface{} `json:"dataDisks"` | ||
ImageReference struct { | ||
ID string `json:"id"` | ||
Offer string `json:"offer"` | ||
Publisher string `json:"publisher"` | ||
Sku string `json:"sku"` | ||
Version string `json:"version"` | ||
} `json:"imageReference"` | ||
OsDisk struct { | ||
Caching string `json:"caching"` | ||
CreateOption string `json:"createOption"` | ||
DiffDiskSettings struct { | ||
Option string `json:"option"` | ||
} `json:"diffDiskSettings"` | ||
DiskSizeGB string `json:"diskSizeGB"` | ||
EncryptionSettings struct { | ||
Enabled string `json:"enabled"` | ||
} `json:"encryptionSettings"` | ||
Image struct { | ||
URI string `json:"uri"` | ||
} `json:"image"` | ||
ManagedDisk struct { | ||
ID string `json:"id"` | ||
StorageAccountType string `json:"storageAccountType"` | ||
} `json:"managedDisk"` | ||
Name string `json:"name"` | ||
OsType string `json:"osType"` | ||
Vhd struct { | ||
URI string `json:"uri"` | ||
} `json:"vhd"` | ||
WriteAcceleratorEnabled string `json:"writeAcceleratorEnabled"` | ||
} `json:"osDisk"` | ||
} `json:"storageProfile"` | ||
SubscriptionID string `json:"subscriptionId"` | ||
Tags string `json:"tags"` | ||
TagsList []interface{} `json:"tagsList"` | ||
Version string `json:"version"` | ||
VMID string `json:"vmId"` | ||
VMScaleSetName string `json:"vmScaleSetName"` | ||
VMSize string `json:"vmSize"` | ||
Zone string `json:"zone"` | ||
} | ||
|
||
type AzureInstanceNetworkMetadata struct { | ||
Interface []struct { | ||
Ipv4 struct { | ||
IPAddress []struct { | ||
PrivateIPAddress string `json:"privateIpAddress"` | ||
PublicIPAddress *string `json:"publicIpAddress,omitempty"` | ||
} `json:"ipAddress"` | ||
Subnet []struct { | ||
Address string `json:"address"` | ||
Prefix string `json:"prefix"` | ||
} `json:"subnet"` | ||
} `json:"ipv4"` | ||
Ipv6 struct { | ||
IPAddress []interface{} `json:"ipAddress"` | ||
} `json:"ipv6"` | ||
MacAddress string `json:"macAddress"` | ||
} `json:"interface"` | ||
} | ||
|
||
type AzureMetadataAPI struct { | ||
ComputeMetadata func() (AzureInstanceComputeMetadata, error) `method:"GET" path:"/compute"` | ||
NetworkMetadata func() (AzureInstanceNetworkMetadata, error) `method:"GET" path:"/network"` | ||
} | ||
|
||
type ProviderAzure struct { | ||
DefaultProviderUtil | ||
*AzureMetadataAPI | ||
} | ||
|
||
func NewAzure() *ProviderAzure { | ||
client := snooze.Client{Root: azureAPIBaseUrl, Before: func(request *retryablehttp.Request, client *retryablehttp.Client) { | ||
request.Header.Add("Metadata", "true") | ||
q := request.URL.Query() | ||
q.Add("api-version", azureAPIVersion) | ||
request.URL.RawQuery = q.Encode() | ||
}} | ||
api := &AzureMetadataAPI{} | ||
client.Create(api) | ||
return &ProviderAzure{AzureMetadataAPI: api} | ||
} | ||
|
||
func (p *ProviderAzure) String() string { | ||
return "Azure" | ||
} | ||
|
||
func (p *ProviderAzure) ShortName() string { | ||
return "azure" | ||
} | ||
|
||
func (p *ProviderAzure) Probe() bool { | ||
_, err := p.ComputeMetadata() | ||
return err == nil | ||
} | ||
|
||
func (p *ProviderAzure) Extract() ([]byte, error) { | ||
|
||
if metadata, err := p.NetworkMetadata(); err == nil { | ||
ip := metadata.Interface[0].Ipv4.IPAddress[0] | ||
|
||
if ip.PublicIPAddress != nil { | ||
if err := p.WriteDataToFile("public ipv4", 0644, *ip.PublicIPAddress, path.Join(ConfigPath, "public_ipv4")); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
if err := p.WriteDataToFile("private ipv4", 0644, ip.PrivateIPAddress, path.Join(ConfigPath, "private_ipv4")); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
if metadata, err := p.ComputeMetadata(); err == nil { | ||
if err := p.WriteDataToFile("instance id", 0644, metadata.VMID, path.Join(ConfigPath, "instance_id")); err != nil { | ||
return nil, err | ||
} | ||
|
||
// there's three major shapes in oracle cloud, flexible, bare metal and VM, so it is definitely the instance type | ||
if err := p.WriteDataToFile("instance type", 0644, metadata.VMSize, path.Join(ConfigPath, "instance_type")); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := p.WriteDataToFile("region", 0644, metadata.Location, path.Join(ConfigPath, "region")); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := p.WriteDataToFile("instance image", 0644, metadata.StorageProfile.OsDisk.Name, path.Join(ConfigPath, "image")); err != nil { | ||
return nil, err | ||
} | ||
|
||
// unfortunately azure assumes the vm name to be the instance host name | ||
if err := p.WriteDataToFile("host name", 0644, metadata.Name, path.Join(ConfigPath, Hostname)); err != nil { | ||
return nil, err | ||
} | ||
|
||
if err := p.WriteDataToFile("availability zone", 0644, metadata.Zone, path.Join(ConfigPath, "availability_zone")); err != nil { | ||
return nil, err | ||
} | ||
|
||
if publicKeys := metadata.PublicKeys; publicKeys != nil && len(*publicKeys) > 0 { | ||
if err := p.MakeFolder("ssh public keys", 0755, path.Join(ConfigPath, SSH)); err != nil { | ||
return nil, err | ||
} | ||
|
||
combinedSSHKeys := strings.Join(funk.Map(publicKeys, func(entry AzurePublicKeyEntry) string { | ||
return entry.KeyData | ||
}).([]string), "\n") | ||
|
||
if err := p.WriteDataToFile("ssh public keys", 0600, combinedSSHKeys, path.Join(ConfigPath, SSH, "authorized_keys")); err != nil { | ||
return nil, err | ||
} | ||
} | ||
|
||
// TODO: this field is disabled, figure out a way to obtain user data somewhere else | ||
return []byte(metadata.CustomData), nil | ||
} | ||
|
||
return nil, nil | ||
} |
Oops, something went wrong.