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

« back to all changes in this revision

Viewing changes to src/gopkg.in/amz.v3/ec2/ec2test/helpers.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
//
 
2
// goamz - Go packages to interact with the Amazon Web Services.
 
3
//
 
4
//   https://wiki.ubuntu.com/goamz
 
5
//
 
6
// Copyright (c) 2011-2015 Canonical Ltd.
 
7
//
 
8
// This file contains shared helpers and related code used internally.
 
9
 
 
10
package ec2test
 
11
 
 
12
import (
 
13
        "encoding/base64"
 
14
        "encoding/xml"
 
15
        "fmt"
 
16
        "io"
 
17
        "net"
 
18
        "net/http"
 
19
        "net/url"
 
20
        "strconv"
 
21
        "strings"
 
22
        "sync/atomic"
 
23
 
 
24
        "gopkg.in/amz.v3/ec2"
 
25
)
 
26
 
 
27
const defaultXMLName = "http://ec2.amazonaws.com/doc/2014-10-01/"
 
28
 
 
29
var b64 = base64.StdEncoding
 
30
 
 
31
// writeError writes an appropriate error response.
 
32
// TODO how should we deal with errors when the
 
33
// error itself is potentially generated by backend-agnostic
 
34
// code?
 
35
func writeError(w http.ResponseWriter, err *ec2.Error) {
 
36
        // Error encapsulates an error returned by EC2.
 
37
        // TODO merge with ec2.Error when xml supports ignoring a field.
 
38
        type ec2error struct {
 
39
                Code      string // EC2 error code ("UnsupportedOperation", ...)
 
40
                Message   string // The human-oriented error message
 
41
                RequestId string
 
42
        }
 
43
 
 
44
        type Response struct {
 
45
                RequestId string
 
46
                Errors    []ec2error `xml:"Errors>Error"`
 
47
        }
 
48
 
 
49
        w.Header().Set("Content-Type", `xml version="1.0" encoding="UTF-8"`)
 
50
        w.WriteHeader(err.StatusCode)
 
51
        xmlMarshal(w, Response{
 
52
                RequestId: err.RequestId,
 
53
                Errors: []ec2error{{
 
54
                        Code:    err.Code,
 
55
                        Message: err.Message,
 
56
                }},
 
57
        })
 
58
}
 
59
 
 
60
// xmlMarshal is the same as xml.Marshal except that
 
61
// it panics on error. The marshalling should not fail,
 
62
// but we want to know if it does.
 
63
func xmlMarshal(w io.Writer, x interface{}) {
 
64
        encoder := xml.NewEncoder(w)
 
65
        encoder.Indent("", "   ")
 
66
        if err := encoder.Encode(x); err != nil {
 
67
                panic(fmt.Errorf("error marshalling %#v: %v", x, err))
 
68
        }
 
69
}
 
70
 
 
71
func parseCidr(val string) string {
 
72
        if val == "" {
 
73
                fatalf(400, "MissingParameter", "missing cidrBlock")
 
74
        }
 
75
        if _, _, err := net.ParseCIDR(val); err != nil {
 
76
                fatalf(400, "InvalidParameterValue", "bad CIDR %q: %v", val, err)
 
77
        }
 
78
        return val
 
79
}
 
80
 
 
81
// parseIDs takes all form fields with the given prefix and returns a
 
82
// map with their values as keys.
 
83
func parseIDs(form url.Values, prefix string) map[string]bool {
 
84
        idMap := make(map[string]bool)
 
85
        for field, allValues := range form {
 
86
                value := allValues[0]
 
87
                if strings.HasPrefix(field, prefix) && !idMap[value] {
 
88
                        idMap[value] = true
 
89
                }
 
90
        }
 
91
        return idMap
 
92
}
 
93
 
 
94
// parseInOrder takes all form fields with the given prefix and
 
95
// returns their values in request order. Suitable for AWS API
 
96
// parameters defining lists, e.g. with fields like
 
97
// "PrivateIpAddress.0": v1, "PrivateIpAddress.1" v2, it returns
 
98
// []string{v1, v2}.
 
99
func parseInOrder(form url.Values, prefix string) []string {
 
100
        idMap := parseIDs(form, prefix)
 
101
        results := make([]string, len(idMap))
 
102
        for field, allValues := range form {
 
103
                if !strings.HasPrefix(field, prefix) {
 
104
                        continue
 
105
                }
 
106
                value := allValues[0]
 
107
                parts := strings.Split(field, ".")
 
108
                if len(parts) != 2 {
 
109
                        panic(fmt.Sprintf("expected indexed key %q", field))
 
110
                }
 
111
                index := atoi(parts[1])
 
112
                if idMap[value] {
 
113
                        results[index] = value
 
114
                }
 
115
        }
 
116
        return results
 
117
}
 
118
 
 
119
type counter struct {
 
120
        value int32
 
121
}
 
122
 
 
123
func (c *counter) next() int {
 
124
        i := atomic.AddInt32(&c.value, 1)
 
125
        return int(i - 1)
 
126
}
 
127
 
 
128
func (c *counter) get() (i int) {
 
129
        return int(atomic.LoadInt32(&c.value))
 
130
}
 
131
 
 
132
func (c *counter) reset() {
 
133
        atomic.StoreInt32(&c.value, 0)
 
134
}
 
135
 
 
136
// atoi is like strconv.Atoi but is fatal if the
 
137
// string is not well formed.
 
138
func atoi(s string) int {
 
139
        i, err := strconv.Atoi(s)
 
140
        if err != nil {
 
141
                fatalf(400, "InvalidParameterValue", "bad number: %v", err)
 
142
        }
 
143
        return i
 
144
}
 
145
 
 
146
func fatalf(statusCode int, code string, f string, a ...interface{}) {
 
147
        panic(&ec2.Error{
 
148
                StatusCode: statusCode,
 
149
                Code:       code,
 
150
                Message:    fmt.Sprintf(f, a...),
 
151
        })
 
152
}