Skip to content
This repository has been archived by the owner on Oct 11, 2019. It is now read-only.

Refactor to remove legacyconfig object #163

Merged
merged 6 commits into from
Feb 15, 2019
Merged

Refactor to remove legacyconfig object #163

merged 6 commits into from
Feb 15, 2019

Conversation

amckague
Copy link
Contributor

At best legacyconfig belongs to the individual plugins, simplify the
existing wiring contract by removing it from the wiring context.
ec2compute v2 no longer has a v1 version present so remove the extra
package, add an api to allow outside users to set the default set of
tags passed in the entangler context

func New() *WiringPlugin {
return &WiringPlugin{
DeveloperRole: func(_ voyager.Location) []string {
return []string{"arn:aws:iam::123456789012:role/micros-server-iam-MicrosServer-ABC"} //example
Copy link
Contributor Author

@amckague amckague Feb 13, 2019

Choose a reason for hiding this comment

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

Legacy config is a major issue for manual or experimental testing of autowiring functions. You have to use the internal build to access this data.
I can probably move most or all of these to envvar lookups.

Tthe way shapes hold things together also practically requires all the functions be in this repo so you can find and reference them simply.

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 disagree, it would be nice to replace LegacyConfig with resource-specific configuration.
The problem is, as I said above, that at the moment there is no way to pass configuration to autowiring plugins, and at the moment we are abusing WiringContext and LegacyConfig as a global per-environment configuration.

Copy link
Contributor

Choose a reason for hiding this comment

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

There is a ticket to make autowiring functions accept configuration into their constructor. Even with legacy config completely gone we'd still need this functionality.

Copy link
Contributor

Choose a reason for hiding this comment

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

That's exactly what I meant, if it wasn't clear :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We build the list of plugins. All of their "constructors" are accessible. There is not requirement to use known plugins object.

Copy link
Contributor

Choose a reason for hiding this comment

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

Then the first trivial change would be to pass LegacyConfig to plugin constructors which use information from it, and remove it from the context? This would be a global LegacyConfig I suppose (not location-specific), but that's ok. It could also be a function providing a LegacyConfig for a given location. This should be a relatively simple isolated change, easy to review.

Copy link
Contributor

Choose a reason for hiding this comment

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

Actually, we already have this function: https://github.com/atlassian/voyager/blob/master/pkg/orchestration/wiring/entangler.go#L161-L173
So we just need to pass this function to plugin constructors, instead of Entangler invoking it and adding to the context. The only problem again is that list of plugins is static at the moment IIRC, i.e. you can't pass a different configuration to it for testing vs production.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Look at the main function for orchestration. It takes registry.KnownWiringPlugins as an arg of type map[voyager.ResourceType]wiringplugin.WiringPlugin. There is no reason this needs to be the same map inside the close source repo.

Copy link
Contributor Author

@amckague amckague Feb 14, 2019

Choose a reason for hiding this comment

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

Also notice that master of this repo currently stubs legacy config with a nothing but empty strings.

// We hack this Atlassianism in here rather than putting in user
// tags in the configmap because it's at the same level as legacyConfig
// (i.e. want to make it obvious they should be removed at the same time).
legacyEnvironmentTagName = "environment"
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Get to kill some todo's with this move as well

@@ -68,12 +59,19 @@ type TagNames struct {
EnvironmentTypeTag voyager.Tag
}

type TagGenerator func(
Copy link
Contributor Author

@amckague amckague Feb 13, 2019

Choose a reason for hiding this comment

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

This API is possibly too broad. Please comment on possible alternatives.

tags[en.TagNames.ResourceOwnerTag] = context.ServiceProperties.ResourceOwner
tags[en.TagNames.EnvironmentTypeTag] = string(location.EnvType)
tags[en.TagNames.PlatformTag] = "voyager"
tags[legacyEnvironmentTagName] = legacyConfig.MicrosEnv
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This lookup is what requires the tags generation to be a function and not just a static map. The other keys could be seen as opinionated defaults.

func New() *WiringPlugin {
return &WiringPlugin{
VPC: func(location voyager.Location) *oap.VPCEnvironment {
return oap.ExampleVPC(location.Label, location.Region)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

VPCEnvironment has a much smaller surface area than legacy config.

@@ -158,7 +163,7 @@ func (p *WiringPlugin) WireUp(resource *orch_v1.StateResource, context *wiringpl

// instanceParameters constructs ServiceInstance parameters.
// sharedDbDep may be nil
func instanceParameters(resource *orch_v1.StateResource, context *wiringplugin.WiringContext, sharedDbDep *wiringplugin.WiredDependency) ([]byte, bool /* externalErr */, bool /* retriable */, error) {
func (p *WiringPlugin) instanceParameters(resource *orch_v1.StateResource, context *wiringplugin.WiringContext, sharedDbDep *wiringplugin.WiredDependency) ([]byte, bool /* externalErr */, bool /* retriable */, error) {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@nilebox I opted for a receiver param over an additional function param to avoid clashing with your plans in this place. I would prefer a function param if it doesn't get in the way.

Copy link
Contributor

Choose a reason for hiding this comment

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

that's fine

@@ -122,12 +121,6 @@ type StateContext struct {
// from the EntanglerContext.
Location voyager.Location

// LegacyConfig is read by a function specified in the entangler struct.
// TODO this is a temporary container for 'stuff that's in Micros config.js'.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

gone

Copy link
Contributor

@ash2k ash2k left a comment

Choose a reason for hiding this comment

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

I'm not sure I understand the intent. I think you are doing two big things in a single PR - moving stuff from common and changing the legacy config. Can it be done in separate steps? Or we need to sit down together and go though it because I cannot tell what code is new and what code has just been moved. Too many changes.

bindingOutputInstanceProfileARNKey = "InstanceProfileARN"
inputParameterEnvVarName = "secretEnvVars"

MaximumServiceNameLength = 26
)

// HACK: Some tags the EC2 provider doesn't like, because it wants to
// set them itself... (NB handles business_unit/resource_owner separately)
// We only really worry about the tags that we're likely to set here
// (it's ok if the user errors out from the provider).
var forbiddenTags = map[string]struct{}{
Copy link
Contributor

Choose a reason for hiding this comment

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

set of strings?

@ash2k
Copy link
Contributor

ash2k commented Feb 13, 2019

Legacy configuration should be moved to providers, we have tickets to do that. But I'm not opposed to refactoring this if it makes our life easier.

@@ -159,7 +194,27 @@ func constructComputeParameters(origSpec *runtime.RawExtension, iamRoleRef, iamI
return rawExtension, false, false, nil
}

func WireUp(stateResource *orch_v1.StateResource, context *wiringplugin.WiringContext) wiringplugin.WiringResult {
func New() *WiringPlugin {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

The members of this struct and it's use are the only changes to this class, everything else is just moving code from the extra package.

Copy link
Contributor

@nilebox nilebox left a comment

Choose a reason for hiding this comment

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

I like the idea of replacing LegacyConfig with resource-specific configuration for wiring plugins, but at the moment it's just stubs without actual solution for per-environment plugin configurations.

So instead of starting with deletion of LegacyConfig, I would first solve the problem of making wiring plugins configurable (e.g. via additional AddFlags function, plus some shared flags for common configuration replacing LegacyConfig), then start migrating function to it, and once LegacyConfig is not used anymore, we can delete it.

return &WiringPlugin{}
return &WiringPlugin{
Environment: func(_ voyager.Location) string {
return "microstestenv"
Copy link
Contributor

Choose a reason for hiding this comment

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

shouldn't you accept environment as parameter in constructor instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

For all of them yes.

@@ -158,7 +163,7 @@ func (p *WiringPlugin) WireUp(resource *orch_v1.StateResource, context *wiringpl

// instanceParameters constructs ServiceInstance parameters.
// sharedDbDep may be nil
func instanceParameters(resource *orch_v1.StateResource, context *wiringplugin.WiringContext, sharedDbDep *wiringplugin.WiredDependency) ([]byte, bool /* externalErr */, bool /* retriable */, error) {
func (p *WiringPlugin) instanceParameters(resource *orch_v1.StateResource, context *wiringplugin.WiringContext, sharedDbDep *wiringplugin.WiredDependency) ([]byte, bool /* externalErr */, bool /* retriable */, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

that's fine

@@ -30,9 +29,9 @@ import (
)

type ControllerConstructor struct {
FlagConfigFile string
GetLegacyConfigFunc func(voyager.Location) *legacy.Config
Copy link
Contributor

Choose a reason for hiding this comment

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

The real problem, I think, is that autowiring functions at the moment are not configurable (they are all hardcoded), and the only way to pass configuration is via context and orchestration controller constructor

Copy link
Contributor

@ychen-atlassian ychen-atlassian Feb 14, 2019

Choose a reason for hiding this comment

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

What about moving the plugins out of wiring/registry? We can pass them as parameters into the constructor for orchestration controller.

This matches up with what @amckague has done for the example tag generator, and it's what we sort of do for smith too. We're going to want to split the wiring out of this repo anyway.

@@ -88,14 +87,7 @@ func (cc *ControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Context) (*
Plugins: cc.Plugins,
ClusterLocation: opts.Location.ClusterLocation(),
ClusterConfig: toClusterConfig(opts.Cluster),
TagNames: wiring.TagNames{
Copy link
Contributor

Choose a reason for hiding this comment

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

Why this change? Seems unrelated to LegacyConfig. Could you split into multiple PRs please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

See the comment about introducing the tag generator. If the tags come from a function there's no need to make their keys come in via config.

@@ -13,7 +13,7 @@ import (
creator_v1 "github.com/atlassian/voyager/pkg/apis/creator/v1"
"github.com/atlassian/voyager/pkg/creator/luigi"
"github.com/atlassian/voyager/pkg/creator/ssam"
ec2compute_common "github.com/atlassian/voyager/pkg/orchestration/wiring/ec2compute/common"
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 also unrelated to LegacyConfig? separate PR please.

Cfn: wiringutil.StatusAdapter(Resource(Cfn, CfnName, CfnClass, CfnPlan, CfnServiceEnvironment, cfnShapes).WireUp),
}
var (
emptyVPC = func(location voyager.Location) *oap.VPCEnvironment {
Copy link
Contributor

Choose a reason for hiding this comment

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

How do you construct non-empty VPC and make it environment-specific without LegacyConfig?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

We're passing a function type based on public types. I won't be using know authowire plugins in the close repo.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm sorry, I don't understand this English :(

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's not. Follow the code in the orchestration main in this PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm confused. If you want to construct plugins dynamically, these static plugin variables simply should not exist, at least in the non-test package.

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree with Nail's point. Would be better to move the not-really-ready-to-use instances of plugins (and other "stubby" stuff) into some testing package

Copy link
Contributor Author

@amckague amckague Feb 14, 2019

Choose a reason for hiding this comment

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

Think these comments are now outdated.

func New() *WiringPlugin {
return &WiringPlugin{
DeveloperRole: func(_ voyager.Location) []string {
return []string{"arn:aws:iam::123456789012:role/micros-server-iam-MicrosServer-ABC"} //example
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 disagree, it would be nice to replace LegacyConfig with resource-specific configuration.
The problem is, as I said above, that at the moment there is no way to pass configuration to autowiring plugins, and at the moment we are abusing WiringContext and LegacyConfig as a global per-environment configuration.

At best legacyconfig belongs to the individual plugins, simplify the
existing wiring contract by removing it from the wiring context.
ec2compute v2 no longer has a v1 version present so remove the extra
package, add an api to allow outside users to set the default set of
tags passed in the entangler context
@amckague amckague dismissed nilebox’s stale review February 14, 2019 00:50

Overly complicated solution that doesn't solve removing legacy config from the entagler api

@amckague
Copy link
Contributor Author

amckague commented Feb 14, 2019

@nilebox @ash2k separate commits for moving common vs removing legacy. See cmd/orchestration/app main.go for an idea of how I'll be using this code inside our closed source repo.

@@ -23,18 +25,23 @@ const (
)

func Main() {
CustomMain(emptyLegacyConfigFunc, registry.KnownWiringPlugins)
CustomMain(registry.KnownWiringPlugins(
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks better 👍

@nilebox
Copy link
Contributor

nilebox commented Feb 14, 2019

@amckague the code looks better now (there is still a lot unrelated changes, so I would prefer to have separate PRs rather than commits, but that's up to you).

My concern though is that if we merge this change, we won't be able to use the latest master until we copy bits from deleted LegacyConfig to a Stash repo and construct all the things there. As alternative, we could keep such code inside this repo for now as a default behavior, and once we rewrite the code in Stash to explicitly pass configuration, we can get rid of this backward compatibility.

i.e. I propose to keep KnownWiringPlugins constructless and mark it as deprecated, and add a new method that will accept configuration that we need to migrate to.

sqs.ResourceType: wiringutil.StatusAdapter(sqs.WireUp),
asapkey.ResourceType: wiringutil.StatusAdapter(asapkey.New().WireUp),
apiplatformdns.ResourceType: wiringutil.StatusAdapter(platformdns.New().WireUp),
func KnownWiringPlugins(
Copy link
Contributor

Choose a reason for hiding this comment

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

Sort of related to Nail's comment up https://github.com/atlassian/voyager/pull/163/files#r256667823, we only need to do this because we need to pass a bunch of parameters through the orchestration constructor. When we end up extracting these I assume we'll have a custom orchestration cmd in stash voyager that combines the wiring (like how we combine smith plugins and smith)

Copy link
Contributor

Choose a reason for hiding this comment

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

I have some ideas of how we can have configuration passed to plugins from a shared config file but in a typed way. I view passing functions is a temporary shortcut - instantiating code (orchstration) should not have any knowledge about what configuration is needed i.e. that "configuration" cannot be a function. It should be just a blob of data. But this is one of the next steps.

Copy link
Contributor

Choose a reason for hiding this comment

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

And same with smith - we need a way to pass configuration to plugins atlassian/smith#319 without recompiling smith to change that configuration. We obviously don't want to have a binary per environment, for example.

@@ -2,34 +2,59 @@ package v2

Copy link
Contributor

Choose a reason for hiding this comment

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

Now we can get rid of v2 altogether and just call it ec2compute!

Copy link
Contributor

Choose a reason for hiding this comment

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

just wait for V3 :)
just kidding - yeah, version is not needed anymore (but again, I would prefer this change to be a separate PR)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In our glorious future of go modules that would be breaking the version number in the package path requirement. Also it's separate commits.

ash2k
ash2k previously approved these changes Feb 14, 2019
Copy link
Contributor

@ash2k ash2k left a comment

Choose a reason for hiding this comment

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

conflict

@amckague amckague dismissed stale reviews from ash2k and ychen-atlassian via 3329943 February 15, 2019 04:57
@amckague amckague merged commit 8314b18 into master Feb 15, 2019
func MakeServiceEnvironmentFromContext(context *wiringplugin.WiringContext) *ServiceEnvironment {
config := context.StateContext.LegacyConfig
location := context.StateContext.Location
func MakeServiceEnvironmentFromContext(context *wiringplugin.WiringContext, vpc *VPCEnvironment) *ServiceEnvironment {
serviceProperties := context.StateContext.ServiceProperties
alarmEndpoints := PagerdutyAlarmEndpoints(
serviceProperties.Notifications.PagerdutyEndpoint.CloudWatch,
serviceProperties.Notifications.LowPriorityPagerdutyEndpoint.CloudWatch)

return &ServiceEnvironment{
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Look here for the vpc info

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants