-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'main' into facu/capability-docs
- Loading branch information
Showing
22 changed files
with
3,295 additions
and
24 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
codegen: | ||
(cd internal; buf generate) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
# Cosmos SDK Core | ||
|
||
The [cosmossdk.io/core](https://pkg.go.dev/cosmossdk.io/core) go module defines | ||
"core" functionality for the Cosmos SDK. | ||
|
||
Currently functionality for registering modules using the [appmodule](https://pkg.go.dev/cosmossdk.io/core/appmodule) | ||
package and composing apps using the [appconfig](https://pkg.go.dev/cosmossdk.io/core/appconfig) | ||
package is provided. | ||
|
||
In the future core functionality for building Cosmos SDK app modules will be | ||
provided in this go module. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
package appconfig | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
"strings" | ||
|
||
"google.golang.org/protobuf/encoding/protojson" | ||
"google.golang.org/protobuf/proto" | ||
protoreflect "google.golang.org/protobuf/reflect/protoreflect" | ||
"google.golang.org/protobuf/reflect/protoregistry" | ||
"google.golang.org/protobuf/types/known/anypb" | ||
"sigs.k8s.io/yaml" | ||
|
||
"github.com/cosmos/cosmos-sdk/container" | ||
|
||
appv1alpha1 "github.com/cosmos/cosmos-sdk/api/cosmos/app/v1alpha1" | ||
|
||
"cosmossdk.io/core/internal" | ||
) | ||
|
||
// LoadJSON loads an app config in JSON format. | ||
func LoadJSON(bz []byte) container.Option { | ||
config := &appv1alpha1.Config{} | ||
err := protojson.Unmarshal(bz, config) | ||
if err != nil { | ||
return container.Error(err) | ||
} | ||
|
||
return Compose(config) | ||
} | ||
|
||
// LoadYAML loads an app config in YAML format. | ||
func LoadYAML(bz []byte) container.Option { | ||
j, err := yaml.YAMLToJSON(bz) | ||
if err != nil { | ||
return container.Error(err) | ||
} | ||
|
||
return LoadJSON(j) | ||
} | ||
|
||
// Compose composes a v1alpha1 app config into a container option by resolving | ||
// the required modules and composing their options. | ||
func Compose(appConfig *appv1alpha1.Config) container.Option { | ||
opts := []container.Option{ | ||
container.Supply(appConfig), | ||
} | ||
|
||
for _, module := range appConfig.Modules { | ||
if module.Name == "" { | ||
return container.Error(fmt.Errorf("module is missing name")) | ||
} | ||
|
||
if module.Config == nil { | ||
return container.Error(fmt.Errorf("module %q is missing a config object", module.Name)) | ||
} | ||
|
||
msgType, err := protoregistry.GlobalTypes.FindMessageByURL(module.Config.TypeUrl) | ||
if err != nil { | ||
return container.Error(err) | ||
} | ||
|
||
modules, err := internal.ModulesByProtoMessageName() | ||
if err != nil { | ||
return container.Error(err) | ||
} | ||
|
||
init, ok := modules[msgType.Descriptor().FullName()] | ||
if !ok { | ||
modDesc := proto.GetExtension(msgType.Descriptor().Options(), appv1alpha1.E_Module).(*appv1alpha1.ModuleDescriptor) | ||
if modDesc == nil { | ||
return container.Error(fmt.Errorf("no module registered for type URL %s and that protobuf type does not have the option %s\n\n%s", | ||
module.Config.TypeUrl, appv1alpha1.E_Module.TypeDescriptor().FullName(), dumpRegisteredModules(modules))) | ||
} | ||
|
||
return container.Error(fmt.Errorf("no module registered for type URL %s, did you forget to import %s\n\n%s", | ||
module.Config.TypeUrl, modDesc.GoImport, dumpRegisteredModules(modules))) | ||
} | ||
|
||
config := init.ConfigProtoMessage.ProtoReflect().Type().New().Interface() | ||
err = anypb.UnmarshalTo(module.Config, config, proto.UnmarshalOptions{}) | ||
if err != nil { | ||
|
||
return container.Error(err) | ||
} | ||
|
||
opts = append(opts, container.Provide(container.ProviderDescriptor{ | ||
Inputs: nil, | ||
Outputs: []container.ProviderOutput{{Type: init.ConfigGoType}}, | ||
Fn: func(values []reflect.Value) ([]reflect.Value, error) { | ||
return []reflect.Value{reflect.ValueOf(config)}, nil | ||
}, | ||
Location: container.LocationFromCaller(0), | ||
})) | ||
|
||
for _, provider := range init.Providers { | ||
opts = append(opts, container.ProvideInModule(module.Name, provider)) | ||
} | ||
} | ||
|
||
return container.Options(opts...) | ||
} | ||
|
||
func dumpRegisteredModules(modules map[protoreflect.FullName]*internal.ModuleInitializer) string { | ||
var mods []string | ||
for name := range modules { | ||
mods = append(mods, " "+string(name)) | ||
} | ||
return fmt.Sprintf("registered modules are:\n%s", strings.Join(mods, "\n")) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
package appconfig_test | ||
|
||
import ( | ||
"bytes" | ||
"reflect" | ||
"testing" | ||
|
||
"gotest.tools/v3/assert" | ||
|
||
"github.com/cosmos/cosmos-sdk/container" | ||
|
||
"cosmossdk.io/core/appconfig" | ||
"cosmossdk.io/core/appmodule" | ||
"cosmossdk.io/core/internal" | ||
"cosmossdk.io/core/internal/testpb" | ||
_ "cosmossdk.io/core/internal/testpb" | ||
) | ||
|
||
func expectContainerErrorContains(t *testing.T, option container.Option, contains string) { | ||
t.Helper() | ||
err := container.Build(option) | ||
assert.ErrorContains(t, err, contains) | ||
} | ||
|
||
func TestCompose(t *testing.T) { | ||
opt := appconfig.LoadJSON([]byte(`{"modules":[{}]}`)) | ||
expectContainerErrorContains(t, opt, "module is missing name") | ||
|
||
opt = appconfig.LoadJSON([]byte(`{"modules":[{"name": "a"}]}`)) | ||
expectContainerErrorContains(t, opt, `module "a" is missing a config object`) | ||
|
||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: a | ||
config: | ||
"@type": testpb.ModuleFoo | ||
`)) | ||
expectContainerErrorContains(t, opt, `unable to resolve`) | ||
|
||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: a | ||
config: | ||
"@type": cosmos.app.v1alpha1.Config # this is not actually a module config type! | ||
`)) | ||
expectContainerErrorContains(t, opt, "does not have the option cosmos.app.v1alpha1.module") | ||
expectContainerErrorContains(t, opt, "registered modules are") | ||
expectContainerErrorContains(t, opt, "testpb.TestModuleA") | ||
|
||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: a | ||
config: | ||
"@type": testpb.TestUnregisteredModule | ||
`)) | ||
expectContainerErrorContains(t, opt, "did you forget to import cosmossdk.io/core/internal/testpb") | ||
expectContainerErrorContains(t, opt, "registered modules are") | ||
expectContainerErrorContains(t, opt, "testpb.TestModuleA") | ||
|
||
var app testpb.App | ||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: runtime | ||
config: | ||
"@type": testpb.TestRuntimeModule | ||
- name: a | ||
config: | ||
"@type": testpb.TestModuleA | ||
- name: b | ||
config: | ||
"@type": testpb.TestModuleB | ||
`)) | ||
assert.NilError(t, container.Build(opt, &app)) | ||
buf := &bytes.Buffer{} | ||
app(buf) | ||
const expected = `got store key a | ||
got store key b | ||
running module handler a | ||
result: hello | ||
running module handler b | ||
result: goodbye | ||
` | ||
assert.Equal(t, expected, buf.String()) | ||
|
||
// module registration failures: | ||
appmodule.Register(&testpb.TestNoModuleOptionModule{}) | ||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: a | ||
config: | ||
"@type": testpb.TestNoGoImportModule | ||
`)) | ||
expectContainerErrorContains(t, opt, "module should have the option cosmos.app.v1alpha1.module") | ||
|
||
internal.ModuleRegistry = map[reflect.Type]*internal.ModuleInitializer{} // reset module registry | ||
appmodule.Register(&testpb.TestNoGoImportModule{}) | ||
opt = appconfig.LoadYAML([]byte(` | ||
modules: | ||
- name: a | ||
config: | ||
"@type": testpb.TestNoGoImportModule | ||
`)) | ||
expectContainerErrorContains(t, opt, "module should have ModuleDescriptor.go_import specified") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// Package appconfig defines functionality for loading declarative Cosmos SDK | ||
// app configurations. | ||
package appconfig |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
// Package appmodule defines the functionality for registering Cosmos SDK app | ||
// modules that are assembled using the github.com/cosmos/cosmos-sdk/container | ||
// dependency injection system and the declarative app configuration format | ||
// handled by the appconfig package. | ||
package appmodule |
Oops, something went wrong.