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

OSTree Plugin #28

Merged
merged 34 commits into from
Jan 15, 2024
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
4c078da
adds plugins.md as starting point for plugin how-to documentation
Nov 16, 2023
1a683b2
adds IsTLSMiddleware for convenience
Dec 7, 2023
f94b00e
ignore intellij project state files
Dec 7, 2023
60456e8
refactors service to a non-generic form
Dec 7, 2023
e3c4d74
initial implementation of ostree plugin (without mirroring)
Dec 7, 2023
a0e014e
gofumpt
Dec 8, 2023
0124423
gofumpt
Dec 15, 2023
f34ec0c
adds plugins.md as starting point for plugin how-to documentation
Nov 16, 2023
052611d
adds IsTLSMiddleware for convenience
Dec 7, 2023
46978c5
ignore intellij project state files
Dec 7, 2023
4375255
refactors service to a non-generic form
Dec 7, 2023
95adf48
initial implementation of ostree plugin (without mirroring)
Dec 7, 2023
29f5dbb
gofumpt
Dec 8, 2023
80d309d
gofumpt
Dec 15, 2023
d4db914
Merge branch 'main' into docs
Dec 15, 2023
d75a5b1
various changes from PR review
Dec 15, 2023
efa5db0
Merge remote-tracking branch 'origin/docs' into docs
Dec 15, 2023
7b00e6d
more fixes for linter
Dec 15, 2023
6fb8f97
Merge branch 'main' into docs
Jan 2, 2024
70da0f2
adds libostree testdata to gitignore
Jan 11, 2024
aac24f2
libostree finished
Jan 11, 2024
9478fb4
fixes various bugs discovered after manual testing
Jan 12, 2024
7876f55
gofumpt
Jan 12, 2024
4320e9c
removes unused dockerfile
Jan 12, 2024
3158651
fixes unit test build failure by introducing buildEnv and buildExecSt…
Jan 12, 2024
feae074
removes mistaken C import causing mage to no longer see test targets.
Jan 12, 2024
793ac41
fixes logic error in Depth() libostree option
Jan 12, 2024
0109dc8
Merge remote-tracking branch 'upstream/main' into docs
Jan 12, 2024
9d39093
rebase upstream main
Jan 12, 2024
fb8337f
removed comments again...
Jan 13, 2024
85c6ea5
fixes linter issues
Jan 15, 2024
7049ce3
adds libostree testdata
Jan 15, 2024
bca7378
adds libostree testdata
Jan 15, 2024
a95e957
adds --priviledged option to test:unit container
Jan 15, 2024
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,5 @@ build/output
.envrc.local
vendor
go.work.sum

.idea
9 changes: 9 additions & 0 deletions .idea/beskar.iml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ It's designed to support various artifacts and expose them through dedicated plu

### Features

* Modular/Extensible via plugins
* Modular/Extensible via [plugins](docs/plugins.md)
* Support for YUM repositories (beskar-yum)
* Support for static file repositories (beskar-static)

Expand Down
14 changes: 14 additions & 0 deletions build/mage/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const (
beskarctlBinary = "beskarctl"
beskarYUMBinary = "beskar-yum"
beskarStaticBinary = "beskar-static"
beskarOSTreeBinary = "beskar-ostree"
)

var binaries = map[string]binaryConfig{
Expand Down Expand Up @@ -103,6 +104,18 @@ var binaries = map[string]binaryConfig{
useProto: true,
baseImage: BaseImage,
},
beskarOSTreeBinary: {
configFiles: map[string]string{
"internal/plugins/ostree/pkg/config/default/beskar-ostree.yaml": "/etc/beskar/beskar-ostree.yaml",
},
genAPI: &genAPI{
path: "pkg/plugins/ostree/api/v1",
filename: "api.go",
interfaceName: "OSTree",
},
useProto: true,
baseImage: "alpine:3.17",
},
kyleishie marked this conversation as resolved.
Show resolved Hide resolved
}

