diff --git a/cmd/app/cmd.go b/cmd/app/cmd.go index b63e6d7c..7cea51d9 100644 --- a/cmd/app/cmd.go +++ b/cmd/app/cmd.go @@ -12,6 +12,7 @@ import ( "github.com/gardener/docforge/pkg/api" "github.com/gardener/docforge/pkg/hugo" + "github.com/gardener/docforge/pkg/resourcehandlers" "github.com/spf13/cobra" "k8s.io/klog/v2" ) @@ -43,15 +44,24 @@ func NewCommand(ctx context.Context, cancel context.CancelFunc) *cobra.Command { flags := &cmdFlags{} cmd := &cobra.Command{ Use: "docforge", - Short: "Build documentation bundle", + Short: "Forge a documentation bundle", RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true + var ( + doc *api.Documentation + rhs []resourcehandlers.ResourceHandler + err error + ) options := NewOptions(flags) - doc := Manifest(flags.documentationManifestPath, flags.variables) + if rhs, err = initResourceHandlers(ctx, options.GitHubTokens, options.Metering); err != nil { + return err + } + if doc, err = manifest(ctx, flags.documentationManifestPath, rhs, flags.variables); err != nil { + return err + } if err := api.ValidateManifest(doc); err != nil { return err } - reactor, err := NewReactor(ctx, options, doc.Links) if err != nil { return err @@ -90,7 +100,7 @@ func (flags *cmdFlags) Configure(command *cobra.Command) { command.Flags().StringVar(&flags.resourcesPath, "resources-download-path", "__resources", "Resources download path.") command.Flags().StringVar(&flags.ghOAuthToken, "github-oauth-token", "", - "GitHub personal token authorizing read access from GitHub.com repositories. For authorization credentials for multiple GitHub instances, see --gtihub-oauth-token-map") + "GitHub personal token authorizing read access from GitHub.com repositories. For authorization credentials for multiple GitHub instances, see --github-oauth-token-map") command.Flags().StringToStringVar(&flags.ghOAuthTokens, "github-oauth-token-map", map[string]string{}, "GitHub personal tokens authorizing read access from repositories per GitHub instance. Note that if the GitHub token is already provided by `github-oauth-token` it will be overridden by it.") command.Flags().StringVar(&flags.ghInfoDestination, "github-info-destination", "", diff --git a/cmd/app/config.go b/cmd/app/config.go deleted file mode 100644 index d247225d..00000000 --- a/cmd/app/config.go +++ /dev/null @@ -1,48 +0,0 @@ -// SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors -// -// SPDX-License-Identifier: Apache-2.0 - -package app - -import ( - "bytes" - "fmt" - "html/template" - "io/ioutil" - - "github.com/gardener/docforge/pkg/api" -) - -// Manifest creates documentation model from configration file -func Manifest(filePath string, vars map[string]string) *api.Documentation { - var ( - docs *api.Documentation - ) - blob, err := ioutil.ReadFile(filePath) - if err != nil { - panic(fmt.Sprintf("%v\n", err)) - } - blob, err = resolveVariables(blob, vars) - if err != nil { - panic(fmt.Sprintf("%v\n", err)) - } - if docs, err = api.Parse(blob); err != nil { - panic(fmt.Sprintf("%v\n", err)) - } - return docs -} - -func resolveVariables(manifestContent []byte, vars map[string]string) ([]byte, error) { - var ( - tmpl *template.Template - err error - b bytes.Buffer - ) - if tmpl, err = template.New("").Parse(string(manifestContent)); err != nil { - return nil, err - } - if err := tmpl.Execute(&b, vars); err != nil { - return nil, err - } - return b.Bytes(), nil -} diff --git a/cmd/app/manifest.go b/cmd/app/manifest.go new file mode 100644 index 00000000..88ddf960 --- /dev/null +++ b/cmd/app/manifest.go @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2020 SAP SE or an SAP affiliate company and Gardener contributors +// +// SPDX-License-Identifier: Apache-2.0 + +package app + +import ( + "bytes" + "context" + "fmt" + "html/template" + "strings" + + "github.com/gardener/docforge/pkg/api" + "github.com/gardener/docforge/pkg/resourcehandlers" +) + +// Manifest reads the resource at uri, resolves it as template applying vars, +// and finally parses it into api.Documentation model +func manifest(ctx context.Context, uri string, resourceHandlers []resourcehandlers.ResourceHandler, vars map[string]string) (*api.Documentation, error) { + var ( + docs *api.Documentation + err error + blob []byte + handler resourcehandlers.ResourceHandler + ) + uri = strings.TrimSpace(uri) + registry := resourcehandlers.NewRegistry(resourceHandlers...) + if handler = registry.Get(uri); handler == nil { + return nil, fmt.Errorf("no suitable reader found for %s. Is this path correct?", uri) + } + if blob, err = handler.Read(ctx, uri); err != nil { + return nil, err + } + blob, err = resolveVariables(blob, vars) + if err != nil { + panic(fmt.Sprintf("%v\n", err)) + } + if docs, err = api.Parse(blob); err != nil { + panic(fmt.Sprintf("%v\n", err)) + } + return docs, nil +} + +func resolveVariables(manifestContent []byte, vars map[string]string) ([]byte, error) { + var ( + tmpl *template.Template + err error + b bytes.Buffer + ) + if tmpl, err = template.New("").Parse(string(manifestContent)); err != nil { + return nil, err + } + if err := tmpl.Execute(&b, vars); err != nil { + return nil, err + } + return b.Bytes(), nil +} diff --git a/pkg/resourcehandlers/github/github_resource_handler.go b/pkg/resourcehandlers/github/github_resource_handler.go index 529058a0..1efb8c28 100644 --- a/pkg/resourcehandlers/github/github_resource_handler.go +++ b/pkg/resourcehandlers/github/github_resource_handler.go @@ -327,9 +327,18 @@ func (gh *GitHub) Accept(uri string) bool { if gh.acceptedHosts == nil { return false } + // Quick sanity check, preventing panic when trying to + // resolve relative paths in url.Parse + if !strings.HasPrefix(uri, "http") { + return false + } if url, err = url.Parse(uri); err != nil { return false } + // check if this is a GitHub URL + if rl, err := parse(uri); rl == nil || err != nil { + return false + } for _, s := range gh.acceptedHosts { if url.Host == s { return true