gce.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. package cloudinit
  2. import (
  3. "io/ioutil"
  4. "strings"
  5. log "github.com/Sirupsen/logrus"
  6. "google.golang.org/cloud/compute/metadata"
  7. "gopkg.in/yaml.v2"
  8. )
  9. type GceCloudConfig struct {
  10. FileName string
  11. UserData string
  12. NonUserDataSSHKeys []string
  13. }
  14. const (
  15. gceCloudConfigFile = "/var/lib/rancher/conf/gce_cloudinit_config.yml"
  16. )
  17. func NewGceCloudConfig() *GceCloudConfig {
  18. userData, err := metadata.InstanceAttributeValue("user-data")
  19. if err != nil {
  20. log.Errorf("Could not retrieve user-data: %s", err)
  21. }
  22. projectSSHKeys, err := metadata.ProjectAttributeValue("sshKeys")
  23. if err != nil {
  24. log.Errorf("Could not retrieve project SSH Keys: %s", err)
  25. }
  26. instanceSSHKeys, err := metadata.InstanceAttributeValue("sshKeys")
  27. if err != nil {
  28. log.Errorf("Could not retrieve instance SSH Keys: %s", err)
  29. }
  30. nonUserDataSSHKeysRaw := projectSSHKeys + "\n" + instanceSSHKeys
  31. nonUserDataSSHKeys := gceSshKeyFormatter(nonUserDataSSHKeysRaw)
  32. gceCC := &GceCloudConfig{
  33. FileName: gceCloudConfigFile,
  34. UserData: userData,
  35. NonUserDataSSHKeys: nonUserDataSSHKeys,
  36. }
  37. return gceCC
  38. }
  39. func GetAndCreateGceDataSourceFilename() (string, error) {
  40. gceCC := NewGceCloudConfig()
  41. err := gceCC.saveToFile(gceCC.FileName)
  42. if err != nil {
  43. log.Errorf("Error: %s", err)
  44. return "", err
  45. }
  46. return gceCC.FileName, nil
  47. }
  48. func (cc *GceCloudConfig) saveToFile(filename string) error {
  49. //Get Merged UserData sshkeys
  50. data, err := cc.getMergedUserData()
  51. if err != nil {
  52. log.Errorf("Could not process userdata: %s", err)
  53. return err
  54. }
  55. //write file
  56. writeFile(filename, data)
  57. return nil
  58. }
  59. func (cc *GceCloudConfig) getMergedUserData() ([]byte, error) {
  60. var returnUserData []byte
  61. userdata := make(map[string]interface{})
  62. if cc.UserData != "" {
  63. log.Infof("Found UserData Config")
  64. err := yaml.Unmarshal([]byte(cc.UserData), &userdata)
  65. if err != nil {
  66. log.Errorf("Could not unmarshal data: %s", err)
  67. return nil, err
  68. }
  69. }
  70. var auth_keys []string
  71. if _, exists := userdata["ssh_authorized_keys"]; exists {
  72. udSshKeys := userdata["ssh_authorized_keys"].([]interface{})
  73. log.Infof("userdata %s", udSshKeys)
  74. for _, value := range udSshKeys {
  75. auth_keys = append(auth_keys, value.(string))
  76. }
  77. }
  78. if cc.NonUserDataSSHKeys != nil {
  79. for _, value := range cc.NonUserDataSSHKeys {
  80. auth_keys = append(auth_keys, value)
  81. }
  82. }
  83. userdata["ssh_authorized_keys"] = auth_keys
  84. yamlUserData, err := yaml.Marshal(&userdata)
  85. if err != nil {
  86. log.Errorf("Could not Marshal userdata: %s", err)
  87. return nil, err
  88. } else {
  89. returnUserData = append([]byte("#cloud-config\n"), yamlUserData...)
  90. }
  91. return returnUserData, nil
  92. }
  93. func writeFile(filename string, data []byte) error {
  94. if err := ioutil.WriteFile(filename, data, 400); err != nil {
  95. log.Errorf("Could not write file %v", err)
  96. return err
  97. }
  98. return nil
  99. }
  100. func gceSshKeyFormatter(rawKeys string) []string {
  101. keySlice := strings.Split(rawKeys, "\n")
  102. var cloudFormatedKeys []string
  103. if len(keySlice) > 0 {
  104. for i := range keySlice {
  105. keyString := keySlice[i]
  106. sIdx := strings.Index(keyString, ":")
  107. if sIdx != -1 {
  108. key := strings.TrimSpace(keyString[sIdx+1:])
  109. keyA := strings.Split(key, " ")
  110. key = strings.Join(keyA, " ")
  111. if key != "" {
  112. cloudFormatedKeys = append(cloudFormatedKeys, key)
  113. }
  114. }
  115. }
  116. }
  117. return cloudFormatedKeys
  118. }