Skip to content

Commit

Permalink
feat(images): add support for storing and querying related images
Browse files Browse the repository at this point in the history
this uses the `relatedImages` field from the CSV and also extracts
operator images from the deployment specs of CSVs.
  • Loading branch information
ecordell committed Oct 22, 2019
1 parent d57e46a commit 91e63e7
Show file tree
Hide file tree
Showing 12 changed files with 536 additions and 12 deletions.
5 changes: 5 additions & 0 deletions configmap.example.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5710,6 +5710,11 @@ data:
annotations:
tectonic-visibility: ocs
spec:
relatedImages:
- name: etcd-v3.4.0
image: quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84
- name: etcd-3.4.1
image: quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f
displayName: etcd
description: |
etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ metadata:
tectonic-visibility: ocs
alm-examples: '[{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdCluster","metadata":{"name":"example","namespace":"default"},"spec":{"size":3,"version":"3.2.13"}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdRestore","metadata":{"name":"example-etcd-cluster"},"spec":{"etcdCluster":{"name":"example-etcd-cluster"},"backupStorageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}},{"apiVersion":"etcd.database.coreos.com/v1beta2","kind":"EtcdBackup","metadata":{"name":"example-etcd-cluster-backup"},"spec":{"etcdEndpoints":["<etcd-cluster-endpoints>"],"storageType":"S3","s3":{"path":"<full-s3-path>","awsSecret":"<aws-secret>"}}}]'
spec:
relatedImages:
- name: etcd-v3.4.0
image: quay.io/coreos/etcd@sha256:3816b6daf9b66d6ced6f0f966314e2d4f894982c6b1493061502f8c2bf86ac84
- name: etcd-3.4.1
image: quay.io/coreos/etcd@sha256:49d3d4a81e0d030d3f689e7167f23e120abf955f7d08dbedf3ea246485acee9f
displayName: etcd
description: |
etcd is a distributed key value store that provides a reliable way to store data across a cluster of machines. It’s open-source and available on GitHub. etcd gracefully handles leader elections during network partitions and will tolerate machine failure, including the leader. Your applications can read and write data into etcd.
Expand Down
22 changes: 22 additions & 0 deletions pkg/registry/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,28 @@ func (b *Bundle) Serialize() (csvName string, csvBytes []byte, bundleBytes []byt
return csvName, csvBytes, bundleBytes, nil
}

func (b *Bundle) Images() (map[string]struct{}, error) {
csv, err := b.ClusterServiceVersion()
if err != nil {
return nil, err
}

images, err := csv.GetOperatorImages()
if err != nil {
return nil, err
}

relatedImages, err := csv.GetRelatedImages()
if err != nil {
return nil, err
}
for img := range relatedImages {
images[img] = struct{}{}
}

return images, nil
}

func (b *Bundle) cache() error {
if !b.cacheStale {
return nil
Expand Down
75 changes: 75 additions & 0 deletions pkg/registry/csv.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package registry
import (
"encoding/json"

v1 "k8s.io/api/apps/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand All @@ -28,6 +29,9 @@ const (
// The yaml attribute that specifies the version of the ClusterServiceVersion
// expected to be semver and parseable by blang/semver
version = "version"

// The yaml attribute that specifies the related images of the ClusterServiceVersion
relatedImages = "relatedImages"
)

// ClusterServiceVersion is a structured representation of cluster service
Expand Down Expand Up @@ -187,3 +191,74 @@ func (csv *ClusterServiceVersion) GetApiServiceDefinitions() (owned []*Definitio
required = definitions.Required
return
}

// GetRelatedImage returns the list of associated images for the operator
func (csv *ClusterServiceVersion) GetRelatedImages() (imageSet map[string]struct{}, err error) {
var objmap map[string]*json.RawMessage
imageSet = make(map[string]struct{})

if err = json.Unmarshal(csv.Spec, &objmap); err != nil {
return
}

rawValue, ok := objmap[relatedImages]
if !ok || rawValue == nil {
return
}

type relatedImage struct {
Name string `json:"name"`
Ref string `json:"image"`
}
var relatedImages []relatedImage
if err = json.Unmarshal(*rawValue, &relatedImages); err != nil {
return
}

for _, img := range relatedImages {
imageSet[img.Ref] = struct{}{}
}

return
}

// GetOperatorImages returns a list of any images used to run the operator.
// Currently this pulls any images in the pod specs of operator deployments.
func (csv *ClusterServiceVersion) GetOperatorImages() (map[string]struct{}, error) {
type dep struct {
Name string
Spec v1.DeploymentSpec
}
type strategySpec struct {
Deployments []dep
}
type strategy struct {
Name string `json:"strategy"`
Spec strategySpec `json:"spec"`
}
type csvSpec struct {
Install strategy
}

var spec csvSpec
if err := json.Unmarshal(csv.Spec, &spec); err != nil {
return nil, err
}

// this is the only install strategy we know about
if spec.Install.Name != "deployment" {
return nil, nil
}

images := map[string]struct{}{}
for _, d := range spec.Install.Spec.Deployments {
for _, c := range d.Spec.Template.Spec.Containers {
images[c.Image] = struct{}{}
}
for _, c := range d.Spec.Template.Spec.InitContainers {
images[c.Image] = struct{}{}
}
}

return images, nil
}
Loading

0 comments on commit 91e63e7

Please sign in to comment.