type Build mg.Namespace
Expand Down Expand Up @@ -143,6 +156,7 @@ func (b Build) Plugins(ctx context.Context) {
ctx,
mg.F(b.Plugin, beskarYUMBinary),
mg.F(b.Plugin, beskarStaticBinary),
mg.F(b.Plugin, beskarOSTreeBinary),
)
}

Expand Down
73 changes: 73 additions & 0 deletions cmd/beskar-ostree/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package main

import (
"flag"
"fmt"
"log"
"net"
"os"
"syscall"

"go.ciq.dev/beskar/internal/pkg/pluginsrv"
"go.ciq.dev/beskar/internal/plugins/ostree"
"go.ciq.dev/beskar/internal/plugins/ostree/pkg/config"
"go.ciq.dev/beskar/pkg/sighandler"
"go.ciq.dev/beskar/pkg/version"
)

var configDir string

func serve(beskarOSTreeCmd *flag.FlagSet) error {
if err := beskarOSTreeCmd.Parse(os.Args[1:]); err != nil {
return err
}

errCh := make(chan error)

ctx, wait := sighandler.New(errCh, syscall.SIGTERM, syscall.SIGINT)

beskarOSTreeConfig, err := config.ParseBeskarOSTreeConfig(configDir)
if err != nil {
return err
}

ln, err := net.Listen("tcp", beskarOSTreeConfig.Addr)
if err != nil {
return err
}
defer func() {
if err := ln.Close(); err != nil {
fmt.Println(err)
}
}()

plugin, err := ostree.New(ctx, beskarOSTreeConfig)
if err != nil {
return err
}

go func() {
errCh <- pluginsrv.Serve(ln, plugin)
}()

return wait(false)
}

func main() {
beskarOSTreeCmd := flag.NewFlagSet("beskar-ostree", flag.ExitOnError)
beskarOSTreeCmd.StringVar(&configDir, "config-dir", "", "configuration directory")

subCommand := ""
if len(os.Args) > 1 {
subCommand = os.Args[1]
}

switch subCommand {
case "version":
fmt.Println(version.Semver)
default:
if err := serve(beskarOSTreeCmd); err != nil {
log.Fatal(err)
}
}
}
3 changes: 1 addition & 2 deletions cmd/beskar-static/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"go.ciq.dev/beskar/internal/pkg/pluginsrv"
"go.ciq.dev/beskar/internal/plugins/static"
"go.ciq.dev/beskar/internal/plugins/static/pkg/config"
"go.ciq.dev/beskar/internal/plugins/static/pkg/staticrepository"
"go.ciq.dev/beskar/pkg/sighandler"
"go.ciq.dev/beskar/pkg/version"
)
Expand Down Expand Up @@ -47,7 +46,7 @@ func serve(beskarStaticCmd *flag.FlagSet) error {
}

go func() {
errCh <- pluginsrv.Serve[*staticrepository.Handler](ln, plugin)
errCh <- pluginsrv.Serve(ln, plugin)
}()

return wait(false)
Expand Down
3 changes: 1 addition & 2 deletions cmd/beskar-yum/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import (
"go.ciq.dev/beskar/internal/pkg/pluginsrv"
"go.ciq.dev/beskar/internal/plugins/yum"
"go.ciq.dev/beskar/internal/plugins/yum/pkg/config"
"go.ciq.dev/beskar/internal/plugins/yum/pkg/yumrepository"
"go.ciq.dev/beskar/pkg/sighandler"
"go.ciq.dev/beskar/pkg/version"
)
Expand Down Expand Up @@ -47,7 +46,7 @@ func serve(beskarYumCmd *flag.FlagSet) error {
}

go func() {
errCh <- pluginsrv.Serve[*yumrepository.Handler](ln, plugin)
errCh <- pluginsrv.Serve(ln, plugin)
}()

return wait(false)
Expand Down
32 changes: 32 additions & 0 deletions cmd/beskarctl/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# beskarctl
`beskarctl` is a command line tool for interacting with Beskar Artifact Registries.

## Installation
```
go install go.ciq.dev/beskar/cmd/beskarctl@latest
```

## Usage
`beskarctl` is very similar to `kubectl` in that it provide various subcommands for interacting with Beskar repositories.
The following subcommands are available:
```
beskarctl yum <subcommand> [flags]
beskarctl static <subcommand> [flags]
beskarctl ostree <subcommand> [flags]
```
For more information on a specific subcommand, run `beskarctl <subcommand> --help`.

## Adding a new subcommand
Adding a new subcommand is fairly straightforward. Feel free to use the existing subcommands as a template, e.g.,
`cmd/beskarctl/static/`. The following steps should be followed:

1. Create a new file in `cmd/beskarctl/<subcommand>/root.go`.
2. Add a new `cobra.Command` to the `rootCmd` variable in `cmd/beskarctl/<subcommand>/root.go`.
3. Add an accessor function to `cmd/beskarctl/<subcommand>/root.go` that returns the new `cobra.Command`.
4. Register the new subcommand in `cmd/beskarctl/ctl/root.go` by calling the accessor function.

### Implementation Notes
- The `cobra.Command` you create should not be exported. Rather, your package should export an accessor function that
returns the `cobra.Command`. The accessor function is your chance to set up any flags or subcommands that your
`cobra.Command` needs. Please avoid the use of init functi
- helper functions are available for common values such as `--repo` and `--registry`. See `cmd/beskarctl/ctl/helpers.go`
13 changes: 13 additions & 0 deletions cmd/beskarctl/ctl/error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package ctl

import "fmt"

type Err string
kyleishie marked this conversation as resolved.
Show resolved Hide resolved

func (e Err) Error() string {
return string(e)
}

func Errf(str string, a ...any) Err {
return Err(fmt.Sprintf(str, a...))
}
48 changes: 48 additions & 0 deletions cmd/beskarctl/ctl/helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package ctl

import (
"os"

"github.com/spf13/cobra"
)

const (
ErrMissingFlagRepo = Err("missing repo flag")
ErrMissingFlagRegistry = Err("missing registry flag")
)

const (
FlagNameRepo = "repo"
FlagNameRegistry = "registry"
)

// RegisterFlags registers the flags that are common to all commands.
func RegisterFlags(cmd *cobra.Command) {
// Flags that are common to all commands.
cmd.PersistentFlags().String(FlagNameRepo, "", "The repository to operate on.")
cmd.PersistentFlags().String(FlagNameRegistry, "", "The registry to operate on.")
}

// Repo returns the repository name from the command line.
// If the repository is not specified, the command will exit with an error.
func Repo() string {
repo, err := rootCmd.Flags().GetString(FlagNameRepo)
if err != nil || repo == "" {
rootCmd.PrintErrln(ErrMissingFlagRepo)
os.Exit(1)
}

return repo
}

// Registry returns the registry name from the command line.
// If the registry is not specified, the command will exit with an error.
func Registry() string {
registry, err := rootCmd.Flags().GetString(FlagNameRegistry)
if err != nil || registry == "" {
rootCmd.PrintErrln(ErrMissingFlagRegistry)
os.Exit(1)
}

return registry
kyleishie marked this conversation as resolved.
Show resolved Hide resolved
}
27 changes: 27 additions & 0 deletions cmd/beskarctl/ctl/root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package ctl

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Use: "beskarctl",
Short: "Operations related to beskar.",
}

func Execute(cmds ...*cobra.Command) {
RegisterFlags(rootCmd)

rootCmd.AddCommand(
cmds...,
)

err := rootCmd.Execute()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
}
97 changes: 9 additions & 88 deletions cmd/beskarctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,95 +4,16 @@
package main

