~juju-qa/ubuntu/yakkety/juju/juju-1.25.8

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/provider/gce/google/conn.go

  • Committer: Nicholas Skaggs
  • Date: 2016-12-02 17:28:37 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161202172837-jkrbdlyjcxtrii2n
Initial commit of 1.25.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package google
 
5
 
 
6
import (
 
7
        "github.com/juju/errors"
 
8
        "google.golang.org/api/compute/v1"
 
9
)
 
10
 
 
11
// rawConnectionWrapper facilitates mocking out the GCE API during tests.
 
12
type rawConnectionWrapper interface {
 
13
        // GetProject sends a request to the GCE API for info about the
 
14
        // specified project. If the project does not exist then an error
 
15
        // will be returned.
 
16
        GetProject(projectID string) (*compute.Project, error)
 
17
        // GetInstance sends a request to the GCE API for info about the
 
18
        // specified instance. If the instance does not exist then an error
 
19
        // will be returned.
 
20
        GetInstance(projectID, id, zone string) (*compute.Instance, error)
 
21
        // ListInstances sends a request to the GCE API for a list of all
 
22
        // instances in project for which the name starts with the provided
 
23
        // prefix. The result is also limited to those instances with one of
 
24
        // the specified statuses (if any).
 
25
        ListInstances(projectID, prefix string, status ...string) ([]*compute.Instance, error)
 
26
        // AddInstance sends a request to GCE to add a new instance to the
 
27
        // given project, with the provided instance data. The call blocks
 
28
        // until the instance is created or the request fails.
 
29
        AddInstance(projectID, zone string, spec *compute.Instance) error
 
30
        // RemoveInstance sends a request to the GCE API to remove the instance
 
31
        // with the provided ID (in the specified zone). The call blocks until
 
32
        // the instance is removed (or the request fails).
 
33
        RemoveInstance(projectID, id, zone string) error
 
34
        // GetFirewall sends an API request to GCE for the information about
 
35
        // the named firewall and returns it. If the firewall is not found,
 
36
        // errors.NotFound is returned.
 
37
        GetFirewall(projectID, name string) (*compute.Firewall, error)
 
38
        // AddFirewall requests GCE to add a firewall with the provided info.
 
39
        // If the firewall already exists then an error will be returned.
 
40
        // The call blocks until the firewall is added or the request fails.
 
41
        AddFirewall(projectID string, firewall *compute.Firewall) error
 
42
        // UpdateFirewall requests GCE to update the named firewall with the
 
43
        // provided info, overwriting the existing data. If the firewall does
 
44
        // not exist then an error will be returned. The call blocks until the
 
45
        // firewall is updated or the request fails.
 
46
        UpdateFirewall(projectID, name string, firewall *compute.Firewall) error
 
47
        // RemoveFirewall removed the named firewall from the project. If it
 
48
        // does not exist then this is a noop. The call blocks until the
 
49
        // firewall is added or the request fails.
 
50
        RemoveFirewall(projectID, name string) error
 
51
        // ListAvailabilityZones returns the list of availability zones for a given
 
52
        // GCE region. If none are found the the list is empty. Any failure in
 
53
        // the low-level request is returned as an error.
 
54
        ListAvailabilityZones(projectID, region string) ([]*compute.Zone, error)
 
55
        // CreateDisk will create a gce Persistent Block device that matches
 
56
        // the specified in spec.
 
57
        CreateDisk(project, zone string, spec *compute.Disk) error
 
58
        // ListDisks returns a list of disks available for a given project.
 
59
        ListDisks(project, zone string) ([]*compute.Disk, error)
 
60
        // RemoveDisk will delete the disk identified by id.
 
61
        RemoveDisk(project, zone, id string) error
 
62
        // GetDisk will return the disk correspondent to the passed id.
 
63
        GetDisk(project, zone, id string) (*compute.Disk, error)
 
64
        // AttachDisk will attach the disk described in attachedDisks (if it exists) into
 
65
        // the instance with id instanceId.
 
66
        AttachDisk(project, zone, instanceId string, attachedDisk *compute.AttachedDisk) error
 
67
        // Detach disk detaches device diskDeviceName (if it exists and its attached)
 
68
        // form the machine with id instanceId.
 
69
        DetachDisk(project, zone, instanceId, diskDeviceName string) error
 
70
        // InstanceDisks returns the disks attached to the instance identified
 
71
        // by instanceId
 
72
        InstanceDisks(project, zone, instanceId string) ([]*compute.AttachedDisk, error)
 
73
}
 
74
 
 
75
// TODO(ericsnow) Add specific error types for common failures
 
76
// (e.g. BadRequest, RequestFailed, RequestError, ConnectionFailed)?
 
77
 
 
78
// Connection provides methods for interacting with the GCE API. The
 
79
// methods are limited to those needed by the juju GCE provider.
 
80
//
 
81
// Before calling any of the methods, the Connect method should be
 
82
// called to authenticate and open the raw connection to the GCE API.
 
83
// Otherwise a panic will result.
 
84
type Connection struct {
 
85
        // TODO(ericsnow) name this something else?
 
86
        raw       rawConnectionWrapper
 
87
        region    string
 
88
        projectID string
 
89
}
 
90
 
 
91
// Connect authenticates using the provided credentials and opens a
 
92
// low-level connection to the GCE API for the Connection. Calling
 
93
// Connect after a successful connection has already been made will
 
94
// result in an error. All errors that happen while authenticating and
 
95
// connecting are returned by Connect.
 
96
func Connect(connCfg ConnectionConfig, creds *Credentials) (*Connection, error) {
 
97
        raw, err := newRawConnection(creds)
 
98
        if err != nil {
 
99
                return nil, errors.Trace(err)
 
100
        }
 
101
 
 
102
        conn := &Connection{
 
103
                raw:       &rawConn{raw},
 
104
                region:    connCfg.Region,
 
105
                projectID: connCfg.ProjectID,
 
106
        }
 
107
        return conn, nil
 
108
}
 
109
 
 
110
var newRawConnection = func(creds *Credentials) (*compute.Service, error) {
 
111
        return newConnection(creds)
 
112
}
 
113
 
 
114
// TODO(ericsnow) Verify in each method that Connection.raw is set?
 
115
 
 
116
// VerifyCredentials ensures that the authentication credentials used
 
117
// to connect are valid for use in the project and region defined for
 
118
// the Connection. If they are not then an error is returned.
 
119
func (gc Connection) VerifyCredentials() error {
 
120
        if _, err := gc.raw.GetProject(gc.projectID); err != nil {
 
121
                // TODO(ericsnow) Wrap err with something about bad credentials?
 
122
                return errors.Trace(err)
 
123
        }
 
124
        return nil
 
125
}
 
126
 
 
127
// AvailabilityZones returns the list of availability zones for a given
 
128
// GCE region. If none are found the the list is empty. Any failure in
 
129
// the low-level request is returned as an error.
 
130
func (gc *Connection) AvailabilityZones(region string) ([]AvailabilityZone, error) {
 
131
        rawZones, err := gc.raw.ListAvailabilityZones(gc.projectID, region)
 
132
        if err != nil {
 
133
                return nil, errors.Trace(err)
 
134
        }
 
135
 
 
136
        var zones []AvailabilityZone
 
137
        for _, rawZone := range rawZones {
 
138
                zones = append(zones, AvailabilityZone{rawZone})
 
139
        }
 
140
        return zones, nil
 
141
}