<commit_before>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package google

import (
	"code.google.com/p/google-api-go-client/compute/v1"
	"github.com/juju/errors"
)

// instance sends a request to GCE for a low-level snapshot of data
// about an instance and returns it.
func (gce *Connection) instance(zone, id string) (*compute.Instance, error) {
	svc := Services{
		InstanceGet: gce.raw.Instances.Get(gce.ProjectID, zone, id),
	}

	result, err := doCall(svc)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst, ok := result.(*compute.Instance)
	if !ok {
		return nil, errors.New("unable to convert result to compute.Instance")
	}
	return inst, nil
}

// addInstance sends a request to GCE to add a new instance to the
// connection's project, with the provided instance data and machine
// type. Each of the provided zones is attempted and the first available
// zone is where the instance is provisioned. If no zones are available
// then an error is returned. The instance that was passed in is updated
// with the new instance's data upon success. The call blocks until the
// instance is created or the request fails.
func (gce *Connection) addInstance(inst *compute.Instance, machineType string, zones []string) error {
	for _, zoneName := range zones {
		inst.MachineType = resolveMachineType(zoneName, machineType)
		call := gce.raw.Instances.Insert(
			gce.ProjectID,
			zoneName,
			inst,
		)
		svc := Services{InstanceInsert: call}
		result, err := doCall(svc)
		if err != nil {
			// We are guaranteed the insert failed at the point.
			return errors.Annotate(err, "sending new instance request")
		}

		operation, ok := result.(*compute.Operation)
		if !ok {
			return errors.New("unable to convert result to compute.Operation")
		}

		waitErr := gce.waitOperation(operation, attemptsLong)

		// Check if the instance was created.
		realized, err := rawInstance(gce, zoneName, inst.Name)
		if err != nil {
			if waitErr == nil {
				return errors.Trace(err)
			}
			// Try the next zone.
			logger.Errorf("failed to get new instance in zone %q: %v", zoneName, waitErr)
			continue
		}

		// Success!
		*inst = *realized
		return nil
	}
	return errors.Errorf("not able to provision in any zone")
}

var rawInstance = func(conn *Connection, zone, id string) (*compute.Instance, error) {
	return conn.instance(zone, id)
}

// Instances sends a request to the GCE API for a list of all instances
// (in the Connection's project) for which the name starts with the
// provided prefix. The result is also limited to those instances with
// one of the specified statuses (if any).
func (gce *Connection) Instances(prefix string, statuses ...string) ([]Instance, error) {
	call := gce.raw.Instances.AggregatedList(gce.ProjectID)
	call = call.Filter("name eq " + prefix + ".*")
	svc := Services{InstanceList: call}

	// TODO(ericsnow) Add a timeout?
	var results []Instance
	for {
		result, err := doCall(svc)
		if err != nil {
			return results, errors.Trace(err)
		}

		raw, ok := result.(*compute.InstanceAggregatedList)
		if !ok {
			return nil, errors.New("unable to convert result to compute.InstanceList")
		}

		for _, item := range raw.Items {
			for _, rawInst := range item.Instances {
				inst := newInstance(rawInst)
				results = append(results, *inst)
			}
		}

		if raw.NextPageToken == "" {
			break
		}
		svc.InstanceList = instsNextPage(call, raw.NextPageToken)
	}

	return filterInstances(results, statuses...), nil
}

var instsNextPage = func(call *compute.InstancesAggregatedListCall, token string) *compute.InstancesAggregatedListCall {
	return call.PageToken(token)
}