import (
"flag"
"fmt"
"os"

"github.com/google/go-containerregistry/pkg/authn"
"github.com/google/go-containerregistry/pkg/name"
"github.com/google/go-containerregistry/pkg/v1/remote"
"go.ciq.dev/beskar/pkg/oras"
"go.ciq.dev/beskar/pkg/orasrpm"
"go.ciq.dev/beskar/pkg/version"
"go.ciq.dev/beskar/cmd/beskarctl/ctl"
"go.ciq.dev/beskar/cmd/beskarctl/ostree"
"go.ciq.dev/beskar/cmd/beskarctl/static"
"go.ciq.dev/beskar/cmd/beskarctl/yum"
)

func fatal(format string, a ...any) {
fmt.Printf(format+"\n", a...)
os.Exit(1)
}

func main() {
pushCmd := flag.NewFlagSet("push", flag.ExitOnError)
pushRepo := pushCmd.String("repo", "", "repo")
pushRegistry := pushCmd.String("registry", "", "registry")

pushMetadataCmd := flag.NewFlagSet("push-metadata", flag.ExitOnError)
pushMetadataRepo := pushMetadataCmd.String("repo", "", "repo")
pushMetadataRegistry := pushMetadataCmd.String("registry", "", "registry")
pushMetadataType := pushMetadataCmd.String("type", "", "type")

if len(os.Args) == 1 {
fatal("missing subcommand")
}

switch os.Args[1] {
case "version":
fmt.Println(version.Semver)
case "push":
if err := pushCmd.Parse(os.Args[2:]); err != nil {
fatal("while parsing command arguments: %w", err)
}
rpm := pushCmd.Arg(0)
if rpm == "" {
fatal("an RPM package must be specified")
} else if pushRegistry == nil || *pushRegistry == "" {
fatal("a registry must be specified")
} else if pushRepo == nil || *pushRepo == "" {
fatal("a repo must be specified")
}
if err := push(rpm, *pushRepo, *pushRegistry); err != nil {
fatal("while pushing RPM package: %s", err)
}
case "push-metadata":
if err := pushMetadataCmd.Parse(os.Args[2:]); err != nil {
fatal("while parsing command arguments: %w", err)
}
metadata := pushMetadataCmd.Arg(0)
if metadata == "" {
fatal("a metadata file must be specified")
} else if pushMetadataRegistry == nil || *pushMetadataRegistry == "" {
fatal("a registry must be specified")
} else if pushMetadataRepo == nil || *pushMetadataRepo == "" {
fatal("a repo must be specified")
} else if pushMetadataType == nil || *pushMetadataType == "" {
fatal("a metadata type must be specified")
}
if err := pushMetadata(metadata, *pushMetadataType, *pushMetadataRepo, *pushMetadataRegistry); err != nil {
fatal("while pushing metadata: %s", err)
}
default:
fatal("unknown %q subcommand", os.Args[1])
}
}

func push(rpmPath string, repo, registry string) error {
pusher, err := orasrpm.NewRPMPusher(rpmPath, repo, name.WithDefaultRegistry(registry))
if err != nil {
return fmt.Errorf("while creating RPM pusher: %w", err)
}

fmt.Printf("Pushing %s to %s\n", rpmPath, pusher.Reference())

return oras.Push(pusher, remote.WithAuthFromKeychain(authn.DefaultKeychain))
}

func pushMetadata(metadataPath string, dataType, repo, registry string) error {
pusher, err := orasrpm.NewRPMExtraMetadataPusher(metadataPath, repo, dataType, name.WithDefaultRegistry(registry))
if err != nil {
return fmt.Errorf("while creating RPM metadata pusher: %w", err)
}

fmt.Printf("Pushing %s to %s\n", metadataPath, pusher.Reference())

return oras.Push(pusher, remote.WithAuthFromKeychain(authn.DefaultKeychain))
ctl.Execute(
yum.RootCmd(),
static.RootCmd(),
ostree.RootCmd(),
)
}
Loading
Loading