Skip to content

Commit

Permalink
adding call to pyxis for non EOL catalogs and updating imagestream logic
Browse files Browse the repository at this point in the history
Signed-off-by: Adam D. Cornett <[email protected]>
  • Loading branch information
acornett21 committed Aug 19, 2024
1 parent 81fab96 commit d124aba
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 26 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ require (
github.com/onsi/gomega v1.34.1
github.com/openshift/api v0.0.0-20240802200810-346347bccbc8
github.com/operator-framework/api v0.26.0
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466
github.com/tektoncd/pipeline v0.62.0
k8s.io/api v0.30.3
k8s.io/apimachinery v0.30.3
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,8 @@ github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDN
github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
Expand Down
72 changes: 72 additions & 0 deletions internal/pyxis/pyxis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package pyxis

import (
"context"
"fmt"
"net/http"

"github.com/shurcooL/graphql"
)

const (
DefaultPyxisHost = "catalog.redhat.com/api/containers"
)

type PyxisClient struct {
Client *http.Client
PyxisHost string
}

func (p *PyxisClient) getPyxisGraphqlURL() string {
return fmt.Sprintf("https://%s/graphql/", p.PyxisHost)
}

func NewPyxisClient(pyxisHost string, httpClient *http.Client) *PyxisClient {
return &PyxisClient{
Client: httpClient,
PyxisHost: pyxisHost,
}
}

func (p *PyxisClient) FindOperatorIndices(ctx context.Context, organization string) ([]OperatorIndex, error) {
// our graphQL query
var query struct {
FindOperatorIndices struct {
OperatorIndex []struct {
OCPVersion graphql.String `graphql:"ocp_version"`
Organization graphql.String `graphql:"organization"`
EndOfLife graphql.String `graphql:"end_of_life"`
} `graphql:"data"`
Errors struct {
Status graphql.Int `graphql:"status"`
Detail graphql.String `graphql:"detail"`
} `graphql:"error"`
Total graphql.Int
Page graphql.Int
// filter to make sure we get exact results, end_of_life is a string, querying for `null` yields active OCP versions.
} `graphql:"find_operator_indices(filter:{and:[{organization:{eq:$organization}},{end_of_life:{eq:null}}]})"`
}

// variables to feed to our graphql filter
variables := map[string]interface{}{
"organization": graphql.String(organization),
}

// make our query
client := graphql.NewClient(p.getPyxisGraphqlURL(), p.Client)

err := client.Query(ctx, &query, variables)
if err != nil {
return nil, fmt.Errorf("error while executing remote query for %s catalogs: %v", organization, err)
}

operatorIndices := make([]OperatorIndex, len(query.FindOperatorIndices.OperatorIndex))
for idx, operator := range query.FindOperatorIndices.OperatorIndex {
operatorIndices[idx] = OperatorIndex{
OCPVersion: string(operator.OCPVersion),
Organization: string(operator.Organization),
}
}

return operatorIndices, nil
}
7 changes: 7 additions & 0 deletions internal/pyxis/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package pyxis

type OperatorIndex struct {
OCPVersion string `json:"ocp_version"`
Organization string `json:"organization"`
EndOfLife string `json:"end_of_life,omitempty"`
}
47 changes: 34 additions & 13 deletions internal/reconcilers/certified_image_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package reconcilers

import (
"context"
"fmt"
"net/http"
"time"

"github.com/redhat-openshift-ecosystem/operator-certification-operator/api/v1alpha1"
"github.com/redhat-openshift-ecosystem/operator-certification-operator/internal/objects"
"github.com/redhat-openshift-ecosystem/operator-certification-operator/internal/pyxis"

"github.com/go-logr/logr"
imagev1 "github.com/openshift/api/image/v1"
Expand All @@ -22,20 +26,29 @@ const (

type CertifiedImageStreamReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Log logr.Logger
Scheme *runtime.Scheme
PyxisClient *pyxis.PyxisClient
}

func NewCertifiedImageStreamReconciler(client client.Client, log logr.Logger, scheme *runtime.Scheme) *CertifiedImageStreamReconciler {
return &CertifiedImageStreamReconciler{
Client: client,
Log: log,
Scheme: scheme,
PyxisClient: pyxis.NewPyxisClient(
pyxis.DefaultPyxisHost,
&http.Client{Timeout: 60 * time.Second}),
}
}

// reconcileCertifiedImageStream will ensure that the certified operator ImageStream is present and up to date.
func (r *CertifiedImageStreamReconciler) Reconcile(ctx context.Context, pipeline *v1alpha1.OperatorPipeline) (bool, error) {
operatorIndices, err := r.PyxisClient.FindOperatorIndices(ctx, "certified-operators")
if err != nil {
return true, err
}

key := types.NamespacedName{
Namespace: pipeline.Namespace,
Name: certifiedIndex,
Expand All @@ -62,19 +75,27 @@ func (r *CertifiedImageStreamReconciler) Reconcile(ctx context.Context, pipeline

imgImport := newImageStreamImport(key)
imgImport.Spec.Import = true
imgImport.Spec.Repository = &imagev1.RepositoryImportSpec{
From: corev1.ObjectReference{
Kind: "DockerImage",
Name: "registry.redhat.io/redhat/certified-operator-index",
},
ImportPolicy: imagev1.TagImportPolicy{
Scheduled: true,
},
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},

imageSpecs := make([]imagev1.ImageImportSpec, 0, len(operatorIndices))

for _, index := range operatorIndices {
imageSpec := imagev1.ImageImportSpec{
From: corev1.ObjectReference{
Kind: "DockerImage",
Name: fmt.Sprintf("%s:v%s", "registry.redhat.io/redhat/certified-operator-index", index.OCPVersion),
},
ImportPolicy: imagev1.TagImportPolicy{
Scheduled: true,
},
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},
}
imageSpecs = append(imageSpecs, imageSpec)
}

imgImport.Spec.Images = imageSpecs

log.Info("creating new certified image stream import")
if err := r.Client.Create(ctx, imgImport); err != nil {
return true, err
Expand Down
47 changes: 34 additions & 13 deletions internal/reconcilers/marketplace_image_stream.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,13 @@ package reconcilers

import (
"context"
"fmt"
"net/http"
"time"

"github.com/redhat-openshift-ecosystem/operator-certification-operator/api/v1alpha1"
"github.com/redhat-openshift-ecosystem/operator-certification-operator/internal/objects"
"github.com/redhat-openshift-ecosystem/operator-certification-operator/internal/pyxis"

"github.com/go-logr/logr"
imagev1 "github.com/openshift/api/image/v1"
Expand All @@ -21,20 +25,29 @@ const (

type MarketplaceImageStreamReconciler struct {
client.Client
Log logr.Logger
Scheme *runtime.Scheme
Log logr.Logger
Scheme *runtime.Scheme
PyxisClient *pyxis.PyxisClient
}

func NewMarketplaceImageStreamReconciler(client client.Client, log logr.Logger, scheme *runtime.Scheme) *MarketplaceImageStreamReconciler {
return &MarketplaceImageStreamReconciler{
Client: client,
Log: log,
Scheme: scheme,
PyxisClient: pyxis.NewPyxisClient(
pyxis.DefaultPyxisHost,
&http.Client{Timeout: 60 * time.Second}),
}
}

// reconcileMarketplaceImageStream will ensure that the Red Hat Marketplace ImageStream is present and up to date.
func (r *MarketplaceImageStreamReconciler) Reconcile(ctx context.Context, pipeline *v1alpha1.OperatorPipeline) (bool, error) {
operatorIndices, err := r.PyxisClient.FindOperatorIndices(ctx, "redhat-marketplace")
if err != nil {
return true, err
}

key := types.NamespacedName{
Namespace: pipeline.Namespace,
Name: marketplaceIndex,
Expand All @@ -61,19 +74,27 @@ func (r *MarketplaceImageStreamReconciler) Reconcile(ctx context.Context, pipeli

imgImport := newImageStreamImport(key)
imgImport.Spec.Import = true
imgImport.Spec.Repository = &imagev1.RepositoryImportSpec{
From: corev1.ObjectReference{
Kind: "DockerImage",
Name: "registry.redhat.io/redhat/redhat-marketplace-index",
},
ImportPolicy: imagev1.TagImportPolicy{
Scheduled: true,
},
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},

imageSpecs := make([]imagev1.ImageImportSpec, 0, len(operatorIndices))

for _, index := range operatorIndices {
imageSpec := imagev1.ImageImportSpec{
From: corev1.ObjectReference{
Kind: "DockerImage",
Name: fmt.Sprintf("%s:v%s", "registry.redhat.io/redhat/redhat-marketplace-index", index.OCPVersion),
},
ImportPolicy: imagev1.TagImportPolicy{
Scheduled: true,
},
ReferencePolicy: imagev1.TagReferencePolicy{
Type: imagev1.LocalTagReferencePolicy,
},
}
imageSpecs = append(imageSpecs, imageSpec)
}

imgImport.Spec.Images = imageSpecs

log.Info("creating new marketplace image stream import")
if err := r.Client.Create(ctx, imgImport); err != nil {
return true, err
Expand Down

0 comments on commit d124aba

Please sign in to comment.