From fb89c9574711e3caafbe5f90fb7e19d31d0cce82 Mon Sep 17 00:00:00 2001 From: Damian Czaja Date: Wed, 30 Jun 2021 15:26:25 +0200 Subject: [PATCH] Add badges, fix some Go Report Card issues (#364) Co-authored-by: Mateusz Szostok --- .github/workflows/branch-build.yaml | 2 +- .golangci.yml | 4 +- README.md | 4 + cmd/argo-actions/main.go | 1 + cmd/cli/cmd/action/action.go | 1 + cmd/cli/cmd/action/create.go | 1 + cmd/cli/cmd/action/delete.go | 1 + cmd/cli/cmd/action/get.go | 1 + cmd/cli/cmd/action/run.go | 1 + cmd/cli/cmd/action/watch.go | 2 + cmd/cli/cmd/completion.go | 2 + cmd/cli/cmd/config/config.go | 1 + cmd/cli/cmd/config/get.go | 1 + cmd/cli/cmd/config/set.go | 1 + cmd/cli/cmd/docs.go | 1 + cmd/cli/cmd/hub/hub.go | 1 + cmd/cli/cmd/hub/implementations/get.go | 1 + .../hub/implementations/implementations.go | 1 + cmd/cli/cmd/hub/interfaces/browse.go | 1 + cmd/cli/cmd/hub/interfaces/get.go | 1 + cmd/cli/cmd/hub/interfaces/interfaces.go | 1 + cmd/cli/cmd/login.go | 3 +- cmd/cli/cmd/logout.go | 1 + cmd/cli/cmd/policy/apply.go | 1 + cmd/cli/cmd/policy/edit.go | 2 + cmd/cli/cmd/policy/get.go | 1 + cmd/cli/cmd/policy/policy.go | 1 + cmd/cli/cmd/root.go | 1 + cmd/cli/cmd/typeinstance/apply.go | 4 +- cmd/cli/cmd/typeinstance/create.go | 4 +- cmd/cli/cmd/typeinstance/delete.go | 1 + cmd/cli/cmd/typeinstance/edit.go | 1 + cmd/cli/cmd/typeinstance/get.go | 4 + cmd/cli/cmd/typeinstance/type_instance.go | 1 + cmd/cli/cmd/upgrade.go | 1 + cmd/cli/cmd/validate.go | 1 + cmd/cli/cmd/version.go | 1 + cmd/cloudsql-runner/main.go | 1 + cmd/gateway/main.go | 1 + cmd/k8s-engine/main.go | 10 +- .../cmd/register/capact_installation.go | 1 + cmd/populator/cmd/register/ocf_manifests.go | 1 + cmd/populator/cmd/register/register.go | 1 + cmd/populator/cmd/root.go | 1 + cmd/populator/main.go | 4 +- .../dgraph/app/internal/client/client.go | 1 - .../graph-db/dgraph/app/internal/dso.go | 4 +- docs/investigation/graph-db/grakn/helpers.go | 2 +- docs/investigation/graph-db/grakn/resolver.go | 2 +- .../graph-db/neo4j-gogm/graphql/models.go | 23 ++-- .../graph-db/neo4j-gogm/graphql/resolver.go | 2 +- .../neo4j-gogm/graphql/schema.resolvers.go | 7 +- .../investigation/graph-db/neo4j-gogm/main.go | 104 +++++++++--------- docs/investigation/workflow-rendering/main.go | 7 +- .../workflow-rendering/render/manifests.go | 2 +- .../workflow-rendering/render/render.go | 4 +- hack/lint.sh | 2 +- pkg/argo-actions/actions.go | 3 + pkg/argo-actions/download_type_instances.go | 6 + pkg/argo-actions/errors.go | 2 + pkg/argo-actions/update_type_instances.go | 9 +- pkg/argo-actions/upload_type_instances.go | 9 +- pkg/engine/api/graphql/json.go | 3 + pkg/engine/api/graphql/policy.go | 4 + pkg/engine/api/graphql/timestamp.go | 3 + pkg/engine/k8s/policy/error.go | 2 + pkg/engine/k8s/policy/from_yaml.go | 5 + pkg/engine/k8s/policy/types.go | 30 ++++- pkg/engine/k8s/policy/workflow.go | 27 ++++- pkg/httputil/client.go | 2 + pkg/httputil/doc.go | 2 +- pkg/hub/client/client.go | 3 + pkg/hub/client/fake/fake.go | 24 +++- pkg/hub/client/local/client.go | 10 ++ pkg/hub/client/policy_enforced_client.go | 18 ++- pkg/hub/client/public/client.go | 16 +++ pkg/hub/client/public/fields.go | 6 + pkg/hub/client/public/filter.go | 3 + pkg/hub/client/public/options.go | 9 +- pkg/hub/client/public/sort.go | 3 + pkg/runner/api.go | 5 +- pkg/runner/argo/argo.go | 3 +- pkg/runner/cloudsql/creds.go | 4 + pkg/runner/cloudsql/runner.go | 7 ++ pkg/runner/cloudsql/types.go | 16 ++- pkg/runner/common.go | 3 + pkg/runner/config.go | 4 + pkg/runner/helm/adapter.go | 5 + pkg/runner/helm/output.go | 6 + pkg/runner/helm/render.go | 5 + pkg/runner/helm/types.go | 13 +++ pkg/runner/helm/upgrade.go | 3 +- pkg/runner/helm/value_override.go | 3 +- pkg/runner/manager.go | 3 +- pkg/runner/status-reporter/noop_reporter.go | 1 + pkg/runner/terraform/runner.go | 10 +- pkg/runner/terraform/terraform.go | 9 +- pkg/runner/terraform/types.go | 17 +++ pkg/runner/terraform/variables.go | 3 + pkg/sdk/apis/0.0.1/types/types.extend.go | 2 +- pkg/sdk/dbpopulator/loader.go | 4 +- pkg/sdk/dbpopulator/server.go | 4 +- pkg/sdk/manifest/validation.go | 13 ++- pkg/sdk/renderer/argo/dedicated_renderer.go | 2 + pkg/sdk/renderer/argo/errors.go | 9 ++ pkg/sdk/renderer/argo/helpers.go | 1 + pkg/sdk/renderer/argo/options.go | 9 ++ pkg/sdk/renderer/argo/renderer.go | 5 + pkg/sdk/renderer/argo/typeinstance_handler.go | 14 +++ pkg/sdk/renderer/argo/types.go | 16 ++- pkg/sdk/renderer/config.go | 1 + 111 files changed, 503 insertions(+), 134 deletions(-) diff --git a/.github/workflows/branch-build.yaml b/.github/workflows/branch-build.yaml index a2ed657de..cd4cba0c5 100644 --- a/.github/workflows/branch-build.yaml +++ b/.github/workflows/branch-build.yaml @@ -1,4 +1,4 @@ -name: Default branch build +name: Main branch on: push: diff --git a/.golangci.yml b/.golangci.yml index bc9aa682b..6e4e3ef9f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -31,12 +31,12 @@ linters: - typecheck - unused - varcheck - - golint + - revive - gofmt - misspell - gochecknoinits - unparam - - scopelint + - exportloopref - gosec - goimports - whitespace diff --git a/README.md b/README.md index 55ee47c50..7fd8c3ba6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # Capact +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) +[![GitHub Actions main branch CI](https://github.com/capactio/capact/actions/workflows/branch-build.yaml/badge.svg?branch=main)](https://github.com/capactio/capact/actions/workflows/branch-build.yaml?query=branch%3Amain) +[![Go Report Card](https://goreportcard.com/badge/github.com/capactio/capact)](https://goreportcard.com/report/github.com/capactio/capact) + **Capact** (pronounced: "cape-act", /ˈkeɪp.ækt/) is a simple way to manage applications and infrastructure. > **⚠️ WARNING**: Capact versions prior to 0.4.0 are considered experimental. Capact 0.4.0, the very first public Capact release, is coming very soon, along with the **capact.io** website going live. Until this moment, the links may not work properly. Stay tuned for the announcement! diff --git a/cmd/argo-actions/main.go b/cmd/argo-actions/main.go index 274b4a897..810e8dadb 100644 --- a/cmd/argo-actions/main.go +++ b/cmd/argo-actions/main.go @@ -14,6 +14,7 @@ import ( "go.uber.org/zap" ) +// Config for the argo-actions command. type Config struct { Action string DownloadConfig []argoactions.DownloadConfig `envconfig:"optional"` diff --git a/cmd/cli/cmd/action/action.go b/cmd/cli/cmd/action/action.go index 1c829b0d2..32d45faea 100644 --- a/cmd/cli/cmd/action/action.go +++ b/cmd/cli/cmd/action/action.go @@ -26,6 +26,7 @@ var argoHiddenFlags = []string{ "node-field-selector", } +// NewCmd returns a new cobra.Command subcommand for Action related operations. func NewCmd() *cobra.Command { root := &cobra.Command{ Use: "action", diff --git a/cmd/cli/cmd/action/create.go b/cmd/cli/cmd/action/create.go index d303c90e4..f70d273a5 100644 --- a/cmd/cli/cmd/action/create.go +++ b/cmd/cli/cmd/action/create.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" ) +// NewCreate returns a new cobra.Command for creating a new Action. func NewCreate() *cobra.Command { var opts action.CreateOptions diff --git a/cmd/cli/cmd/action/delete.go b/cmd/cli/cmd/action/delete.go index e2443327f..5c85f0a5a 100644 --- a/cmd/cli/cmd/action/delete.go +++ b/cmd/cli/cmd/action/delete.go @@ -12,6 +12,7 @@ import ( "github.com/spf13/cobra" ) +// NewDelete returns a new cobra.Command for deleting an Action. func NewDelete() *cobra.Command { var opts action.DeleteOptions diff --git a/cmd/cli/cmd/action/get.go b/cmd/cli/cmd/action/get.go index f9f686dc0..adcc39c78 100644 --- a/cmd/cli/cmd/action/get.go +++ b/cmd/cli/cmd/action/get.go @@ -11,6 +11,7 @@ import ( "github.com/spf13/cobra" ) +// NewGet returns a cobra.Command for getting Actions. func NewGet() *cobra.Command { var opts action.GetOptions diff --git a/cmd/cli/cmd/action/run.go b/cmd/cli/cmd/action/run.go index 180b2ba04..24083e354 100644 --- a/cmd/cli/cmd/action/run.go +++ b/cmd/cli/cmd/action/run.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" ) +// NewRun returns a new cobra.Command for running rendered Actions. func NewRun() *cobra.Command { var opts action.RunOptions diff --git a/cmd/cli/cmd/action/watch.go b/cmd/cli/cmd/action/watch.go index d9d1cadeb..0aced4597 100644 --- a/cmd/cli/cmd/action/watch.go +++ b/cmd/cli/cmd/action/watch.go @@ -9,6 +9,8 @@ import ( "github.com/spf13/cobra" ) +// NewWatch returns a cobra.Command for watching of runnning Actions. +// It uses the command from "argo watch". func NewWatch() *cobra.Command { cmd := commands.NewWatchCommand() cmd.Use = "watch ACTION" diff --git a/cmd/cli/cmd/completion.go b/cmd/cli/cmd/completion.go index 686771890..dfa484792 100644 --- a/cmd/cli/cmd/completion.go +++ b/cmd/cli/cmd/completion.go @@ -10,6 +10,8 @@ import ( "github.com/spf13/cobra" ) +// NewCompletion returns a cobra.Command for shell autocompletion generation. +// Supported shells: bash, zsh, fish, powershell func NewCompletion() *cobra.Command { cmd := &cobra.Command{ Use: "completion [bash|zsh|fish|powershell]", diff --git a/cmd/cli/cmd/config/config.go b/cmd/cli/cmd/config/config.go index 778b3f989..1fe9f0270 100644 --- a/cmd/cli/cmd/config/config.go +++ b/cmd/cli/cmd/config/config.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" ) +// NewCmd returns a cobra.Command for CLI configuration related operations. // TODO: Add support for target configuration (instead of relying on current default context in kubectl) func NewCmd() *cobra.Command { cmd := &cobra.Command{ diff --git a/cmd/cli/cmd/config/get.go b/cmd/cli/cmd/config/get.go index 58124442f..aa3bbcf51 100644 --- a/cmd/cli/cmd/config/get.go +++ b/cmd/cli/cmd/config/get.go @@ -13,6 +13,7 @@ import ( "github.com/spf13/cobra" ) +// NewGet returns a cobra.Command for getting the available Capact contexts. func NewGet() *cobra.Command { return &cobra.Command{ Use: "get-contexts", diff --git a/cmd/cli/cmd/config/set.go b/cmd/cli/cmd/config/set.go index e04aa32cd..320e1692c 100644 --- a/cmd/cli/cmd/config/set.go +++ b/cmd/cli/cmd/config/set.go @@ -16,6 +16,7 @@ type setContextOptions struct { serverAddress string } +// NewSet returns a cobra.Command for setting an active CLI context. func NewSet() *cobra.Command { var opts setContextOptions diff --git a/cmd/cli/cmd/docs.go b/cmd/cli/cmd/docs.go index c8328a54d..3a2e4318b 100644 --- a/cmd/cli/cmd/docs.go +++ b/cmd/cli/cmd/docs.go @@ -19,6 +19,7 @@ title: %s ` ) +// NewDocs returns a cobra.Command for generating Capact CLI documentation. func NewDocs() *cobra.Command { return &cobra.Command{ Use: "gen-usage-docs", diff --git a/cmd/cli/cmd/hub/hub.go b/cmd/cli/cmd/hub/hub.go index 82e1ddc12..13d028249 100644 --- a/cmd/cli/cmd/hub/hub.go +++ b/cmd/cli/cmd/hub/hub.go @@ -7,6 +7,7 @@ import ( "github.com/spf13/cobra" ) +// NewCmd returns a cobra.Command for interacting with the Hub. func NewCmd() *cobra.Command { hub := &cobra.Command{ Use: "hub", diff --git a/cmd/cli/cmd/hub/implementations/get.go b/cmd/cli/cmd/hub/implementations/get.go index 99431b2cc..ed60a256c 100644 --- a/cmd/cli/cmd/hub/implementations/get.go +++ b/cmd/cli/cmd/hub/implementations/get.go @@ -21,6 +21,7 @@ type getOptions struct { implementationPaths []string } +// NewGet returns a cobra.Command for getting Implementations from a Public Hub. func NewGet() *cobra.Command { var opts getOptions diff --git a/cmd/cli/cmd/hub/implementations/implementations.go b/cmd/cli/cmd/hub/implementations/implementations.go index bcecff54d..ccf150183 100644 --- a/cmd/cli/cmd/hub/implementations/implementations.go +++ b/cmd/cli/cmd/hub/implementations/implementations.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" ) +// NewImplementations returns a cobra.Command for Hub Implementation related operations. func NewImplementations() *cobra.Command { cmd := &cobra.Command{ Use: "implementations", diff --git a/cmd/cli/cmd/hub/interfaces/browse.go b/cmd/cli/cmd/hub/interfaces/browse.go index 9c5343cdf..1885edf3c 100644 --- a/cmd/cli/cmd/hub/interfaces/browse.go +++ b/cmd/cli/cmd/hub/interfaces/browse.go @@ -20,6 +20,7 @@ type browseOptions struct { pathPattern string } +// NewBrowse returns a cobra.Command for browsing available Interfaces in a Public Hub. func NewBrowse() *cobra.Command { var opts browseOptions diff --git a/cmd/cli/cmd/hub/interfaces/get.go b/cmd/cli/cmd/hub/interfaces/get.go index 05a1e3260..a1a936134 100644 --- a/cmd/cli/cmd/hub/interfaces/get.go +++ b/cmd/cli/cmd/hub/interfaces/get.go @@ -24,6 +24,7 @@ var ( allPathPrefix = "cap.interface.*" ) +// NewGet returns a cobra.Command for getting available Implementations in a Public Hub. func NewGet() *cobra.Command { var opts getOptions diff --git a/cmd/cli/cmd/hub/interfaces/interfaces.go b/cmd/cli/cmd/hub/interfaces/interfaces.go index ffdcca97b..00e2afdae 100644 --- a/cmd/cli/cmd/hub/interfaces/interfaces.go +++ b/cmd/cli/cmd/hub/interfaces/interfaces.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" ) +// NewInterfaces returns a cobra.Command for Hub Interfaces related operations. func NewInterfaces() *cobra.Command { cmd := &cobra.Command{ Use: "interfaces", diff --git a/cmd/cli/cmd/login.go b/cmd/cli/cmd/login.go index 7ddd87077..310c762a1 100644 --- a/cmd/cli/cmd/login.go +++ b/cmd/cli/cmd/login.go @@ -26,8 +26,7 @@ type loginOptions struct { password string } -// TODO: Validate the Gateway Hub URL - +// NewLogin returns a cobra.Command for logging into a Hub. func NewLogin() *cobra.Command { var opts loginOptions diff --git a/cmd/cli/cmd/logout.go b/cmd/cli/cmd/logout.go index 96f75343a..7d3d57e23 100644 --- a/cmd/cli/cmd/logout.go +++ b/cmd/cli/cmd/logout.go @@ -15,6 +15,7 @@ import ( "github.com/spf13/cobra" ) +// NewLogout returns a cobra.Command for logout from a Hub. func NewLogout() *cobra.Command { cmd := &cobra.Command{ Use: "logout [SERVER]", diff --git a/cmd/cli/cmd/policy/apply.go b/cmd/cli/cmd/policy/apply.go index 247e379f3..08afc065f 100644 --- a/cmd/cli/cmd/policy/apply.go +++ b/cmd/cli/cmd/policy/apply.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" ) +// NewApply returns a cobra.Command for applying Capact Global policy on a Capact environment. func NewApply() *cobra.Command { var opts policy.ApplyOptions diff --git a/cmd/cli/cmd/policy/edit.go b/cmd/cli/cmd/policy/edit.go index fb70e9488..a4798c33a 100644 --- a/cmd/cli/cmd/policy/edit.go +++ b/cmd/cli/cmd/policy/edit.go @@ -9,6 +9,8 @@ import ( "github.com/spf13/cobra" ) +// NewEdit returns a cobra.Command for interactive editing +// of Capact Global policy on a Capact environment. func NewEdit() *cobra.Command { cmd := &cobra.Command{ Use: "edit", diff --git a/cmd/cli/cmd/policy/get.go b/cmd/cli/cmd/policy/get.go index 4e00e5e42..c09a4e19b 100644 --- a/cmd/cli/cmd/policy/get.go +++ b/cmd/cli/cmd/policy/get.go @@ -9,6 +9,7 @@ import ( "github.com/spf13/cobra" ) +// NewGet return a cobra.Command for getting the Capact Global policy on a Capact environment. func NewGet() *cobra.Command { resourcePrinter := printer.NewForResource(os.Stdout, printer.WithJSON(), printer.WithYAML(), printer.WithDefaultOutputFormat(printer.YAMLFormat)) diff --git a/cmd/cli/cmd/policy/policy.go b/cmd/cli/cmd/policy/policy.go index 2032e29fe..530248d1d 100644 --- a/cmd/cli/cmd/policy/policy.go +++ b/cmd/cli/cmd/policy/policy.go @@ -2,6 +2,7 @@ package policy import "github.com/spf13/cobra" +// NewCmd returns a cobra.Command for policy related operations. func NewCmd() *cobra.Command { root := &cobra.Command{ Use: "policy", diff --git a/cmd/cli/cmd/root.go b/cmd/cli/cmd/root.go index fdd6eca09..7ca86f2ec 100644 --- a/cmd/cli/cmd/root.go +++ b/cmd/cli/cmd/root.go @@ -22,6 +22,7 @@ var ( configPath string ) +// NewRoot returns a root cobra.Command for the whole Capact CLI. func NewRoot() *cobra.Command { rootCmd := &cobra.Command{ Use: cli.Name, diff --git a/cmd/cli/cmd/typeinstance/apply.go b/cmd/cli/cmd/typeinstance/apply.go index a66f931db..c12c62984 100644 --- a/cmd/cli/cmd/typeinstance/apply.go +++ b/cmd/cli/cmd/typeinstance/apply.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "capact.io/capact/internal/cli" "capact.io/capact/internal/cli/client" @@ -23,6 +24,7 @@ type applyOptions struct { TypeInstancesFiles []string } +// NewApply returns a cobra.Command for applying a TypeInstance on a Local Hub. func NewApply() *cobra.Command { var opts applyOptions @@ -95,7 +97,7 @@ func typeInstancesFromFile(typeInstancesFiles []string) ([]gqllocalapi.UpdateTyp } func loadUpdateTypeInstanceFromFile(path string) ([]gqllocalapi.UpdateTypeInstancesInput, error) { - f, err := os.Open(path) + f, err := os.Open(filepath.Clean(path)) if err != nil { return nil, errors.Wrap(err, "cannot open file with TypeInstance input") } diff --git a/cmd/cli/cmd/typeinstance/create.go b/cmd/cli/cmd/typeinstance/create.go index c21179a14..1198497d8 100644 --- a/cmd/cli/cmd/typeinstance/create.go +++ b/cmd/cli/cmd/typeinstance/create.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "os" + "path/filepath" "capact.io/capact/internal/cli" "capact.io/capact/internal/cli/client" @@ -23,6 +24,7 @@ type createOptions struct { TypeInstancesFiles []string } +// NewCreate returns a cobra.Command for creating a TypeInstance on a Local Hub. func NewCreate() *cobra.Command { var opts createOptions @@ -112,7 +114,7 @@ func createTI(ctx context.Context, opts createOptions, resourcePrinter *printer. } func loadCreateTypeInstanceFromFile(path string) (*gqllocalapi.CreateTypeInstancesInput, error) { - f, err := os.Open(path) + f, err := os.Open(filepath.Clean(path)) if err != nil { return nil, errors.Wrap(err, "cannot open file with TypeInstance input") } diff --git a/cmd/cli/cmd/typeinstance/delete.go b/cmd/cli/cmd/typeinstance/delete.go index c087741f8..5cc2ea735 100644 --- a/cmd/cli/cmd/typeinstance/delete.go +++ b/cmd/cli/cmd/typeinstance/delete.go @@ -15,6 +15,7 @@ import ( "github.com/spf13/cobra" ) +// NewDelete returns a cobra.Command for deleting a TypeInstance on a Local Hub. func NewDelete() *cobra.Command { cmd := &cobra.Command{ Use: "delete TYPE_INSTANCE_ID...", diff --git a/cmd/cli/cmd/typeinstance/edit.go b/cmd/cli/cmd/typeinstance/edit.go index dbe8b487e..79b72ded9 100644 --- a/cmd/cli/cmd/typeinstance/edit.go +++ b/cmd/cli/cmd/typeinstance/edit.go @@ -21,6 +21,7 @@ type editOptions struct { EditTypeInstanceID string } +// NewEdit returns a cobra.Command for editing a TypeInstance on a Local Hub. func NewEdit() *cobra.Command { var opts editOptions diff --git a/cmd/cli/cmd/typeinstance/get.go b/cmd/cli/cmd/typeinstance/get.go index 258be55fc..32a724d3f 100644 --- a/cmd/cli/cmd/typeinstance/get.go +++ b/cmd/cli/cmd/typeinstance/get.go @@ -19,13 +19,17 @@ import ( const yamlFileSeparator = "---" +// GetOptions is used to store the configuration flags for the Get command. type GetOptions struct { RequestedTypeInstancesIDs []string ExportToUpdateFormat bool } +// ErrTableFormatWithExportFlag is used to inform that --export flag was used with table output, +// which is not supported. var ErrTableFormatWithExportFlag = fmt.Errorf("cannot use --export with table output") +// NewGet returns a cobra.Command for getting TypeInstances on a Local Hub. func NewGet() *cobra.Command { var opts GetOptions out := os.Stdout diff --git a/cmd/cli/cmd/typeinstance/type_instance.go b/cmd/cli/cmd/typeinstance/type_instance.go index 9f13a0100..9e39c70c6 100644 --- a/cmd/cli/cmd/typeinstance/type_instance.go +++ b/cmd/cli/cmd/typeinstance/type_instance.go @@ -9,6 +9,7 @@ const ( decodeBufferSize = 4096 ) +// NewCmd returns a cobra.Command for TypeInstance related operations. func NewCmd() *cobra.Command { root := &cobra.Command{ Use: "typeinstance", diff --git a/cmd/cli/cmd/upgrade.go b/cmd/cli/cmd/upgrade.go index 8f8829b81..fe5e743d1 100644 --- a/cmd/cli/cmd/upgrade.go +++ b/cmd/cli/cmd/upgrade.go @@ -12,6 +12,7 @@ import ( "github.com/spf13/cobra" ) +// NewUpgrade returns a cobra.Command for upgrading a Capact environment. func NewUpgrade() *cobra.Command { var opts upgrade.Options diff --git a/cmd/cli/cmd/validate.go b/cmd/cli/cmd/validate.go index 75fb3a462..f14116ab2 100644 --- a/cmd/cli/cmd/validate.go +++ b/cmd/cli/cmd/validate.go @@ -13,6 +13,7 @@ import ( "github.com/spf13/cobra" ) +// NewValidate returns a cobra.Command for validating Hub Manifests. func NewValidate() *cobra.Command { schemaProvider := schema.Provider{} diff --git a/cmd/cli/cmd/version.go b/cmd/cli/cmd/version.go index 773b1b9ea..2e17af2c2 100644 --- a/cmd/cli/cmd/version.go +++ b/cmd/cli/cmd/version.go @@ -33,6 +33,7 @@ var ( ` ) +// NewVersion returns a cobra.Command for showing Capact CLI binary information. func NewVersion() *cobra.Command { cmd := &cobra.Command{ Use: "version", diff --git a/cmd/cloudsql-runner/main.go b/cmd/cloudsql-runner/main.go index 0ae5d36c6..895350881 100644 --- a/cmd/cloudsql-runner/main.go +++ b/cmd/cloudsql-runner/main.go @@ -14,6 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/manager/signals" ) +// Config holds the input parameters for the CloudSQL runner binary. type Config struct { GCP cloudsql.GCPConfig Output cloudsql.OutputConfig diff --git a/cmd/gateway/main.go b/cmd/gateway/main.go index 401502e83..3b401cc03 100644 --- a/cmd/gateway/main.go +++ b/cmd/gateway/main.go @@ -39,6 +39,7 @@ type Config struct { Auth BasicAuth } +// BasicAuth holds the credentials for HTTP basic access authentication. type BasicAuth struct { Username string `envconfig:"default=graphql"` Password string diff --git a/cmd/k8s-engine/main.go b/cmd/k8s-engine/main.go index 816fef202..b8e91bf69 100644 --- a/cmd/k8s-engine/main.go +++ b/cmd/k8s-engine/main.go @@ -38,8 +38,8 @@ var ( ) const ( - GraphQLServerName = "engine-graphql" - PolicyServiceName = "policy-svc" + graphQLServerName = "engine-graphql" + policyServiceName = "policy-svc" ) // Config holds application related configuration @@ -112,7 +112,7 @@ func main() { exitOnError(err, "while creating Argo client") actionValidator := validate.NewActionValidator(wfCli) - policySvcLogger := logger.Named(PolicyServiceName) + policySvcLogger := logger.Named(policyServiceName) policyService := policy.NewService(policySvcLogger, mgr.GetClient(), cfg.Policy) actionSvc := controller.NewActionService( @@ -141,12 +141,12 @@ func main() { k8sCli, err := client.New(k8sCfg, client.Options{Scheme: scheme}) exitOnError(err, "while creating K8s client") - gqlLogger := logger.Named(GraphQLServerName) + gqlLogger := logger.Named(graphQLServerName) execSchema := graphql.NewExecutableSchema(graphql.Config{ Resolvers: domaingraphql.NewRootResolver(gqlLogger, k8sCli, policyService), }) - gqlSrv := gqlServer(gqlLogger, execSchema, cfg.GraphQLAddr, GraphQLServerName) + gqlSrv := gqlServer(gqlLogger, execSchema, cfg.GraphQLAddr, graphQLServerName) err = mgr.Add(gqlSrv) exitOnError(err, "while adding GraphQL server") diff --git a/cmd/populator/cmd/register/capact_installation.go b/cmd/populator/cmd/register/capact_installation.go index bfcb0a609..041bf65ec 100644 --- a/cmd/populator/cmd/register/capact_installation.go +++ b/cmd/populator/cmd/register/capact_installation.go @@ -8,6 +8,7 @@ import ( "capact.io/capact/internal/installation" ) +// NewCapactInstallation returns a cobra.Command for populating Capact installation TypeInstances // TODO: support configuration both via flags and environment variables func NewCapactInstallation(cliName string) *cobra.Command { return &cobra.Command{ diff --git a/cmd/populator/cmd/register/ocf_manifests.go b/cmd/populator/cmd/register/ocf_manifests.go index c24c2a266..885bcec7c 100644 --- a/cmd/populator/cmd/register/ocf_manifests.go +++ b/cmd/populator/cmd/register/ocf_manifests.go @@ -24,6 +24,7 @@ import ( "go.uber.org/zap" ) +// NewOCFManifests returns a cobra.Command for populating manifests into a Neo4j database. // TODO: support configuration both via flags and environment variables func NewOCFManifests(cliName string) *cobra.Command { return &cobra.Command{ diff --git a/cmd/populator/cmd/register/register.go b/cmd/populator/cmd/register/register.go index 686f8e63c..201d2bbb4 100644 --- a/cmd/populator/cmd/register/register.go +++ b/cmd/populator/cmd/register/register.go @@ -4,6 +4,7 @@ import ( "github.com/spf13/cobra" ) +// NewRegister returns a cobra.Command subcommand for registering Capact resources. func NewRegister(cliName string) *cobra.Command { hub := &cobra.Command{ Use: "register", diff --git a/cmd/populator/cmd/root.go b/cmd/populator/cmd/root.go index b11a8162d..ec47b9402 100644 --- a/cmd/populator/cmd/root.go +++ b/cmd/populator/cmd/root.go @@ -8,6 +8,7 @@ import ( "github.com/spf13/cobra" ) +// NewRoot returns a root cobra.Command for the db populator. func NewRoot(cliName string) *cobra.Command { rootCmd := &cobra.Command{ Use: cliName, diff --git a/cmd/populator/main.go b/cmd/populator/main.go index 915507747..fcd1536c5 100644 --- a/cmd/populator/main.go +++ b/cmd/populator/main.go @@ -6,10 +6,10 @@ import ( "capact.io/capact/cmd/populator/cmd" ) -const CLIName = "populator" +const cliName = "populator" func main() { - if err := cmd.NewRoot(CLIName).Execute(); err != nil { + if err := cmd.NewRoot(cliName).Execute(); err != nil { os.Exit(1) } } diff --git a/docs/investigation/graph-db/dgraph/app/internal/client/client.go b/docs/investigation/graph-db/dgraph/app/internal/client/client.go index a06efd0d4..903a61631 100644 --- a/docs/investigation/graph-db/dgraph/app/internal/client/client.go +++ b/docs/investigation/graph-db/dgraph/app/internal/client/client.go @@ -23,4 +23,3 @@ func New() (*dgo.Dgraph, error) { api.NewDgraphClient(d), ), nil } - diff --git a/docs/investigation/graph-db/dgraph/app/internal/dso.go b/docs/investigation/graph-db/dgraph/app/internal/dso.go index def0d2ce8..f912a076b 100644 --- a/docs/investigation/graph-db/dgraph/app/internal/dso.go +++ b/docs/investigation/graph-db/dgraph/app/internal/dso.go @@ -47,7 +47,7 @@ type ImplementationRevision struct { type ImplementationSpec struct { Implements []InterfaceReference `mapstructure:"ImplementationSpec.implements"` - Requires [] TypeReference `mapstructure:"ImplementationSpec.requires"` + Requires []TypeReference `mapstructure:"ImplementationSpec.requires"` } type TypeReference struct { @@ -64,7 +64,7 @@ type InterfaceReference struct { type DecodeInterfaceQuery struct { Path string Revisions []struct { - Uid string + Uid string Rev string } } diff --git a/docs/investigation/graph-db/grakn/helpers.go b/docs/investigation/graph-db/grakn/helpers.go index 415fab73d..64c0596ce 100644 --- a/docs/investigation/graph-db/grakn/helpers.go +++ b/docs/investigation/graph-db/grakn/helpers.go @@ -4,9 +4,9 @@ import ( "context" "time" + grakn "capact.io/capact/poc/graph-db/grakn/go-grakn/gograkn/session" "github.com/99designs/gqlgen/graphql" grpc "google.golang.org/grpc" - grakn "capact.io/capact/poc/graph-db/grakn/go-grakn/gograkn/session" ) func GetPreloads(ctx context.Context) []string { diff --git a/docs/investigation/graph-db/grakn/resolver.go b/docs/investigation/graph-db/grakn/resolver.go index 95a9f2be4..98abff658 100644 --- a/docs/investigation/graph-db/grakn/resolver.go +++ b/docs/investigation/graph-db/grakn/resolver.go @@ -48,7 +48,7 @@ func toQuery(fields []string) string { query += ", has name $ifaceName" } - // this would go to a new funciton which would get implementation query + // this would go to a new function which would get implementation query if _, ok := mapped["interfaces.revisions.implementations"]; ok { query += ";$impl isa implementation" relations += ";$impl-iface (defines: $iface, implements: $impl) isa implementator" diff --git a/docs/investigation/graph-db/neo4j-gogm/graphql/models.go b/docs/investigation/graph-db/neo4j-gogm/graphql/models.go index f0a330413..5d5e2ad33 100644 --- a/docs/investigation/graph-db/neo4j-gogm/graphql/models.go +++ b/docs/investigation/graph-db/neo4j-gogm/graphql/models.go @@ -2,9 +2,10 @@ package graphql import ( "fmt" - "github.com/mindstand/gogm" "io" "strconv" + + "github.com/mindstand/gogm" ) // inputs @@ -66,18 +67,18 @@ type TypeInstance interface { type GenericMetadata struct { gogm.BaseNode `json:"-"` - InterfaceGroup *InterfaceGroup `json:"-" gogm:"direction=incoming;relationship=describedWith"` + InterfaceGroup *InterfaceGroup `json:"-" gogm:"direction=incoming;relationship=describedWith"` InterfaceRevision *InterfaceRevision `json:"-" gogm:"direction=incoming;relationship=describedWith"` Name string `json:"name" gogm:"name=name"` - Prefix string `json:"prefix" gogm:"name=prefix"` - Path string `json:"path" gogm:"name=path"` - DisplayName string `json:"displayName" gogm:"name=displayName"` + Prefix string `json:"prefix" gogm:"name=prefix"` + Path string `json:"path" gogm:"name=path"` + DisplayName string `json:"displayName" gogm:"name=displayName"` Description string `json:"description" gogm:"name=description"` Maintainers []*Maintainer `json:"maintainers" gogm:"direction=outgoing;relationship=maintainedBy"` - DocumentationURL string `json:"documentationURL" gogm:"name=documentationURL"` - SupportURL string `json:"supportURL" gogm:"name=supportURL"` - IconURL string `json:"iconURL" gogm:"name=iconURL"` + DocumentationURL string `json:"documentationURL" gogm:"name=documentationURL"` + SupportURL string `json:"supportURL" gogm:"name=supportURL"` + IconURL string `json:"iconURL" gogm:"name=iconURL"` } func (GenericMetadata) IsMetadataBaseFields() {} @@ -214,7 +215,7 @@ type Interface struct { Path string `json:"path" gogm:"name=path"` //LatestRevision *InterfaceRevision `json:"latestRevision" gogm:"direction=outgoing;relationship=latest_revision"` //Revision *InterfaceRevision `json:"revision" gogm:"direction=outgoing;relationship=revision"` - Revisions []*InterfaceRevision `json:"revisions" gogm:"direction=outgoing;relationship=revision"` + Revisions []*InterfaceRevision `json:"revisions" gogm:"direction=outgoing;relationship=revision"` } type InterfaceGroup struct { @@ -248,7 +249,7 @@ type InterfaceReference struct { type InterfaceRevision struct { gogm.BaseNode `json:"-"` - Interface *Interface `json:"-" gogm:"direction=incoming;relationship=revision"` + Interface *Interface `json:"-" gogm:"direction=incoming;relationship=revision"` Metadata *GenericMetadata `json:"metadata" gogm:"direction=outgoing;relationship=describedWith"` Revision string `json:"revision" gogm:"name=revision"` @@ -271,7 +272,7 @@ type Maintainer struct { GenericMetadata *GenericMetadata `json:"-" gogm:"direction=incoming;relationship=maintainedBy"` Name string `json:"name" gogm:"name=name"` - Email string `json:"email" gogm:"name=email"` + Email string `json:"email" gogm:"name=email"` URL string `json:"url" gogm:"name=url"` } diff --git a/docs/investigation/graph-db/neo4j-gogm/graphql/resolver.go b/docs/investigation/graph-db/neo4j-gogm/graphql/resolver.go index 54abc4089..388922ef2 100644 --- a/docs/investigation/graph-db/neo4j-gogm/graphql/resolver.go +++ b/docs/investigation/graph-db/neo4j-gogm/graphql/resolver.go @@ -6,7 +6,7 @@ import "github.com/mindstand/gogm" // // It serves as dependency injection for your app, add any dependencies you require here. -type Resolver struct{ +type Resolver struct { sess *gogm.Session } diff --git a/docs/investigation/graph-db/neo4j-gogm/graphql/schema.resolvers.go b/docs/investigation/graph-db/neo4j-gogm/graphql/schema.resolvers.go index 76cdccd21..d582c93cb 100644 --- a/docs/investigation/graph-db/neo4j-gogm/graphql/schema.resolvers.go +++ b/docs/investigation/graph-db/neo4j-gogm/graphql/schema.resolvers.go @@ -5,8 +5,9 @@ package graphql import ( "context" - go_cypherdsl "github.com/mindstand/go-cypherdsl" "log" + + go_cypherdsl "github.com/mindstand/go-cypherdsl" ) func (r *queryResolver) InterfaceGroups(ctx context.Context, filter *InterfaceGroupFilter) ([]*InterfaceGroup, error) { @@ -20,7 +21,6 @@ func (r *queryResolver) InterfaceGroups(ctx context.Context, filter *InterfaceGr return items, nil } - // // Not used resolvers - uncomment in `config.yaml` custom resolvers to play around // @@ -36,8 +36,7 @@ func (r *interfaceResolver) Revision(ctx context.Context, obj *Interface, revisi }).And(&go_cypherdsl.ConditionConfig{}) // TODO: How to build the condition? var items []*InterfaceRevision - err := r.sess.LoadAllDepthFilter(&items, 20, condition, map[string]interface{}{ - }) + err := r.sess.LoadAllDepthFilter(&items, 20, condition, map[string]interface{}{}) if err != nil { log.Println(err) return nil, err diff --git a/docs/investigation/graph-db/neo4j-gogm/main.go b/docs/investigation/graph-db/neo4j-gogm/main.go index 35b5515bc..c8fd3d949 100644 --- a/docs/investigation/graph-db/neo4j-gogm/main.go +++ b/docs/investigation/graph-db/neo4j-gogm/main.go @@ -1,12 +1,13 @@ package main import ( - "github.com/99designs/gqlgen/graphql/handler" - "github.com/99designs/gqlgen/graphql/playground" - "github.com/mindstand/gogm" "log" "net/http" + "capact.io/capact/poc/graph-db/neo4j-gogm/graphql" + "github.com/99designs/gqlgen/graphql/handler" + "github.com/99designs/gqlgen/graphql/playground" + "github.com/mindstand/gogm" ) func main() { @@ -67,39 +68,39 @@ func mustLoadModels(sess *gogm.Session) { interfaceGroups := []*graphql.InterfaceGroup{ { - Metadata: &graphql.GenericMetadata{ - Name: "foo", - Prefix: "prefix", - Path: "path", - DisplayName: "Foo", - Description: "Foo", - Maintainers: []*graphql.Maintainer{ + Metadata: &graphql.GenericMetadata{ + Name: "foo", + Prefix: "prefix", + Path: "path", + DisplayName: "Foo", + Description: "Foo", + Maintainers: []*graphql.Maintainer{ { - Name: "Maitainer 1", - Email: "foo@bar.com", + Name: "Maitainer 1", + Email: "foo@bar.com", }, }, }, - Signature: &graphql.Signature{ - Och: "och1", + Signature: &graphql.Signature{ + Och: "och1", }, Interfaces: []*graphql.Interface{ { - Name: "interface 1", - Prefix: "prefix int", - Path: "int path", - Revisions: []*graphql.InterfaceRevision{ + Name: "interface 1", + Prefix: "prefix int", + Path: "int path", + Revisions: []*graphql.InterfaceRevision{ { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "Revision 1", }, - Revision: "0.0.1", + Revision: "0.0.1", }, { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "Revision 2", }, - Revision: "0.0.2", + Revision: "0.0.2", }, }, }, @@ -107,62 +108,62 @@ func mustLoadModels(sess *gogm.Session) { }, { - Metadata: &graphql.GenericMetadata{ - Name: "bar", - Prefix: "prefix", - Path: "path", - DisplayName: "Bar", - Description: "Bar", - Maintainers: []*graphql.Maintainer{ + Metadata: &graphql.GenericMetadata{ + Name: "bar", + Prefix: "prefix", + Path: "path", + DisplayName: "Bar", + Description: "Bar", + Maintainers: []*graphql.Maintainer{ { - Name: "Maitainer 1", - Email: "foo@bar.com", + Name: "Maitainer 1", + Email: "foo@bar.com", }, { - Name: "Maitainer 1", - Email: "bar@bar.com", + Name: "Maitainer 1", + Email: "bar@bar.com", }, }, }, - Signature: &graphql.Signature{ - Och: "och2", + Signature: &graphql.Signature{ + Och: "och2", }, Interfaces: []*graphql.Interface{ { - Name: "bar interface 1", - Prefix: "prefix int", - Path: "int path", - Revisions: []*graphql.InterfaceRevision{ + Name: "bar interface 1", + Prefix: "prefix int", + Path: "int path", + Revisions: []*graphql.InterfaceRevision{ { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "bar 1 Revision 1", }, - Revision: "0.0.1", + Revision: "0.0.1", }, { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "bar 1 Revision 2", }, - Revision: "0.0.2", + Revision: "0.0.2", }, }, }, { - Name: "bar interface 2", - Prefix: "prefix int", - Path: "int path", - Revisions: []*graphql.InterfaceRevision{ + Name: "bar interface 2", + Prefix: "prefix int", + Path: "int path", + Revisions: []*graphql.InterfaceRevision{ { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "bar 2 Revision 1", }, - Revision: "0.0.1", + Revision: "0.0.1", }, { - Metadata: &graphql.GenericMetadata{ + Metadata: &graphql.GenericMetadata{ Name: "bar 2 Revision 2", }, - Revision: "0.0.2", + Revision: "0.0.2", }, }, }, @@ -170,7 +171,6 @@ func mustLoadModels(sess *gogm.Session) { }, } - for _, iG := range interfaceGroups { err := sess.SaveDepth(iG, 10) if err != nil { diff --git a/docs/investigation/workflow-rendering/main.go b/docs/investigation/workflow-rendering/main.go index e4d552497..b1feea5f2 100644 --- a/docs/investigation/workflow-rendering/main.go +++ b/docs/investigation/workflow-rendering/main.go @@ -3,13 +3,14 @@ package main import ( "flag" "fmt" - "github.com/ghodss/yaml" - "github.com/mitchellh/mapstructure" "io/ioutil" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "log" + "capact.io/capact/docs/investigation/workflow-rendering/render" "capact.io/capact/pkg/engine/k8s/api/v1alpha1" + "github.com/ghodss/yaml" + "github.com/mitchellh/mapstructure" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) type renderInput struct { diff --git a/docs/investigation/workflow-rendering/render/manifests.go b/docs/investigation/workflow-rendering/render/manifests.go index af2672964..3998b1549 100644 --- a/docs/investigation/workflow-rendering/render/manifests.go +++ b/docs/investigation/workflow-rendering/render/manifests.go @@ -7,9 +7,9 @@ import ( "os" "path/filepath" - "github.com/pkg/errors" "capact.io/capact/pkg/engine/k8s/api/v1alpha1" "capact.io/capact/pkg/sdk/apis/0.0.1/types" + "github.com/pkg/errors" "sigs.k8s.io/yaml" ) diff --git a/docs/investigation/workflow-rendering/render/render.go b/docs/investigation/workflow-rendering/render/render.go index b4cf44601..19dff2638 100644 --- a/docs/investigation/workflow-rendering/render/render.go +++ b/docs/investigation/workflow-rendering/render/render.go @@ -6,13 +6,13 @@ import ( "regexp" "strings" + "capact.io/capact/pkg/engine/k8s/api/v1alpha1" + "capact.io/capact/pkg/sdk/apis/0.0.1/types" "github.com/Knetic/govaluate" wfv1 "github.com/argoproj/argo/pkg/apis/workflow/v1alpha1" "github.com/ghodss/yaml" "github.com/pkg/errors" apiv1 "k8s.io/api/core/v1" - "capact.io/capact/pkg/engine/k8s/api/v1alpha1" - "capact.io/capact/pkg/sdk/apis/0.0.1/types" ) type Workflow struct { diff --git a/hack/lint.sh b/hack/lint.sh index 3dd0e878a..6e1f4ce8f 100755 --- a/hack/lint.sh +++ b/hack/lint.sh @@ -15,7 +15,7 @@ TMP_DIR=$(mktemp -d) readonly TMP_DIR readonly CURRENT_DIR readonly REPO_ROOT_DIR -readonly GOLANGCI_LINT_VERSION="v1.31.0" +readonly GOLANGCI_LINT_VERSION="v1.41.1" LINT_TIMEOUT=${LINT_TIMEOUT:-5m} SKIP_DEPS_INSTALLATION=${SKIP_DEPS_INSTALLATION:-true} diff --git a/pkg/argo-actions/actions.go b/pkg/argo-actions/actions.go index 414797a1e..16c56a51e 100644 --- a/pkg/argo-actions/actions.go +++ b/pkg/argo-actions/actions.go @@ -2,6 +2,9 @@ package argoactions import "context" +// Action is a interface with the Do method. +// The Do(context.Context) error method is used to execute an operation +// on the TypeInstances in the Local Hub. type Action interface { Do(context.Context) error } diff --git a/pkg/argo-actions/download_type_instances.go b/pkg/argo-actions/download_type_instances.go index d59c7d21f..947e97844 100644 --- a/pkg/argo-actions/download_type_instances.go +++ b/pkg/argo-actions/download_type_instances.go @@ -11,19 +11,24 @@ import ( "sigs.k8s.io/yaml" ) +// DownloadAction represents the download TypeInstance action. const DownloadAction = "DownloadAction" +// DownloadConfig stores the configuration parameters for the download TypeInstance action. type DownloadConfig struct { ID string Path string } +// Download implements the Action interface. +// It is used to download a TypeInstance from the Local Hub and save on local filesystem. type Download struct { log *zap.Logger cfg []DownloadConfig client *local.Client } +// NewDownloadAction returns a new Download instance. func NewDownloadAction(log *zap.Logger, client *local.Client, cfg []DownloadConfig) Action { return &Download{ log: log, @@ -32,6 +37,7 @@ func NewDownloadAction(log *zap.Logger, client *local.Client, cfg []DownloadConf } } +// Do downloads a TypeInstance from the Local Hub. func (d *Download) Do(ctx context.Context) error { for _, config := range d.cfg { d.log.Info("Downloading TypeInstance", zap.String("ID", config.ID), zap.String("Path", config.Path)) diff --git a/pkg/argo-actions/errors.go b/pkg/argo-actions/errors.go index c38ad8e0e..c878848af 100644 --- a/pkg/argo-actions/errors.go +++ b/pkg/argo-actions/errors.go @@ -2,10 +2,12 @@ package argoactions import "github.com/pkg/errors" +// ErrMissingTypeInstanceValue returns an error indicating missing TypeInstance value file. func ErrMissingTypeInstanceValue(typeInstanceName string) error { return errors.Errorf("missing file with values for TypeInstances %s", typeInstanceName) } +// ErrMissingResourceVersion returns an error indicating missing resourceVersion. func ErrMissingResourceVersion() error { return errors.Errorf("resourceVersion is missing") } diff --git a/pkg/argo-actions/update_type_instances.go b/pkg/argo-actions/update_type_instances.go index c849e1480..faa30f87e 100644 --- a/pkg/argo-actions/update_type_instances.go +++ b/pkg/argo-actions/update_type_instances.go @@ -4,6 +4,7 @@ import ( "context" "io/ioutil" "path" + "path/filepath" graphqllocal "capact.io/capact/pkg/hub/api/graphql/local" "capact.io/capact/pkg/hub/client/local" @@ -12,19 +13,24 @@ import ( "sigs.k8s.io/yaml" ) +// UpdateAction represents the update TypeInstancess action. const UpdateAction = "UpdateAction" +// UpdateConfig stores the configuration parameters for update TypeInstances action. type UpdateConfig struct { PayloadFilepath string TypeInstancesDir string } +// Update implements the Action interface. +// It is used to update existing TypeInstances in the Local Hub. type Update struct { log *zap.Logger client *local.Client cfg UpdateConfig } +// NewUpdateAction returns a new Update instance. func NewUpdateAction(log *zap.Logger, client *local.Client, cfg UpdateConfig) Action { return &Update{ log: log, @@ -33,6 +39,7 @@ func NewUpdateAction(log *zap.Logger, client *local.Client, cfg UpdateConfig) Ac } } +// Do updates existing TypeInstances in the Local Hub. func (u *Update) Do(ctx context.Context) error { payloadBytes, err := ioutil.ReadFile(u.cfg.PayloadFilepath) if err != nil { @@ -59,7 +66,7 @@ func (u *Update) Do(ctx context.Context) error { for _, f := range files { path := path.Join(u.cfg.TypeInstancesDir, f.Name()) - typeInstanceValueBytes, err := ioutil.ReadFile(path) + typeInstanceValueBytes, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return errors.Wrapf(err, "while reading TypeInstance value file %s", path) } diff --git a/pkg/argo-actions/upload_type_instances.go b/pkg/argo-actions/upload_type_instances.go index 7bd025fc5..0812bf79c 100644 --- a/pkg/argo-actions/upload_type_instances.go +++ b/pkg/argo-actions/upload_type_instances.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io/ioutil" + "path/filepath" graphqllocal "capact.io/capact/pkg/hub/api/graphql/local" "capact.io/capact/pkg/hub/client/local" @@ -12,19 +13,24 @@ import ( "sigs.k8s.io/yaml" ) +// UploadAction represents the upload TypeInstances action. const UploadAction = "UploadAction" +// UploadConfig stores the configuration parameters for the upload TypeInstances action. type UploadConfig struct { PayloadFilepath string TypeInstancesDir string } +// Upload implements the Action interface. +// It is used to upload TypeInstances to the Local Hub. type Upload struct { log *zap.Logger client *local.Client cfg UploadConfig } +// NewUploadAction returns a new Upload instance. func NewUploadAction(log *zap.Logger, client *local.Client, cfg UploadConfig) Action { return &Upload{ log: log, @@ -33,6 +39,7 @@ func NewUploadAction(log *zap.Logger, client *local.Client, cfg UploadConfig) Ac } } +// Do uploads TypeInstances to the Local Hub. func (u *Upload) Do(ctx context.Context) error { payloadBytes, err := ioutil.ReadFile(u.cfg.PayloadFilepath) if err != nil { @@ -59,7 +66,7 @@ func (u *Upload) Do(ctx context.Context) error { for _, f := range files { path := fmt.Sprintf("%s/%s", u.cfg.TypeInstancesDir, f.Name()) - typeInstanceValueBytes, err := ioutil.ReadFile(path) + typeInstanceValueBytes, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return errors.Wrapf(err, "while reading TypeInstance value file %s", path) } diff --git a/pkg/engine/api/graphql/json.go b/pkg/engine/api/graphql/json.go index f125a25de..0142b30db 100644 --- a/pkg/engine/api/graphql/json.go +++ b/pkg/engine/api/graphql/json.go @@ -10,8 +10,10 @@ import ( "log" ) +// JSON represents a GraphQL scalar, which holds a JSON string. type JSON string +// UnmarshalGQL unmarshals the GraphQL input to JSON. func (j *JSON) UnmarshalGQL(v interface{}) error { val, err := graphqlutil.ScalarToString(v) if err != nil { @@ -27,6 +29,7 @@ func (j *JSON) UnmarshalGQL(v interface{}) error { return nil } +// MarshalGQL writes the JSON to the provided writer. func (j JSON) MarshalGQL(w io.Writer) { _, err := io.WriteString(w, strconv.Quote(string(j))) if err != nil { diff --git a/pkg/engine/api/graphql/policy.go b/pkg/engine/api/graphql/policy.go index 0c854c2c9..51f036186 100644 --- a/pkg/engine/api/graphql/policy.go +++ b/pkg/engine/api/graphql/policy.go @@ -2,11 +2,14 @@ package graphql // The types had to be moved out from generated models to add `omitempty` tags. +// PolicyRule represents a single policy rule. type PolicyRule struct { ImplementationConstraints *PolicyRuleImplementationConstraints `json:"implementationConstraints,omitempty"` Inject *PolicyRuleInjectData `json:"inject,omitempty"` } +// PolicyRuleImplementationConstraints represent the constraints, which must be meet by an Implementation, +// so the rule will match. type PolicyRuleImplementationConstraints struct { // Refers a specific required TypeInstance by path and optional revision. Requires []*ManifestReferenceWithOptionalRevision `json:"requires,omitempty"` @@ -16,6 +19,7 @@ type PolicyRuleImplementationConstraints struct { Path *string `json:"path,omitempty"` } +// ManifestReferenceWithOptionalRevision is used to represent a manifest reference with an optional revision property. type ManifestReferenceWithOptionalRevision struct { Path string `json:"path"` Revision *string `json:"revision,omitempty"` diff --git a/pkg/engine/api/graphql/timestamp.go b/pkg/engine/api/graphql/timestamp.go index 8be71bcc2..9a5811d32 100644 --- a/pkg/engine/api/graphql/timestamp.go +++ b/pkg/engine/api/graphql/timestamp.go @@ -9,10 +9,12 @@ import ( "capact.io/capact/internal/graphqlutil" ) +// Timestamp is a GraphQL scalar, which represents time. It can be used like the Go time.Time struct. type Timestamp struct { time.Time } +// UnmarshalGQL unmarshals the provided GraphQL scalar to this Timestamp struct. The scalar must be a string representing time formatted in RFC3339. func (t *Timestamp) UnmarshalGQL(v interface{}) error { tmpStr, err := graphqlutil.ScalarToString(v) if err != nil { @@ -28,6 +30,7 @@ func (t *Timestamp) UnmarshalGQL(v interface{}) error { return nil } +// MarshalGQL writes the RFC3339 formatted Timestamp to the provided writer. func (t Timestamp) MarshalGQL(w io.Writer) { _, err := w.Write([]byte(strconv.Quote(t.Format(time.RFC3339)))) if err != nil { diff --git a/pkg/engine/k8s/policy/error.go b/pkg/engine/k8s/policy/error.go index 3dc326892..85bfe16d3 100644 --- a/pkg/engine/k8s/policy/error.go +++ b/pkg/engine/k8s/policy/error.go @@ -5,6 +5,7 @@ import ( "strings" ) +// UnsupportedAPIVersionError indicates that the Policy APIVersion is not supported. type UnsupportedAPIVersionError struct { constraintErrors []error } @@ -17,6 +18,7 @@ func (e UnsupportedAPIVersionError) Error() string { return fmt.Sprintf("unsupported API version: %s", strings.Join(errMsgs, ", ")) } +// NewUnsupportedAPIVersionError returns a new UnsupportedAPIVersionError error. func NewUnsupportedAPIVersionError(constraintErrors []error) *UnsupportedAPIVersionError { return &UnsupportedAPIVersionError{constraintErrors: constraintErrors} } diff --git a/pkg/engine/k8s/policy/from_yaml.go b/pkg/engine/k8s/policy/from_yaml.go index c52d30b25..96e72a613 100644 --- a/pkg/engine/k8s/policy/from_yaml.go +++ b/pkg/engine/k8s/policy/from_yaml.go @@ -11,8 +11,10 @@ import ( const supportedAPIVersionConstraintString = "^0.2" +// SupportedAPIVersionMap stores the supported API versions of the policy. type SupportedAPIVersionMap map[string]struct{} +// ToStringSlice returns a string slice of the supported API versions. func (m SupportedAPIVersionMap) ToStringSlice() []string { var strSlice []string for key := range m { @@ -23,6 +25,8 @@ func (m SupportedAPIVersionMap) ToStringSlice() []string { return strSlice } +// FromYAMLString reads the Policy from the input string. +// It will return an error, if the Policy APIVersion is not supported. func FromYAMLString(in string) (Policy, error) { bytes := []byte(in) err := Validate(bytes) @@ -38,6 +42,7 @@ func FromYAMLString(in string) (Policy, error) { return policy, nil } +// Validate checks, if the apiVersion in the provided Policy is supported. func Validate(in []byte) error { var unmarshalled struct { APIVersion semver.Version `json:"apiVersion"` diff --git a/pkg/engine/k8s/policy/types.go b/pkg/engine/k8s/policy/types.go index 2076cc861..0fdea05a1 100644 --- a/pkg/engine/k8s/policy/types.go +++ b/pkg/engine/k8s/policy/types.go @@ -7,28 +7,40 @@ import ( ) const ( - CurrentAPIVersion = "0.2.0" - AnyInterfacePath string = "cap.*" + // CurrentAPIVersion holds the current Policy API version. + CurrentAPIVersion = "0.2.0" + // AnyInterfacePath holds a value, which represents any Interface path. + AnyInterfacePath string = "cap.*" ) +// Type is the type of the Policy. type Type string + +// MergeOrder holds the merge order of the Policies. type MergeOrder []Type const ( - Global Type = "GLOBAL" - Action Type = "ACTION" + // Global indicates the Global policy. + Global Type = "GLOBAL" + // Action indicates the Action policy. + Action Type = "ACTION" + // Workflow indicates the Workflow step policy. Workflow Type = "WORKFLOW" ) +// Policy holds the policy properties. type Policy struct { APIVersion string `json:"apiVersion"` Rules RulesList `json:"rules"` } +// ActionPolicy holds the Action policy properties. type ActionPolicy Policy +// RulesList holds the list of the rules in the policy. type RulesList []RulesForInterface +// RulesForInterface holds a single policy rule for an Interface. type RulesForInterface struct { // Interface refers to a given Interface manifest. Interface types.ManifestRef `json:"interface"` @@ -36,16 +48,22 @@ type RulesForInterface struct { OneOf []Rule `json:"oneOf"` } +// Rule holds the constraints an Implementation must match. +// It also stores data, which should be injected, +// if this Implementation is selected. type Rule struct { ImplementationConstraints ImplementationConstraints `json:"implementationConstraints,omitempty"` Inject *InjectData `json:"inject,omitempty"` } +// InjectData holds the data, which should be injected into the Action. type InjectData struct { TypeInstances []TypeInstanceToInject `json:"typeInstances,omitempty"` AdditionalInput map[string]interface{} `json:"additionalInput,omitempty"` } +// ImplementationConstraints represents the constraints +// for an Implementation to match a rule. type ImplementationConstraints struct { // Requires refers a specific requirement path and optional revision. Requires *[]types.ManifestRef `json:"requires,omitempty"` @@ -57,6 +75,7 @@ type ImplementationConstraints struct { Path *string `json:"path,omitempty"` } +// TypeInstanceToInject holds a TypeInstances to be injected to the Action. type TypeInstanceToInject struct { ID string `json:"id"` @@ -64,6 +83,7 @@ type TypeInstanceToInject struct { TypeRef types.ManifestRef `json:"typeRef"` } +// ToYAMLString converts the Policy to a string. func (p Policy) ToYAMLString() (string, error) { bytes, err := yaml.Marshal(&p) @@ -99,6 +119,8 @@ func (in *InjectData) DeepCopyInto(out *InjectData) { } } +// MergeMaps performs a deep merge of two maps. +// It is used to merge the additional parameters in the policies. func MergeMaps(current, overwrite map[string]interface{}) map[string]interface{} { out := make(map[string]interface{}, len(current)) for k, v := range current { diff --git a/pkg/engine/k8s/policy/workflow.go b/pkg/engine/k8s/policy/workflow.go index a09b7aa37..6b8e1cd4b 100644 --- a/pkg/engine/k8s/policy/workflow.go +++ b/pkg/engine/k8s/policy/workflow.go @@ -11,18 +11,25 @@ import ( "capact.io/capact/pkg/sdk/apis/0.0.1/types" ) +// WorkflowPolicy represents a Workflow step policy. type WorkflowPolicy struct { APIVersion string `json:"apiVersion"` Rules WorkflowRulesList `json:"rules"` } +// WorkflowRulesList holds the list of the rules in the policy. type WorkflowRulesList []WorkflowRulesForInterface +// WorkflowInterfaceRef represents an reference to an Interface +// in the workflow step policy. +// The Interface can be provided either using the full path and revision +// or using an alias from the imported Interfaces in the Implementation. type WorkflowInterfaceRef struct { ManifestRef *types.ManifestRef Alias *string } +// WorkflowRulesForInterface holds a single policy rule for an Interface. type WorkflowRulesForInterface struct { // Interface refers to a given Interface manifest. Interface WorkflowInterfaceRef `json:"interface"` @@ -30,15 +37,23 @@ type WorkflowRulesForInterface struct { OneOf []WorkflowRule `json:"oneOf"` } +// WorkflowRule holds the constraints an Implementation must match. +// It also stores data, which should be injected, +// if this Implementation is selected. type WorkflowRule struct { ImplementationConstraints ImplementationConstraints `json:"implementationConstraints,omitempty"` Inject *WorkflowInjectData `json:"inject,omitempty"` } +// WorkflowInjectData holds the data, which should be injected into the Action. +// Compared to other policies, injecting TypeInstances +// is not supported in the Workflow step policy. type WorkflowInjectData struct { AdditionalInput map[string]interface{} `json:"additionalInput,omitempty"` } +// ResolveImports is used to resolve the Manifest Reference for the rules, +// if the Interface reference is provided using an alias. func (p *WorkflowPolicy) ResolveImports(imports []*hubpublicapi.ImplementationImport) error { for i, r := range p.Rules { if r.Interface.Alias == nil || *r.Interface.Alias == "" { @@ -54,6 +69,7 @@ func (p *WorkflowPolicy) ResolveImports(imports []*hubpublicapi.ImplementationIm return nil } +// ToYAMLBytes marshals the policy into a byte slice. func (p WorkflowPolicy) ToYAMLBytes() ([]byte, error) { bytes, err := yaml.Marshal(&p) @@ -64,11 +80,13 @@ func (p WorkflowPolicy) ToYAMLBytes() ([]byte, error) { return bytes, nil } +// ToYAMLString converts the policy into a string. func (p WorkflowPolicy) ToYAMLString() (string, error) { bytes, err := p.ToYAMLBytes() return string(bytes), err } +// ToPolicy converts the WorkflowPolicy to a generic Policy struct. func (p WorkflowPolicy) ToPolicy() (Policy, error) { newPolicy := Policy{} bytes, err := p.ToYAMLBytes() @@ -83,6 +101,8 @@ func (p WorkflowPolicy) ToPolicy() (Policy, error) { return newPolicy, nil } +// UnmarshalJSON fills the WorkflowInterfaceRef properties from the provided byte slice. +// The byte slice must be JSON encoded. func (i *WorkflowInterfaceRef) UnmarshalJSON(b []byte) error { i.ManifestRef = &types.ManifestRef{} err := json.Unmarshal(b, i.ManifestRef) @@ -91,12 +111,11 @@ func (i *WorkflowInterfaceRef) UnmarshalJSON(b []byte) error { } i.Alias = ptr.String("") - if err := json.Unmarshal(b, i.Alias); err != nil { - return err - } - return nil + + return json.Unmarshal(b, i.Alias) } +// MarshalJSON marshals the WorkflowInterfaceRef to a JSON encoded byte slice. func (i *WorkflowInterfaceRef) MarshalJSON() ([]byte, error) { return json.Marshal(i.ManifestRef) } diff --git a/pkg/httputil/client.go b/pkg/httputil/client.go index 872f2890c..1990c4724 100644 --- a/pkg/httputil/client.go +++ b/pkg/httputil/client.go @@ -23,12 +23,14 @@ func NewClient(timeout time.Duration, opts ...ClientOption) *http.Client { // modify the behaviour of the Client. type ClientOption func(*http.Client) +// WithBasicAuth returns a ClientOption to add basic access authentication credentials. func WithBasicAuth(user, pass string) ClientOption { return func(client *http.Client) { client.Transport.(*configurableTransport).SetBasicAuth(user, pass) } } +// WithTLSInsecureSkipVerify returns a ClientOption to skip TLS verification for the HTTP server. func WithTLSInsecureSkipVerify(skip bool) func(client *http.Client) { return func(client *http.Client) { client.Transport.(*configurableTransport).SetTLSInsecureSkipVerify(skip) diff --git a/pkg/httputil/doc.go b/pkg/httputil/doc.go index 64e80aea4..8746fc98b 100644 --- a/pkg/httputil/doc.go +++ b/pkg/httputil/doc.go @@ -1,2 +1,2 @@ -// This package provides a syntactic sugar and helper functions to make http things easier to read or to express +// Package httputil provides a syntactic sugar and helper functions to make http things easier to read or to express package httputil diff --git a/pkg/hub/client/client.go b/pkg/hub/client/client.go index 7043c03c9..984b0945d 100644 --- a/pkg/hub/client/client.go +++ b/pkg/hub/client/client.go @@ -18,6 +18,7 @@ type Client struct { Public } +// Local interface aggregates methods to interact with Capact Local Hub. type Local interface { CreateTypeInstance(ctx context.Context, in *hublocalgraphql.CreateTypeInstanceInput) (*hublocalgraphql.TypeInstance, error) CreateTypeInstances(ctx context.Context, in *hublocalgraphql.CreateTypeInstancesInput) ([]hublocalgraphql.CreateTypeInstanceOutput, error) @@ -30,6 +31,7 @@ type Local interface { UpdateTypeInstances(ctx context.Context, in []hublocalgraphql.UpdateTypeInstancesInput) ([]hublocalgraphql.TypeInstance, error) } +// Public interface aggregates methods to interact with Capact Public Hub. type Public interface { ListInterfacesMetadata(ctx context.Context) ([]hubpublicgraphql.Interface, error) GetInterfaceLatestRevisionString(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (string, error) @@ -39,6 +41,7 @@ type Public interface { ListImplementationRevisions(ctx context.Context, filter *hubpublicgraphql.ImplementationRevisionFilter) ([]*hubpublicgraphql.ImplementationRevision, error) } +// New returns a new Client to interact with the Capact Local and Public Hub. func New(endpoint string, httpClient *http.Client) *Client { clientOpt := graphql.WithHTTPClient(httpClient) client := graphql.NewClient(endpoint, clientOpt) diff --git a/pkg/hub/client/fake/fake.go b/pkg/hub/client/fake/fake.go index 781f63245..30abb0a1b 100644 --- a/pkg/hub/client/fake/fake.go +++ b/pkg/hub/client/fake/fake.go @@ -21,6 +21,7 @@ import ( const manifestsExtension = ".yaml" +// FileSystemClient is a client, which reads Hub manifests from a file system. type FileSystemClient struct { loadTypeInstances bool TypeInstances map[string]hublocalgraphql.TypeInstance @@ -28,6 +29,11 @@ type FileSystemClient struct { Interfaces []hubpublicgraphql.InterfaceRevision } +// NewFromLocal returns a new FileSystemClient. +// The Manifest files are loaded in this function and served from memory +// so changes done to the files after the FileSystemClient is created +// will not be reflected. +// The function will return an error, if loading of the manifests failed. func NewFromLocal(manifestDir string, loadTypeInstances bool) (*FileSystemClient, error) { cli := &FileSystemClient{ loadTypeInstances: loadTypeInstances, @@ -43,6 +49,7 @@ func NewFromLocal(manifestDir string, loadTypeInstances bool) (*FileSystemClient return cli, nil } +// ListImplementationRevisionsForInterface returns ImplementationRevisions for the given Interface. func (s *FileSystemClient) ListImplementationRevisionsForInterface(ctx context.Context, ref hubpublicgraphql.InterfaceReference, opts ...public.GetImplementationOption) ([]hubpublicgraphql.ImplementationRevision, error) { getOpts := &public.ListImplementationRevisionsOptions{} getOpts.Apply(opts...) @@ -68,6 +75,7 @@ func (s *FileSystemClient) ListImplementationRevisionsForInterface(ctx context.C return public.SortImplementationRevisions(result, getOpts), nil } +// ListTypeInstancesTypeRef returns the TypeReferences of the present TypeInstances. func (s *FileSystemClient) ListTypeInstancesTypeRef(ctx context.Context) ([]hublocalgraphql.TypeInstanceTypeReference, error) { var typeInstanceTypeRefs []hublocalgraphql.TypeInstanceTypeReference for _, ti := range s.TypeInstances { @@ -81,6 +89,8 @@ func (s *FileSystemClient) ListTypeInstancesTypeRef(ctx context.Context) ([]hubl return typeInstanceTypeRefs, nil } +// GetInterfaceLatestRevisionString returns the latest revision of the available Interfaces. +// Semantic versioning is used to determine the latest revision. func (s *FileSystemClient) GetInterfaceLatestRevisionString(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (string, error) { var versions semver.Collection for _, impl := range s.Implementations { @@ -104,6 +114,8 @@ func (s *FileSystemClient) GetInterfaceLatestRevisionString(ctx context.Context, return latestVersion.String(), nil } +// FindInterfaceRevision returns the InterfaceRevision for the given InterfaceReference. +// It will return nil, if the InterfaceRevision is not found. func (s *FileSystemClient) FindInterfaceRevision(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (*hubpublicgraphql.InterfaceRevision, error) { for i := range s.Interfaces { iface := s.Interfaces[i] @@ -123,6 +135,8 @@ func (s *FileSystemClient) FindInterfaceRevision(ctx context.Context, ref hubpub return nil, nil } +// FindTypeInstance returns the TypeInstance with the given ID. +// It will return nil, if the TypeInstances is not found. func (s *FileSystemClient) FindTypeInstance(_ context.Context, id string) (*hublocalgraphql.TypeInstance, error) { ti, found := s.TypeInstances[id] if !found { @@ -156,8 +170,8 @@ func (s *FileSystemClient) loadManifests(dir string) error { return nil } -func (s *FileSystemClient) loadManifest(filepath string) error { - data, err := ioutil.ReadFile(filepath) +func (s *FileSystemClient) loadManifest(path string) error { + data, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return errors.Wrap(err, "while reading file") } @@ -167,7 +181,7 @@ func (s *FileSystemClient) loadManifest(filepath string) error { return errors.Wrap(err, "while converting YAML to JSON") } - if strings.Contains(filepath, "implementation") { + if strings.Contains(path, "implementation") { impl := hubpublicgraphql.ImplementationRevision{} if err := json.Unmarshal(jsonData, &impl); err != nil { return err @@ -175,7 +189,7 @@ func (s *FileSystemClient) loadManifest(filepath string) error { s.Implementations = append(s.Implementations, impl) } - if strings.Contains(filepath, "interface") { + if strings.Contains(path, "interface") { iface := hubpublicgraphql.InterfaceRevision{} if err := json.Unmarshal(jsonData, &iface); err != nil { return err @@ -183,7 +197,7 @@ func (s *FileSystemClient) loadManifest(filepath string) error { s.Interfaces = append(s.Interfaces, iface) } - if s.loadTypeInstances && strings.Contains(filepath, "typeinstance") { + if s.loadTypeInstances && strings.Contains(path, "typeinstance") { ti := hublocalgraphql.TypeInstance{} if err := json.Unmarshal(jsonData, &ti); err != nil { return err diff --git a/pkg/hub/client/local/client.go b/pkg/hub/client/local/client.go index ee9a133c8..acbeb571e 100644 --- a/pkg/hub/client/local/client.go +++ b/pkg/hub/client/local/client.go @@ -39,6 +39,7 @@ func NewDefaultClient(endpoint string, opts ...httputil.ClientOption) *Client { return NewClient(client) } +// CreateTypeInstance creates a new TypeInstances in the local Hub. func (c *Client) CreateTypeInstance(ctx context.Context, in *hublocalgraphql.CreateTypeInstanceInput) (*hublocalgraphql.TypeInstance, error) { query := fmt.Sprintf(`mutation CreateTypeInstance($in: CreateTypeInstanceInput!) { createTypeInstance( @@ -64,6 +65,7 @@ func (c *Client) CreateTypeInstance(ctx context.Context, in *hublocalgraphql.Cre return resp.TypeInstance, nil } +// CreateTypeInstances creates new TypeInstances and allows to define "uses" relationships between them. func (c *Client) CreateTypeInstances(ctx context.Context, in *hublocalgraphql.CreateTypeInstancesInput) ([]hublocalgraphql.CreateTypeInstanceOutput, error) { query := `mutation CreateTypeInstances($in: CreateTypeInstancesInput!) { createTypeInstances( @@ -90,6 +92,7 @@ func (c *Client) CreateTypeInstances(ctx context.Context, in *hublocalgraphql.Cr return resp.CreatedTypeInstances, nil } +// UpdateTypeInstances updates multiple TypeInstances in the local Hub. func (c *Client) UpdateTypeInstances(ctx context.Context, in []hublocalgraphql.UpdateTypeInstancesInput) ([]hublocalgraphql.TypeInstance, error) { query := fmt.Sprintf(`mutation UpdateTypeInstances($in: [UpdateTypeInstancesInput]!) { updateTypeInstances( @@ -115,6 +118,7 @@ func (c *Client) UpdateTypeInstances(ctx context.Context, in []hublocalgraphql.U return resp.TypeInstances, nil } +// FindTypeInstance finds a TypeInstance with the given ID. If no TypeInstance is found, it returns nil. func (c *Client) FindTypeInstance(ctx context.Context, id string) (*hublocalgraphql.TypeInstance, error) { query := fmt.Sprintf(`query FindTypeInstance($id: ID!) { typeInstance(id: $id) { @@ -138,6 +142,7 @@ func (c *Client) FindTypeInstance(ctx context.Context, id string) (*hublocalgrap return resp.TypeInstance, nil } +// ListTypeInstances lists the TypeInstances in the local Hub. You can pass a filter limit the list of returned TypeInstances. func (c *Client) ListTypeInstances(ctx context.Context, filter *hublocalgraphql.TypeInstanceFilter) ([]hublocalgraphql.TypeInstance, error) { query := fmt.Sprintf(`query ListTypeInstances($filter: TypeInstanceFilter) { typeInstances(filter: $filter) { @@ -161,6 +166,8 @@ func (c *Client) ListTypeInstances(ctx context.Context, filter *hublocalgraphql. return resp.TypeInstances, nil } +// ListTypeInstancesTypeRef lists TypeInstances with only the TypeReference fields filled. It can be used to determine, +// if a TypeInstance of a given TypeReference exists in the local Hub. func (c *Client) ListTypeInstancesTypeRef(ctx context.Context) ([]hublocalgraphql.TypeInstanceTypeReference, error) { query := `query ListTypeInstancesTypeRef { typeInstances { @@ -195,6 +202,7 @@ func (c *Client) ListTypeInstancesTypeRef(ctx context.Context) ([]hublocalgraphq return typeRefs, nil } +// DeleteTypeInstance deletes a TypeInstances from the local Hub. func (c *Client) DeleteTypeInstance(ctx context.Context, id string) error { req := graphql.NewRequest(`mutation DeleteTypeInstance($id: ID!) { deleteTypeInstance( @@ -214,6 +222,7 @@ func (c *Client) DeleteTypeInstance(ctx context.Context, id string) error { return nil } +// LockTypeInstances locks the given TypeInstances. It will return an error, if the TypeInstance is already locked by an another owner. func (c *Client) LockTypeInstances(ctx context.Context, in *hublocalgraphql.LockTypeInstancesInput) error { query := `mutation LockTypeInstances($in: LockTypeInstancesInput!) { lockTypeInstances(in: $in) @@ -232,6 +241,7 @@ func (c *Client) LockTypeInstances(ctx context.Context, in *hublocalgraphql.Lock return nil } +// UnlockTypeInstances unlocks the given TypeInstances. It will return an error, if the TypeInstances are locked by a different owner. func (c *Client) UnlockTypeInstances(ctx context.Context, in *hublocalgraphql.UnlockTypeInstancesInput) error { query := `mutation UnlockTypeInstances($in: UnlockTypeInstancesInput!) { unlockTypeInstances(in: $in) diff --git a/pkg/hub/client/policy_enforced_client.go b/pkg/hub/client/policy_enforced_client.go index a76c0b088..c71cbf3f7 100644 --- a/pkg/hub/client/policy_enforced_client.go +++ b/pkg/hub/client/policy_enforced_client.go @@ -15,6 +15,7 @@ import ( "capact.io/capact/pkg/sdk/apis/0.0.1/types" ) +// HubClient interface agreggates methods for interacting with the Local and Public Hub. type HubClient interface { GetInterfaceLatestRevisionString(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (string, error) ListImplementationRevisionsForInterface(ctx context.Context, ref hubpublicgraphql.InterfaceReference, opts ...public.GetImplementationOption) ([]hubpublicgraphql.ImplementationRevision, error) @@ -22,6 +23,8 @@ type HubClient interface { FindInterfaceRevision(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (*hubpublicgraphql.InterfaceRevision, error) } +// PolicyEnforcedClient is a client, which can interact with the Local and Public Hub. +// It can be configured with policies to filter the Implementations returned by the Hub. type PolicyEnforcedClient struct { hubCli HubClient globalPolicy policy.Policy @@ -32,11 +35,14 @@ type PolicyEnforcedClient struct { mu sync.RWMutex } +// NewPolicyEnforcedClient returns a new NewPolicyEnforcedClient. func NewPolicyEnforcedClient(hubCli HubClient) *PolicyEnforcedClient { defaultOrder := policy.MergeOrder{policy.Action, policy.Global, policy.Workflow} return &PolicyEnforcedClient{hubCli: hubCli, policyOrder: defaultOrder} } +// ListImplementationRevisionForInterface returns ImplementationRevisions +// for the given Interface and the current policy configuration. func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx context.Context, interfaceRef hubpublicgraphql.InterfaceReference) ([]hubpublicgraphql.ImplementationRevision, policy.Rule, error) { if interfaceRef.Revision == "" { interfaceRevision, err := e.hubCli.GetInterfaceLatestRevisionString(ctx, interfaceRef) @@ -66,6 +72,8 @@ func (e *PolicyEnforcedClient) ListImplementationRevisionForInterface(ctx contex return implementations, rule, nil } +// ListTypeInstancesToInjectBasedOnPolicy returns the input TypeInstance references, +// which have to be injected into the Action, based on the current policies. func (e *PolicyEnforcedClient) ListTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) []types.InputTypeInstanceRef { if policyRule.Inject == nil || len(policyRule.Inject.TypeInstances) == 0 { return nil @@ -90,7 +98,9 @@ func (e *PolicyEnforcedClient) ListTypeInstancesToInjectBasedOnPolicy(policyRule return typeInstancesToInject } -// check if rules has AdditionalInput to inject and if implementation expects AdditionalInput +// ListAdditionalInputToInjectBasedOnPolicy returns additional input parameters, +// which have to be injected into the Action, based on the current policies. +// TODO: check if rules has AdditionalInput to inject and if implementation expects AdditionalInput func (e *PolicyEnforcedClient) ListAdditionalInputToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicgraphql.ImplementationRevision) map[string]interface{} { if policyRule.Inject == nil || len(policyRule.Inject.AdditionalInput) == 0 || @@ -103,10 +113,13 @@ func (e *PolicyEnforcedClient) ListAdditionalInputToInjectBasedOnPolicy(policyRu return policyRule.Inject.AdditionalInput } +// FindInterfaceRevision finds InterfaceRevision for the provided reference. +// It will return nil, if no revision was found. func (e *PolicyEnforcedClient) FindInterfaceRevision(ctx context.Context, ref hubpublicgraphql.InterfaceReference) (*hubpublicgraphql.InterfaceRevision, error) { return e.hubCli.FindInterfaceRevision(ctx, ref) } +// SetPolicyOrder sets the policy merging order for the client. This setter is thread safe. func (e *PolicyEnforcedClient) SetPolicyOrder(order policy.MergeOrder) { e.mu.Lock() e.policyOrder = order @@ -300,7 +313,8 @@ func (e *PolicyEnforcedClient) listCurrentTypeInstanceValues(ctx context.Context func (e *PolicyEnforcedClient) typeInstancesToTypeInstanceValues(in []hublocalgraphql.TypeInstanceTypeReference) []*hubpublicgraphql.TypeInstanceValue { var out []*hubpublicgraphql.TypeInstanceValue - for _, typeRef := range in { + for i := range in { + typeRef := in[i] out = append(out, &hubpublicgraphql.TypeInstanceValue{ TypeRef: &hubpublicgraphql.TypeReferenceWithOptionalRevision{ Path: typeRef.Path, diff --git a/pkg/hub/client/public/client.go b/pkg/hub/client/public/client.go index 105b5d69c..868c6d702 100644 --- a/pkg/hub/client/public/client.go +++ b/pkg/hub/client/public/client.go @@ -20,6 +20,7 @@ type Client struct { client *graphql.Client } +// NewClient creates a public client with a given GraphQL custom client instance. func NewClient(cli *graphql.Client) *Client { return &Client{client: cli} } @@ -47,6 +48,8 @@ func (c *Client) ListInterfacesMetadata(ctx context.Context) ([]gqlpublicapi.Int return resp.Interfaces, nil } +// FindInterfaceRevision returns the InterfaceRevision for the given InterfaceReference. +// It will return nil, if the InterfaceRevision is not found. func (c *Client) FindInterfaceRevision(ctx context.Context, ref gqlpublicapi.InterfaceReference) (*gqlpublicapi.InterfaceRevision, error) { query, params := c.interfaceQueryForRef(ref) req := graphql.NewRequest(fmt.Sprintf(`query FindInterfaceRevision($interfacePath: NodePath!, %s) { @@ -74,6 +77,8 @@ func (c *Client) FindInterfaceRevision(ctx context.Context, ref gqlpublicapi.Int return resp.Interface.Revision, nil } +// ListInterfacesWithLatestRevision returns the latest revision of the Interfaces, +// which match the provided filter. func (c *Client) ListInterfacesWithLatestRevision(ctx context.Context, filter gqlpublicapi.InterfaceFilter) ([]*gqlpublicapi.Interface, error) { req := graphql.NewRequest(fmt.Sprintf(`query ListInterfacesWithLatestRevision($interfaceFilter: InterfaceFilter!) { interfaces(filter: $interfaceFilter) { @@ -97,6 +102,8 @@ func (c *Client) ListInterfacesWithLatestRevision(ctx context.Context, filter gq return resp.Interfaces, nil } +// GetInterfaceLatestRevisionString returns the latest revision of the available Interfaces. +// Semantic versioning is used to determine the latest revision. func (c *Client) GetInterfaceLatestRevisionString(ctx context.Context, ref gqlpublicapi.InterfaceReference) (string, error) { req := graphql.NewRequest(`query GetInterfaceLatestRevisionString($interfacePath: NodePath!) { interface(path: $interfacePath) { @@ -129,6 +136,8 @@ func (c *Client) GetInterfaceLatestRevisionString(ctx context.Context, ref gqlpu return resp.Interface.LatestRevision.Revision, nil } +// ListImplementationRevisions returns ImplementationRevisions, +// which match the given filter. func (c *Client) ListImplementationRevisions(ctx context.Context, filter *gqlpublicapi.ImplementationRevisionFilter) ([]*gqlpublicapi.ImplementationRevision, error) { req := graphql.NewRequest(fmt.Sprintf(`query ListImplementationRevisions{ implementations { @@ -157,6 +166,7 @@ func (c *Client) ListImplementationRevisions(ctx context.Context, filter *gqlpub return revs, nil } +// ListImplementationRevisionsForInterface returns ImplementationRevisions for the given Interface. func (c *Client) ListImplementationRevisionsForInterface(ctx context.Context, ref gqlpublicapi.InterfaceReference, opts ...GetImplementationOption) ([]gqlpublicapi.ImplementationRevision, error) { getOpts := &ListImplementationRevisionsOptions{} getOpts.Apply(opts...) @@ -195,8 +205,12 @@ func (c *Client) ListImplementationRevisionsForInterface(ctx context.Context, re var key = regexp.MustCompile(`\$(\w+):`) +// Args is used to store arguments to GraphQL queries. type Args map[string]interface{} +// Query returns the definition for the arguments +// stored in this Args, which has to be put in the +// GraphQL query. func (a Args) Query() string { var out []string for k := range a { @@ -205,6 +219,8 @@ func (a Args) Query() string { return strings.Join(out, ",") } +// PopulateVars fills the variables stores in this Args +// in the provided *graphql.Request. func (a Args) PopulateVars(req *graphql.Request) { for k, v := range a { name := key.FindStringSubmatch(k) diff --git a/pkg/hub/client/public/fields.go b/pkg/hub/client/public/fields.go index a1bccd593..f5eb5eea0 100644 --- a/pkg/hub/client/public/fields.go +++ b/pkg/hub/client/public/fields.go @@ -2,6 +2,7 @@ package public import "fmt" +// GenericMetadataFields for querying the GenericMetadata fields. var GenericMetadataFields = ` prefix path @@ -18,6 +19,7 @@ var GenericMetadataFields = ` iconURL ` +// AttributeFields for quering the Attributes fields and GenericMetadata. var AttributeFields = fmt.Sprintf(` metadata { %s @@ -31,6 +33,7 @@ var AttributeFields = fmt.Sprintf(` } `, GenericMetadataFields) +// ImplementationFields for quering the Implementation fields with all revisions. var ImplementationFields = fmt.Sprintf(` path name @@ -40,6 +43,7 @@ var ImplementationFields = fmt.Sprintf(` } `, ImplementationRevisionFields) +// ImplementationRevisionFields for quering ImplementationRevision fields. var ImplementationRevisionFields = fmt.Sprintf(` metadata { %s @@ -129,6 +133,7 @@ var ImplementationRevisionFields = fmt.Sprintf(` } `, GenericMetadataFields, AttributeFields) +// InterfaceRevisionFields for quering InterfaceRevision fields with GenericMetadata and all revisions. var InterfaceRevisionFields = fmt.Sprintf(` revision metadata { @@ -164,6 +169,7 @@ var InterfaceRevisionFields = fmt.Sprintf(` } `, GenericMetadataFields, ImplementationRevisionFields) +// InterfacesFields for quering Interface with the latest revision only. var InterfacesFields = fmt.Sprintf(` path name diff --git a/pkg/hub/client/public/filter.go b/pkg/hub/client/public/filter.go index b5b830729..c565aba31 100644 --- a/pkg/hub/client/public/filter.go +++ b/pkg/hub/client/public/filter.go @@ -7,6 +7,9 @@ import ( gqlpublicapi "capact.io/capact/pkg/hub/api/graphql/public" ) +// FilterImplementationRevisions filters the provided ImplementationRevisions using the given filter options. +// It is used to perform client-side filtering during rendering to find an ImplementationRevision, +// which matches the given constraints. func FilterImplementationRevisions(revs []gqlpublicapi.ImplementationRevision, opts *ListImplementationRevisionsOptions) []gqlpublicapi.ImplementationRevision { if opts == nil { return revs diff --git a/pkg/hub/client/public/options.go b/pkg/hub/client/public/options.go index 84237d127..d234caf1b 100644 --- a/pkg/hub/client/public/options.go +++ b/pkg/hub/client/public/options.go @@ -2,6 +2,7 @@ package public import gqlpublicapi "capact.io/capact/pkg/hub/api/graphql/public" +// ListImplementationRevisionsOptions stores Implementation Revision filtering parameters. type ListImplementationRevisionsOptions struct { attrFilter map[gqlpublicapi.FilterRule]map[string]*string implPathPattern *string @@ -10,15 +11,17 @@ type ListImplementationRevisionsOptions struct { sortByPathAscAndRevisionDesc bool } +// Apply is used to configure the ListImplementationRevisionsOptions. func (o *ListImplementationRevisionsOptions) Apply(opts ...GetImplementationOption) { for _, opt := range opts { opt(o) } } -// ListOption is some configuration that modifies options for a list request. +// GetImplementationOption provides an option to configure the get request for Implementations. type GetImplementationOption func(*ListImplementationRevisionsOptions) +// WithFilter returns an options, which adds a filter for ImplementationRevisions. func WithFilter(filter gqlpublicapi.ImplementationRevisionFilter) GetImplementationOption { return func(opt *ListImplementationRevisionsOptions) { // 1. Process attributes @@ -63,6 +66,10 @@ func WithFilter(filter gqlpublicapi.ImplementationRevisionFilter) GetImplementat } } +// WithSortingByPathAscAndRevisionDesc returns an options, which ensures +// that the returned ImplementationRevision slice will be sorted +// in ascending order by the Implementation path +// and descending by the Implementation revision. func WithSortingByPathAscAndRevisionDesc() GetImplementationOption { return func(options *ListImplementationRevisionsOptions) { options.sortByPathAscAndRevisionDesc = true diff --git a/pkg/hub/client/public/sort.go b/pkg/hub/client/public/sort.go index 1a31ac6a5..13cde642a 100644 --- a/pkg/hub/client/public/sort.go +++ b/pkg/hub/client/public/sort.go @@ -7,6 +7,9 @@ import ( "github.com/Masterminds/semver/v3" ) +// SortImplementationRevisions will sort the ImplementationRevisions, +// if the sortByPathAscAndRevisionDesc property is true in the opts. +// In other case it will return the original revs. func SortImplementationRevisions(revs []gqlpublicapi.ImplementationRevision, opts *ListImplementationRevisionsOptions) []gqlpublicapi.ImplementationRevision { if opts == nil { return revs diff --git a/pkg/runner/api.go b/pkg/runner/api.go index 2bc1bf55f..eeeb659be 100644 --- a/pkg/runner/api.go +++ b/pkg/runner/api.go @@ -6,8 +6,8 @@ import ( "fmt" ) -// API types used to ensure extendable function input/output. type ( + // StartInput defines the input arguments to start a runner. StartInput struct { // RunnerCtx contains Runner data provided by Engine. RunnerCtx Context @@ -15,16 +15,19 @@ type ( Args json.RawMessage } + // StartOutput defines the output from a starting an operation. StartOutput struct { // Status holds generic status object that is later marshalled to JSON format. Status interface{} } + // WaitForCompletionInput defines the input for the wait step of the runner. WaitForCompletionInput struct { // RunnerCtx contains Runner data provided by Engine. RunnerCtx Context } + // WaitForCompletionOutput defines the output from the wait step of the runner. WaitForCompletionOutput struct { // Succeeded indicates if runner finished successfully or not. Succeeded bool diff --git a/pkg/runner/argo/argo.go b/pkg/runner/argo/argo.go index 69be34169..93477049b 100644 --- a/pkg/runner/argo/argo.go +++ b/pkg/runner/argo/argo.go @@ -24,11 +24,12 @@ const ( runnerName = "argo-runner" ) -// Provides info to easily identify started Argo Workflow. type ( + // Status provides info to easily identify started Argo Workflow. Status struct { ArgoWorkflowRef WorkflowRef `json:"argoWorkflowRef"` } + // WorkflowRef represents a Argo Workflow CR. WorkflowRef struct { Name string `json:"name"` Namespace string `json:"namespace"` diff --git a/pkg/runner/cloudsql/creds.go b/pkg/runner/cloudsql/creds.go index 392817208..42ad7ee60 100644 --- a/pkg/runner/cloudsql/creds.go +++ b/pkg/runner/cloudsql/creds.go @@ -10,6 +10,7 @@ import ( "sigs.k8s.io/yaml" ) +// GCPConfig hold information about the GCP SA configuration and credentials. type GCPConfig struct { ServiceAccount struct { Filepath string `envconfig:"default=/etc/gcp/sa.json"` @@ -21,7 +22,9 @@ type GCPConfig struct { type CredentialsFormat string const ( + // JSON indicates GCP credentials in JSON format. JSON CredentialsFormat = "JSON" + // YAML indicates GCP credentials in YAML format. YAML CredentialsFormat = "YAML" ) @@ -49,6 +52,7 @@ var scopes = []string{ "https://www.googleapis.com/auth/sqlservice.admin", } +// LoadGCPCredentials loads the google.Credentials from a GCPConfig. func LoadGCPCredentials(cfg GCPConfig) (*google.Credentials, error) { rawInput, err := ioutil.ReadFile(cfg.ServiceAccount.Filepath) if err != nil { diff --git a/pkg/runner/cloudsql/runner.go b/pkg/runner/cloudsql/runner.go index 8babd395d..e86d39485 100644 --- a/pkg/runner/cloudsql/runner.go +++ b/pkg/runner/cloudsql/runner.go @@ -16,6 +16,7 @@ type runnerAction interface { WaitForCompletion(ctx context.Context, in runner.WaitForCompletionInput) (*runner.WaitForCompletionOutput, error) } +// Runner provides functionality to run and wait for GCP CloudSQL operations. type Runner struct { logger *zap.Logger sqladminService *sqladmin.Service @@ -24,6 +25,7 @@ type Runner struct { outputCfg OutputConfig } +// NewRunner returns new instance of CloudSQL runner. func NewRunner(cfg OutputConfig, sqladminService *sqladmin.Service, gcpProjectName string) *Runner { return &Runner{ outputCfg: cfg, @@ -33,14 +35,18 @@ func NewRunner(cfg OutputConfig, sqladminService *sqladmin.Service, gcpProjectNa } } +// InjectLogger sets the logger on the runner. func (r *Runner) InjectLogger(logger *zap.Logger) { r.logger = logger } +// Name returns the name of the runner. func (r *Runner) Name() string { return "cloudsql" } +// Start starts a CloudSQL operation. +// It will not wait for the operation to finish. func (r *Runner) Start(ctx context.Context, in runner.StartInput) (*runner.StartOutput, error) { args := &Args{} @@ -64,6 +70,7 @@ func (r *Runner) Start(ctx context.Context, in runner.StartInput) (*runner.Start return r.action.Start(ctx, &in) } +// WaitForCompletion waits for the started operation to finish. func (r *Runner) WaitForCompletion(ctx context.Context, in runner.WaitForCompletionInput) (*runner.WaitForCompletionOutput, error) { return r.action.WaitForCompletion(ctx, in) } diff --git a/pkg/runner/cloudsql/types.go b/pkg/runner/cloudsql/types.go index 4301e8e66..58081c2ac 100644 --- a/pkg/runner/cloudsql/types.go +++ b/pkg/runner/cloudsql/types.go @@ -10,31 +10,40 @@ import ( ) const ( - PostgresPort = 5432 + // PostgresPort defines the CloudSQL DB port. + PostgresPort = 5432 + // PostgresDefaultDBName defines the CloudSQL default database name. PostgresDefaultDBName = "postgres" - PostgresRootUser = "postgres" + // PostgresRootUser defines the CloudSQL database instance root user name. + PostgresRootUser = "postgres" createWaitDelay = 10 * time.Second artifactsFileMode os.FileMode = 0644 ) +// CommandType represents the operation type to be performed by the runner. type CommandType string const ( + // CreateCommandType is an operation to create a new CloudSQL instance. CreateCommandType = "create" ) var ( + // ErrInstanceCreateTimeout indicates the operation timed out. ErrInstanceCreateTimeout = errors.New("timed out waiting for DB instance to be ready") - ErrUnknownCommand = errors.New("unknown command") + // ErrUnknownCommand indicates an unknown operation command. + ErrUnknownCommand = errors.New("unknown command") ) +// OutputConfig stores the configuration for the CloudSQL runner output files. type OutputConfig struct { CloudSQLInstanceFilePath string `envconfig:"default=/tmp/cloudSQLInstance.yaml"` AdditionalFilePath string `envconfig:"default=/tmp/additional.yaml"` } +// Args stores the input arguments for the CloudSQL runner operation. type Args struct { Group string `yaml:"group"` Command CommandType `yaml:"command"` @@ -43,6 +52,7 @@ type Args struct { Output OutputArgs `yaml:"output"` } +// OutputArgs stores the arguments for the output of the CloudSQL runner. type OutputArgs struct { GoTemplate json.RawMessage `yaml:"goTemplate"` } diff --git a/pkg/runner/common.go b/pkg/runner/common.go index bd58c7597..bed808ba7 100644 --- a/pkg/runner/common.go +++ b/pkg/runner/common.go @@ -6,8 +6,11 @@ import ( "github.com/pkg/errors" ) +// DefaultFilePermissions are the default file permissions +// of the output artifact files created by the runners. const DefaultFilePermissions = 0644 +// SaveToFile saves the bytes to a file under the path. func SaveToFile(path string, bytes []byte) error { err := ioutil.WriteFile(path, bytes, DefaultFilePermissions) if err != nil { diff --git a/pkg/runner/config.go b/pkg/runner/config.go index a04fbce13..f030c01da 100644 --- a/pkg/runner/config.go +++ b/pkg/runner/config.go @@ -16,6 +16,7 @@ type Config struct { Logger logger.Config } +// InputData holds the input data for the runners. type InputData struct { Context Context `json:"context"` Args json.RawMessage `json:"args"` @@ -40,10 +41,12 @@ type KubernetesPlatformConfig struct { // `json: cannot unmarshal string into Go struct field of type time.Duration` type Duration time.Duration +// Duration returns the time.Duration representation. func (d Duration) Duration() time.Duration { return time.Duration(d) } +// UnmarshalJSON loads the JSON representation of Duration in the byte slice b. func (d *Duration) UnmarshalJSON(b []byte) error { var value string if err := json.Unmarshal(b, &value); err != nil { @@ -57,6 +60,7 @@ func (d *Duration) UnmarshalJSON(b []byte) error { return nil } +// MarshalJSON returns the JSON representation of the Duration. func (d Duration) MarshalJSON() ([]byte, error) { return json.Marshal(time.Duration(d).String()) } diff --git a/pkg/runner/helm/adapter.go b/pkg/runner/helm/adapter.go index 48a403b0f..5d1ee6b3c 100644 --- a/pkg/runner/helm/adapter.go +++ b/pkg/runner/helm/adapter.go @@ -17,12 +17,14 @@ type runnerAdapter struct { out *runner.WaitForCompletionOutput } +// NewRunner returns new instance of Helm runner. func NewRunner(k8sCfg *rest.Config, cfg Config) runner.Runner { return &runnerAdapter{ underlying: newHelmRunner(k8sCfg, cfg), } } +// Start the Helm runner operation. func (r *runnerAdapter) Start(ctx context.Context, in runner.StartInput) (*runner.StartOutput, error) { var err error r.out, err = r.underlying.Do(ctx, in) @@ -37,14 +39,17 @@ func (r *runnerAdapter) Start(ctx context.Context, in runner.StartInput) (*runne }, nil } +// WaitForCompletion waits for the Helm runner operation to complete. func (r *runnerAdapter) WaitForCompletion(_ context.Context, _ runner.WaitForCompletionInput) (*runner.WaitForCompletionOutput, error) { return r.out, nil } +// Name returns the name of the Helm runner. func (r *runnerAdapter) Name() string { return r.underlying.Name() } +// InjectLogger sets the logger on the runner. func (r *runnerAdapter) InjectLogger(logger *zap.Logger) { r.underlying.InjectLogger(logger) } diff --git a/pkg/runner/helm/output.go b/pkg/runner/helm/output.go index 73f906dfd..7dd170397 100644 --- a/pkg/runner/helm/output.go +++ b/pkg/runner/helm/output.go @@ -10,19 +10,24 @@ import ( "sigs.k8s.io/yaml" ) +// ChartRenderer has a Do method. +// The Do method renders the additional output from the Helm Chart release. type ChartRenderer interface { Do(chartData *chart.Chart, release *release.Release, additionalOutputTemplate []byte) ([]byte, error) } +// Outputter handles producing the runner output artifacts. type Outputter struct { log *zap.Logger renderer ChartRenderer } +// NewOutputter returns a new Outputer. func NewOutputter(log *zap.Logger, renderer ChartRenderer) *Outputter { return &Outputter{log: log, renderer: renderer} } +// ProduceHelmRelease creates an output artifacts with the Helm release data. func (o *Outputter) ProduceHelmRelease(repository string, helmRelease *release.Release) ([]byte, error) { releaseData := ChartRelease{ Name: helmRelease.Name, @@ -42,6 +47,7 @@ func (o *Outputter) ProduceHelmRelease(repository string, helmRelease *release.R return bytes, nil } +// ProduceAdditional creates an output artifacts from the output template provided in the args. // TODO: consider to get rid of the chrt arg and use rel.Chart instead. func (o *Outputter) ProduceAdditional(args OutputArgs, chrt *chart.Chart, rel *release.Release) ([]byte, error) { if strings.TrimSpace(args.GoTemplate) == "" { diff --git a/pkg/runner/helm/render.go b/pkg/runner/helm/render.go index d592bdfac..94e0642c9 100644 --- a/pkg/runner/helm/render.go +++ b/pkg/runner/helm/render.go @@ -12,18 +12,23 @@ import ( const additionalOutputTemplateName = "additionalOutputTemplate" +// RenderEngine has a Render method. +// The Render method is used to perform rendering of Chart values. type RenderEngine interface { Render(*chart.Chart, chartutil.Values) (map[string]string, error) } +// Renderer is used to perform rendering of Chart values. It uses the Golang templating engine. type Renderer struct { renderEngine RenderEngine } +// NewRenderer returns a new Renderer instance. func NewRenderer() *Renderer { return &Renderer{renderEngine: &engine.Engine{}} } +// Do renders the additional output data using the deployed Chart release. func (r *Renderer) Do(chartData *chart.Chart, release *release.Release, additionalOutputTemplate []byte) ([]byte, error) { chartData.Templates = append(chartData.Templates, &chart.File{ Name: additionalOutputTemplateName, diff --git a/pkg/runner/helm/types.go b/pkg/runner/helm/types.go index 880208771..c7fb504a3 100644 --- a/pkg/runner/helm/types.go +++ b/pkg/runner/helm/types.go @@ -24,19 +24,24 @@ type Config struct { } } +// CommandType represents the operation type to be performed by the runner. type CommandType string const ( + // InstallCommandType is an operation to install a new Helm chart. InstallCommandType = "install" + // UpgradeCommandType is an operation to upgrade an Helm release. UpgradeCommandType = "upgrade" ) +// Arguments stores the input arguments for the Helm runner operation. type Arguments struct { CommonArgs InstallArgs UpgradeArgs } +// CommonArgs stores common arguments used in every operation. type CommonArgs struct { Values map[string]interface{} `json:"values"` ValuesFromFile string `json:"valuesFromFile"` @@ -45,43 +50,51 @@ type CommonArgs struct { Output OutputArgs `json:"output"` } +// InstallArgs stores input arguments to the install operation. type InstallArgs struct { Name string `json:"name"` GenerateName bool `json:"generateName"` Replace bool `json:"replace"` } +// UpgradeArgs stores input arguments for the upgrade operation. type UpgradeArgs struct { ReuseValues bool `json:"reuseValues"` ResetValues bool `json:"resetValues"` } +// OutputArgs stores input arguments for generating the output artifacts. type OutputArgs struct { GoTemplate string `json:"goTemplate"` } +// Chart represents a Helm chart. type Chart struct { Name string `json:"name"` Version string `json:"version"` Repo string `json:"repo"` } +// ChartRelease represents a Helm chart release. type ChartRelease struct { Name string `json:"name"` Namespace string `json:"namespace"` Chart Chart `json:"chart"` } +// Input stores the input configuration for the runner. type Input struct { Args Arguments Ctx runner.Context } +// Status indicates the status of the runner operation. type Status struct { Succeeded bool Message string } +// Output stores the produces output artifacts. type Output struct { Release []byte Additional []byte diff --git a/pkg/runner/helm/upgrade.go b/pkg/runner/helm/upgrade.go index fdceae450..19984bf15 100644 --- a/pkg/runner/helm/upgrade.go +++ b/pkg/runner/helm/upgrade.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "io/ioutil" + "path/filepath" "github.com/pkg/errors" "go.uber.org/zap" @@ -104,7 +105,7 @@ func (i *upgrader) Do(_ context.Context, in Input) (Output, Status, error) { func (i *upgrader) loadHelmReleaseData(path string) (ChartRelease, error) { i.log.Debug("Reading Helm Release data from file", zap.String("path", path)) - bytes, err := ioutil.ReadFile(path) + bytes, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return ChartRelease{}, errors.Wrapf(err, "while reading values from file %q", path) } diff --git a/pkg/runner/helm/value_override.go b/pkg/runner/helm/value_override.go index 8c94b2383..40ca6ef00 100644 --- a/pkg/runner/helm/value_override.go +++ b/pkg/runner/helm/value_override.go @@ -2,6 +2,7 @@ package helm import ( "io/ioutil" + "path/filepath" "github.com/pkg/errors" "sigs.k8s.io/yaml" @@ -18,7 +19,7 @@ func readValueOverrides(inlineValues map[string]interface{}, valuesFilePath stri return nil, errors.New("providing values both inline and from file is currently unsupported") } - bytes, err := ioutil.ReadFile(valuesFilePath) + bytes, err := ioutil.ReadFile(filepath.Clean(valuesFilePath)) if err != nil { return nil, errors.Wrapf(err, "while reading values from file %q", valuesFilePath) } diff --git a/pkg/runner/manager.go b/pkg/runner/manager.go index 06e0a81ed..e456830aa 100644 --- a/pkg/runner/manager.go +++ b/pkg/runner/manager.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "io/ioutil" + "path/filepath" "capact.io/capact/internal/logger" @@ -104,7 +105,7 @@ func (r *Manager) readRunnerInput() (InputData, error) { } func (r *Manager) unmarshalFromFile(path string, out interface{}) error { - bytes, err := ioutil.ReadFile(path) + bytes, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return errors.Wrapf(err, "while reading file from path %q", path) } diff --git a/pkg/runner/status-reporter/noop_reporter.go b/pkg/runner/status-reporter/noop_reporter.go index 1a1dc257c..988fa2cf4 100644 --- a/pkg/runner/status-reporter/noop_reporter.go +++ b/pkg/runner/status-reporter/noop_reporter.go @@ -18,6 +18,7 @@ func NewNoop() *NoopReporter { return &NoopReporter{} } +// Report does nothing and returns always nil. func (n NoopReporter) Report(ctx context.Context, runnerCtx runner.Context, status interface{}) error { return nil } diff --git a/pkg/runner/terraform/runner.go b/pkg/runner/terraform/runner.go index eb686b0bb..427e82104 100644 --- a/pkg/runner/terraform/runner.go +++ b/pkg/runner/terraform/runner.go @@ -25,12 +25,14 @@ type terraformRunner struct { terraform *terraform } +// NewTerraformRunner returns a new Terraform runner instance. func NewTerraformRunner(cfg Config) runner.Runner { return &terraformRunner{ cfg: cfg, } } +// Start starts the Terraform runner operation. func (r *terraformRunner) Start(ctx context.Context, in runner.StartInput) (*runner.StartOutput, error) { var args Arguments err := yaml.Unmarshal(in.Args, &args) @@ -67,6 +69,7 @@ func (r *terraformRunner) Start(ctx context.Context, in runner.StartInput) (*run }, nil } +// WaitForCompletion waits for the runner operation to complete. func (r *terraformRunner) WaitForCompletion(ctx context.Context, in runner.WaitForCompletionInput) (*runner.WaitForCompletionOutput, error) { if r.terraform == nil { return &runner.WaitForCompletionOutput{}, errors.New("terraform not started yet") @@ -119,10 +122,12 @@ func (r *terraformRunner) WaitForCompletion(ctx context.Context, in runner.WaitF return &runner.WaitForCompletionOutput{Succeeded: true, Message: "Terraform finished"}, nil } +// Name returns the runner name. func (r *terraformRunner) Name() string { return "terraform" } +// InjectLogger sets the logger on the runner. func (r *terraformRunner) InjectLogger(logger *zap.Logger) { r.log = logger } @@ -134,7 +139,10 @@ func (r *terraformRunner) setEnvVars(env []string) error { return fmt.Errorf("Invalid env variable %s", e) } k, v := s[0], s[1] - os.Setenv(k, v) + + if err := os.Setenv(k, v); err != nil { + return errors.Wrapf(err, "while setting env %s", k) + } } return nil } diff --git a/pkg/runner/terraform/terraform.go b/pkg/runner/terraform/terraform.go index 687587882..35fe98791 100644 --- a/pkg/runner/terraform/terraform.go +++ b/pkg/runner/terraform/terraform.go @@ -19,11 +19,8 @@ import ( ) const ( - ApplyCommand = "apply" - DestroyCommand = "destroy" - PlanCommand = "plan" - variablesFile = "terraform.tfvars" - stateFile = "terraform.tfstate" + variablesFile = "terraform.tfvars" + stateFile = "terraform.tfstate" ) type terraform struct { @@ -42,6 +39,7 @@ func newTerraform(log *zap.Logger, workdir string, args Arguments) *terraform { } } +// Start starts the Terraform operation. func (t *terraform) Start(dryRun bool) error { t._waitCh = make(chan error) @@ -76,6 +74,7 @@ func (t *terraform) Start(dryRun bool) error { return nil } +// Wait blocks until the Terraform operation is not finished. func (t *terraform) Wait(ctx context.Context) error { select { case <-ctx.Done(): diff --git a/pkg/runner/terraform/types.go b/pkg/runner/terraform/types.go index 93bcb40ab..086860449 100644 --- a/pkg/runner/terraform/types.go +++ b/pkg/runner/terraform/types.go @@ -2,8 +2,19 @@ package terraform import "encoding/json" +// CommandType represents the operation type to be performed by the runner. type CommandType string +const ( + // ApplyCommand is an operation to perform terraform apply. + ApplyCommand = "apply" + // DestroyCommand is an operation to perform terraform destroy. + DestroyCommand = "destroy" + // PlanCommand is an operation to perform terraform plan. + PlanCommand = "plan" +) + +// Arguments stores the input arguments for the runner operation. type Arguments struct { Command string `yaml:"command"` Name string `yaml:"name"` @@ -14,11 +25,13 @@ type Arguments struct { // TODO destroy needs tfstate file } +// Module stores the source details of the Terraform module. type Module struct { Name string Source string } +// AdditionalOutput stores input arguments for generating the additional output. type AdditionalOutput struct { GoTemplate json.RawMessage `yaml:"goTemplate"` } @@ -31,22 +44,26 @@ type Config struct { Output OutputConfig } +// OutputConfig stores the configuration for the generated output file. type OutputConfig struct { TerraformReleaseFilePath string `envconfig:"default=/tmp/terraform-release.yaml"` AdditionalFilePath string `envconfig:"default=/tmp/additional.yaml"` TfstateFilePath string `envconfig:"default=/tmp/terraform.tfstate"` } +// Release stores the details about the Terraform release. type Release struct { Name string `json:"name"` Source string `json:"source"` } +// StateTypeInstance stores the details about the Terraform state TypeInstance. type StateTypeInstance struct { State []byte `json:"state"` Variables []byte `json:"variables"` } +// Output stores the generated output artifacts. type Output struct { Release []byte Additional []byte diff --git a/pkg/runner/terraform/variables.go b/pkg/runner/terraform/variables.go index 09bad3f55..0d5cb8710 100644 --- a/pkg/runner/terraform/variables.go +++ b/pkg/runner/terraform/variables.go @@ -6,6 +6,8 @@ import ( "github.com/zclconf/go-cty/cty" ) +// LoadVariablesFromFiles loads and merges multiple files with Terraform variables. +// Variables from subsequent files are overriding the variables in files before. func LoadVariablesFromFiles(paths ...string) (map[string]cty.Value, error) { p := configs.NewParser(nil) @@ -25,6 +27,7 @@ func LoadVariablesFromFiles(paths ...string) (map[string]cty.Value, error) { return values, nil } +// MarshalVariables outputs the provided variables as a bytestream in HCL format. func MarshalVariables(variables map[string]cty.Value) []byte { f := hclwrite.NewEmptyFile() rootBody := f.Body() diff --git a/pkg/sdk/apis/0.0.1/types/types.extend.go b/pkg/sdk/apis/0.0.1/types/types.extend.go index 97ecb0946..40d1a4d59 100644 --- a/pkg/sdk/apis/0.0.1/types/types.extend.go +++ b/pkg/sdk/apis/0.0.1/types/types.extend.go @@ -1,4 +1,4 @@ -// Holds manually added types +// Package types holds manually added types. package types // InterfaceRef holds the full path and revision to the Interface diff --git a/pkg/sdk/dbpopulator/loader.go b/pkg/sdk/dbpopulator/loader.go index 334efca8a..c8868a2f3 100644 --- a/pkg/sdk/dbpopulator/loader.go +++ b/pkg/sdk/dbpopulator/loader.go @@ -33,6 +33,7 @@ func getManifestMetadata(yamlBytes []byte) (manifestMetadata, error) { return mm, err } +// Group returns a map of the provided Manifests Paths, grouped by the manifest kind. func Group(paths []string) (map[string][]string, error) { manifests := map[string][]string{} for _, kind := range ordered { @@ -40,7 +41,7 @@ func Group(paths []string) (map[string][]string, error) { } for _, path := range paths { // may just read first 3 lines if there are performance issues - content, err := ioutil.ReadFile(path) + content, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return manifests, errors.Wrapf(err, "while reading file from path %s", path) } @@ -58,6 +59,7 @@ func Group(paths []string) (map[string][]string, error) { return manifests, nil } +// List returns all YAML files in the provided hubPath by using filepath.Walk. func List(hubPath string) ([]string, error) { files := []string{} err := filepath.Walk(hubPath, func(currentPath string, info os.FileInfo, err error) error { diff --git a/pkg/sdk/dbpopulator/server.go b/pkg/sdk/dbpopulator/server.go index 85c7564ee..17c4bc4a4 100644 --- a/pkg/sdk/dbpopulator/server.go +++ b/pkg/sdk/dbpopulator/server.go @@ -11,8 +11,8 @@ import ( "sigs.k8s.io/yaml" ) -// ServeJson serves Hub Manifests -// manifests are converted from YAML to JSON when requested +// MustServeJSON serves Hub Manifests. Manifests are converted from YAML to JSON when requested +// It will run os.Exit(1), if an error occurs. func MustServeJSON(ctx context.Context, listenPort int, validPaths []string) { http.HandleFunc("/", jsonHandler(validPaths)) srv := http.Server{Addr: fmt.Sprintf("0.0.0.0:%d", listenPort)} diff --git a/pkg/sdk/manifest/validation.go b/pkg/sdk/manifest/validation.go index f330f3a21..eaa2ed026 100644 --- a/pkg/sdk/manifest/validation.go +++ b/pkg/sdk/manifest/validation.go @@ -5,6 +5,7 @@ import ( "io/ioutil" "net/http" "os" + "path/filepath" "sort" "github.com/iancoleman/strcase" @@ -13,14 +14,19 @@ import ( "sigs.k8s.io/yaml" ) +// Validator is a interface, with the ValidateFile method. +// ValidateFile validates the manifest in filepath and return a ValidationResult. +// If other, not manifest related errors occur, it will return an error. type Validator interface { ValidateFile(filepath string) (ValidationResult, error) } +// ValidationResult hold the result of the manifest validation. type ValidationResult struct { Errors []error } +// Valid returns true, if the manifest contains no errors. func (r *ValidationResult) Valid() bool { return len(r.Errors) == 0 } @@ -31,6 +37,7 @@ func newValidationResult(errors ...error) ValidationResult { } } +// FilesystemManifestValidator validates manifests using a OCF specification, which is read from a filesystem. type FilesystemManifestValidator struct { schemaRootPath string cachedSchemas map[ocfVersion]*loadedOCFSchema @@ -46,6 +53,7 @@ type loadedOCFSchema struct { kind map[kind]*gojsonschema.Schema } +// NewFilesystemValidator returns a new FilesystemManifestValidator. func NewFilesystemValidator(fs http.FileSystem, schemaRootPath string) Validator { return &FilesystemManifestValidator{ schemaRootPath: schemaRootPath, @@ -54,8 +62,9 @@ func NewFilesystemValidator(fs http.FileSystem, schemaRootPath string) Validator } } -func (v *FilesystemManifestValidator) ValidateFile(filepath string) (ValidationResult, error) { - data, err := ioutil.ReadFile(filepath) +// ValidateFile validates a manifest. +func (v *FilesystemManifestValidator) ValidateFile(path string) (ValidationResult, error) { + data, err := ioutil.ReadFile(filepath.Clean(path)) if err != nil { return newValidationResult(), err } diff --git a/pkg/sdk/renderer/argo/dedicated_renderer.go b/pkg/sdk/renderer/argo/dedicated_renderer.go index e39fc97ba..cae9e1c34 100644 --- a/pkg/sdk/renderer/argo/dedicated_renderer.go +++ b/pkg/sdk/renderer/argo/dedicated_renderer.go @@ -42,6 +42,8 @@ type dedicatedRenderer struct { registeredOutputTypeInstanceNames []*string } +// InputArtifact is an Argo artifact with a reference to a Capact TypeInstance. +// It is used to track the TypeInstance, which is handled in the workflow. type InputArtifact struct { artifact wfv1.Artifact typeInstanceReference *string diff --git a/pkg/sdk/renderer/argo/errors.go b/pkg/sdk/renderer/argo/errors.go index d175c9c6f..01ff04b66 100644 --- a/pkg/sdk/renderer/argo/errors.go +++ b/pkg/sdk/renderer/argo/errors.go @@ -6,26 +6,35 @@ import ( // NOTE: Change the error to Go struct if needed, e.g. someone needs to do such assertion `errors.Is(err, MaxDepthError)` +// NewMaxDepthError indicates that the maximum depth of the nested actions was reached. func NewMaxDepthError(limit int) error { return errors.Errorf("Exceeded maximum render depth level [max depth %d]", limit) } +// NewRunnerContextRefEmptyError indicates that the reference for the runner context is empty. func NewRunnerContextRefEmptyError() error { return errors.Errorf("Empty Runner Context Secret reference") } +// NewWorkflowNilError indicates that there is no workflow defined in the manifest. func NewWorkflowNilError() error { return errors.New("workflow cannot be nil") } +// NewEntrypointWorkflowIndexNotFoundError indicates that the entrypoint template +// cannot be found in the workflow. func NewEntrypointWorkflowIndexNotFoundError(entrypoint string) error { return errors.Errorf("cannot find workflow index specified by entrypoint %q", entrypoint) } +// NewTypeReferenceNotFoundError indicates that the TypeReference for an TypeInstance +// cannot be found in the manifests. func NewTypeReferenceNotFoundError(typeInstanceName string) error { return errors.Errorf("cannot find TypeReference for TypeInstance %s", typeInstanceName) } +// NewMissingOwnerIDError indicates that the OwnerID +// for the workflow has not been set. func NewMissingOwnerIDError() error { return errors.New("missing ownerID used to update TypeInstances") } diff --git a/pkg/sdk/renderer/argo/helpers.go b/pkg/sdk/renderer/argo/helpers.go index 9ac4a9db2..c5c75d786 100644 --- a/pkg/sdk/renderer/argo/helpers.go +++ b/pkg/sdk/renderer/argo/helpers.go @@ -81,6 +81,7 @@ type argoArtifactRef struct { name string } +// ArgoArtifactNoStep indicates that the Argo artifact was not produced in a workflow step. const ArgoArtifactNoStep = "" func getArgoArtifactRef(ref string) (*argoArtifactRef, error) { diff --git a/pkg/sdk/renderer/argo/options.go b/pkg/sdk/renderer/argo/options.go index 3c6fd2c81..b28a632aa 100644 --- a/pkg/sdk/renderer/argo/options.go +++ b/pkg/sdk/renderer/argo/options.go @@ -5,38 +5,47 @@ import ( "capact.io/capact/pkg/sdk/apis/0.0.1/types" ) +// RendererOption is used to provide additional configuration options to the rendering process. type RendererOption func(*dedicatedRenderer) +// WithTypeInstances returns a RendererOption, which adds input TypeInstances to the workflow. func WithTypeInstances(typeInstances []types.InputTypeInstanceRef) RendererOption { return func(r *dedicatedRenderer) { r.inputTypeInstances = typeInstances } } +// WithSecretUserInput returns a RendererOption, which adds user input to the workflow. func WithSecretUserInput(ref *UserInputSecretRef) RendererOption { return func(r *dedicatedRenderer) { r.userInputSecretRef = ref } } +// WithGlobalPolicy returns a RendererOption, which sets the Global policy for the rendering process. func WithGlobalPolicy(policy policy.Policy) RendererOption { return func(r *dedicatedRenderer) { r.policyEnforcedCli.SetGlobalPolicy(policy) } } +// WithActionPolicy returns a RendererOption, which sets Action policy for the rendering process. func WithActionPolicy(policy policy.ActionPolicy) RendererOption { return func(r *dedicatedRenderer) { r.policyEnforcedCli.SetActionPolicy(policy) } } +// WithPolicyOrder returns a RendererOption, which sets the priority order for the policy. +// The priorty order is from the most important policy to the least important. func WithPolicyOrder(order policy.MergeOrder) RendererOption { return func(r *dedicatedRenderer) { r.policyEnforcedCli.SetPolicyOrder(order) } } +// WithOwnerID returns a RendererOption, which sets OwnerID for the workflow. +// The OwnerID is used to lock the TypeInstances. func WithOwnerID(ownerID string) RendererOption { return func(r *dedicatedRenderer) { r.ownerID = &ownerID diff --git a/pkg/sdk/renderer/argo/renderer.go b/pkg/sdk/renderer/argo/renderer.go index a20614417..a4d308e40 100644 --- a/pkg/sdk/renderer/argo/renderer.go +++ b/pkg/sdk/renderer/argo/renderer.go @@ -21,6 +21,8 @@ const ( runnerContext = "runner-context" ) +// PolicyEnforcedHubClient is a interfaces used to interact with the Capact Hubs +// and enforce the policies. type PolicyEnforcedHubClient interface { ListImplementationRevisionForInterface(ctx context.Context, interfaceRef hubpublicapi.InterfaceReference) ([]hubpublicapi.ImplementationRevision, policy.Rule, error) ListTypeInstancesToInjectBasedOnPolicy(policyRule policy.Rule, implRev hubpublicapi.ImplementationRevision) []types.InputTypeInstanceRef @@ -33,6 +35,7 @@ type PolicyEnforcedHubClient interface { FindInterfaceRevision(ctx context.Context, ref hubpublicapi.InterfaceReference) (*hubpublicapi.InterfaceRevision, error) } +// Renderer is used to render the Capact Action workflows. type Renderer struct { maxDepth int renderTimeout time.Duration @@ -41,6 +44,7 @@ type Renderer struct { hubClient hubclient.HubClient } +// NewRenderer returns a new Renderer instance. func NewRenderer(cfg renderer.Config, hubClient hubclient.HubClient, typeInstanceHandler *TypeInstanceHandler) *Renderer { r := &Renderer{ typeInstanceHandler: typeInstanceHandler, @@ -52,6 +56,7 @@ func NewRenderer(cfg renderer.Config, hubClient hubclient.HubClient, typeInstanc return r } +// Render performs the rendering of an Action workflow. func (r *Renderer) Render(ctx context.Context, input *RenderInput) (*RenderOutput, error) { if input == nil { input = &RenderInput{} diff --git a/pkg/sdk/renderer/argo/typeinstance_handler.go b/pkg/sdk/renderer/argo/typeinstance_handler.go index 75dd3e6fc..1f0660133 100644 --- a/pkg/sdk/renderer/argo/typeinstance_handler.go +++ b/pkg/sdk/renderer/argo/typeinstance_handler.go @@ -21,6 +21,7 @@ type TypeInstanceHandler struct { genUUID func() string } +// NewTypeInstanceHandler returns a new TypeInstanceHandler instance. func NewTypeInstanceHandler(hubActionsImage string) *TypeInstanceHandler { return &TypeInstanceHandler{ hubActionsImage: hubActionsImage, @@ -30,6 +31,8 @@ func NewTypeInstanceHandler(hubActionsImage string) *TypeInstanceHandler { } } +// AddInputTypeInstances adds steps to the workflow to download +// the input TypeInstances. func (r *TypeInstanceHandler) AddInputTypeInstances(rootWorkflow *Workflow, instances []types.InputTypeInstanceRef) error { if len(instances) == 0 { return nil @@ -90,28 +93,38 @@ func (r *TypeInstanceHandler) AddInputTypeInstances(rootWorkflow *Workflow, inst return nil } +// OutputTypeInstanceRelation holds a relationship between the output TypeInstances. type OutputTypeInstanceRelation struct { From *string To *string } +// OutputTypeInstance holds details about a output TypeInstance, +// which will be created in the workflow. type OutputTypeInstance struct { ArtifactName *string TypeInstance types.OutputTypeInstance } +// OutputTypeInstances holds information about the output TypeInstances +// created in the workflow and the relationships between them. type OutputTypeInstances struct { typeInstances []OutputTypeInstance relations []OutputTypeInstanceRelation } +// UpdateTypeInstance holds details about a TypeInstance, +// which will be updated in the workflow. type UpdateTypeInstance struct { ArtifactName string ID string } +// UpdateTypeInstances holds the TypeInstances, +// which will be updates in the workflow. type UpdateTypeInstances []UpdateTypeInstance +// AddUploadTypeInstancesStep adds workflow steps to upload TypeInstances to the Capact Local Hub. func (r *TypeInstanceHandler) AddUploadTypeInstancesStep(rootWorkflow *Workflow, output *OutputTypeInstances, ownerID string) error { artifacts := wfv1.Artifacts{} arguments := wfv1.Artifacts{} @@ -213,6 +226,7 @@ func (r *TypeInstanceHandler) AddUploadTypeInstancesStep(rootWorkflow *Workflow, return nil } +// AddUpdateTypeInstancesStep adds a workflow step to update TypeInstances in the Capact Local Hub. func (r *TypeInstanceHandler) AddUpdateTypeInstancesStep(rootWorkflow *Workflow, typeInstances UpdateTypeInstances, ownerID string) error { artifacts := wfv1.Artifacts{} arguments := wfv1.Artifacts{} diff --git a/pkg/sdk/renderer/argo/types.go b/pkg/sdk/renderer/argo/types.go index f91513736..9f86fcb77 100644 --- a/pkg/sdk/renderer/argo/types.go +++ b/pkg/sdk/renderer/argo/types.go @@ -1,6 +1,7 @@ -// We had to copy the Argo Workflow Go struct as we need to extend the WorkflowStep syntax with our own keywords package argo +// We had to copy the Argo Workflow Go struct as we need to extend the WorkflowStep syntax with our own keywords. + import ( "regexp" @@ -9,18 +10,23 @@ import ( wfv1 "github.com/argoproj/argo/v2/pkg/apis/workflow/v1alpha1" ) +// Workflow is the specification of a Workflow. type Workflow struct { *wfv1.WorkflowSpec Templates []*Template `json:"templates"` } +// Template is a reusable and composable unit of execution in a workflow. type Template struct { *wfv1.Template Steps []ParallelSteps `json:"steps,omitempty"` } +// ParallelSteps define a series of sequential/parallel workflow steps. type ParallelSteps []*WorkflowStep +// WorkflowStep is a reference to a template to execute in a series of step. +// It extends the Argo WorkflowStep and adds Capact specific properties. type WorkflowStep struct { *wfv1.WorkflowStep CapactWhen *string `json:"capact-when,omitempty"` @@ -33,27 +39,35 @@ type WorkflowStep struct { typeInstanceOutputs map[string]*string } +// TypeInstanceDefinition represents a TypeInstance, +// which is created in a step. type TypeInstanceDefinition struct { Name string `json:"name"` From string `json:"from"` } +// RunnerContextSecretRef hold a reference to the runner context +// in a Kubernetes Secret resource. type RunnerContextSecretRef struct { Name string Key string } +// UserInputSecretRef hold a reference to the runner context +// in a Kubernetes Secret resource. type UserInputSecretRef struct { Name string Key string } +// RenderInput holds the input parameters to the Render method. type RenderInput struct { RunnerContextSecretRef RunnerContextSecretRef InterfaceRef types.InterfaceRef Options []RendererOption } +// RenderOutput holds the output of the Render method. type RenderOutput struct { Action *types.Action TypeInstancesToLock []string diff --git a/pkg/sdk/renderer/config.go b/pkg/sdk/renderer/config.go index 13cc03256..a81fdbd78 100644 --- a/pkg/sdk/renderer/config.go +++ b/pkg/sdk/renderer/config.go @@ -2,6 +2,7 @@ package renderer import "time" +// Config stores the configuration for a Workflow renderer. type Config struct { RenderTimeout time.Duration `envconfig:"default=10m"` MaxDepth int `envconfig:"default=50"`