-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
12 changed files
with
1,166 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
|
||
# Go template downloaded with gut | ||
*.exe | ||
*.exe~ | ||
*.dll | ||
*.so | ||
*.dylib | ||
*.test | ||
*.out | ||
go.work | ||
.gut | ||
|
||
# Dev files | ||
*.log | ||
devManifest.* | ||
.init | ||
|
||
dist/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
|
||
version: 2 | ||
|
||
before: | ||
hooks: | ||
# You may remove this if you don't use go modules. | ||
- go mod tidy | ||
|
||
builds: | ||
- env: | ||
- CGO_ENABLED=0 | ||
goos: | ||
- linux | ||
- windows | ||
- darwin | ||
binary: docker | ||
id: anyquery | ||
ldflags: "-s -w" | ||
|
||
goarch: | ||
- amd64 | ||
- arm64 | ||
|
||
archives: | ||
- format: binary | ||
|
||
changelog: | ||
sort: asc | ||
filters: | ||
exclude: | ||
- "^docs:" | ||
- "^test:" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
files := $(wildcard *.go) | ||
|
||
all: $(files) | ||
go build -o docker.out $(files) | ||
|
||
prod: $(files) | ||
go build -o docker.out -ldflags "-s -w" $(files) | ||
|
||
clean: | ||
rm -f docker.out | ||
|
||
.PHONY: all clean |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
# Docker plugin | ||
|
||
The Docker plugin allows you to query Docker containers, images and networks over SQL. | ||
|
||
## Installation | ||
|
||
```bash | ||
anyquery install docker | ||
``` | ||
|
||
## Usage | ||
|
||
```sql | ||
-- List all containers | ||
SELECT * FROM docker_containers; | ||
|
||
-- List all images from another docker daemon | ||
SELECT * FROM docker_images('tcp://0.0.0.0:2375'); | ||
|
||
-- List all networks | ||
SELECT * FROM docker_networks; | ||
``` | ||
|
||
Each table can specify another docker daemon to connect to by passing the connection string as an argument to the table function. You can also set the column `host` like this: | ||
|
||
```sql | ||
-- List all containers from another docker daemon | ||
SELECT * FROM docker_containers WHERE host='tcp://0.0.0.0:2375'; | ||
``` | ||
|
||
Finally, the plugin reads the environment variable `DOCKER_HOST` to connect to the docker daemon. If the variable is not set, it will connect to the default docker daemon. | ||
|
||
## Schema | ||
|
||
### docker_containers | ||
|
||
| Column index | Column name | type | | ||
| ------------ | ------------ | ------- | | ||
| 0 | id | TEXT | | ||
| 1 | names | TEXT | | ||
| 2 | image | TEXT | | ||
| 3 | image_id | TEXT | | ||
| 4 | command | TEXT | | ||
| 5 | created_at | TEXT | | ||
| 6 | ports | TEXT | | ||
| 7 | labels | TEXT | | ||
| 8 | size_rw | INTEGER | | ||
| 9 | size_root_fs | INTEGER | | ||
| 10 | state | TEXT | | ||
| 11 | status | TEXT | | ||
| 12 | networks | TEXT | | ||
| 13 | mounts | TEXT | | ||
|
||
### docker_container | ||
|
||
| Column index | Column name | type | | ||
| ------------ | ---------------- | ------- | | ||
| 0 | id | TEXT | | ||
| 1 | created_at | TEXT | | ||
| 2 | path | TEXT | | ||
| 3 | args | TEXT | | ||
| 4 | container_state | TEXT | | ||
| 5 | image | TEXT | | ||
| 6 | resolv_conf_path | TEXT | | ||
| 7 | hostname_path | TEXT | | ||
| 8 | hosts_path | TEXT | | ||
| 9 | log_path | TEXT | | ||
| 10 | name | TEXT | | ||
| 11 | restart_count | INTEGER | | ||
| 12 | driver | TEXT | | ||
| 13 | platform | TEXT | | ||
| 14 | mount_label | TEXT | | ||
| 15 | process_label | TEXT | | ||
| 16 | host_config | TEXT | | ||
| 17 | mounts | TEXT | | ||
| 18 | config | TEXT | | ||
| 19 | network_settings | TEXT | | ||
|
||
### docker_images | ||
|
||
| Column index | Column name | type | | ||
| ------------ | --------------- | ------- | | ||
| 0 | id | TEXT | | ||
| 1 | created_at | TEXT | | ||
| 2 | labels | TEXT | | ||
| 3 | parent_id | TEXT | | ||
| 4 | repo_tags | TEXT | | ||
| 5 | repo_digests | TEXT | | ||
| 6 | container_count | INTEGER | | ||
| 7 | shared_size | INTEGER | | ||
| 8 | size | INTEGER | | ||
|
||
### docker_networks | ||
|
||
| Column index | Column name | type | | ||
| ------------ | ----------- | ------- | | ||
| 0 | id | TEXT | | ||
| 1 | name | TEXT | | ||
| 2 | created_at | TEXT | | ||
| 3 | scope | TEXT | | ||
| 4 | driver | TEXT | | ||
| 5 | enable_ipv6 | INTEGER | | ||
| 6 | ipam | TEXT | | ||
| 7 | containers | TEXT | | ||
| 8 | options | TEXT | | ||
| 9 | labels | TEXT | | ||
| 10 | peers | TEXT | | ||
| 11 | services | TEXT | | ||
| 12 | internal | INTEGER | | ||
| 13 | attachable | INTEGER | | ||
| 14 | ingress | INTEGER | | ||
| 15 | config_only | INTEGER | | ||
| 16 | config_from | TEXT | | ||
|
||
## Caveats | ||
|
||
- The plugin does not do any caching. Each query will fetch the data from the docker daemon. | ||
- The plugin does not support inserts/updates/deletes. | ||
- Some columns are returned as JSON objects. You can use the `json_extract` or the `->>` operator to extract the data with the json path. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,193 @@ | ||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/julien040/anyquery/rpc" | ||
) | ||
|
||
// A constructor to create a new table instance | ||
// This function is called everytime a new connection is made to the plugin | ||
// | ||
// It should return a new table instance, the database schema and if there is an error | ||
func containerCreator(args rpc.TableCreatorArgs) (rpc.Table, *rpc.DatabaseSchema, error) { | ||
return &containerTable{}, &rpc.DatabaseSchema{ | ||
Columns: []rpc.DatabaseSchemaColumn{ | ||
{ | ||
Name: "container_id", | ||
Type: rpc.ColumnTypeString, | ||
IsParameter: true, | ||
IsRequired: true, | ||
}, | ||
{ | ||
Name: "host", | ||
Type: rpc.ColumnTypeString, | ||
IsParameter: true, | ||
}, | ||
|
||
{ | ||
Name: "id", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "created_at", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "path", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "args", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "container_state", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "image", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "resolv_conf_path", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "hostname_path", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "hosts_path", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "log_path", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "name", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "restart_count", | ||
Type: rpc.ColumnTypeInt, | ||
}, | ||
{ | ||
Name: "driver", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "platform", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "mount_label", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "process_label", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "host_config", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "mounts", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "config", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
{ | ||
Name: "network_settings", | ||
Type: rpc.ColumnTypeString, | ||
}, | ||
}, | ||
}, nil | ||
} | ||
|
||
type containerTable struct { | ||
} | ||
|
||
type containerCursor struct { | ||
} | ||
|
||
// Return a slice of rows that will be returned to Anyquery and filtered. | ||
// The second return value is true if the cursor has no more rows to return | ||
// | ||
// The constraints are used for optimization purposes to "pre-filter" the rows | ||
// If the rows returned don't match the constraints, it's not an issue. Anyquery will filter them out | ||
func (t *containerCursor) Query(constraints rpc.QueryConstraint) ([][]interface{}, bool, error) { | ||
client, err := createClient(constraints, 1) | ||
if err != nil { | ||
return nil, true, fmt.Errorf("failed to create client: %w", err) | ||
} | ||
|
||
containerID := retrieveArgString(constraints, 0) | ||
if containerID == "" { | ||
return nil, true, fmt.Errorf("missing container ID") | ||
} | ||
|
||
container, err := client.ContainerInspect(context.Background(), containerID) | ||
if err != nil { | ||
return nil, true, fmt.Errorf("failed to inspect container: %w", err) | ||
} | ||
|
||
return [][]interface{}{ | ||
{ | ||
container.ID, | ||
container.Created, | ||
container.Path, | ||
container.Args, | ||
serializeJSON(container.State), | ||
container.Image, | ||
container.ResolvConfPath, | ||
container.HostnamePath, | ||
container.HostsPath, | ||
container.LogPath, | ||
container.Name, | ||
container.RestartCount, | ||
container.Driver, | ||
container.Platform, | ||
container.MountLabel, | ||
container.ProcessLabel, | ||
serializeJSON(container.HostConfig), | ||
serializeJSON(container.Mounts), | ||
serializeJSON(container.Config), | ||
serializeJSON(container.NetworkSettings), | ||
}, | ||
}, true, nil | ||
|
||
} | ||
|
||
// Create a new cursor that will be used to read rows | ||
func (t *containerTable) CreateReader() rpc.ReaderInterface { | ||
return &containerCursor{} | ||
} | ||
|
||
// A slice of rows to insert | ||
func (t *containerTable) Insert(rows [][]interface{}) error { | ||
return nil | ||
} | ||
|
||
// A slice of rows to update | ||
// The first element of each row is the primary key | ||
// while the rest are the values to update | ||
// The primary key is therefore present twice | ||
func (t *containerTable) Update(rows [][]interface{}) error { | ||
return nil | ||
} | ||
|
||
// A slice of primary keys to delete | ||
func (t *containerTable) Delete(primaryKeys []interface{}) error { | ||
return nil | ||
} | ||
|
||
// A destructor to clean up resources | ||
func (t *containerTable) Close() error { | ||
return nil | ||
} |
Oops, something went wrong.