Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d888951

Browse files
committedJul 27, 2020
Adding deprecated property type to bundles
Adding support marking bundles as deprecated and truncating the update graph of a given package. Deprecated versions will not be installable. Deprecating a bundle can result in the removal of channels but this is not permitted for the default channel. Bundles that are not in the index will be ignored during deprecation.
1 parent 3403f43 commit d888951

File tree

14 files changed

+847
-7
lines changed

14 files changed

+847
-7
lines changed
 
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
annotations:
22
operators.operatorframework.io.bundle.package.v1: "etcd"
3-
operators.operatorframework.io.bundle.channels.v1: "alpha,stable"
3+
operators.operatorframework.io.bundle.channels.v1: "alpha,stable,beta"
44
operators.operatorframework.io.bundle.channel.default.v1: "stable"

‎cmd/opm/index/cmd.go

+1
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@ func AddCommand(parent *cobra.Command) {
2525
addIndexAddCmd(cmd)
2626
cmd.AddCommand(newIndexExportCmd())
2727
cmd.AddCommand(newIndexPruneCmd())
28+
cmd.AddCommand(newIndexDeprecateCmd())
2829
}

‎cmd/opm/index/deprecate.go

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package index
2+
3+
import (
4+
"github.com/sirupsen/logrus"
5+
"github.com/spf13/cobra"
6+
"k8s.io/kubectl/pkg/util/templates"
7+
8+
"github.com/operator-framework/operator-registry/pkg/containertools"
9+
"github.com/operator-framework/operator-registry/pkg/lib/indexer"
10+
)
11+
12+
var deprecateLong = templates.LongDesc(`
13+
Deprecate operator bundles from an index.
14+
15+
Deprecated bundles will no longer be installable. Bundles that are replaced by deprecated bundles will be removed enirely from the index.
16+
17+
For example:
18+
19+
Given the update graph in quay.io/my/index:v1
20+
1.4.0 -- replaces -> 1.3.0 -- replaces -> 1.2.0 -- replaces -> 1.1.0
21+
22+
Applying the command:
23+
opm index deprecate --bundles "quay.io/my/bundle:1.3.0" --from-index "quay.io/my/index:v1" --tag "quay.io/my/index:v2"
24+
25+
Produces the following update graph in quay.io/my/index:v2
26+
1.4.0 -- replaces -> 1.3.0 [deprecated]
27+
28+
Deprecating a bundle that removes the default channel is not allowed.
29+
`)
30+
31+
func newIndexDeprecateCmd() *cobra.Command {
32+
indexCmd := &cobra.Command{
33+
Use: "deprecate",
34+
Short: "Deprecate operator bundles from an index.",
35+
Long: "",
36+
PreRunE: func(cmd *cobra.Command, args []string) error {
37+
if debug, _ := cmd.Flags().GetBool("debug"); debug {
38+
logrus.SetLevel(logrus.DebugLevel)
39+
}
40+
return nil
41+
},
42+
RunE: runIndexDeprecateCmdFunc,
43+
}
44+
45+
indexCmd.Flags().Bool("debug", false, "enable debug logging")
46+
indexCmd.Flags().Bool("generate", false, "if enabled, just creates the dockerfile and saves it to local disk")
47+
indexCmd.Flags().StringP("out-dockerfile", "d", "", "if generating the dockerfile, this flag is used to (optionally) specify a dockerfile name")
48+
indexCmd.Flags().StringP("from-index", "f", "", "previous index to add to")
49+
indexCmd.Flags().StringSliceP("bundles", "b", nil, "comma separated list of bundles to add")
50+
if err := indexCmd.MarkFlagRequired("bundles"); err != nil {
51+
logrus.Panic("Failed to set required `bundles` flag for `index add`")
52+
}
53+
indexCmd.Flags().StringP("binary-image", "i", "", "container image for on-image `opm` command")
54+
indexCmd.Flags().StringP("container-tool", "c", "", "tool to interact with container images (save, build, etc.). One of: [docker, podman]")
55+
indexCmd.Flags().StringP("build-tool", "u", "", "tool to build container images. One of: [docker, podman]. Defaults to podman. Overrides part of container-tool.")
56+
indexCmd.Flags().StringP("pull-tool", "p", "", "tool to pull container images. One of: [none, docker, podman]. Defaults to none. Overrides part of container-tool.")
57+
indexCmd.Flags().StringP("tag", "t", "", "custom tag for container image being built")
58+
indexCmd.Flags().Bool("permissive", false, "allow registry load errors")
59+
if err := indexCmd.Flags().MarkHidden("debug"); err != nil {
60+
logrus.Panic(err.Error())
61+
}
62+
63+
return indexCmd
64+
}
65+
66+
func runIndexDeprecateCmdFunc(cmd *cobra.Command, args []string) error {
67+
generate, err := cmd.Flags().GetBool("generate")
68+
if err != nil {
69+
return err
70+
}
71+
72+
outDockerfile, err := cmd.Flags().GetString("out-dockerfile")
73+
if err != nil {
74+
return err
75+
}
76+
77+
fromIndex, err := cmd.Flags().GetString("from-index")
78+
if err != nil {
79+
return err
80+
}
81+
82+
bundles, err := cmd.Flags().GetStringSlice("bundles")
83+
if err != nil {
84+
return err
85+
}
86+
87+
binaryImage, err := cmd.Flags().GetString("binary-image")
88+
if err != nil {
89+
return err
90+
}
91+
92+
tag, err := cmd.Flags().GetString("tag")
93+
if err != nil {
94+
return err
95+
}
96+
97+
permissive, err := cmd.Flags().GetBool("permissive")
98+
if err != nil {
99+
return err
100+
}
101+
102+
pullTool, buildTool, err := getContainerTools(cmd)
103+
if err != nil {
104+
return err
105+
}
106+
107+
logger := logrus.WithFields(logrus.Fields{"bundles": bundles})
108+
109+
logger.Info("deprecating bundles from the index")
110+
111+
indexDeprecator := indexer.NewIndexDeprecator(
112+
containertools.NewContainerTool(buildTool, containertools.PodmanTool),
113+
containertools.NewContainerTool(pullTool, containertools.NoneTool),
114+
logger)
115+
116+
request := indexer.DeprecateFromIndexRequest{
117+
Generate: generate,
118+
FromIndex: fromIndex,
119+
BinarySourceImage: binaryImage,
120+
OutDockerfile: outDockerfile,
121+
Tag: tag,
122+
Bundles: bundles,
123+
Permissive: permissive,
124+
}
125+
126+
err = indexDeprecator.DeprecateFromIndex(request)
127+
if err != nil {
128+
return err
129+
}
130+
131+
return nil
132+
}