// removeInstance sends a request to the GCE API to remove the instance
// with the provided ID (in the specified zone). The call blocks until
// the instance is removed (or the request fails).
func (gce *Connection) removeInstance(id, zone string) error {
	svc := Services{
		InstanceDelete: gce.raw.Instances.Delete(gce.ProjectID, zone, id),
	}

	result, err := doCall(svc)
	if err != nil {<commit_msg>provider/gce: Do not filter instances if no statuses are passed.<commit_after>// Copyright 2014 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.

package google

import (
	"code.google.com/p/google-api-go-client/compute/v1"
	"github.com/juju/errors"
)

// instance sends a request to GCE for a low-level snapshot of data
// about an instance and returns it.
func (gce *Connection) instance(zone, id string) (*compute.Instance, error) {
	svc := Services{
		InstanceGet: gce.raw.Instances.Get(gce.ProjectID, zone, id),
	}

	result, err := doCall(svc)
	if err != nil {
		return nil, errors.Trace(err)
	}

	inst, ok := result.(*compute.Instance)
	if !ok {
		return nil, errors.New("unable to convert result to compute.Instance")
	}
	return inst, nil
}

// addInstance sends a request to GCE to add a new instance to the
// connection's project, with the provided instance data and machine
// type. Each of the provided zones is attempted and the first available
// zone is where the instance is provisioned. If no zones are available
// then an error is returned. The instance that was passed in is updated
// with the new instance's data upon success. The call blocks until the
// instance is created or the request fails.
func (gce *Connection) addInstance(inst *compute.Instance, machineType string, zones []string) error {
	for _, zoneName := range zones {
		inst.MachineType = resolveMachineType(zoneName, machineType)
		call := gce.raw.Instances.Insert(
			gce.ProjectID,
			zoneName,
			inst,
		)
		svc := Services{InstanceInsert: call}
		result, err := doCall(svc)
		if err != nil {
			// We are guaranteed the insert failed at the point.
			return errors.Annotate(err, "sending new instance request")
		}

		operation, ok := result.(*compute.Operation)
		if !ok {
			return errors.New("unable to convert result to compute.Operation")
		}

		waitErr := gce.waitOperation(operation, attemptsLong)

		// Check if the instance was created.
		realized, err := rawInstance(gce, zoneName, inst.Name)
		if err != nil {
			if waitErr == nil {
				return errors.Trace(err)
			}
			// Try the next zone.
			logger.Errorf("failed to get new instance in zone %q: %v", zoneName, waitErr)
			continue
		}

		// Success!
		*inst = *realized
		return nil
	}
	return errors.Errorf("not able to provision in any zone")
}

var rawInstance = func(conn *Connection, zone, id string) (*compute.Instance, error) {
	return conn.instance(zone, id)
}

// Instances sends a request to the GCE API for a list of all instances
// (in the Connection's project) for which the name starts with the
// provided prefix. The result is also limited to those instances with
// one of the specified statuses (if any).
func (gce *Connection) Instances(prefix string, statuses ...string) ([]Instance, error) {
	call := gce.raw.Instances.AggregatedList(gce.ProjectID)
	call = call.Filter("name eq " + prefix + ".*")
	svc := Services{InstanceList: call}

	// TODO(ericsnow) Add a timeout?
	var results []Instance
	for {
		result, err := doCall(svc)
		if err != nil {
			return results, errors.Trace(err)
		}

		raw, ok := result.(*compute.InstanceAggregatedList)
		if !ok {
			return nil, errors.New("unable to convert result to compute.InstanceList")
		}

		for _, item := range raw.Items {
			for _, rawInst := range item.Instances {
				inst := newInstance(rawInst)
				results = append(results, *inst)
			}
		}

		if raw.NextPageToken == "" {
			break
		}
		svc.InstanceList = instsNextPage(call, raw.NextPageToken)
	}

	if len(statuses) == 0 {
		return results, nil
	}
	return filterInstances(results, statuses...), nil
}

var instsNextPage = func(call *compute.InstancesAggregatedListCall, token string) *compute.InstancesAggregatedListCall {
	return call.PageToken(token)
}

// removeInstance sends a request to the GCE API to remove the instance
// with the provided ID (in the specified zone). The call blocks until
// the instance is removed (or the request fails).
func (gce *Connection) removeInstance(id, zone string) error {
	svc := Services{
		InstanceDelete: gce.raw.Instances.Delete(gce.ProjectID, zone, id),
	}

	result, err := doCall(svc)
	if err != nil {
{'fraction_non_alphanumeric': 0.11042198710932749, 'fraction_numerical': 0.0015809315335035875, 'mean_word_length': 3.7183017785427426, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '957522', 'n_tokens_mistral': 2703, 'n_tokens_neox': 2520, 'n_words': 913}