in pkg/deploy/lattice/rule_manager.go [146:199]
func (r *defaultRuleManager) Upsert(
ctx context.Context,
modelRule *model.Rule,
modelListener *model.Listener,
modelSvc *model.Service,
) (model.RuleStatus, error) {
if modelListener.Status == nil || modelListener.Status.Id == "" {
return model.RuleStatus{}, errors.New("listener is missing id")
}
if modelSvc.Status == nil || modelSvc.Status.Id == "" {
return model.RuleStatus{}, errors.New("model service is missing id")
}
for i, mtg := range modelRule.Spec.Action.TargetGroups {
if mtg.LatticeTgId == "" {
return model.RuleStatus{}, fmt.Errorf("rule %d action %d is missing lattice target group id", modelRule.Spec.Priority, i)
}
}
latticeServiceId := modelSvc.Status.Id
latticeListenerId := modelListener.Status.Id
// this allows us to make apples to apples comparisons with what's in Lattice already
latticeRuleFromModel, err := r.buildLatticeRule(modelRule)
if err != nil {
return model.RuleStatus{}, err
}
r.log.Debugf(ctx, "Upsert rule %s for service %s-%s and listener port %d and protocol %s",
aws.StringValue(latticeRuleFromModel.Name), latticeServiceId, latticeListenerId,
modelListener.Spec.Port, modelListener.Spec.Protocol)
lri := vpclattice.ListRulesInput{
ServiceIdentifier: aws.String(modelSvc.Status.Id),
ListenerIdentifier: aws.String(modelListener.Status.Id),
}
// TODO: fetching all rules every time is not efficient - maybe have a separate public method to prepopulate?
currentLatticeRules, err := r.cloud.Lattice().GetRulesAsList(ctx, &lri)
if err != nil {
return model.RuleStatus{}, err
}
var matchingRule *vpclattice.GetRuleOutput
for _, clr := range currentLatticeRules {
if isMatchEqual(latticeRuleFromModel, clr) {
matchingRule = clr
break
}
}
if matchingRule == nil {
return r.create(ctx, currentLatticeRules, latticeRuleFromModel, latticeServiceId, latticeListenerId)
} else {
return r.updateIfNeeded(ctx, latticeRuleFromModel, matchingRule, latticeServiceId, latticeListenerId)
}
}