Skip to content

Commit 8d0e8b8

Browse files
committed
Add augerctl get
Signed-off-by: Shiming Zhang <[email protected]>
1 parent 3647fff commit 8d0e8b8

13 files changed

+1139
-0
lines changed

augerctl/README.md

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
augerctl
2+
========
3+
4+
`augerctl` is a command line client for [Kubernetes][kubernetes] specific [etcd][etcd],
5+
and as close as possible to [kubectl][kubectl].
6+
It can be used in scripts or for administrators to explore an etcd cluster.
7+
8+
## Getting augerctl
9+
10+
The latest release is not yet available as a binary on [Github][github-release],
11+
the next release will be available.
12+
13+
so that it can be built from source.
14+
15+
``` bash
16+
git clone https://github.com/etcd-io/auger
17+
cd auger
18+
go install ./augerctl
19+
```
20+
21+
or
22+
23+
``` bash
24+
go install github.com/etcd-io/auger/augerctl@main
25+
```
26+
27+
and the binary will be available in the path `$GOBIN` or `$GOPATH/bin`
28+
29+
## Configuration
30+
31+
### --endpoints
32+
+ a comma-delimited list of machine addresses in the etcd cluster
33+
+ default: `"http://127.0.0.1:2379"`
34+
35+
### --cert
36+
+ identify HTTPS client using this SSL certificate file
37+
+ default: none
38+
39+
### --key
40+
+ identify HTTPS client using this SSL key file
41+
+ default: none
42+
43+
### --cacert
44+
+ verify certificates of HTTPS-enabled servers using this CA bundle
45+
+ default: none
46+
47+
### --user
48+
+ provide username[:password]
49+
+ default: none
50+
51+
### --password
52+
+ provide password only available if --user has no password
53+
+ default: none
54+
55+
## Usage
56+
57+
### Setting a resource
58+
59+
TODO
60+
61+
### Retrieving a resource
62+
63+
List a single service with namespace `default` and name `kubernetes`
64+
65+
``` bash
66+
augerctl get services -n default kubernetes
67+
68+
# Nearly equivalent
69+
kubectl get services -n default kubernetes -o yaml
70+
```
71+
72+
List a single resource of type `priorityclasses` and name `system-node-critical` without namespaced
73+
74+
``` bash
75+
augerctl get priorityclasses system-node-critical
76+
77+
# Nearly equivalent
78+
kubectl get priorityclasses system-node-critical -o yaml
79+
```
80+
81+
List all leases with namespace `kube-system`
82+
83+
``` bash
84+
augerctl get leases -n kube-system
85+
86+
# Nearly equivalent
87+
kubectl get leases -n kube-system -o yaml
88+
```
89+
90+
List a single resource of type `apiservices.apiregistration.k8s.io` and name `v1.apps`
91+
92+
``` bash
93+
augerctl get apiservices.apiregistration.k8s.io v1.apps
94+
95+
# Nearly equivalent
96+
kubectl get apiservices.apiregistration.k8s.io v1.apps -o yaml
97+
```
98+
99+
List all resources
100+
101+
``` bash
102+
augerctl get
103+
104+
# Nearly equivalent
105+
kubectl get $(kubectl api-resources --verbs=list --output=name | paste -s -d, - ) -A -o yaml
106+
```
107+
108+
### Deleting a resource
109+
110+
TODO
111+
112+
### Watching for changes
113+
114+
TODO
115+
116+
## Endpoint
117+
118+
If the etcd cluster isn't available on `http://127.0.0.1:2379`, specify a `--endpoints` flag.
119+
120+
## Project Details
121+
122+
### Versioning
123+
124+
augerctl uses [semantic versioning][semver].
125+
Releases will follow with the [Kubernetes][kubernetes] release cycle as possible (need API updates),
126+
but the version numbers will be not.
127+
128+
### License
129+
130+
augerctl is under the Apache 2.0 license. See the [LICENSE][license] file for details.
131+
132+
[kubernetes]: https://kubernetes.io/
133+
[kubectl]: https://kubectl.sigs.k8s.io/
134+
[etcd]: https://github.com/etcd-io/etcd
135+
[github-release]: https://github.com/etcd-io/auger/releases/
136+
[license]: ../LICENSE
137+
[semver]: http://semver.org/

augerctl/command/ctl.go

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package command is a simple command line client for directly accessing data objects stored in etcd by Kubernetes.
18+
package command
19+
20+
import (
21+
"github.com/spf13/cobra"
22+
23+
"go.etcd.io/etcd/client/pkg/v3/transport"
24+
)
25+
26+
type flagpole struct {
27+
Endpoints []string
28+
29+
InsecureSkipVerify bool
30+
InsecureDiscovery bool
31+
TLS transport.TLSInfo
32+
33+
User string
34+
Password string
35+
}
36+
37+
// NewCtlCommand returns a new cobra.Command for use ctl
38+
func NewCtlCommand() *cobra.Command {
39+
flags := &flagpole{}
40+
41+
cmd := &cobra.Command{
42+
Use: "augerctl",
43+
Short: "A simple command line client for directly accessing data objects stored in etcd by Kubernetes.",
44+
}
45+
cmd.PersistentFlags().StringSliceVar(&flags.Endpoints, "endpoints", []string{"127.0.0.1:2379"}, "gRPC endpoints of etcd cluster")
46+
47+
cmd.PersistentFlags().BoolVar(&flags.InsecureDiscovery, "insecure-discovery", true, "accept insecure SRV records describing cluster endpoints")
48+
cmd.PersistentFlags().BoolVar(&flags.InsecureSkipVerify, "insecure-skip-tls-verify", false, "skip server certificate verification")
49+
cmd.PersistentFlags().StringVar(&flags.TLS.CertFile, "cert", "", "identify secure client using this TLS certificate file")
50+
cmd.PersistentFlags().StringVar(&flags.TLS.KeyFile, "key", "", "identify secure client using this TLS key file")
51+
cmd.PersistentFlags().StringVar(&flags.TLS.TrustedCAFile, "cacert", "", "verify certificates of TLS-enabled secure servers using this CA bundle")
52+
cmd.PersistentFlags().StringVar(&flags.User, "user", "", "username for authentication")
53+
cmd.PersistentFlags().StringVar(&flags.Password, "password", "", "password for authentication")
54+
55+
cmd.AddCommand(
56+
newCtlGetCommand(flags),
57+
)
58+
return cmd
59+
}

