Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gok: add gus command + subcommands #62

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 11 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ module github.com/gokrazy/tools
go 1.19

require (
github.com/antihax/optional v1.0.0
github.com/breml/rootcerts v0.2.10
github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0
github.com/gokrazy/internal v0.0.0-20231010202000-a93c67aeb340
github.com/gokrazy/gokapi v0.0.0-20230221202227-fc8991bfa4ab
github.com/gokrazy/internal v0.0.0-20231013065356-235d00ca4845
github.com/gokrazy/updater v0.0.0-20230215172637-813ccc7f21e2
github.com/google/go-cmp v0.5.9
github.com/google/renameio/v2 v2.0.0
Expand All @@ -16,4 +18,11 @@ require (
golang.org/x/sys v0.5.0
)

require github.com/inconshreveable/mousetrap v1.1.0 // indirect
require (
github.com/golang/protobuf v1.5.2 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/oauth2 v0.5.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
)
32 changes: 28 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
github.com/antihax/optional v1.0.0 h1:xK2lYat7ZLaVVcIuj82J8kIro4V6kDe0AUDFboUCwcg=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/breml/rootcerts v0.2.10 h1:UGVZ193UTSUASpGtg6pbDwzOd7XQP+at0Ssg1/2E4h8=
github.com/breml/rootcerts v0.2.10/go.mod h1:24FDtzYMpqIeYC7QzaE8VPRQaFZU5TIUDlyk8qwjD88=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/damdo/internal v0.0.0-20231010185710-329afa6a2d6e h1:8gKsjwVk9zS/SYhK0f5wmGE6Mm1fTd3Xo17JPSNYC+0=
github.com/damdo/internal v0.0.0-20231010185710-329afa6a2d6e/go.mod h1:CIE3ta1pA9UGyV1BM6wSc9BvNIZTm6keFCy/ifi6PCw=
github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0 h1:C7t6eeMaEQVy6e8CarIhscYQlNmw5e3G36y7l7Y21Ao=
github.com/donovanhide/eventsource v0.0.0-20210830082556-c59027999da0/go.mod h1:56wL82FO0bfMU5RvfXoIwSOP2ggqqxT+tAfNEIyxuHw=
github.com/gokrazy/internal v0.0.0-20231010202000-a93c67aeb340 h1:ddYQ2L0WsOFaD28ex00IgDP9r3oRlDVyprwaUk2BGYo=
github.com/gokrazy/internal v0.0.0-20231010202000-a93c67aeb340/go.mod h1:CIE3ta1pA9UGyV1BM6wSc9BvNIZTm6keFCy/ifi6PCw=
github.com/gokrazy/gokapi v0.0.0-20230221202227-fc8991bfa4ab h1:w40XuAWHVKBrglRpyTGDCxn6LgTB2IhrAjRadZuYkVk=
github.com/gokrazy/gokapi v0.0.0-20230221202227-fc8991bfa4ab/go.mod h1:gsfT8xJ3ocl55b26EKYqBihG/Z5iu/9AP/6YlaAd16U=
github.com/gokrazy/internal v0.0.0-20231013065356-235d00ca4845 h1:wMiZodG33pO4pTMAO9g4uWmuBkv5m0KOJ6XlVygA+CU=
github.com/gokrazy/internal v0.0.0-20231013065356-235d00ca4845/go.mod h1:CIE3ta1pA9UGyV1BM6wSc9BvNIZTm6keFCy/ifi6PCw=
github.com/gokrazy/updater v0.0.0-20230215172637-813ccc7f21e2 h1:kBY5R1tSf+EYZ+QaSrofLaVJtBqYsVNVBWkdMq3Smcg=
github.com/gokrazy/updater v0.0.0-20230215172637-813ccc7f21e2/go.mod h1:PYOvzGOL4nlBmuxu7IyKQTFLaxr61+WPRNRzVtuYOHw=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/renameio/v2 v2.0.0 h1:UifI23ZTGY8Tt29JbYFiuyIU3eX+RNFtUwefq9qAhxg=
Expand All @@ -21,11 +28,28 @@ github.com/spf13/cobra v1.6.1 h1:o94oiPyS4KD1mPy2fmcYYHHfCxLqYjJOhGsCHFZtEzA=
github.com/spf13/cobra v1.6.1/go.mod h1:IOw/AERYS7UzyrGinqmz6HLUo219MORXGxhbaJUqzrY=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/mod v0.11.0 h1:bUO06HqtnRcc/7l71XBe4WcqTZ+3AH1J59zWDDwLKgU=
golang.org/x/mod v0.11.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s=
golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
97 changes: 97 additions & 0 deletions internal/gok/diff.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
package gok

import (
"bytes"
"context"
"fmt"
"io"
"strings"

"github.com/antihax/optional"
"github.com/gokrazy/gokapi/gusapi"
"github.com/gokrazy/internal/config"
"github.com/gokrazy/internal/instanceflag"
"github.com/spf13/cobra"
)

// diffCmd is gok gus diff.
var diffCmd = &cobra.Command{
// GroupID: "server",
Use: "diff",
Short: "Compare the SBOM on disk with the one set on the remote GUS server",
Long: `gok gus diff compares the SBOM of the gokrazy instance on disk with the one currently set on the remote GUS server

Examples:
# check if there is diff between a local and remote GUS server's SBOM
% gok -i scanner diff --server gus.gokrazy.org
`,
RunE: func(cmd *cobra.Command, args []string) error {
return diffImpl.run(cmd.Context(), args, cmd.OutOrStdout(), cmd.OutOrStderr())
},
}

type diffConfig struct {
server string
}

var diffImpl diffConfig

func init() {
diffCmd.Flags().StringVarP(&diffImpl.server, "server", "", "", "HTTP(S) URL to the server to diff against")
instanceflag.RegisterPflags(diffCmd.Flags())
diffCmd.MarkFlagRequired("server")
}

func (r *diffConfig) run(ctx context.Context, args []string, stdout, stderr io.Writer) error {
cfg, err := config.ReadFromFile()
if err != nil {
return err
}

machineID, err := getMachineID(cfg)
if err != nil {
return fmt.Errorf("error getting machineID: %w", err)
}

sc := sbomConfig{format: "hash"}
stdOutbuf := new(bytes.Buffer)
if err := sc.run(ctx, nil, stdOutbuf, nil); err != nil {
return err
}
localSBOMHash := strings.TrimSpace(stdOutbuf.String())

gusCfg := gusapi.NewConfiguration()
gusCfg.BasePath = r.server
gusCli := gusapi.NewAPIClient(gusCfg)

response, _, err := gusCli.UpdateApi.Update(ctx, &gusapi.UpdateApiUpdateOpts{
Body: optional.NewInterface(&gusapi.UpdateRequest{
MachineId: machineID,
}),
})
if err != nil {
return fmt.Errorf("error making update request to GUS server: %w", err)
}

if localSBOMHash != response.SbomHash {
return fmt.Errorf("local: %s != remote: %s", localSBOMHash, response.SbomHash)
}

return nil
}

func getMachineID(cfg *config.Struct) (string, error) {
if cfg == nil {
return "", fmt.Errorf("error reading nil config")
}
v, ok := cfg.PackageConfig["github.com/gokrazy/gokrazy/cmd/randomd"]
if !ok {
return "", fmt.Errorf("error undefined machineID")
}
rawMachineID, ok := v.ExtraFileContents["/etc/machine-id"]
if !ok {
return "", fmt.Errorf("error undefined machineID")
}

return strings.TrimSpace(rawMachineID), nil
}
35 changes: 35 additions & 0 deletions internal/gok/gus.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package gok

import (
"github.com/gokrazy/internal/instanceflag"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

// gusCmd is gok push.
var gusCmd = &cobra.Command{
GroupID: "server",
Use: "gus",
Short: "Interacts with a remote GUS server",
Long: `gok gus interacts with a remote GUS server.

When the --json flag is specified, the server response is printed to stdout.

Examples:
# interact with a remote GUS server
% gok gus diff ...
% gok gus set ...
% gok gus unset ...

`,
RunE: func(cmd *cobra.Command, args []string) error {
return pflag.ErrHelp
},
}

func init() {
instanceflag.RegisterPflags(gusCmd.Flags())
gusCmd.AddCommand(diffCmd)
gusCmd.AddCommand(setCmd)
gusCmd.AddCommand(unsetCmd)
}
1 change: 1 addition & 0 deletions internal/gok/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ func init() {
RootCmd.AddCommand(getCmd)
RootCmd.AddCommand(sbomCmd)
RootCmd.AddCommand(pushCmd)
RootCmd.AddCommand(gusCmd)
}
72 changes: 72 additions & 0 deletions internal/gok/set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package gok

import (
"context"
"fmt"
"io"

"github.com/antihax/optional"
"github.com/gokrazy/gokapi/gusapi"
"github.com/gokrazy/internal/instanceflag"
"github.com/spf13/cobra"
)

// setCmd is gok gus set.
var setCmd = &cobra.Command{
// GroupID: "server",
Use: "set",
Short: "Set the desired SBOM version for a machineID pattern on the remote GUS server",
Long: `gok gus set sets the SBOM version for a machineID pattern on the remote GUS server

Examples:
# check if there is set between a local and remote GUS server's SBOM
% gok -i scanner set --server gus.gokrazy.org --sbom_hash="..." --download_link="..." --registry_type="..." --machine_id_pattern=""
`,
RunE: func(cmd *cobra.Command, args []string) error {
return setImpl.run(cmd.Context(), args, cmd.OutOrStdout(), cmd.OutOrStderr())
},
}

type setConfig struct {
server string
sbomHash string
registryType string
downloadLink string
machineIDPattern string
}

var setImpl setConfig

func init() {
setCmd.Flags().StringVarP(&setImpl.server, "server", "", "", "HTTP(S) URL to the server to set against")
setCmd.Flags().StringVarP(&setImpl.sbomHash, "sbom_hash", "", "", "The version (SBOM Hash string) of the desired gokrazy image")
setCmd.Flags().StringVarP(&setImpl.downloadLink, "download_link", "", "", "relative (localdisk registry) or absolute download link with which gokrazy devices can download the build")
setCmd.Flags().StringVarP(&setImpl.registryType, "registry_type", "", "", "The type of registry on which the build is stored. see download_link")
setCmd.Flags().StringVarP(&setImpl.machineIDPattern, "machine_id_pattern", "", "", "The pattern to match the machineIDs to which apply the provided version")
instanceflag.RegisterPflags(setCmd.Flags())
setCmd.MarkFlagRequired("server")
setCmd.MarkFlagRequired("sbom_hash")
setCmd.MarkFlagRequired("machine_id_pattern")
setCmd.MarkFlagRequired("registry_type")
setCmd.MarkFlagRequired("download_link")
}

func (r *setConfig) run(ctx context.Context, args []string, stdout, stderr io.Writer) error {
gusCfg := gusapi.NewConfiguration()
gusCfg.BasePath = r.server
gusCli := gusapi.NewAPIClient(gusCfg)

_, _, err := gusCli.IngestApi.Ingest(ctx, &gusapi.IngestApiIngestOpts{
Body: optional.NewInterface(&gusapi.IngestRequest{
MachineIdPattern: r.machineIDPattern,
SbomHash: r.sbomHash,
RegistryType: r.registryType,
DownloadLink: r.downloadLink,
}),
})
if err != nil {
return fmt.Errorf("error making update request to GUS server: %w", err)
}

return nil
}
64 changes: 64 additions & 0 deletions internal/gok/unset.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package gok

import (
"context"
"fmt"
"io"

"github.com/gokrazy/internal/instanceflag"
"github.com/spf13/cobra"
)

// unsetCmd is gok gus unset.
var unsetCmd = &cobra.Command{
// GroupID: "server",
Use: "unset",
Short: "unset the desired SBOM version for a machineID pattern on the remote GUS server",
Long: `gok gus unset unsets the SBOM version for a machineID pattern on the remote GUS server

Examples:
# check if there is unset between a local and remote GUS server's SBOM
% gok -i scanner unset --server gus.gokrazy.org
`,
RunE: func(cmd *cobra.Command, args []string) error {
return unsetImpl.run(cmd.Context(), args, cmd.OutOrStdout(), cmd.OutOrStderr())
},
}

type unsetConfig struct {
server string
machineIDPattern string
}

var unsetImpl unsetConfig

func init() {
unsetCmd.Flags().StringVarP(&unsetImpl.server, "server", "", "", "HTTP(S) URL to the server to unset against")
unsetCmd.Flags().StringVarP(&unsetImpl.machineIDPattern, "machine_id_pattern", "", "", "The pattern to match the machineIDs to which apply the provided version")
instanceflag.RegisterPflags(unsetCmd.Flags())
unsetCmd.MarkFlagRequired("server")
unsetCmd.MarkFlagRequired("machine_id_pattern")
}

func (r *unsetConfig) run(ctx context.Context, args []string, stdout, stderr io.Writer) error {
fmt.Println("NOT IMPLEMENTED!")

// // TODO: finish this when gokapi has a method for unsetting.
// gusCfg := gusapi.NewConfiguration()
// gusCfg.BasePath = r.server
// gusCli := gusapi.NewAPIClient(gusCfg)

// _, _, err := gusCli.IngestApi.Ingest(ctx, &gusapi.IngestApiIngestOpts{
// Body: optional.NewInterface(&gusapi.IngestRequest{
// MachineIdPattern: r.machineIDPattern,
// SbomHash: "",
// RegistryType: "",
// DownloadLink: "",
// }),
// })
// if err != nil {
// return fmt.Errorf("error making update request to GUS server: %w", err)
// }

return nil
}