Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reconcile OperatorSource type #4

Merged
merged 1 commit into from
Sep 26, 2018

Conversation

tkashem
Copy link
Collaborator

@tkashem tkashem commented Sep 24, 2018

Reconcile OperatorSource type by doing the following in order:

  • Pull down operator manifests from the specified app registry server and store them locally.
  • Create a corresponding CatalogSourceConfig instance.

@openshift-ci-robot openshift-ci-robot added the size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files. label Sep 24, 2018
Gopkg.lock Show resolved Hide resolved
Gopkg.toml Show resolved Hide resolved
Gopkg.lock Show resolved Hide resolved
cmd/marketplace-operator/main.go Show resolved Hide resolved
// Type of operator source
Type string `json:"type"`

// Source points to the URL from where operator manifests can be fetched
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Endpoint points to...


// Given a name of an instance of OperatorSource type, this function returns the name of the associated CatalogSourceConfig type object
func getCatalogSourceConfigName(operatorSourceName string) string {
return fmt.Sprintf("os-%s", operatorSourceName)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the os prefix to something else given that is such an overloaded (Operating System, OpenShift etc) abbreviation. Plus I think it is an internal Go package name. I suggest opsrc or some such thing.

Nit: you could go a step further and make the prefix a constant like we have for CatalogSourceConfig.

return fmt.Sprintf("os-%s", operatorSourceName)
}

func (r *reconciler) IsAlreadyReconciled(os *v1alpha1.OperatorSource) (bool, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above for the os variable name. I had to do a double take to realize you mean OperatorSource :-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i like opsrc :)

pkg/operatorsource/reconciler.go Show resolved Hide resolved
)

func TestReconcile(t *testing.T) {
os.Setenv("KUBERNETES_CONFIG", getKubeConfigFilePath())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same request as above

Copy link
Collaborator Author

@tkashem tkashem Sep 25, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

taken care of

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the config doesn't exist? Won't it be better to catch that and make the test fail gracefully ?

pkg/stub/handler.go Show resolved Hide resolved
@tkashem tkashem force-pushed the registry branch 4 times, most recently from b40a36a to 53d849d Compare September 25, 2018 20:23
@tkashem
Copy link
Collaborator Author

tkashem commented Sep 25, 2018

@aravindhp let me know if you have more comments

Copy link
Member

@aravindhp aravindhp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Everything looks good except for the two unresolved comments.

)

func TestReconcile(t *testing.T) {
os.Setenv("KUBERNETES_CONFIG", getKubeConfigFilePath())
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the config doesn't exist? Won't it be better to catch that and make the test fail gracefully ?

@aravindhp
Copy link
Member

LGTM to me except for #4 (comment)

specified app registry server and making it available to the cluster
@aravindhp aravindhp merged commit e304bbc into operator-framework:master Sep 26, 2018
@@ -31,10 +31,12 @@ func main() {
if err != nil {
logrus.Fatalf("failed to get watch namespace: %v", err)
}
resyncPeriod := time.Duration(5) * time.Second
logrus.Infof("Watching %s, %s, %s", resource, catalogSourceConfigKind, namespace)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove blank lines.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resyncPeriod is shared by the two types here, hence it gets its own spacing.

@@ -0,0 +1,48 @@
package appregistry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole file could be named as factory.go

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, good point. I thought about it. I also like the idea of a {package name}.go file which has the entry level function for the given package. NewFactory is the entry level function one must call to use the appregistry package.

mediaType string = "helm"
)

// This interface (internal to this package) encapsulates nitty gritty details of go-appr client bindings
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment could have been a bit more clear on why 3 methods.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's all we need for this iteration. Do you want more clarity on why this interface exists? I don't think we need to explain why an interface has N number of methods.

}

func (a *apprApiAdapterImpl) ListPackages() (appr_models.Packages, error) {
params := appr_package.NewListPackagesParams()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we allow listing packages within a namespace? I think we should allow some filtering here

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I already have a new PR in review that allows to filter by namespace.

func TestRetrieveAll(t *testing.T) {
factory := appregistry.NewClientFactory()

client, err := factory.New("appregistry", "http://localhost:5000/cnr")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure, if the assumption is we have some service running on 5000? Or did you mock it somewhere?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is hanging around here for debugging purposes. It will be replaced by a unit test.

@@ -0,0 +1,22 @@
package appregistry_test
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why a new package for testing?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am treating this test as a black box test, hence a new package for test(s) and explicit import of package being tested.

return nil, err
}

list := make([]*OperatorMetadata, len(packages))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

operatorMetaDataList probably would have made more sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have to implement a operatorMetaDataList. This is not a k8s type.

for i, pkg := range packages {
manifest, err := c.RetrieveOne(pkg.Name, pkg.Default)
if err != nil {
return nil, err
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want to return error, if retrieving one package is erroring? It could that one package is misbehaving, probably aggregated errorlist would make more sense.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a rudimentary version geared toward the proof of concept. I am working on prod ready reconciliation process now.

"io"
)

type blobDecoder interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you could have avoided interface altogether here and just used the struct.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On the contrary, I can easily mock this interface when I am testing the unit that depends on this interface, Look at TestRetrieveOne_PackageExists_SuccessExpected. Not shy to use interfaces :)

// Source: ./pkg/appregistry/adapter.go

// Package appregistry is a generated GoMock package.
package appregistry
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this here? Either we shouldn't checkin the generated code or if we absolutely need it we should create a script to generate it. I thought appregistry is not generated

}
}

type hashmapDatastore struct {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the name to something appropriate like DataStore

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, do you have any suggestions? MemoryDatastore, TransientDatastore or DummyDatastore maybe? :)

}

type hashmapDatastore struct {
list map[string]*appregistry.OperatorMetadata
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change list to something appropriate.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm, I can rename it to packages. That is not so generic as list

}

type Handler struct {
// Fill me
operatorSourceHanlder operatorsource.Handler
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo..

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size/XXL Denotes a PR that changes 1000+ lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants