github.com/emc-advanced-dev/unik@v0.0.0-20190717152701-a58d3e8e33b7/pkg/providers/gcloud/run_instance.go (about) 1 package gcloud 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "github.com/sirupsen/logrus" 7 "github.com/emc-advanced-dev/pkg/errors" 8 "github.com/solo-io/unik/pkg/providers/common" 9 "github.com/solo-io/unik/pkg/types" 10 "google.golang.org/api/compute/v1" 11 "time" 12 ) 13 14 func (p *GcloudProvider) RunInstance(params types.RunInstanceParams) (_ *types.Instance, err error) { 15 logrus.WithFields(logrus.Fields{ 16 "image-id": params.ImageId, 17 "mounts": params.MntPointsToVolumeIds, 18 "env": params.Env, 19 }).Infof("running instance %s", params.Name) 20 21 var instanceId string 22 23 defer func() { 24 if err != nil { 25 logrus.WithError(err).Errorf("gcloud running instance encountered an error") 26 if instanceId != "" { 27 if params.NoCleanup { 28 logrus.Warnf("because --no-cleanup flag was provided, not cleaning up failed instance %s0", instanceId) 29 return 30 } 31 logrus.Warnf("cleaning up instance %s", instanceId) 32 p.compute().Instances.Delete(p.config.ProjectID, p.config.Zone, instanceId) 33 if cleanupErr := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 34 delete(instances, instanceId) 35 return nil 36 }); cleanupErr != nil { 37 logrus.Error(errors.New("modifying instance map in state", cleanupErr)) 38 } 39 } 40 } 41 }() 42 43 image, err := p.GetImage(params.ImageId) 44 if err != nil { 45 return nil, errors.New("getting image", err) 46 } 47 48 if err := common.VerifyMntsInput(p, image, params.MntPointsToVolumeIds); err != nil { 49 return nil, errors.New("invalid mapping for volume", err) 50 } 51 52 envData, err := json.Marshal(params.Env) 53 if err != nil { 54 return nil, errors.New("could not convert instance env to json", err) 55 } 56 57 //if not set, use default 58 if params.InstanceMemory <= 0 { 59 params.InstanceMemory = image.RunSpec.DefaultInstanceMemory 60 } 61 62 if len(envData) > 32768 { 63 return nil, errors.New("total length of env metadata must be <= 32768 bytes; have json string "+string(envData), nil) 64 } 65 66 disks := []*compute.AttachedDisk{ 67 //boot disk 68 &compute.AttachedDisk{ 69 AutoDelete: true, 70 Boot: true, 71 //DeviceName: "sd0" 72 InitializeParams: &compute.AttachedDiskInitializeParams{ 73 SourceImage: "global/images/" + image.Name, 74 }, 75 }, 76 } 77 78 for _, volumeId := range params.MntPointsToVolumeIds { 79 disks = append(disks, &compute.AttachedDisk{ 80 AutoDelete: false, 81 Boot: false, 82 Source: volumeId, 83 }) 84 } 85 86 instanceSpec := &compute.Instance{ 87 Name: params.Name, 88 Metadata: &compute.Metadata{ 89 Items: []*compute.MetadataItems{ 90 &compute.MetadataItems{ 91 Key: "ENV_DATA", 92 Value: pointerTo(string(envData)), 93 }, 94 }, 95 }, 96 Disks: disks, 97 MachineType: fmt.Sprintf("zones/%s/machineTypes/%s", p.config.Zone, "g1-small"), 98 NetworkInterfaces: []*compute.NetworkInterface{ 99 &compute.NetworkInterface{ 100 AccessConfigs: []*compute.AccessConfig{ 101 &compute.AccessConfig{ 102 Type: "ONE_TO_ONE_NAT", 103 Name: "External NAT", 104 }, 105 }, 106 Network: "global/networks/default", 107 }, 108 }, 109 } 110 111 gInstance, err := p.compute().Instances.Insert(p.config.ProjectID, p.config.Zone, instanceSpec).Do() 112 if err != nil { 113 return nil, errors.New("creating instance on gcloud failed", err) 114 } 115 logrus.Infof("gcloud instance created: %+v", gInstance) 116 117 instanceId = params.Name 118 119 //must add instance to state before attaching volumes 120 instance := &types.Instance{ 121 Id: instanceId, 122 Name: params.Name, 123 State: types.InstanceState_Pending, 124 Infrastructure: types.Infrastructure_GCLOUD, 125 ImageId: image.Id, 126 Created: time.Now(), 127 } 128 129 if err := p.state.ModifyInstances(func(instances map[string]*types.Instance) error { 130 instances[instance.Id] = instance 131 return nil 132 }); err != nil { 133 return nil, errors.New("modifying instance map in state", err) 134 } 135 136 logrus.WithFields(logrus.Fields{"instance": instance}).Infof("instance created succesfully") 137 138 return instance, nil 139 } 140 141 func pointerTo(v string) *string { 142 return &v 143 }