1package api
2
3import (
4	"context"
5	"errors"
6	"fmt"
7
8	"github.com/mitchellh/mapstructure"
9)
10
11func (c *Sys) ListMounts() (map[string]*MountOutput, error) {
12	r := c.c.NewRequest("GET", "/v1/sys/mounts")
13
14	ctx, cancelFunc := context.WithCancel(context.Background())
15	defer cancelFunc()
16	resp, err := c.c.RawRequestWithContext(ctx, r)
17	if err != nil {
18		return nil, err
19	}
20	defer resp.Body.Close()
21
22	secret, err := ParseSecret(resp.Body)
23	if err != nil {
24		return nil, err
25	}
26	if secret == nil || secret.Data == nil {
27		return nil, errors.New("data from server response is empty")
28	}
29
30	mounts := map[string]*MountOutput{}
31	err = mapstructure.Decode(secret.Data, &mounts)
32	if err != nil {
33		return nil, err
34	}
35
36	return mounts, nil
37}
38
39func (c *Sys) Mount(path string, mountInfo *MountInput) error {
40	r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s", path))
41	if err := r.SetJSONBody(mountInfo); err != nil {
42		return err
43	}
44
45	ctx, cancelFunc := context.WithCancel(context.Background())
46	defer cancelFunc()
47	resp, err := c.c.RawRequestWithContext(ctx, r)
48	if err != nil {
49		return err
50	}
51	defer resp.Body.Close()
52
53	return nil
54}
55
56func (c *Sys) Unmount(path string) error {
57	r := c.c.NewRequest("DELETE", fmt.Sprintf("/v1/sys/mounts/%s", path))
58
59	ctx, cancelFunc := context.WithCancel(context.Background())
60	defer cancelFunc()
61	resp, err := c.c.RawRequestWithContext(ctx, r)
62	if err == nil {
63		defer resp.Body.Close()
64	}
65	return err
66}
67
68func (c *Sys) Remount(from, to string) error {
69	body := map[string]interface{}{
70		"from": from,
71		"to":   to,
72	}
73
74	r := c.c.NewRequest("POST", "/v1/sys/remount")
75	if err := r.SetJSONBody(body); err != nil {
76		return err
77	}
78
79	ctx, cancelFunc := context.WithCancel(context.Background())
80	defer cancelFunc()
81	resp, err := c.c.RawRequestWithContext(ctx, r)
82	if err == nil {
83		defer resp.Body.Close()
84	}
85	return err
86}
87
88func (c *Sys) TuneMount(path string, config MountConfigInput) error {
89	r := c.c.NewRequest("POST", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
90	if err := r.SetJSONBody(config); err != nil {
91		return err
92	}
93
94	ctx, cancelFunc := context.WithCancel(context.Background())
95	defer cancelFunc()
96	resp, err := c.c.RawRequestWithContext(ctx, r)
97	if err == nil {
98		defer resp.Body.Close()
99	}
100	return err
101}
102
103func (c *Sys) MountConfig(path string) (*MountConfigOutput, error) {
104	r := c.c.NewRequest("GET", fmt.Sprintf("/v1/sys/mounts/%s/tune", path))
105
106	ctx, cancelFunc := context.WithCancel(context.Background())
107	defer cancelFunc()
108	resp, err := c.c.RawRequestWithContext(ctx, r)
109	if err != nil {
110		return nil, err
111	}
112	defer resp.Body.Close()
113
114	secret, err := ParseSecret(resp.Body)
115	if err != nil {
116		return nil, err
117	}
118	if secret == nil || secret.Data == nil {
119		return nil, errors.New("data from server response is empty")
120	}
121
122	var result MountConfigOutput
123	err = mapstructure.Decode(secret.Data, &result)
124	if err != nil {
125		return nil, err
126	}
127
128	return &result, err
129}
130
131type MountInput struct {
132	Type                  string            `json:"type"`
133	Description           string            `json:"description"`
134	Config                MountConfigInput  `json:"config"`
135	Local                 bool              `json:"local"`
136	SealWrap              bool              `json:"seal_wrap" mapstructure:"seal_wrap"`
137	ExternalEntropyAccess bool              `json:"external_entropy_access" mapstructure:"external_entropy_access"`
138	Options               map[string]string `json:"options"`
139
140	// Deprecated: Newer server responses should be returning this information in the
141	// Type field (json: "type") instead.
142	PluginName string `json:"plugin_name,omitempty"`
143}
144
145type MountConfigInput struct {
146	Options                   map[string]string `json:"options" mapstructure:"options"`
147	DefaultLeaseTTL           string            `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
148	Description               *string           `json:"description,omitempty" mapstructure:"description"`
149	MaxLeaseTTL               string            `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
150	ForceNoCache              bool              `json:"force_no_cache" mapstructure:"force_no_cache"`
151	AuditNonHMACRequestKeys   []string          `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
152	AuditNonHMACResponseKeys  []string          `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
153	ListingVisibility         string            `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
154	PassthroughRequestHeaders []string          `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
155	AllowedResponseHeaders    []string          `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
156	TokenType                 string            `json:"token_type,omitempty" mapstructure:"token_type"`
157
158	// Deprecated: This field will always be blank for newer server responses.
159	PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
160}
161
162type MountOutput struct {
163	UUID                  string            `json:"uuid"`
164	Type                  string            `json:"type"`
165	Description           string            `json:"description"`
166	Accessor              string            `json:"accessor"`
167	Config                MountConfigOutput `json:"config"`
168	Options               map[string]string `json:"options"`
169	Local                 bool              `json:"local"`
170	SealWrap              bool              `json:"seal_wrap" mapstructure:"seal_wrap"`
171	ExternalEntropyAccess bool              `json:"external_entropy_access" mapstructure:"external_entropy_access"`
172}
173
174type MountConfigOutput struct {
175	DefaultLeaseTTL           int      `json:"default_lease_ttl" mapstructure:"default_lease_ttl"`
176	MaxLeaseTTL               int      `json:"max_lease_ttl" mapstructure:"max_lease_ttl"`
177	ForceNoCache              bool     `json:"force_no_cache" mapstructure:"force_no_cache"`
178	AuditNonHMACRequestKeys   []string `json:"audit_non_hmac_request_keys,omitempty" mapstructure:"audit_non_hmac_request_keys"`
179	AuditNonHMACResponseKeys  []string `json:"audit_non_hmac_response_keys,omitempty" mapstructure:"audit_non_hmac_response_keys"`
180	ListingVisibility         string   `json:"listing_visibility,omitempty" mapstructure:"listing_visibility"`
181	PassthroughRequestHeaders []string `json:"passthrough_request_headers,omitempty" mapstructure:"passthrough_request_headers"`
182	AllowedResponseHeaders    []string `json:"allowed_response_headers,omitempty" mapstructure:"allowed_response_headers"`
183	TokenType                 string   `json:"token_type,omitempty" mapstructure:"token_type"`
184
185	// Deprecated: This field will always be blank for newer server responses.
186	PluginName string `json:"plugin_name,omitempty" mapstructure:"plugin_name"`
187}
188