142 lines
3.2 KiB
Go
142 lines
3.2 KiB
Go
package cloudsigma
|
|
|
|
import (
|
|
"encoding/base64"
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/coreos/coreos-cloudinit/third_party/github.com/cloudsigma/cepgo"
|
|
)
|
|
|
|
const (
|
|
userDataFieldName = "cloudinit-user-data"
|
|
)
|
|
|
|
type serverContextService struct {
|
|
client interface {
|
|
All() (interface{}, error)
|
|
Key(string) (interface{}, error)
|
|
Meta() (map[string]string, error)
|
|
FetchRaw(string) ([]byte, error)
|
|
}
|
|
}
|
|
|
|
func NewServerContextService() *serverContextService {
|
|
return &serverContextService{
|
|
client: cepgo.NewCepgo(),
|
|
}
|
|
}
|
|
|
|
func (_ *serverContextService) IsAvailable() bool {
|
|
productNameFile, err := os.Open("/sys/class/dmi/id/product_name")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
productName := make([]byte, 10)
|
|
_, err = productNameFile.Read(productName)
|
|
return err == nil && string(productName) == "CloudSigma"
|
|
}
|
|
|
|
func (_ *serverContextService) AvailabilityChanges() bool {
|
|
return true
|
|
}
|
|
|
|
func (_ *serverContextService) ConfigRoot() string {
|
|
return ""
|
|
}
|
|
|
|
func (_ *serverContextService) Type() string {
|
|
return "server-context"
|
|
}
|
|
|
|
func (scs *serverContextService) FetchMetadata() ([]byte, error) {
|
|
var (
|
|
inputMetadata struct {
|
|
Name string `json:"name"`
|
|
UUID string `json:"uuid"`
|
|
Meta map[string]string `json:"meta"`
|
|
Nics []struct {
|
|
Runtime struct {
|
|
InterfaceType string `json:"interface_type"`
|
|
IPv4 struct {
|
|
IP string `json:"uuid"`
|
|
} `json:"ip_v4"`
|
|
} `json:"runtime"`
|
|
} `json:"nics"`
|
|
}
|
|
outputMetadata struct {
|
|
Hostname string `json:"name"`
|
|
PublicKeys map[string]string `json:"public_keys"`
|
|
LocalIPv4 string `json:"local-ipv4"`
|
|
PublicIPv4 string `json:"public-ipv4"`
|
|
}
|
|
)
|
|
|
|
rawMetadata, err := scs.client.FetchRaw("")
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
err = json.Unmarshal(rawMetadata, &inputMetadata)
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
if inputMetadata.Name != "" {
|
|
outputMetadata.Hostname = inputMetadata.Name
|
|
} else {
|
|
outputMetadata.Hostname = inputMetadata.UUID
|
|
}
|
|
|
|
if key, ok := inputMetadata.Meta["ssh_public_key"]; ok {
|
|
splitted := strings.Split(key, " ")
|
|
outputMetadata.PublicKeys = make(map[string]string)
|
|
outputMetadata.PublicKeys[splitted[len(splitted)-1]] = key
|
|
}
|
|
|
|
for _, nic := range inputMetadata.Nics {
|
|
if nic.Runtime.IPv4.IP != "" {
|
|
if nic.Runtime.InterfaceType == "public" {
|
|
outputMetadata.PublicIPv4 = nic.Runtime.IPv4.IP
|
|
} else {
|
|
outputMetadata.LocalIPv4 = nic.Runtime.IPv4.IP
|
|
}
|
|
}
|
|
}
|
|
|
|
return json.Marshal(outputMetadata)
|
|
}
|
|
|
|
func (scs *serverContextService) FetchUserdata() ([]byte, error) {
|
|
metadata, err := scs.client.Meta()
|
|
if err != nil {
|
|
return []byte{}, err
|
|
}
|
|
|
|
userData, ok := metadata[userDataFieldName]
|
|
if ok && isBase64Encoded(userDataFieldName, metadata) {
|
|
if decodedUserData, err := base64.StdEncoding.DecodeString(userData); err == nil {
|
|
return decodedUserData, nil
|
|
} else {
|
|
return []byte{}, nil
|
|
}
|
|
}
|
|
|
|
return []byte(userData), nil
|
|
}
|
|
|
|
func isBase64Encoded(field string, userdata map[string]string) bool {
|
|
base64Fields, ok := userdata["base64_fields"]
|
|
if !ok {
|
|
return false
|
|
}
|
|
|
|
for _, base64Field := range strings.Split(base64Fields, ",") {
|
|
if field == base64Field {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|