augerctl/command/get_command.go

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package command
18+
19+
import (
20+
"context"
21+
"fmt"
22+
"os"
23+
24+
"github.com/etcd-io/auger/pkg/client"
25+
"github.com/spf13/cobra"
26+
"k8s.io/apimachinery/pkg/runtime/schema"
27+
)
28+
29+
type getFlagpole struct {
30+
Namespace string
31+
Output string
32+
ChunkSize int64
33+
Prefix string
34+
}
35+
36+
var (
37+
getExample = `
38+
# List a single service with namespace "default" and name "kubernetes"
39+
augerctl get services -n default kubernetes
40+
# Nearly equivalent
41+
kubectl get services -n default kubernetes -o yaml
42+
43+
# List a single resource of type "priorityclasses" and name "system-node-critical" without namespaced
44+
augerctl get priorityclasses system-node-critical
45+
# Nearly equivalent
46+
kubectl get priorityclasses system-node-critical -A -o yaml
47+
48+
# List all leases with namespace "kube-system"
49+
augerctl get leases -n kube-system
50+
# Nearly equivalent
51+
kubectl get leases -n kube-system -o yaml
52+
53+
# List a single resource of type "apiservices.apiregistration.k8s.io" and name "v1.apps"
54+
augerctl get apiservices.apiregistration.k8s.io v1.apps
55+
# Nearly equivalent
56+
kubectl get apiservices.apiregistration.k8s.io v1.apps -o yaml
57+
58+
# List all resources
59+
augerctl get
60+
# Nearly equivalent
61+
kubectl get $(kubectl api-resources --verbs=list --output=name | paste -s -d, - ) -A -o yaml
62+
`
63+
)
64+
65+
func newCtlGetCommand(f *flagpole) *cobra.Command {
66+
flags := &getFlagpole{}
67+
68+
cmd := &cobra.Command{
69+
Args: cobra.RangeArgs(0, 2),
70+
Use: "get [resource] [name]",
71+
Short: "Gets the resource of Kubernetes in etcd",
72+
Example: getExample,
73+
RunE: func(cmd *cobra.Command, args []string) error {
74+
etcdclient, err := clientFromCmd(f)
75+
if err != nil {
76+
return err
77+
}
78+
err = getCommand(cmd.Context(), etcdclient, flags, args)
79+
80+
if err != nil {
81+
return fmt.Errorf("%v: %w", args, err)
82+
}
83+
return nil
84+
},
85+
}
86+
87+
cmd.Flags().StringVarP(&flags.Output, "output", "o", "yaml", "output format. One of: (yaml).")
88+
cmd.Flags().StringVarP(&flags.Namespace, "namespace", "n", "", "namespace of resource")
89+
cmd.Flags().Int64Var(&flags.ChunkSize, "chunk-size", 500, "chunk size of the list pager")
90+
cmd.Flags().StringVar(&flags.Prefix, "prefix", "/registry", "prefix to prepend to the resource")
91+
92+
return cmd
93+
}
94+
95+
func getCommand(ctx context.Context, etcdclient client.Client, flags *getFlagpole, args []string) error {
96+
var targetGr schema.GroupResource
97+
var targetName string
98+
var targetNamespace string
99+
if len(args) != 0 {
100+
// TODO: Support get information from CRD and scheme.Codecs
101+
// Support short name
102+
// Check for namespaced
103+
104+
gr := schema.ParseGroupResource(args[0])
105+
if gr.Empty() {
106+
return fmt.Errorf("invalid resource %q", args[0])
107+
}
108+
targetGr = gr
109+
targetNamespace = flags.Namespace
110+
if len(args) >= 2 {
111+
targetName = args[1]
112+
}
113+
}
114+
115+
printer := NewPrinter(os.Stdout, flags.Output)
116+
if printer == nil {
117+
return fmt.Errorf("invalid output format: %q", flags.Output)
118+
}
119+
120+
opOpts := []client.OpOption{
121+
client.WithName(targetName, targetNamespace),
122+
client.WithGroupResource(targetGr),
123+
client.WithChunkSize(flags.ChunkSize),
124+
client.WithResponse(printer.Print),
125+
}
126+
127+
// TODO: Support watch
128+
129+
_, err := etcdclient.Get(ctx, flags.Prefix,
130+
opOpts...,
131+
)
132+
if err != nil {
133+
return err
134+
}
135+
136+
return nil
137+
}

0 commit comments

Comments
 (0)