1package secrets
2
3import (
4	"encoding/json"
5	"io"
6	"io/ioutil"
7	"time"
8
9	"github.com/gophercloud/gophercloud"
10	"github.com/gophercloud/gophercloud/pagination"
11)
12
13// Secret represents a secret stored in the key manager service.
14type Secret struct {
15	// BitLength is the bit length of the secret.
16	BitLength int `json:"bit_length"`
17
18	// Algorithm is the algorithm type of the secret.
19	Algorithm string `json:"algorithm"`
20
21	// Expiration is the expiration date of the secret.
22	Expiration time.Time `json:"-"`
23
24	// ContentTypes are the content types of the secret.
25	ContentTypes map[string]string `json:"content_types"`
26
27	// Created is the created date of the secret.
28	Created time.Time `json:"-"`
29
30	// CreatorID is the creator of the secret.
31	CreatorID string `json:"creator_id"`
32
33	// Mode is the mode of the secret.
34	Mode string `json:"mode"`
35
36	// Name is the name of the secret.
37	Name string `json:"name"`
38
39	// SecretRef is the URL to the secret.
40	SecretRef string `json:"secret_ref"`
41
42	// SecretType represents the type of secret.
43	SecretType string `json:"secret_type"`
44
45	// Status represents the status of the secret.
46	Status string `json:"status"`
47
48	// Updated is the updated date of the secret.
49	Updated time.Time `json:"-"`
50}
51
52func (r *Secret) UnmarshalJSON(b []byte) error {
53	type tmp Secret
54	var s struct {
55		tmp
56		Created    gophercloud.JSONRFC3339NoZ `json:"created"`
57		Updated    gophercloud.JSONRFC3339NoZ `json:"updated"`
58		Expiration gophercloud.JSONRFC3339NoZ `json:"expiration"`
59	}
60	err := json.Unmarshal(b, &s)
61	if err != nil {
62		return err
63	}
64	*r = Secret(s.tmp)
65
66	r.Created = time.Time(s.Created)
67	r.Updated = time.Time(s.Updated)
68	r.Expiration = time.Time(s.Expiration)
69
70	return nil
71}
72
73type commonResult struct {
74	gophercloud.Result
75}
76
77// Extract interprets any commonResult as a Secret.
78func (r commonResult) Extract() (*Secret, error) {
79	var s *Secret
80	err := r.ExtractInto(&s)
81	return s, err
82}
83
84// GetResult is the response from a Get operation. Call its Extract method
85// to interpret it as a secrets.
86type GetResult struct {
87	commonResult
88}
89
90// CreateResult is the response from a Create operation. Call its Extract method
91// to interpret it as a secrets.
92type CreateResult struct {
93	commonResult
94}
95
96// UpdateResult is the response from an Update operation. Call its ExtractErr to
97// determine if the request succeeded or failed.
98type UpdateResult struct {
99	gophercloud.ErrResult
100}
101
102// DeleteResult is the response from a Delete operation. Call its ExtractErr to
103// determine if the request succeeded or failed.
104type DeleteResult struct {
105	gophercloud.ErrResult
106}
107
108// PayloadResult is the response from a GetPayload operation. Call its Extract
109// method to extract the payload as a string.
110type PayloadResult struct {
111	gophercloud.Result
112	Body io.ReadCloser
113}
114
115// Extract is a function that takes a PayloadResult's io.Reader body
116// and reads all available data into a slice of bytes. Please be aware that due
117// to the nature of io.Reader is forward-only - meaning that it can only be read
118// once and not rewound. You can recreate a reader from the output of this
119// function by using bytes.NewReader(downloadBytes)
120func (r PayloadResult) Extract() ([]byte, error) {
121	if r.Err != nil {
122		return nil, r.Err
123	}
124	defer r.Body.Close()
125	body, err := ioutil.ReadAll(r.Body)
126	if err != nil {
127		return nil, err
128	}
129	r.Body.Close()
130	return body, nil
131}
132
133// SecretPage is a single page of secrets results.
134type SecretPage struct {
135	pagination.LinkedPageBase
136}
137
138// IsEmpty determines whether or not a page of secrets contains any results.
139func (r SecretPage) IsEmpty() (bool, error) {
140	secrets, err := ExtractSecrets(r)
141	return len(secrets) == 0, err
142}
143
144// NextPageURL extracts the "next" link from the links section of the result.
145func (r SecretPage) NextPageURL() (string, error) {
146	var s struct {
147		Next     string `json:"next"`
148		Previous string `json:"previous"`
149	}
150	err := r.ExtractInto(&s)
151	if err != nil {
152		return "", err
153	}
154	return s.Next, err
155}
156
157// ExtractSecrets returns a slice of Secrets contained in a single page of
158// results.
159func ExtractSecrets(r pagination.Page) ([]Secret, error) {
160	var s struct {
161		Secrets []Secret `json:"secrets"`
162	}
163	err := (r.(SecretPage)).ExtractInto(&s)
164	return s.Secrets, err
165}
166
167// MetadataResult is the result of a metadata request. Call its Extract method
168// to interpret it as a map[string]string.
169type MetadataResult struct {
170	gophercloud.Result
171}
172
173// Extract interprets any MetadataResult as map[string]string.
174func (r MetadataResult) Extract() (map[string]string, error) {
175	var s struct {
176		Metadata map[string]string `json:"metadata"`
177	}
178	err := r.ExtractInto(&s)
179	return s.Metadata, err
180}
181
182// MetadataCreateResult is the result of a metadata create request. Call its
183// Extract method to interpret it as a map[string]string.
184type MetadataCreateResult struct {
185	gophercloud.Result
186}
187
188// Extract interprets any MetadataCreateResult as a map[string]string.
189func (r MetadataCreateResult) Extract() (map[string]string, error) {
190	var s map[string]string
191	err := r.ExtractInto(&s)
192	return s, err
193}
194
195// Metadatum represents an individual metadata.
196type Metadatum struct {
197	Key   string `json:"key"`
198	Value string `json:"value"`
199}
200
201// MetadatumResult is the result of a metadatum request. Call its
202// Extract method to interpret it as a map[string]string.
203type MetadatumResult struct {
204	gophercloud.Result
205}
206
207// Extract interprets any MetadatumResult as a map[string]string.
208func (r MetadatumResult) Extract() (*Metadatum, error) {
209	var s *Metadatum
210	err := r.ExtractInto(&s)
211	return s, err
212}
213
214// MetadatumCreateResult is the response from a metadata Create operation. Call
215// it's ExtractErr to determine if the request succeeded or failed.
216//
217// NOTE: This could be a MetadatumResponse but, at the time of testing, it looks
218// like Barbican was returning errneous JSON in the response.
219type MetadatumCreateResult struct {
220	gophercloud.ErrResult
221}
222
223// MetadatumDeleteResult is the response from a metadatum Delete operation. Call
224// its ExtractErr to determine if the request succeeded or failed.
225type MetadatumDeleteResult struct {
226	gophercloud.ErrResult
227}
228