Skip to content

Commit 3389781

Browse files
committedJan 24, 2020
Adding ability to export package from index
1 parent cb8d55a commit 3389781

20 files changed

+856
-75
lines changed
 

‎Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -44,3 +44,5 @@ generate-fakes:
4444
clean:
4545
@rm -rf ./bin
4646

47+
opm-test:
48+
$(shell ./opm-test.sh || echo "opm-test FAIL")

‎bundles/etcd.0.9.2/manifests/etcdoperator.v0.9.2.clusterserviceversion.yaml

+17
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,23 @@ spec:
164164
fieldRef:
165165
fieldPath: metadata.name
166166
customresourcedefinitions:
167+
required:
168+
- name: etcdclusters.etcd.database.coreos.com
169+
version: v1beta2
170+
kind: EtcdCluster
171+
displayName: etcd Cluster
172+
description: Represents a cluster of etcd nodes.
173+
resources:
174+
- kind: Service
175+
version: v1
176+
- kind: Pod
177+
version: v1
178+
specDescriptors:
179+
- description: The desired number of member Pods for the etcd cluster.
180+
displayName: Size
181+
path: size
182+
x-descriptors:
183+
- 'urn:alm:descriptor:com.tectonic.ui:podCount'
167184
owned:
168185
- name: etcdclusters.etcd.database.coreos.com
169186
version: v1beta2

‎cmd/opm/index/cmd.go

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ func AddCommand(parent *cobra.Command) {
2323
parent.AddCommand(cmd)
2424
cmd.AddCommand(newIndexDeleteCmd())
2525
addIndexAddCmd(cmd)
26+
cmd.AddCommand(newIndexExportCmd())
2627
}

‎cmd/opm/index/export.go

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
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/lib/indexer"
9+
)
10+
11+
var exportLong = templates.LongDesc(`
12+
Export an operator from an index image into the appregistry format.
13+
14+
This command will take an index image (specified by the --index option), parse it for the given operator (set by
15+
the --operator option) and export the operator metadata into an appregistry compliant format (a package.yaml file).
16+
This command requires access to docker or podman to complete successfully.
17+
18+
Note: the appregistry format is being deprecated in favor of the new index image and image bundle format.
19+
`)
20+
21+
func newIndexExportCmd() *cobra.Command {
22+
indexCmd := &cobra.Command{
23+
Use: "export",
24+
Short: "Export an operator from an index into the appregistry format",
25+
Long: exportLong,
26+
27+
PreRunE: func(cmd *cobra.Command, args []string) error {
28+
if debug, _ := cmd.Flags().GetBool("debug"); debug {
29+
logrus.SetLevel(logrus.DebugLevel)
30+
}
31+
return nil
32+
},
33+
34+
RunE: runIndexExportCmdFunc,
35+
}
36+
37+
indexCmd.Flags().Bool("debug", false, "enable debug logging")
38+
indexCmd.Flags().StringP("index", "i", "", "index to get package from")
39+
if err := indexCmd.MarkFlagRequired("index"); err != nil {
40+
logrus.Panic("Failed to set required `index` flag for `index export`")
41+
}
42+
indexCmd.Flags().StringP("package", "o", "", "the package to export")
43+
if err := indexCmd.MarkFlagRequired("package"); err != nil {
44+
logrus.Panic("Failed to set required `package` flag for `index export`")
45+
}
46+
indexCmd.Flags().StringP("download-folder", "f", "downloaded", "directory where downloaded operator bundle(s) will be stored")
47+
indexCmd.Flags().StringP("container-tool", "c", "podman", "tool to interact with container images (save, build, etc.). One of: [docker, podman]")
48+
if err := indexCmd.Flags().MarkHidden("debug"); err != nil {
49+
logrus.Panic(err.Error())
50+
}
51+
52+
return indexCmd
53+
54+
}
55+
56+
func runIndexExportCmdFunc(cmd *cobra.Command, args []string) error {
57+
index, err := cmd.Flags().GetString("index")
58+
if err != nil {
59+
return err
60+
}
61+
62+
packageName, err := cmd.Flags().GetString("package")
63+
if err != nil {
64+
return err
65+
}
66+
67+
downloadPath, err := cmd.Flags().GetString("download-folder")
68+
if err != nil {
69+
return err
70+
}
71+
72+
containerTool, err := cmd.Flags().GetString("container-tool")
73+
if err != nil {
74+
return err
75+
}
76+
77+
logger := logrus.WithFields(logrus.Fields{"index": index, "package": packageName})
78+
79+
logger.Info("export from the index")
80+
81+
indexExporter := indexer.NewIndexExporter(containerTool, logger)
82+
83+
request := indexer.ExportFromIndexRequest{
84+
Index: index,
85+
Package: packageName,
86+
DownloadPath: downloadPath,
87+
ContainerTool: containerTool,
88+
}
89+
90+
err = indexExporter.ExportFromIndex(request)
91+
if err != nil {
92+
return err
93+
}
94+
95+
return nil
96+
}

