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

control-plane: introduce a client for Konvoy REST API in the form of "remote" ResourceStore #73

Merged
merged 5 commits into from
Aug 1, 2019

Conversation

yskopets
Copy link
Contributor

@yskopets yskopets commented Jul 25, 2019

Context:

  • konvoyctl must be able to request and unmarshal a list of resources from Konvoy API Server

Changes:

  • introduce model.ResourceRegistry abstraction to instantiate a resource by its ResourceType
  • introduce rest.ResourceListReceiver type to unmarshal into rest.ResourceList
  • introduce rest.Mapper abstraction to describe REST representation of a resource
  • introduce a client for Konvoy API Server in the form of "remote" ResourceStore

@yskopets yskopets added this to the 0.1 milestone Jul 25, 2019
@yskopets yskopets changed the title control-plane: unmarshal rest.ResourceList control-plane: introduce a client for Konvoy REST API in the form of "remote" ResourceStore Jul 25, 2019
@yskopets yskopets force-pushed the feature/unmarshal-rest-resourcelist branch 2 times, most recently from 2c4bb11 to 92ef280 Compare July 25, 2019 18:15
return m.Version
}

func NewStore(client http.Client, mapper rest.Mapper) store.ResourceStore {
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need this Mapper abstraction? Why just pass there WsDefinitions and use them internally.
Why this is an interface? What other implementation do you expect to see?

btw. Mapper don't tell me much. What does it maps? How about ResourcePaths. ResourcePaths.get(resource).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

WsDefinitions is a server-side description of the API, rest.Mapper is a client-side counterpart.

Between plain map[model.ResourceType]ResourceMapping and func(model.ResourceType) (ResourceMapping, error) I chose the latter to avoid inconsistent handling of missing types by client code.

And then it's a design principle to promote a function into a single method interface.

Copy link
Contributor

Choose a reason for hiding this comment

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

WsDefinitions is a server-side description of the API

It's server side, but it's used for client anyways, just after one layer.

inconsistent handling of missing types by client code

where this incosistency can occur?
func(model.ResourceType) (ResourceMapping, error) can be just a method of remoteStore that uses the map.

I'm fine with this mapper, but please rename it to more descriptive name like ResourcePaths

Copy link
Contributor Author

Choose a reason for hiding this comment

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

rest.Mapper was renamed into rest.Api

return err
}
for _, ri := range rsr.ResourceList.Items {
r := rs.NewItem()
Copy link
Contributor

Choose a reason for hiding this comment

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

This is question for the whole codebase. Why do we name the variables with such a short name?
I get that receiver s *remoteStore is short, because it's used all the time (although I'd prefer this, but this seems not to be go way...), but
rsr, b, ri, r? Why not listReceiver, body, listItem, item?
Sometimes is hard to follow and I need to go back to variable declaration to remember what was that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

"idiomatic golang"

Copy link
Contributor

Choose a reason for hiding this comment

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

I like to be pragmatic. If convention hurts readability then it's maybe not the best one.
Clean code (descriptive names) can be applied no mater what is the languages. I'm not a fan of superLongNamedFromTheJavaWorld, but I think there should be a middle ground somewhere.

if err := json.Unmarshal(b, &r.Meta); err != nil {
return err
}
cr, err := newResource(model.ResourceType(r.Meta.Type))
Copy link
Contributor

Choose a reason for hiding this comment

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

what does cr stands for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

core resource

ResourceRegistry: &model.SimpleResourceRegistry{
ResourceTypes: map[model.ResourceType]model.Resource{
(rs.GetItemType()): rs.NewItem(),
},
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we need a ResourceRegistry with interface and impl if all we support is one type, that we already know. Why don't we just pass function to ResourceListReceiver for creating a new item.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ResourceRegistry is an interface for creating a new item of any supported type.

A function can always be wrapped into ResourceRegistry (e.g., http.Handler and http.HandlerFunc).

I could replace in-place instantiation ( &model.SimpleResourceRegistry{ ... } ) with a factory method, e.g. SingleTypeRegistry(model.ResourceList)

Copy link
Contributor

Choose a reason for hiding this comment

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

I understand what it is, but why do we need it? Why not just have

type ResourceListReceiver struct {
	ResourceList
        NewResource func() Resource
}

I think that Go code strives to be simpler without unnecessary abstractions which is common in Java.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Changed to

type ResourceListReceiver struct {
	ResourceList
        NewResource func() Resource
}

@yskopets yskopets force-pushed the feature/unmarshal-rest-resourcelist branch from 92ef280 to 560a7fc Compare August 1, 2019 18:04
@yskopets yskopets merged commit 68c3e3e into master Aug 1, 2019
@yskopets yskopets deleted the feature/unmarshal-rest-resourcelist branch August 13, 2019 22:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants