diff --git a/cmd/aod/main.go b/cmd/aod/main.go new file mode 100644 index 0000000..193a381 --- /dev/null +++ b/cmd/aod/main.go @@ -0,0 +1,42 @@ +// Copyright 2023 The Authors (see AUTHORS file) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package main is the main entrypoint to the application. +package main + +import ( + "context" + "fmt" + "os" + "os/signal" + "syscall" + + "github.com/abcxyz/access-on-demand/pkg/cli" +) + +func main() { + ctx, done := signal.NotifyContext(context.Background(), + syscall.SIGINT, syscall.SIGTERM) + defer done() + + if err := realMain(ctx); err != nil { + done() + fmt.Fprintln(os.Stderr, err.Error()) + os.Exit(1) + } +} + +func realMain(ctx context.Context) error { + return cli.Run(ctx, os.Args[1:]) //nolint:wrapcheck // Want passthrough +} diff --git a/internal/version/version.go b/internal/version/version.go new file mode 100644 index 0000000..8134474 --- /dev/null +++ b/internal/version/version.go @@ -0,0 +1,49 @@ +// Copyright 2023 The Authors (see AUTHORS file) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package version + +import ( + "fmt" + "runtime" + "runtime/debug" +) + +var ( + // Name is the name of the binary. This can be overridden by the build + // process. + Name = "aod" + + // Version is the main package version. This can be overridden by the build + // process. + Version = "source" + + // Commit is the git sha. This can be overridden by the build process. + Commit = func() string { + if info, ok := debug.ReadBuildInfo(); ok { + for _, setting := range info.Settings { + if setting.Key == "vcs.revision" { + return setting.Value + } + } + } + return "HEAD" + }() + + // OSArch is the operating system and architecture combination. + OSArch = fmt.Sprint(runtime.GOOS, "/", runtime.GOARCH) + + // HumanVersion is the compiled version. + HumanVersion = fmt.Sprint(Name, " ", Version, " (", Commit, ", ", OSArch, ")") +) diff --git a/pkg/cli/root.go b/pkg/cli/root.go new file mode 100644 index 0000000..9c24b01 --- /dev/null +++ b/pkg/cli/root.go @@ -0,0 +1,52 @@ +// Copyright 2023 The Authors (see AUTHORS file) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package cli implements the commands for the AOD(Access On Demand) CLI. +package cli + +import ( + "context" + + "github.com/abcxyz/access-on-demand/internal/version" + "github.com/abcxyz/pkg/cli" +) + +// rootCmd defines the starting command structure. +var rootCmd = func() cli.Command { + return &cli.RootCommand{ + Name: "aod", + Version: version.HumanVersion, + Commands: map[string]cli.CommandFactory{ + "iam": func() cli.Command { + return &cli.RootCommand{ + Name: "iam", + Description: "Perform operations related to the IAM request", + Commands: map[string]cli.CommandFactory{ + "handle": func() cli.Command { + return &IAMHandleCommand{} + }, + "validate": func() cli.Command { + return &IAMValidateCommand{} + }, + }, + } + }, + }, + } +} + +// Run executes the CLI. +func Run(ctx context.Context, args []string) error { + return rootCmd().Run(ctx, args) //nolint:wrapcheck // Want passthrough +} diff --git a/pkg/cli/root_test.go b/pkg/cli/root_test.go new file mode 100644 index 0000000..4cb6abb --- /dev/null +++ b/pkg/cli/root_test.go @@ -0,0 +1,35 @@ +// Copyright 2023 The Authors (see AUTHORS file) +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "strings" + "testing" +) + +func TestRootCommand_Help(t *testing.T) { + t.Parallel() + + exp := ` +Usage: aod COMMAND + + iam Perform operations related to the IAM request +` + + cmd := rootCmd() + if got, want := strings.TrimSpace(cmd.Help()), strings.TrimSpace(exp); got != want { + t.Errorf("got\n\n%s\n\nwant\n\n%s\n\n", got, want) + } +}