-
Notifications
You must be signed in to change notification settings - Fork 9
Refactor to remove legacyconfig object #163
Conversation
func New() *WiringPlugin { | ||
return &WiringPlugin{ | ||
DeveloperRole: func(_ voyager.Location) []string { | ||
return []string{"arn:aws:iam::123456789012:role/micros-server-iam-MicrosServer-ABC"} //example |
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.
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.
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 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.
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.
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.
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.
That's exactly what I meant, if it wasn't clear :)
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.
We build the list of plugins. All of their "constructors" are accessible. There is not requirement to use known plugins object.
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.
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.
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.
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.
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.
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.
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.
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" |
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.
Get to kill some todo's with this move as well
@@ -68,12 +59,19 @@ type TagNames struct { | |||
EnvironmentTypeTag voyager.Tag | |||
} | |||
|
|||
type TagGenerator func( |
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 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 |
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 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) |
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.
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) { |
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.
@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.
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.
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'. |
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.
gone
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'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{}{ |
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.
set of strings?
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 { |
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 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.
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 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" |
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.
shouldn't you accept environment as parameter in constructor instead?
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.
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) { |
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.
that's fine
@@ -30,9 +29,9 @@ import ( | |||
) | |||
|
|||
type ControllerConstructor struct { | |||
FlagConfigFile string | |||
GetLegacyConfigFunc func(voyager.Location) *legacy.Config |
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 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
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.
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{ |
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.
Why this change? Seems unrelated to LegacyConfig. Could you split into multiple PRs please?
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.
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" |
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 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 { |
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.
How do you construct non-empty VPC and make it environment-specific without LegacyConfig?
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.
We're passing a function type based on public types. I won't be using know authowire plugins in the close repo.
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'm sorry, I don't understand this English :(
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 not. Follow the code in the orchestration main in this PR.
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'm confused. If you want to construct plugins dynamically, these static plugin variables simply should not exist, at least in the non-test package.
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 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
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.
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 |
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 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
0534b03
to
7d1bbdf
Compare
Overly complicated solution that doesn't solve removing legacy config from the entagler api
d44c5f9
to
3e64e43
Compare
@@ -23,18 +25,23 @@ const ( | |||
) | |||
|
|||
func Main() { | |||
CustomMain(emptyLegacyConfigFunc, registry.KnownWiringPlugins) | |||
CustomMain(registry.KnownWiringPlugins( |
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 looks better 👍
@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 |
sqs.ResourceType: wiringutil.StatusAdapter(sqs.WireUp), | ||
asapkey.ResourceType: wiringutil.StatusAdapter(asapkey.New().WireUp), | ||
apiplatformdns.ResourceType: wiringutil.StatusAdapter(platformdns.New().WireUp), | ||
func KnownWiringPlugins( |
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.
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)
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 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.
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 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 | |||
|
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.
Now we can get rid of v2 altogether and just call it ec2compute!
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.
just wait for V3 :)
just kidding - yeah, version is not needed anymore (but again, I would prefer this change to be a separate PR)
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.
In our glorious future of go modules that would be breaking the version number in the package path requirement. Also it's separate commits.
d8d32dc
to
e51288a
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.
conflict
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{ |
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.
Look here for the vpc info
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