~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/gopkg.in/goose.v1/testservices/openstackservice/openstack.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
import (
4
4
        "fmt"
5
5
        "net/http"
 
6
        "strconv"
6
7
        "strings"
7
8
 
8
9
        "gopkg.in/goose.v1/identity"
14
15
// Openstack provides an Openstack service double implementation.
15
16
type Openstack struct {
16
17
        Identity identityservice.IdentityService
17
 
        Nova     *novaservice.Nova
18
 
        Swift    *swiftservice.Swift
 
18
        // Keystone v3 supports serving both V2 and V3 at the same time
 
19
        // this will intend to emulate that behavior.
 
20
        FallbackIdentity identityservice.IdentityService
 
21
        Nova             *novaservice.Nova
 
22
        Swift            *swiftservice.Swift
 
23
        // base url of openstack endpoints, might be required to
 
24
        // simmulate response contents such as the ones from
 
25
        // identity discovery.
 
26
        url string
 
27
}
 
28
 
 
29
func (openstack *Openstack) AddUser(user, secret, tennant string) *identityservice.UserInfo {
 
30
        uinfo := openstack.Identity.AddUser(user, secret, tennant)
 
31
        if openstack.FallbackIdentity != nil {
 
32
                _ = openstack.FallbackIdentity.AddUser(user, secret, tennant)
 
33
        }
 
34
        return uinfo
19
35
}
20
36
 
21
37
// New creates an instance of a full Openstack service double.
26
42
                openstack = Openstack{
27
43
                        Identity: identityservice.NewKeyPair(),
28
44
                }
 
45
        } else if authMode == identity.AuthUserPassV3 {
 
46
                openstack = Openstack{
 
47
                        Identity:         identityservice.NewV3UserPass(),
 
48
                        FallbackIdentity: identityservice.NewUserPass(),
 
49
                }
29
50
        } else {
30
51
                openstack = Openstack{
31
 
                        Identity: identityservice.NewUserPass(),
 
52
                        Identity:         identityservice.NewUserPass(),
 
53
                        FallbackIdentity: identityservice.NewV3UserPass(),
32
54
                }
33
55
        }
34
 
        userInfo := openstack.Identity.AddUser(cred.User, cred.Secrets, cred.TenantName)
 
56
        userInfo := openstack.AddUser(cred.User, cred.Secrets, cred.TenantName)
35
57
        if cred.TenantName == "" {
36
58
                panic("Openstack service double requires a tenant to be specified.")
37
59
        }
38
 
        openstack.Nova = novaservice.New(cred.URL, "v2", userInfo.TenantId, cred.Region, openstack.Identity)
 
60
        openstack.Nova = novaservice.New(cred.URL, "v2", userInfo.TenantId, cred.Region, openstack.Identity, openstack.FallbackIdentity)
39
61
        // Create the swift service using only the region base so we emulate real world deployments.
40
62
        regionParts := strings.Split(cred.Region, ".")
41
63
        baseRegion := regionParts[len(regionParts)-1]
42
 
        openstack.Swift = swiftservice.New(cred.URL, "v1", userInfo.TenantId, baseRegion, openstack.Identity)
 
64
        openstack.Swift = swiftservice.New(cred.URL, "v1", userInfo.TenantId, baseRegion, openstack.Identity, openstack.FallbackIdentity)
 
65
        openstack.url = cred.URL
43
66
        // Create container and add image metadata endpoint so that product-streams URLs are included
44
67
        // in the keystone catalog.
45
68
        err := openstack.Swift.AddContainer("imagemetadata")
47
70
                panic(fmt.Errorf("setting up image metadata container: %v", err))
48
71
        }
49
72
        url := openstack.Swift.Endpoints()[0].PublicURL
