-
Notifications
You must be signed in to change notification settings - Fork 51
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
Chain APIs for orderer, application, consortium, and channel operations #11
Conversation
c0dfc2d
to
3ed3691
Compare
@wlahti per CI, looks like theres a couple of linting issues with comments on exported functions |
/ci-run |
1 similar comment
/ci-run |
You are not authorized to trigger builds for this pull request! |
Will, we enabled the |
You are not authorized to trigger builds for this pull request! |
f4756c0
to
b7c21fc
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started looking at this fairly closely but decided to step back once I got to the examples.
From my perspective, the examples are the key to all of this. I really want to see examples that show how to use the library. That should drive out the API bits that we need. When I look through the examples, I don't see any references to OriginalConfig
. We use a pattern where we create an object that is populated from state in the original config (and we maintain it for our delta computation) but it's never something that someone using the API ever gets.
So, why do we have it? Do we really need it? If we don't need it, then we remove at least one level of chaining that exists already.
The other thing that stands out to me is that we didn't really update the examples to show how chaining would work in practice. All of the calls seem to use the same prefix pattern instead of holding onto the state and modifying the things that need to modified.
Then there are chains like this:
c.UpdatedConfig().Consortiums().Consortium("SampleConsortium").SetChannelCreationPolicy(...)
where I wonder if Consortium(name string)
and Consortiums()
are the correct API. This style lines up nicely with the REST patterns most of us a used to where the plural form results in a list and the singular form allows a reference to a single instance based on a qualifier.
I know I haven't been involved in the day-to-day of this for a bit so I don't know all of the consideration that went into what's here right now. My ask is that we really put ourselves into the consumer's shoes and see if what's being surfaced is what we'd wand to use.
configtx/capabilities_test.go
Outdated
@@ -37,13 +37,13 @@ func TestChannelCapabilities(t *testing.T) { | |||
err := setValue(config.ChannelGroup, capabilitiesValue(expectedCapabilities), AdminsPolicyKey) | |||
gt.Expect(err).NotTo(HaveOccurred()) | |||
|
|||
channelCapabilities, err := c.ChannelCapabilities() | |||
channelCapabilities, err := c.OriginalConfig().Channel().Capabilities() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the Config
suffix?
configtx/channel.go
Outdated
// UpdatedChannelGroup is a ChannelGroup that can be modified in order to | ||
// generate a config update. | ||
type UpdatedChannelGroup struct { | ||
*ChannelGroup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice.
configtx/channel.go
Outdated
var ( | ||
err error | ||
consortium string | ||
application Application | ||
orderer Orderer | ||
consortiums []Consortium | ||
capabilities []string | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of 6 vars, should this simply be a Channel and err? Not sure the temporary is buying much since you're just populating the channel object.
Basically, assign each field after getting the data instead of carrying things. That keeps each of the field related blocks together. Given the length of the method, I think that would be easier to read.
configtx/application_test.go
Outdated
@@ -361,7 +361,7 @@ func TestAddAnchorPeer(t *testing.T) { | |||
err = c.AddAnchorPeer("Org2", newOrg2AnchorPeer) | |||
gt.Expect(err).NotTo(HaveOccurred()) | |||
|
|||
gt.Expect(proto.Equal(c.UpdatedConfig(), expectedUpdatedConfig)).To(BeTrue()) | |||
gt.Expect(proto.Equal(c.UpdatedConfig().Config, expectedUpdatedConfig)).To(BeTrue()) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As a follow-on, I'd suggest writing a matcher and using it.
configtx/capabilities_test.go
Outdated
@@ -67,13 +67,13 @@ func TestOrdererCapabilities(t *testing.T) { | |||
|
|||
c := New(config) | |||
|
|||
ordererCapabilities, err := c.OrdererCapabilities() | |||
ordererCapabilities, err := c.OriginalConfig().Orderer().Capabilities() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I may have said this already in a different section but I think removing the Config
suffix from Original and Updated would probably be a good move.
configtx/example_test.go
Outdated
orderer.Kafka.Brokers = []string{"kafka0:9092", "kafka1:9092", "kafka2:9092"} | ||
orderer.BatchSize.MaxMessageCount = 500 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is where embedding is good; makes it easy to change the updated version. It's modification of the original that I worry about but it may not be a problem...
configtx/example_test.go
Outdated
if err != nil { | ||
panic(err) | ||
} | ||
|
||
orderer.Kafka.Brokers = []string{"kafka0:9092", "kafka1:9092", "kafka2:9092"} | ||
orderer.BatchSize.MaxMessageCount = 500 | ||
|
||
err = c.SetOrdererConfiguration(orderer) | ||
err = c.UpdatedConfig().Orderer().SetConfiguration(orderer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The repeated use of the chain does not demonstrate how I'd expect this to be used IRL. Why isn't the orderer reference obtained and maintained across the calls?
configtx/example_test.go
Outdated
err = c.UpdatedConfig().Orderer().Organization("OrdererOrg").RemovePolicy(configtx.WritersPolicyKey) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
err = c.SetOrdererOrgPolicy("OrdererOrg", configtx.AdminsPolicyKey, "TestPolicy", | ||
err = c.UpdatedConfig().Orderer().Organization("OrdererOrg").SetPolicy( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here; The first half of the chain is the reference that should be maintained.
configtx/example_test.go
Outdated
err = c.UpdatedConfig().Orderer().RemovePolicy(configtx.WritersPolicyKey) | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
err = c.SetOrdererPolicy(configtx.AdminsPolicyKey, "TestPolicy", configtx.Policy{ | ||
err = c.UpdatedConfig().Orderer().SetPolicy(configtx.AdminsPolicyKey, "TestPolicy", configtx.Policy{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And here. :) This is an example.
I'll assume this applies to the other occurrences as well.
configtx/example_test.go
Outdated
baseConfig := fetchChannelConfig() | ||
c := configtx.New(baseConfig) | ||
|
||
msp, err := c.OrdererMSP("OrdererOrg") | ||
msp, err := c.UpdatedConfig().Orderer().Organization("OrdererOrg").MSP() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little odd for me that, as a user, I'd create a new object from the base config and then have to call UpdatedConfig
to get the thing I can actually work with.
So, why is that the case?
7202497
to
8a8de75
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored the Original/UpdatedConfig logic to simplify things and address your comments.
configtx/config.go
Outdated
@@ -274,7 +287,7 @@ func newSystemChannelGroup(channelConfig Channel) (*cb.ConfigGroup, error) { | |||
|
|||
err = setPolicies(channelGroup, channelConfig.Policies, AdminsPolicyKey) | |||
if err != nil { | |||
return nil, fmt.Errorf("failed to set system channel policies: %v", err) | |||
return nil, fmt.Errorf("failed to add system channel policies: %v", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch. Done.
0b68f8c
to
63b156d
Compare
FAB-17744 Signed-off-by: Will Lahti <[email protected]>
FAB-17744 Signed-off-by: Will Lahti <[email protected]>
FAB-17744 Signed-off-by: Will Lahti <[email protected]>
FAB-17744 Signed-off-by: Will Lahti <[email protected]>
FAB-17744 Signed-off-by: Will Lahti <[email protected]>
Change from c.Consortiums().Consortium() to c.Consortium(). FAB-17744 Signed-off-by: Will Lahti <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
After some discussion back and forth offline we've come to a better conclusion on this track of work. I'm going to go ahead and merge this as it seems like the direction we're going in with the chaining of the APIs is appropriate and we can iterate more on it to cleanup small nuances
Type of change
Description
First commit:
Second commit:
Third commit:
Fourth commit:
Related issues
FAB-17744