‎pkg/lib/indexer/indexer.go

+59
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ type ImageIndexer struct {
4141
RegistryAdder registry.RegistryAdder
4242
RegistryDeleter registry.RegistryDeleter
4343
RegistryPruner registry.RegistryPruner
44+
RegistryDeprecator registry.RegistryDeprecator
4445
BuildTool containertools.ContainerTool
4546
PullTool containertools.ContainerTool
4647
Logger *logrus.Entry
@@ -527,3 +528,61 @@ func generatePackageYaml(dbQuerier pregistry.Query, packageName, downloadPath st
527528

528529
return utilerrors.NewAggregate(errs)
529530
}
531+
532+
// DeprecateFromIndexRequest defines the parameters to send to the PruneFromIndex API
533+
type DeprecateFromIndexRequest struct {
534+
Generate bool
535+
Permissive bool
536+
BinarySourceImage string
537+
FromIndex string
538+
OutDockerfile string
539+
Bundles []string
540+
Tag string
541+
}
542+
543+
// DeprecateFromIndex takes a DeprecateFromIndexRequest and deprecates the requested
544+
// bundles.
545+
func (i ImageIndexer) DeprecateFromIndex(request DeprecateFromIndexRequest) error {
546+
buildDir, outDockerfile, cleanup, err := buildContext(request.Generate, request.OutDockerfile)
547+
defer cleanup()
548+
if err != nil {
549+
return err
550+
}
551+
552+
databasePath, err := i.extractDatabase(buildDir, request.FromIndex)
553+
if err != nil {
554+
return err
555+
}
556+
557+
// Run opm registry prune on the database
558+
deprecateFromRegistryReq := registry.DeprecateFromRegistryRequest{
559+
Bundles: request.Bundles,
560+
InputDatabase: databasePath,
561+
Permissive: request.Permissive,
562+
}
563+
564+
// Prune the bundles from the registry
565+
err = i.RegistryDeprecator.DeprecateFromRegistry(deprecateFromRegistryReq)
566+
if err != nil {
567+
return err
568+
}
569+
570+
// generate the dockerfile
571+
dockerfile := i.DockerfileGenerator.GenerateIndexDockerfile(request.BinarySourceImage, databasePath)
572+
err = write(dockerfile, outDockerfile, i.Logger)
573+
if err != nil {
574+
return err
575+
}
576+
577+
if request.Generate {
578+
return nil
579+
}
580+
581+
// build the dockerfile
582+
err = build(outDockerfile, request.Tag, i.CommandRunner, i.Logger)
583+
if err != nil {
584+
return err
585+
}
586+
587+
return nil
588+
}

‎pkg/lib/indexer/interfaces.go

+17
Original file line numberDiff line numberDiff line change
@@ -80,3 +80,20 @@ func NewIndexPruner(containerTool containertools.ContainerTool, logger *logrus.E
8080
Logger: logger,
8181
}
8282
}
83+
84+
// IndexDeprecator prunes operators out of an index
85+
type IndexDeprecator interface {
86+
DeprecateFromIndex(DeprecateFromIndexRequest) error
87+
}
88+
89+
func NewIndexDeprecator(buildTool, pullTool containertools.ContainerTool, logger *logrus.Entry) IndexDeprecator {
90+
return ImageIndexer{
91+
DockerfileGenerator: containertools.NewDockerfileGenerator(logger),
92+
CommandRunner: containertools.NewCommandRunner(buildTool, logger),
93+
LabelReader: containertools.NewLabelReader(pullTool, logger),
94+
RegistryDeprecator: registry.NewRegistryDeprecator(logger),
95+
BuildTool: buildTool,
96+
PullTool: pullTool,
97+
Logger: logger,
98+
}
99+
}

