-
Notifications
You must be signed in to change notification settings - Fork 613
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implement build, push, pull and tag artifact commands. For authentication purposes, all `flux <verb> artifact` commands are using the '~/.docker/config.json' config file and the Docker credential helpers. Signed-off-by: Stefan Prodan <stefan.prodan@gmail.com>
- Loading branch information
1 parent
f009fbe
commit 5f2dcf0
Showing
7 changed files
with
416 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
Copyright 2022 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/fluxcd/flux2/internal/oci" | ||
) | ||
|
||
var buildArtifactCmd = &cobra.Command{ | ||
Use: "artifact", | ||
Short: "Build artifact", | ||
Long: `The build artifact command creates an tgz file with the manifests from the given directory.`, | ||
Example: `# Build the given manifests directory into an artifact | ||
flux build artifact --path ./path/to/local/manifests --output ./path/to/artifact.tgz | ||
`, | ||
RunE: buildArtifactCmdRun, | ||
} | ||
|
||
type buildArtifactFlags struct { | ||
output string | ||
path string | ||
} | ||
|
||
var buildArtifactArgs buildArtifactFlags | ||
|
||
func init() { | ||
buildArtifactCmd.Flags().StringVar(&buildArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") | ||
buildArtifactCmd.Flags().StringVarP(&buildArtifactArgs.output, "output", "0", "artifact.tgz", "Path to where the artifact tgz file should be written.") | ||
buildCmd.AddCommand(buildArtifactCmd) | ||
} | ||
|
||
func buildArtifactCmdRun(cmd *cobra.Command, args []string) error { | ||
if buildArtifactArgs.path == "" { | ||
return fmt.Errorf("invalid path %q", buildArtifactArgs.path) | ||
} | ||
|
||
if fs, err := os.Stat(buildArtifactArgs.path); err != nil || !fs.IsDir() { | ||
return fmt.Errorf("invalid path %q", buildArtifactArgs.path) | ||
} | ||
|
||
logger.Actionf("building artifact from %s", buildArtifactArgs.path) | ||
|
||
if err := oci.Build(buildArtifactArgs.output, buildArtifactArgs.path); err != nil { | ||
return fmt.Errorf("bulding artifact failed, error: %w", err) | ||
} | ||
|
||
logger.Successf("artifact created at %s", buildArtifactArgs.output) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
Copyright 2022 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var pullCmd = &cobra.Command{ | ||
Use: "pull", | ||
Short: "Pull artifacts", | ||
Long: "The pull command is used to download OCI artifacts.", | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(pullCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
/* | ||
Copyright 2022 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/fluxcd/flux2/internal/oci" | ||
) | ||
|
||
var pullArtifactCmd = &cobra.Command{ | ||
Use: "artifact", | ||
Short: "Push artifact", | ||
Long: `The pull artifact command downloads and extracts the OCI artifact content to the given path. | ||
The pull command uses the credentials from '~/.docker/config.json'.`, | ||
Example: `# Pull an OCI artifact created by flux from GHCR | ||
flux pull artifact ghcr.io/org/manifests/app:v0.0.1 --output ./path/to/local/manifests | ||
`, | ||
RunE: pullArtifactCmdRun, | ||
} | ||
|
||
type pullArtifactFlags struct { | ||
output string | ||
} | ||
|
||
var pullArtifactArgs pullArtifactFlags | ||
|
||
func init() { | ||
pullArtifactCmd.Flags().StringVarP(&pullArtifactArgs.output, "output", "o", "", "Path where the artifact content should be extracted.") | ||
pullCmd.AddCommand(pullArtifactCmd) | ||
} | ||
|
||
func pullArtifactCmdRun(cmd *cobra.Command, args []string) error { | ||
if len(args) < 1 { | ||
return fmt.Errorf("artifact name is required") | ||
} | ||
url := args[0] | ||
|
||
if pullArtifactArgs.output == "" { | ||
return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) | ||
} | ||
|
||
if fs, err := os.Stat(pullArtifactArgs.output); err != nil || !fs.IsDir() { | ||
return fmt.Errorf("invalid output path %s", pullArtifactArgs.output) | ||
} | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) | ||
defer cancel() | ||
|
||
logger.Actionf("pulling artifact from %s", url) | ||
|
||
meta, err := oci.Pull(ctx, url, pullArtifactArgs.output) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
logger.Successf("source %s", meta.Source) | ||
logger.Successf("revision %s", meta.Revision) | ||
logger.Successf("digest %s", meta.Digest) | ||
logger.Successf("artifact content extracted to %s", pullArtifactArgs.output) | ||
|
||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
Copyright 2021 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var pushCmd = &cobra.Command{ | ||
Use: "push", | ||
Short: "Push artifacts", | ||
Long: "The push command is used to publish OCI artifacts.", | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(pushCmd) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
/* | ||
Copyright 2022 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"os" | ||
|
||
"github.com/spf13/cobra" | ||
|
||
"github.com/fluxcd/flux2/internal/oci" | ||
) | ||
|
||
var pushArtifactCmd = &cobra.Command{ | ||
Use: "artifact", | ||
Short: "Push artifact", | ||
Long: `The push artifact command creates a tarball from the given directory and uploads the artifact to a OCI repository. | ||
The push command uses the credentials from '~/.docker/config.json'.`, | ||
Example: `# Push the local manifests to GHCR | ||
flux push artifact ghcr.io/org/manifests/app:v0.0.1 \ | ||
--path="./path/to/local/manifests" \ | ||
--source="$(git config --get remote.origin.url)" \ | ||
--revision="$(git branch --show-current)/$(git rev-parse HEAD)" | ||
`, | ||
RunE: pushArtifactCmdRun, | ||
} | ||
|
||
type pushArtifactFlags struct { | ||
path string | ||
source string | ||
revision string | ||
} | ||
|
||
var pushArtifactArgs pushArtifactFlags | ||
|
||
func init() { | ||
pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.path, "path", "", "Path to the directory where the Kubernetes manifests are located.") | ||
pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.source, "source", "", "The source address, e.g. Git URL.") | ||
pushArtifactCmd.Flags().StringVar(&pushArtifactArgs.revision, "revision", "", "The source revision in the format '<branch|tag>/<commit-sha>'") | ||
pushCmd.AddCommand(pushArtifactCmd) | ||
} | ||
|
||
func pushArtifactCmdRun(cmd *cobra.Command, args []string) error { | ||
if len(args) < 1 { | ||
return fmt.Errorf("artifact name is required") | ||
} | ||
url := args[0] | ||
|
||
if pushArtifactArgs.source == "" { | ||
return fmt.Errorf("--source is required") | ||
} | ||
|
||
if pushArtifactArgs.revision == "" { | ||
return fmt.Errorf("--revision is required") | ||
} | ||
|
||
if pushArtifactArgs.path == "" { | ||
return fmt.Errorf("invalid path %q", pushArtifactArgs.path) | ||
} | ||
|
||
if fs, err := os.Stat(pushArtifactArgs.path); err != nil || !fs.IsDir() { | ||
return fmt.Errorf("invalid path %q", pushArtifactArgs.path) | ||
} | ||
|
||
meta := oci.Metadata{ | ||
Source: pushArtifactArgs.source, | ||
Revision: pushArtifactArgs.revision, | ||
} | ||
|
||
ctx, cancel := context.WithTimeout(context.Background(), rootArgs.timeout) | ||
defer cancel() | ||
|
||
logger.Actionf("pushing artifact to %s", url) | ||
|
||
digest, err := oci.Push(ctx, url, pushArtifactArgs.path, meta) | ||
if err != nil { | ||
return fmt.Errorf("pushing artifact failed: %w", err) | ||
} | ||
|
||
logger.Successf("artifact successfully pushed to %s", digest) | ||
|
||
return nil | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
/* | ||
Copyright 2021 The Flux authors | ||
Licensed under the Apache License, Version 2.0 (the "License"); | ||
you may not use this file except in compliance with the License. | ||
You may obtain a copy of the License at | ||
http://www.apache.org/licenses/LICENSE-2.0 | ||
Unless required by applicable law or agreed to in writing, software | ||
distributed under the License is distributed on an "AS IS" BASIS, | ||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
See the License for the specific language governing permissions and | ||
limitations under the License. | ||
*/ | ||
|
||
package main | ||
|
||
import ( | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
var tagCmd = &cobra.Command{ | ||
Use: "tag", | ||
Short: "Tag artifacts", | ||
Long: "The tag command is used to tag OCI artifacts.", | ||
} | ||
|
||
func init() { | ||
rootCmd.AddCommand(tagCmd) | ||
} |
Oops, something went wrong.