50
 
        serviceDef := identityservice.Service{
 
73
        serviceDef := identityservice.V2Service{
51
74
                Name: "simplestreams",
52
75
                Type: "product-streams",
53
76
                Endpoints: []identityservice.Endpoint{
54
77
                        {PublicURL: url + "/imagemetadata", Region: cred.Region},
55
78
                }}
56
 
        openstack.Identity.AddService(serviceDef)
 
79
        service3Def := identityservice.V3Service{
 
80
                Name:      "simplestreams",
 
81
                Type:      "product-streams",
 
82
                Endpoints: identityservice.NewV3Endpoints("", "", url+"/imagemetadata", cred.Region),
 
83
        }
 
84
 
 
85
        openstack.Identity.AddService(identityservice.Service{V2: serviceDef, V3: service3Def})
57
86
        // Add public bucket endpoint so that juju-tools URLs are included in the keystone catalog.
58
 
        serviceDef = identityservice.Service{
 
87
        serviceDef = identityservice.V2Service{
59
88
                Name: "juju",
60
89
                Type: "juju-tools",
61
90
                Endpoints: []identityservice.Endpoint{
62
91
                        {PublicURL: url, Region: cred.Region},
63
92
                }}
64
 
        openstack.Identity.AddService(serviceDef)
 
93
        service3Def = identityservice.V3Service{
 
94
                Name:      "juju",
 
95
                Type:      "juju-tools",
 
96
                Endpoints: identityservice.NewV3Endpoints("", "", url, cred.Region),
 
97
        }
 
98
 
 
99
        openstack.Identity.AddService(identityservice.Service{V2: serviceDef, V3: service3Def})
65
100
        return &openstack
66
101
}
67
102
 
68
103
// SetupHTTP attaches all the needed handlers to provide the HTTP API for the Openstack service..
69
104
func (openstack *Openstack) SetupHTTP(mux *http.ServeMux) {
70
105
        openstack.Identity.SetupHTTP(mux)
 
106
        // If there is a FallbackIdentity service also register its urls.
 
107
        if openstack.FallbackIdentity != nil {
 
108
                openstack.FallbackIdentity.SetupHTTP(mux)
 
109
        }
71
110
        openstack.Nova.SetupHTTP(mux)
72
111
        openstack.Swift.SetupHTTP(mux)
 
112
 
 
113
        // Handle root calls to be able to return auth information or fallback
 
114
        // to Nova root handler in case its not an auth info request.
 
115
        mux.Handle("/", openstack)
 
116
 
 
117
}
 
118
 
 
119
const authInformationBody = `{"versions": {"values": [{"status": "stable", ` +
 
120
        `"updated": "2015-03-30T00:00:00Z", "media-types": [{"base": "application/json", ` +
 
121
        `"type": "application/vnd.openstack.identity-v3+json"}], "id": "v3.4", "links": ` +
 
122
        `[{"href": "%s/v3/", "rel": "self"}]}, {"status": "stable", "updated": ` +
 
123
        `"2014-04-17T00:00:00Z", "media-types": [{"base": "application/json", ` +
 
124
        `"type": "application/vnd.openstack.identity-v2.0+json"}], "id": "v2.0", ` +
 
125
        `"links": [{"href": "%s/v2.0/", "rel": "self"}, {"href": ` +
 
126
        `"http://docs.openstack.org/", "type": "text/html", "rel": "describedby"}]}]}}`
 
127
 
 
128
func (openstack *Openstack) ServeHTTP(w http.ResponseWriter, r *http.Request) {
 
129
        if r.URL.Path != "/" {
 
130
                openstack.Nova.HandleRoot(w, r)
 
131
                return
 
132
        }
 
133
        w.Header().Set("Content-Type", "application/json")
 
134
        body := []byte(fmt.Sprintf(authInformationBody, openstack.url, openstack.url))
 
135
        // workaround for https://code.google.com/p/go/issues/detail?id=4454
 
136
        w.Header().Set("Content-Length", strconv.Itoa(len(body)))
 
137
        w.WriteHeader(http.StatusMultipleChoices)
 
138
        w.Write(body)
73
139
}