‎docs/design/opm-tooling.md

+35
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,41 @@ Like `opm registry rm`, this command will remove all versions an entire operator
9393

9494
This will result in the tagged container image `quay.io/operator-framework/monitoring-index:1.0.2` with a registry that no longer contains the `prometheus` operator at all.
9595

96+
#### export
97+
98+
`opm index export` will export a package from an index image into a directory. The format of this directory will match the appregistry manifest format: containing all versions of the package in the index along with a `package.yaml` file. This command takes an `--index` flag that points to an index image, a `--package` flag that states a package name, an optional `--download-folder` as the export location (default is `./downloaded`), and just as the other index commands it takes a `--container-tool` flag. Ex:
99+
100+
`opm index export --index="quay.io/operator-framework/monitoring:1.0.0" --package="prometheus" -c="podman"`
101+
102+
This will result in the following `downloaded` folder directory structure:
103+
104+
```bash
105+
downloaded
106+
├── 0.14.0
107+
│ ├── alertmanager.crd.yaml
108+
│ ├── prometheus.crd.yaml
109+
│ ├── prometheusoperator.0.14.0.clusterserviceversion.yaml
110+
│ ├── prometheusrule.crd.yaml
111+
│ └── servicemonitor.crd.yaml
112+
├── 0.15.0
113+
│ ├── alertmanager.crd.yaml
114+
│ ├── prometheus.crd.yaml
115+
│ ├── prometheusoperator.0.15.0.clusterserviceversion.yaml
116+
│ ├── prometheusrule.crd.yaml
117+
│ └── servicemonitor.crd.yaml
118+
├── 0.22.2
119+
│ ├── alertmanager.crd.yaml
120+
│ ├── prometheus.crd.yaml
121+
│ ├── prometheusoperator.0.22.2.clusterserviceversion.yaml
122+
│ ├── prometheusrule.crd.yaml
123+
│ └── servicemonitor.crd.yaml
124+
└── package.yaml
125+
```
126+
127+
which can be pushed to appregistry.
128+
129+
**Note**: the appregistry format is being deprecated in favor of the new index image and image bundle format.
130+
96131
### Container Tooling
97132

