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

Support flexible folder structures #542

Merged
merged 1 commit into from
Feb 6, 2019
Merged

Support flexible folder structures #542

merged 1 commit into from
Feb 6, 2019

Conversation

jacobgreenleaf
Copy link
Contributor

@jacobgreenleaf jacobgreenleaf commented Jan 9, 2019

An assumption of the base module system was that the module classes (clients, endpoints, etc.) would have a single folder structure that would be extended (but not modified) by consumer applications. Specifically, the code generation system is given a base directory (baseDirectory) and it assumes the built-in modules would be located in exactly the subdirectory of that base directory (e.g. if baseDirectory = "examples/example-gateway" then endpoints will always be located in examples/example-gateway/endpoints). That assumption is encoded in the Directories property, which enumerates all the places where Zanzibar will look for module instances.

This poses a problem for supporting more flexible directory structures, such as keeping clients at examples/example-gateway/clients but allowing instances of endpoints to exist in examples/example-gateway/apps/foo/endpoints; applications could not customize the place where Zanzibar would look for module instances.

This patch changes the module search logic to be more flexible. Instead of the assumption that the place where Zanzibar configuration files like clients will be found is known ahead of time, we instead assume that we will be provided a list of globbing patterns to enumerate all the configuration files that exist:

moduleSearchPaths:
- clients/*
- middlewares/*
- endpoints/*
- endpoints/tchannel/*
- services/*
- app/*/clients/*
- app/*/endpoints/*
- app/*/services/*

The list will be provided in the build.yaml file which is provided by the application and can be customized without modifying Zanzibar. Zanzibar will then look for every instance type it is aware of in every folder. For example, you could have:

clients/
  foo/
    client-config.yaml
  bar/
    endpoint-config.yaml

There's nothing special about the relationship between the module classes and their paths.

Dependency names as stored in the map[string][]*ModuleInstance "tree" are now first extracted from the path name:

Path Qualified Instance Name
clients/foo/client-config.yaml foo
nested/clients/foo/client-config.yaml nested/foo
nested/bar/foo/baz/foo-config.yaml nested/bar/baz
app/demo/services/xyz/service-config.yaml app/demo/xyz

As a convenience, the second to last part of the qualified name is removed (clients/foo is transformed to foo). To depend on a so-called nested dependency, you would use the qualified instance name in the dependency list:

dependencies:
  endpoint:
  - app/demo/abc
  - health

TODO:

  • Create an example case for fully qualified dependency name
  • Verify nested service starts up
  • Fix mock generation
  • Fix lint
  • [ ] (?) Remove name field from *-config.yaml since it's now implied by the path

Copy link
Contributor

@ChuntaoLu ChuntaoLu left a comment

Choose a reason for hiding this comment

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

lgtm overall, a few minor things commented

@@ -134,26 +129,10 @@ func (system *ModuleSystem) validateClassDir(class *ModuleClass, dir string) err
// RegisterClassDir adds the given dir to the directories of the module class with given className.
// This method allows projects built on zanzibar to have arbitrary directories to host module class
// configs, therefore is mainly intended for external use.
//
// Deprecated: Module search paths deprecates this function.
Copy link
Contributor

Choose a reason for hiding this comment

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

Since we are on 0.1 release, shouldn't we just remove this method? This way we don't need do cleanup work in the future.

@@ -218,6 +197,8 @@ func (system *ModuleSystem) populateResolvedDependencies(
}

if dependencyInstance == nil {
fmt.Printf("known module instances: %+v", resolvedModules)
Copy link
Contributor

Choose a reason for hiding this comment

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

debug leftover?

// matched by a longer glob pattern like "endpoints/tchannel/*", so merely print a warning here
// rather than failing to generate. It will fail at a later step if no globbing pattern matches
// the wanted instance.
fmt.Printf("warn: globbing pattern %q: %s\n", moduleDirectoryGlob, instanceErr.Error())
Copy link
Contributor

Choose a reason for hiding this comment

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

This warning message seems unnecessary to me, it warns for each dir that does not contain a module config file, which could become quite a clutter when you have many modules nested.

if strings.HasSuffix(instanceFile.Name(), yamlConfigSuffix) {
className = strings.TrimSuffix(instanceFile.Name(), yamlConfigSuffix)
yamlFileName = instanceFile.Name()
// TODO(jacobg): Is this necessary?
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think it's necessary, should just delete it to avoid future confusion.

NamePlural string
ClassType moduleClassType

// Deprecated: Hard coded list of directory names is replaced with dynamic module search path in build.yaml.
Copy link
Contributor

Choose a reason for hiding this comment

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

same as earlier, deletion instead of deprecation.

moduleSearchPaths:
- clients/*
- middlewares/*
- endpoints/*
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is glob, I would not be surprised to see patterns like "endpoints/*/**" in the yaml file, can we have such a case to make sure things work as intended?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

Choose a reason for hiding this comment

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

okay, does that mean endpoint/* does not match endpoint/foo/bar/endpoint-config.yaml?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, you'd need to write endpoint/*/* to capture that, we might want a more flexible globbing pattern library but I just used the standard library one for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

Okay, got it, this is definitely something worth to document.

@jacobgreenleaf jacobgreenleaf changed the title WIP: Support flexible folder structures Support flexible folder structures Feb 1, 2019
@coveralls
Copy link

Coverage Status

Coverage increased (+7.3%) to 68.288% when pulling 9001235 on jg-appfolders into c7b8c7f on master.

@jacobgreenleaf jacobgreenleaf merged commit 7e3da0b into master Feb 6, 2019
@jacobgreenleaf jacobgreenleaf deleted the jg-appfolders branch February 6, 2019 22:56
@jacobgreenleaf jacobgreenleaf restored the jg-appfolders branch February 6, 2019 22:56
@ChuntaoLu ChuntaoLu deleted the jg-appfolders branch July 8, 2020 17:23
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.

3 participants