‎pkg/lib/registry/interfaces.go

+10
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,13 @@ func NewRegistryPruner(logger *logrus.Entry) RegistryPruner {
3636
Logger: logger,
3737
}
3838
}
39+
40+
type RegistryDeprecator interface {
41+
DeprecateFromRegistry(DeprecateFromRegistryRequest) error
42+
}
43+
44+
func NewRegistryDeprecator(logger *logrus.Entry) RegistryDeprecator {
45+
return RegistryUpdater{
46+
Logger: logger,
47+
}
48+
}

‎pkg/lib/registry/registry.go

+36
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,39 @@ func (r RegistryUpdater) PruneFromRegistry(request PruneFromRegistryRequest) err
228228

229229
return nil
230230
}
231+
232+
type DeprecateFromRegistryRequest struct {
233+
Permissive bool
234+
InputDatabase string
235+
Bundles []string
236+
}
237+
238+
func (r RegistryUpdater) DeprecateFromRegistry(request DeprecateFromRegistryRequest) error {
239+
db, err := sql.Open("sqlite3", request.InputDatabase)
240+
if err != nil {
241+
return err
242+
}
243+
defer db.Close()
244+
245+
dbLoader, err := sqlite.NewSQLLiteLoader(db)
246+
if err != nil {
247+
return err
248+
}
249+
if err := dbLoader.Migrate(context.TODO()); err != nil {
250+
return fmt.Errorf("hello 3 %s", err)
251+
}
252+
253+
deprecator := sqlite.NewSQLDeprecatorForBundles(dbLoader, request.Bundles)
254+
if err := deprecator.Deprecate(); err != nil {
255+
r.Logger.Debugf("unable to deprecate bundles from database: %s", err)
256+
if !request.Permissive {
257+
r.Logger.WithError(err).Error("permissive mode disabled")
258+
return err
259+
} else {
260+
r.Logger.WithError(err).Warn("permissive mode enabled")
261+
}
262+
logrus.WithError(err).Warn("permissive mode enabled")
263+
}
264+
265+
return nil
266+
}

‎pkg/registry/interface.go

+1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ type Load interface {
1212
AddPackageChannels(manifest PackageManifest) error
1313
AddBundlePackageChannels(manifest PackageManifest, bundle *Bundle) error
1414
RemovePackage(packageName string) error
15+
DeprecateBundle(path string) error
1516
ClearNonHeadBundles() error
1617
}
1718

0 commit comments

Comments
 (0)
Please sign in to comment.