98133
Of note, many of these commands require some form of shelling to common container tooling (in the general case at least to pull the bundle image and extract the contents to update the registry). By default, the container tool that `opm` shells to is [podman](https://podman.io/). However, we also support overriding this via the `--container-tool` flag in all of these commands:

‎go.sum

-2
Original file line numberDiff line numberDiff line change
@@ -514,8 +514,6 @@ github.com/openshift/api v3.9.1-0.20190924102528-32369d4db2ad+incompatible/go.mo
514514
github.com/openshift/client-go v0.0.0-20190923180330-3b6373338c9b/go.mod h1:6rzn+JTr7+WYS2E1TExP4gByoABxMznR6y2SnUIkmxk=
515515
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
516516
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
517-
github.com/operator-framework/api v0.0.0-20191127212340-9066a6e95573 h1:bMO43IWWPM3HCGIiuM/GyXjtSJWsrhOlzUpZMesVUw0=
518-
github.com/operator-framework/api v0.0.0-20191127212340-9066a6e95573/go.mod h1:S5IdlJvmKkF84K2tBvsrqJbI2FVy03P88R75snpRxJo=
519517
github.com/operator-framework/api v0.0.0-20200120235816-80fd2f1a09c9 h1:HfxMEPJ0djo/RNfrmli3kI2oKS6IeuIZWu1Q5Rewt/o=
520518
github.com/operator-framework/api v0.0.0-20200120235816-80fd2f1a09c9/go.mod h1:S5IdlJvmKkF84K2tBvsrqJbI2FVy03P88R75snpRxJo=
521519
github.com/operator-framework/operator-lifecycle-manager v0.0.0-20191115003340-16619cd27fa5 h1:rjaihxY50c5C+kbQIK4s36R8zxByATYrgRbua4eiG6o=

‎opm-test.sh

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
set -euxo pipefail
3+
4+
echo "Setting Variables"
5+
read -p "Bunlde image path: " bundleImage
6+
read -p "Index image path: " indexImage
7+
read -p "docker or podman: " containerTool
8+
9+
echo "building opm"
10+
go build -mod=vendor -o bin/opm ./cmd/opm
11+
echo "building prometheus bundles"
12+
./bin/opm alpha bundle build --directory manifests/prometheus/0.14.0 --tag $bundleImage:0.14.0 --package prometheus --channels preview --default preview
13+
./bin/opm alpha bundle build --directory manifests/prometheus/0.15.0 --tag $bundleImage:0.15.0 --package prometheus --channels preview --default preview
14+
./bin/opm alpha bundle build --directory manifests/prometheus/0.22.2 --tag $bundleImage:0.22.2 --package prometheus --channels preview --default preview
15+
echo "pushing prometheus bundles"
16+
docker push $bundleImage:0.14.0
17+
docker push $bundleImage:0.15.0
18+
docker push $bundleImage:0.22.2
19+
echo "building index image with prometheus"
20+
./bin/opm index add -b="$bundleImage:0.14.0,$bundleImage:0.15.0,$bundleImage:0.22.2" -t "$indexImage" -c="$containerTool"
21+
echo "pushing index image"
22+
docker push $indexImage
23+
echo "sleep for 1min before pulling image"
24+
sleep 1m
25+
echo "exporting from index"
26+
./bin/opm index export -i="$indexImage" -o="prometheus" -c="$containerTool"

‎pkg/lib/bundle/exporter.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package bundle
2+
3+
import (
4+
"io/ioutil"
5+
"os"
6+
"path/filepath"
7+
8+
"github.com/otiai10/copy"
9+
"github.com/sirupsen/logrus"
10+
11+
"github.com/operator-framework/operator-registry/pkg/containertools"
12+
)
13+
14+
// BundleExporter exports the manifests of a bundle image into a directory
15+
type BundleExporter struct {
16+
image string
17+
directory string
18+
containerTool string
19+
}
20+
21+
func NewSQLExporterForBundle(image, directory, containerTool string) *BundleExporter {
22+
return &BundleExporter{
23+
image: image,
24+
directory: directory,
25+
containerTool: containerTool,
26+
}
27+
}
28+
29+
func (i *BundleExporter) Export() error {
30+
31+
log := logrus.WithField("img", i.image)
32+
33+
tmpDir, err := ioutil.TempDir("./", "bundle_tmp")
34+
if err != nil {
35+
return err
36+
}
37+
defer os.RemoveAll(tmpDir)
38+
39+
// Pull the image and get the manifests
40+
reader := containertools.NewImageReader(i.containerTool, log)
41+
42+
err = reader.GetImageData(i.image, tmpDir)
43+
if err != nil {
44+
return err
45+
}
46+
if err := os.MkdirAll(i.directory, 0777); err != nil {
47+
return err
48+
}
49+
50+
return copy.Copy(filepath.Join(tmpDir, "manifests"), i.directory)
51+
}

0 commit comments

Comments
 (0)
Please sign in to comment.