Skip to content

Commit 1cefc1e

Browse files
authored
Merge pull request #35 from stacklok/k8s-and-compose
Add `kubernetes` and `docker-compose` sub-commands
2 parents 52c1435 + 72dfb94 commit 1cefc1e

File tree

6 files changed

+215
-35
lines changed

6 files changed

+215
-35
lines changed

cmd/containerimage/yaml.go

Lines changed: 6 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import (
2020

2121
"github.com/spf13/cobra"
2222

23+
intcmd "github.com/stacklok/frizbee/internal/cmd"
2324
"github.com/stacklok/frizbee/pkg/config"
24-
cliutils "github.com/stacklok/frizbee/pkg/utils/cli"
2525
)
2626

2727
// CmdYAML represents the yaml sub-command
@@ -41,28 +41,14 @@ Example:
4141
}
4242

4343
// flags
44-
cmd.Flags().StringP("dir", "d", ".", "workflows directory")
4544
cmd.Flags().StringP("image-regex", "i", "image", "regex to match container image references")
4645

47-
cliutils.DeclareReplacerFlags(cmd)
46+
intcmd.DeclareYAMLReplacerFlags(cmd)
4847

4948
return cmd
5049
}
5150

5251
func replaceYAML(cmd *cobra.Command, _ []string) error {
53-
dir := cmd.Flag("dir").Value.String()
54-
dryRun, err := cmd.Flags().GetBool("dry-run")
55-
if err != nil {
56-
return fmt.Errorf("failed to get dry-run flag: %w", err)
57-
}
58-
errOnModified, err := cmd.Flags().GetBool("error")
59-
if err != nil {
60-
return fmt.Errorf("failed to get error flag: %w", err)
61-
}
62-
quiet, err := cmd.Flags().GetBool("quiet")
63-
if err != nil {
64-
return fmt.Errorf("failed to get quiet flag: %w", err)
65-
}
6652
cfg, err := config.FromContext(cmd.Context())
6753
if err != nil {
6854
return fmt.Errorf("failed to get config from context: %w", err)
@@ -72,20 +58,10 @@ func replaceYAML(cmd *cobra.Command, _ []string) error {
7258
return fmt.Errorf("failed to get image-regex flag: %w", err)
7359
}
7460

75-
dir = cliutils.ProcessDirNameForBillyFS(dir)
76-
77-
ctx := cmd.Context()
78-
79-
replacer := &yamlReplacer{
80-
Replacer: cliutils.Replacer{
81-
Dir: dir,
82-
DryRun: dryRun,
83-
Quiet: quiet,
84-
ErrOnModified: errOnModified,
85-
Cmd: cmd,
86-
},
87-
imageRegex: ir,
61+
replacer, err := intcmd.NewYAMLReplacer(cmd, intcmd.WithImageRegex(ir))
62+
if err != nil {
63+
return err
8864
}
8965

90-
return replacer.do(ctx, cfg)
66+
return replacer.Do(cmd.Context(), cfg)
9167
}

cmd/dockercompose/dockercompose.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2023 Stacklok, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package dockercompose provides command-line utilities to work with container images.
16+
package dockercompose
17+
18+
import (
19+
"fmt"
20+
21+
"github.com/spf13/cobra"
22+
23+
intcmd "github.com/stacklok/frizbee/internal/cmd"
24+
"github.com/stacklok/frizbee/pkg/config"
25+
)
26+
27+
// CmdCompose represents the compose yaml sub-command
28+
func CmdCompose() *cobra.Command {
29+
cmd := &cobra.Command{
30+
Use: "docker-compose",
31+
Aliases: []string{"dockercompose", "compose"},
32+
Short: "Replace container image references with checksums in docker-compose YAML files",
33+
Long: `This utility replaces a tag or branch reference in a container image references
34+
with the digest hash of the referenced tag in docker-compose YAML files.
35+
36+
Example:
37+
38+
$ frizbee docker-compose --dir . --dry-run --quiet --error
39+
`,
40+
RunE: replaceYAML,
41+
SilenceUsage: true,
42+
}
43+
44+
// flags
45+
intcmd.DeclareYAMLReplacerFlags(cmd)
46+
47+
return cmd
48+
}
49+
50+
func replaceYAML(cmd *cobra.Command, _ []string) error {
51+
cfg, err := config.FromContext(cmd.Context())
52+
if err != nil {
53+
return fmt.Errorf("failed to get config from context: %w", err)
54+
}
55+
56+
replacer, err := intcmd.NewYAMLReplacer(cmd)
57+
if err != nil {
58+
return err
59+
}
60+
61+
return replacer.Do(cmd.Context(), cfg)
62+
}

cmd/kubernetes/kubernetes.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright 2023 Stacklok, Inc.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Package kubernetes provides command-line utilities to work with kubernetes manifests.
16+
package kubernetes
17+
18+
import (
19+
"fmt"
20+
21+
"github.com/spf13/cobra"
22+
23+
intcmd "github.com/stacklok/frizbee/internal/cmd"
24+
"github.com/stacklok/frizbee/pkg/config"
25+
)
26+
27+
// CmdK8s represents the k8s yaml sub-command
28+
func CmdK8s() *cobra.Command {
29+
cmd := &cobra.Command{
30+
Use: "kubernetes",
31+
Aliases: []string{"k8s"},
32+
Short: "Replace container image references with checksums in kubernetes YAML files",
33+
Long: `This utility replaces a tag or branch reference in a container image references
34+
with the digest hash of the referenced tag in YAML files.
35+
36+
Example:
37+
38+
$ frizbee kubernetes --dir . --dry-run --quiet --error
39+
`,
40+
RunE: replaceYAML,
41+
SilenceUsage: true,
42+
}
43+
44+
// flags
45+
cmd.Flags().StringP("image-regex", "i", "image", "regex to match container image references")
46+
47+
intcmd.DeclareYAMLReplacerFlags(cmd)
48+
49+
return cmd
50+
}
51+
52+
func replaceYAML(cmd *cobra.Command, _ []string) error {
53+
cfg, err := config.FromContext(cmd.Context())
54+
if err != nil {
55+
return fmt.Errorf("failed to get config from context: %w", err)
56+
}
57+
ir, err := cmd.Flags().GetString("image-regex")
58+
if err != nil {
59+
return fmt.Errorf("failed to get image-regex flag: %w", err)
60+
}
61+
62+
replacer, err := intcmd.NewYAMLReplacer(cmd, intcmd.WithImageRegex(ir))
63+
if err != nil {
64+
return err
65+
}
66+
67+
return replacer.Do(cmd.Context(), cfg)
68+
}

cmd/root.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ import (
2424
"github.com/spf13/cobra"
2525

2626
"github.com/stacklok/frizbee/cmd/containerimage"
27+
"github.com/stacklok/frizbee/cmd/dockercompose"
2728
"github.com/stacklok/frizbee/cmd/ghactions"
29+
"github.com/stacklok/frizbee/cmd/kubernetes"
2830
"github.com/stacklok/frizbee/pkg/config"
2931
)
3032

@@ -40,6 +42,8 @@ func Execute() {
4042

4143
rootCmd.AddCommand(ghactions.CmdGHActions())
4244
rootCmd.AddCommand(containerimage.CmdContainerImage())
45+
rootCmd.AddCommand(dockercompose.CmdCompose())
46+
rootCmd.AddCommand(kubernetes.CmdK8s())
4347

4448
if err := rootCmd.ExecuteContext(context.Background()); err != nil {
4549
os.Exit(1)

internal/cmd/doc.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// Copyright 2023 Stacklok, Inc.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
// Package cmd provide common implementations for commands
17+
package cmd

cmd/containerimage/yamlreplacer.go renamed to internal/cmd/yamlreplacer.go

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
// See the License for the specific language governing permissions and
1414
// limitations under the License.
1515

16-
package containerimage
16+
package cmd
1717

1818
import (
1919
"bytes"
@@ -24,6 +24,7 @@ import (
2424
"sync/atomic"
2525

2626
"github.com/go-git/go-billy/v5/osfs"
27+
"github.com/spf13/cobra"
2728
"golang.org/x/sync/errgroup"
2829

2930
"github.com/stacklok/frizbee/pkg/config"
@@ -32,12 +33,64 @@ import (
3233
cliutils "github.com/stacklok/frizbee/pkg/utils/cli"
3334
)
3435

35-
type yamlReplacer struct {
36+
// DeclareYAMLReplacerFlags declares the flags for the YAML replacer
37+
func DeclareYAMLReplacerFlags(cli *cobra.Command) {
38+
cli.Flags().StringP("dir", "d", ".", "manifests file or directory")
39+
40+
cliutils.DeclareReplacerFlags(cli)
41+
}
42+
43+
// YAMLReplacer replaces container image references in YAML files
44+
type YAMLReplacer struct {
3645
cliutils.Replacer
37-
imageRegex string
46+
ImageRegex string
47+
}
48+
49+
// WithImageRegex sets the image regex
50+
func WithImageRegex(regex string) func(*YAMLReplacer) {
51+
return func(r *YAMLReplacer) {
52+
r.ImageRegex = regex
53+
}
54+
}
55+
56+
// NewYAMLReplacer creates a new YAMLReplacer from the given
57+
// command-line arguments and options
58+
func NewYAMLReplacer(cli *cobra.Command, opts ...func(*YAMLReplacer)) (*YAMLReplacer, error) {
59+
dir := cli.Flag("dir").Value.String()
60+
dryRun, err := cli.Flags().GetBool("dry-run")
61+
if err != nil {
62+
return nil, fmt.Errorf("failed to get dry-run flag: %w", err)
63+
}
64+
errOnModified, err := cli.Flags().GetBool("error")
65+
if err != nil {
66+
return nil, fmt.Errorf("failed to get error flag: %w", err)
67+
}
68+
quiet, err := cli.Flags().GetBool("quiet")
69+
if err != nil {
70+
return nil, fmt.Errorf("failed to get quiet flag: %w", err)
71+
}
72+
73+
dir = cliutils.ProcessDirNameForBillyFS(dir)
74+
75+
r := &YAMLReplacer{
76+
Replacer: cliutils.Replacer{
77+
Dir: dir,
78+
DryRun: dryRun,
79+
Quiet: quiet,
80+
ErrOnModified: errOnModified,
81+
Cmd: cli,
82+
},
83+
ImageRegex: "image",
84+
}
85+
for _, opt := range opts {
86+
opt(r)
87+
}
88+
89+
return r, nil
3890
}
3991

40-
func (r *yamlReplacer) do(ctx context.Context, _ *config.Config) error {
92+
// Do runs the YAMLReplacer
93+
func (r *YAMLReplacer) Do(ctx context.Context, _ *config.Config) error {
4194
basedir := filepath.Dir(r.Dir)
4295
base := filepath.Base(r.Dir)
4396
// NOTE: For some reason using boundfs causes a panic when trying to open a file.
@@ -69,7 +122,7 @@ func (r *yamlReplacer) do(ctx context.Context, _ *config.Config) error {
69122
r.Logf("Processing %s\n", path)
70123

71124
buf := bytes.Buffer{}
72-
m, err := containers.ReplaceReferenceFromYAMLWithCache(ctx, r.imageRegex, f, &buf, cache)
125+
m, err := containers.ReplaceReferenceFromYAMLWithCache(ctx, r.ImageRegex, f, &buf, cache)
73126
if err != nil {
74127
return fmt.Errorf("failed to process YAML file %s: %w", path, err)
75128
}

0 commit comments

Comments
 (0)