1package api
2
3import (
4	"fmt"
5	"time"
6)
7
8// Namespace is the configuration of a single namespace. Namespacing is a Consul Enterprise feature.
9type Namespace struct {
10	// Name is the name of the Namespace. It must be unique and
11	// must be a DNS hostname. There are also other reserved names
12	// that may not be used.
13	Name string `json:"Name"`
14
15	// Description is where the user puts any information they want
16	// about the namespace. It is not used internally.
17	Description string `json:"Description,omitempty"`
18
19	// ACLs is the configuration of ACLs for this namespace. It has its
20	// own struct so that we can add more to it in the future.
21	// This is nullable so that we can omit if empty when encoding in JSON
22	ACLs *NamespaceACLConfig `json:"ACLs,omitempty"`
23
24	// Meta is a map that can be used to add kv metadata to the namespace definition
25	Meta map[string]string `json:"Meta,omitempty"`
26
27	// DeletedAt is the time when the Namespace was marked for deletion
28	// This is nullable so that we can omit if empty when encoding in JSON
29	DeletedAt *time.Time `json:"DeletedAt,omitempty" alias:"deleted_at"`
30
31	// CreateIndex is the Raft index at which the Namespace was created
32	CreateIndex uint64 `json:"CreateIndex,omitempty"`
33
34	// ModifyIndex is the latest Raft index at which the Namespace was modified.
35	ModifyIndex uint64 `json:"ModifyIndex,omitempty"`
36}
37
38// NamespaceACLConfig is the Namespace specific ACL configuration container
39type NamespaceACLConfig struct {
40	// PolicyDefaults is the list of policies that should be used for the parent authorizer
41	// of all tokens in the associated namespace.
42	PolicyDefaults []ACLLink `json:"PolicyDefaults" alias:"policy_defaults"`
43	// RoleDefaults is the list of roles that should be used for the parent authorizer
44	// of all tokens in the associated namespace.
45	RoleDefaults []ACLLink `json:"RoleDefaults" alias:"role_defaults"`
46}
47
48// Namespaces can be used to manage Namespaces in Consul Enterprise..
49type Namespaces struct {
50	c *Client
51}
52
53// Operator returns a handle to the operator endpoints.
54func (c *Client) Namespaces() *Namespaces {
55	return &Namespaces{c}
56}
57
58func (n *Namespaces) Create(ns *Namespace, q *WriteOptions) (*Namespace, *WriteMeta, error) {
59	if ns.Name == "" {
60		return nil, nil, fmt.Errorf("Must specify a Name for Namespace creation")
61	}
62
63	r := n.c.newRequest("PUT", "/v1/namespace")
64	r.setWriteOptions(q)
65	r.obj = ns
66	rtt, resp, err := requireOK(n.c.doRequest(r))
67	if err != nil {
68		return nil, nil, err
69	}
70	defer closeResponseBody(resp)
71
72	wm := &WriteMeta{RequestTime: rtt}
73	var out Namespace
74	if err := decodeBody(resp, &out); err != nil {
75		return nil, nil, err
76	}
77
78	return &out, wm, nil
79}
80
81func (n *Namespaces) Update(ns *Namespace, q *WriteOptions) (*Namespace, *WriteMeta, error) {
82	if ns.Name == "" {
83		return nil, nil, fmt.Errorf("Must specify a Name for Namespace updating")
84	}
85
86	r := n.c.newRequest("PUT", "/v1/namespace/"+ns.Name)
87	r.setWriteOptions(q)
88	r.obj = ns
89	rtt, resp, err := requireOK(n.c.doRequest(r))
90	if err != nil {
91		return nil, nil, err
92	}
93	defer closeResponseBody(resp)
94
95	wm := &WriteMeta{RequestTime: rtt}
96	var out Namespace
97	if err := decodeBody(resp, &out); err != nil {
98		return nil, nil, err
99	}
100
101	return &out, wm, nil
102}
103
104func (n *Namespaces) Read(name string, q *QueryOptions) (*Namespace, *QueryMeta, error) {
105	var out Namespace
106	r := n.c.newRequest("GET", "/v1/namespace/"+name)
107	r.setQueryOptions(q)
108	found, rtt, resp, err := requireNotFoundOrOK(n.c.doRequest(r))
109	if err != nil {
110		return nil, nil, err
111	}
112	defer closeResponseBody(resp)
113
114	qm := &QueryMeta{}
115	parseQueryMeta(resp, qm)
116	qm.RequestTime = rtt
117
118	if !found {
119		return nil, qm, nil
120	}
121
122	if err := decodeBody(resp, &out); err != nil {
123		return nil, nil, err
124	}
125	return &out, qm, nil
126}
127
128func (n *Namespaces) Delete(name string, q *WriteOptions) (*WriteMeta, error) {
129	r := n.c.newRequest("DELETE", "/v1/namespace/"+name)
130	r.setWriteOptions(q)
131	rtt, resp, err := requireOK(n.c.doRequest(r))
132	if err != nil {
133		return nil, err
134	}
135	closeResponseBody(resp)
136
137	wm := &WriteMeta{RequestTime: rtt}
138	return wm, nil
139}
140
141func (n *Namespaces) List(q *QueryOptions) ([]*Namespace, *QueryMeta, error) {
142	var out []*Namespace
143	r := n.c.newRequest("GET", "/v1/namespaces")
144	r.setQueryOptions(q)
145	rtt, resp, err := requireOK(n.c.doRequest(r))
146	if err != nil {
147		return nil, nil, err
148	}
149	defer closeResponseBody(resp)
150
151	qm := &QueryMeta{}
152	parseQueryMeta(resp, qm)
153	qm.RequestTime = rtt
154
155	if err := decodeBody(resp, &out); err != nil {
156		return nil, nil, err
157	}
158	return out, qm, nil
159}
160