1// Copyright 2016 The etcd Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package command
16
17import (
18	"fmt"
19	"strings"
20
21	v3 "github.com/coreos/etcd/clientv3"
22	pb "github.com/coreos/etcd/etcdserver/etcdserverpb"
23)
24
25type simplePrinter struct {
26	isHex     bool
27	valueOnly bool
28}
29
30func (s *simplePrinter) Del(resp v3.DeleteResponse) {
31	fmt.Println(resp.Deleted)
32	for _, kv := range resp.PrevKvs {
33		printKV(s.isHex, s.valueOnly, kv)
34	}
35}
36
37func (s *simplePrinter) Get(resp v3.GetResponse) {
38	for _, kv := range resp.Kvs {
39		printKV(s.isHex, s.valueOnly, kv)
40	}
41}
42
43func (s *simplePrinter) Put(r v3.PutResponse) {
44	fmt.Println("OK")
45	if r.PrevKv != nil {
46		printKV(s.isHex, s.valueOnly, r.PrevKv)
47	}
48}
49
50func (s *simplePrinter) Txn(resp v3.TxnResponse) {
51	if resp.Succeeded {
52		fmt.Println("SUCCESS")
53	} else {
54		fmt.Println("FAILURE")
55	}
56
57	for _, r := range resp.Responses {
58		fmt.Println("")
59		switch v := r.Response.(type) {
60		case *pb.ResponseOp_ResponseDeleteRange:
61			s.Del((v3.DeleteResponse)(*v.ResponseDeleteRange))
62		case *pb.ResponseOp_ResponsePut:
63			s.Put((v3.PutResponse)(*v.ResponsePut))
64		case *pb.ResponseOp_ResponseRange:
65			s.Get(((v3.GetResponse)(*v.ResponseRange)))
66		default:
67			fmt.Printf("unexpected response %+v\n", r)
68		}
69	}
70}
71
72func (s *simplePrinter) Watch(resp v3.WatchResponse) {
73	for _, e := range resp.Events {
74		fmt.Println(e.Type)
75		if e.PrevKv != nil {
76			printKV(s.isHex, s.valueOnly, e.PrevKv)
77		}
78		printKV(s.isHex, s.valueOnly, e.Kv)
79	}
80}
81
82func (s *simplePrinter) Grant(resp v3.LeaseGrantResponse) {
83	fmt.Printf("lease %016x granted with TTL(%ds)\n", resp.ID, resp.TTL)
84}
85
86func (p *simplePrinter) Revoke(id v3.LeaseID, r v3.LeaseRevokeResponse) {
87	fmt.Printf("lease %016x revoked\n", id)
88}
89
90func (p *simplePrinter) KeepAlive(resp v3.LeaseKeepAliveResponse) {
91	fmt.Printf("lease %016x keepalived with TTL(%d)\n", resp.ID, resp.TTL)
92}
93
94func (s *simplePrinter) TimeToLive(resp v3.LeaseTimeToLiveResponse, keys bool) {
95	txt := fmt.Sprintf("lease %016x granted with TTL(%ds), remaining(%ds)", resp.ID, resp.GrantedTTL, resp.TTL)
96	if keys {
97		ks := make([]string, len(resp.Keys))
98		for i := range resp.Keys {
99			ks[i] = string(resp.Keys[i])
100		}
101		txt += fmt.Sprintf(", attached keys(%v)", ks)
102	}
103	fmt.Println(txt)
104}
105
106func (s *simplePrinter) Alarm(resp v3.AlarmResponse) {
107	for _, e := range resp.Alarms {
108		fmt.Printf("%+v\n", e)
109	}
110}
111
112func (s *simplePrinter) MemberAdd(r v3.MemberAddResponse) {
113	fmt.Printf("Member %16x added to cluster %16x\n", r.Member.ID, r.Header.ClusterId)
114}
115
116func (s *simplePrinter) MemberRemove(id uint64, r v3.MemberRemoveResponse) {
117	fmt.Printf("Member %16x removed from cluster %16x\n", id, r.Header.ClusterId)
118}
119
120func (s *simplePrinter) MemberUpdate(id uint64, r v3.MemberUpdateResponse) {
121	fmt.Printf("Member %16x updated in cluster %16x\n", id, r.Header.ClusterId)
122}
123
124func (s *simplePrinter) MemberList(resp v3.MemberListResponse) {
125	_, rows := makeMemberListTable(resp)
126	for _, row := range rows {
127		fmt.Println(strings.Join(row, ", "))
128	}
129}
130
131func (s *simplePrinter) EndpointStatus(statusList []epStatus) {
132	_, rows := makeEndpointStatusTable(statusList)
133	for _, row := range rows {
134		fmt.Println(strings.Join(row, ", "))
135	}
136}
137
138func (s *simplePrinter) DBStatus(ds dbstatus) {
139	_, rows := makeDBStatusTable(ds)
140	for _, row := range rows {
141		fmt.Println(strings.Join(row, ", "))
142	}
143}
144
145func (s *simplePrinter) RoleAdd(role string, r v3.AuthRoleAddResponse) {
146	fmt.Printf("Role %s created\n", role)
147}
148
149func (s *simplePrinter) RoleGet(role string, r v3.AuthRoleGetResponse) {
150	fmt.Printf("Role %s\n", role)
151	fmt.Println("KV Read:")
152
153	printRange := func(perm *v3.Permission) {
154		sKey := string(perm.Key)
155		sRangeEnd := string(perm.RangeEnd)
156		fmt.Printf("\t[%s, %s)", sKey, sRangeEnd)
157		if strings.Compare(v3.GetPrefixRangeEnd(sKey), sRangeEnd) == 0 {
158			fmt.Printf(" (prefix %s)", sKey)
159		}
160		fmt.Printf("\n")
161	}
162
163	for _, perm := range r.Perm {
164		if perm.PermType == v3.PermRead || perm.PermType == v3.PermReadWrite {
165			if len(perm.RangeEnd) == 0 {
166				fmt.Printf("\t%s\n", string(perm.Key))
167			} else {
168				printRange((*v3.Permission)(perm))
169			}
170		}
171	}
172	fmt.Println("KV Write:")
173	for _, perm := range r.Perm {
174		if perm.PermType == v3.PermWrite || perm.PermType == v3.PermReadWrite {
175			if len(perm.RangeEnd) == 0 {
176				fmt.Printf("\t%s\n", string(perm.Key))
177			} else {
178				printRange((*v3.Permission)(perm))
179			}
180		}
181	}
182}
183
184func (s *simplePrinter) RoleList(r v3.AuthRoleListResponse) {
185	for _, role := range r.Roles {
186		fmt.Printf("%s\n", role)
187	}
188}
189
190func (s *simplePrinter) RoleDelete(role string, r v3.AuthRoleDeleteResponse) {
191	fmt.Printf("Role %s deleted\n", role)
192}
193
194func (s *simplePrinter) RoleGrantPermission(role string, r v3.AuthRoleGrantPermissionResponse) {
195	fmt.Printf("Role %s updated\n", role)
196}
197
198func (s *simplePrinter) RoleRevokePermission(role string, key string, end string, r v3.AuthRoleRevokePermissionResponse) {
199	if len(end) == 0 {
200		fmt.Printf("Permission of key %s is revoked from role %s\n", key, role)
201		return
202	}
203	fmt.Printf("Permission of range [%s, %s) is revoked from role %s\n", key, end, role)
204}
205
206func (s *simplePrinter) UserAdd(name string, r v3.AuthUserAddResponse) {
207	fmt.Printf("User %s created\n", name)
208}
209
210func (s *simplePrinter) UserGet(name string, r v3.AuthUserGetResponse) {
211	fmt.Printf("User: %s\n", name)
212	fmt.Printf("Roles:")
213	for _, role := range r.Roles {
214		fmt.Printf(" %s", role)
215	}
216	fmt.Printf("\n")
217}
218
219func (s *simplePrinter) UserChangePassword(v3.AuthUserChangePasswordResponse) {
220	fmt.Println("Password updated")
221}
222
223func (s *simplePrinter) UserGrantRole(user string, role string, r v3.AuthUserGrantRoleResponse) {
224	fmt.Printf("Role %s is granted to user %s\n", role, user)
225}
226
227func (s *simplePrinter) UserRevokeRole(user string, role string, r v3.AuthUserRevokeRoleResponse) {
228	fmt.Printf("Role %s is revoked from user %s\n", role, user)
229}
230
231func (s *simplePrinter) UserDelete(user string, r v3.AuthUserDeleteResponse) {
232	fmt.Printf("User %s deleted\n", user)
233}
234
235func (s *simplePrinter) UserList(r v3.AuthUserListResponse) {
236	for _, user := range r.Users {
237		fmt.Printf("%s\n", user)
238	}
239}
240