package dsdssandboxes import ( "context" compute "google.golang.org/api/compute/v1" ) type setLabelMethod func(string, *compute.InstancesSetLabelsRequest) error type listVMsmethod func() (*compute.InstanceList, error) type progressHookMethod func(string) type ProjectLabeller struct { Name string setLabels setLabelMethod listVMs listVMsmethod progressHook progressHookMethod } func ProjectLabellerFromConf(conf BillingConf, zone string) (*ProjectLabeller, error) { return ProjectLabellerFromName(conf.Metadata.Name, zone) } func ProjectLabellerFromName(name string, zone string) (*ProjectLabeller, error) { ctx := context.Background() service, err := compute.NewService(ctx) if err != nil { return nil, err } //Wrap calls to GCP in a closure to allow test injection setLabels := func(instance string, labelRequest *compute.InstancesSetLabelsRequest) error { _, err := service.Instances.SetLabels(name, zone, instance, labelRequest).Context(ctx).Do() return err } listVMs := func() (*compute.InstanceList, error) { instanceList, err := service.Instances.List(name, zone).Context(ctx).Do() return instanceList, err } return &ProjectLabeller{ Name: name, setLabels: setLabels, listVMs: listVMs, progressHook: nil, }, nil } // Provide a method that will be called with the name of the VM instance being processed func (p *ProjectLabeller) SetVMProgressHook(vmHook progressHookMethod) { p.progressHook = vmHook } // Apply the schedule labels for the provided schedule to all VMs in this project func (p *ProjectLabeller) AddVMScheduleLabels(schedule Schedule) error { instanceList, err := p.listVMs() if err != nil { return err } for _, instance := range instanceList.Items { if p.progressHook != nil { p.progressHook(instance.Name) } labels := schedule.ToLabelMap() err := p.addLabelToVM(instance, labels) if err != nil { return err } } return nil } func (p *ProjectLabeller) addLabelToVM(instance *compute.Instance, labels map[string]string) error { fingerprint := instance.LabelFingerprint combinedLabels := instance.Labels for k, v := range labels { combinedLabels[k] = v } labelRequest := &compute.InstancesSetLabelsRequest{ Labels: combinedLabels, LabelFingerprint: fingerprint, } err := p.setLabels(instance.Name, labelRequest) if err != nil { return err } return nil }