Skip to content

Commit

Permalink
fix(intent): Refactor security group to only map to a single region (#49
Browse files Browse the repository at this point in the history
)
  • Loading branch information
robzienert committed Jan 26, 2018
1 parent d8e756f commit 9be18df
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,15 @@ class SecurityGroupIntent
schema = CURRENT_SCHEMA,
spec = spec
) {
// TODO rz - Region needs to be included in the id, but we also need a way to supercede other intents if a region is
// added or removed.
@JsonIgnore override val defaultId = "$KIND:${spec.cloudProvider}:${spec.accountName}:${spec.name}"
@JsonIgnore override val defaultId = "$KIND:${spec.cloudProvider}:${spec.accountName}:${spec.region}:${spec.name}"
}

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "kind")
abstract class SecurityGroupSpec : ApplicationAwareIntentSpec() {
abstract val name: String
abstract val cloudProvider: String
abstract val accountName: String
abstract val regions: Set<String>
abstract val region: String
abstract val inboundRules: Set<SecurityGroupRule>
}

Expand All @@ -55,7 +53,7 @@ data class AmazonSecurityGroupSpec(
override val name: String,
override val cloudProvider: String,
override val accountName: String,
override val regions: Set<String>,
override val region: String,
override val inboundRules: Set<SecurityGroupRule>,
val outboundRules: Set<SecurityGroupRule>,
// We don't care to support EC2 Classic, but for some reason clouddriver returns nulls (and isn't "default" vpcs)
Expand Down Expand Up @@ -110,7 +108,6 @@ data class CrossAccountReferenceSecurityGroupRule(
override val protocol: String,
override val name: String,
val account: String,
val region: String, // TODO rz - remove; can only x-account to same region
val vpcName: String
) : SecurityGroupRule(), PortRangeSupport

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class SecurityGroupIntentProcessor
return ConvergeResult(listOf(), changeSummary)
}

changeSummary.type = if (currentState.isEmpty()) ChangeType.CREATE else ChangeType.UPDATE
changeSummary.type = if (currentState == null) ChangeType.CREATE else ChangeType.UPDATE

return ConvergeResult(listOf(
OrchestrationRequest(
Expand All @@ -93,65 +93,45 @@ class SecurityGroupIntentProcessor
)
}

private fun getSecurityGroups(spec: SecurityGroupSpec): Set<SecurityGroup> {
private fun getSecurityGroups(spec: SecurityGroupSpec): SecurityGroup? {
if (spec is AmazonSecurityGroupSpec) {
return spec.regions
.map { region ->
try {
return@map if (spec.vpcName == null) {
cloudDriverService.getSecurityGroup(spec.accountName, "aws", spec.name, region)
} else {
cloudDriverService.getSecurityGroup(spec.accountName, "aws", spec.name, region, clouddriverCache.networkBy(
spec.vpcName,
spec.accountName,
region
).id)
}
} catch (e: RetrofitError) {
if (e.notFound()) {
return@map null
}
throw e
}
try {
return if (spec.vpcName == null) {
cloudDriverService.getSecurityGroup(spec.accountName, "aws", spec.name, spec.region)
} else {
cloudDriverService.getSecurityGroup(spec.accountName, "aws", spec.name, spec.region, clouddriverCache.networkBy(
spec.vpcName,
spec.accountName,
spec.region
).id)
}
.filterNotNull()
.toSet()
} catch (e: RetrofitError) {
if (e.notFound()) {
return null
}
throw e
}
}
throw NotImplementedError("Only amazon security groups are supported at the moment")
}

private fun currentStateUpToDate(intentId: String,
currentState: Set<SecurityGroup>,
currentState: SecurityGroup?,
desiredState: SecurityGroupSpec,
changeSummary: ChangeSummary): Boolean {

if (currentState.size != desiredState.regions.size) return false

val desired = securityGroupConverter.convertToState(desiredState)

val statePairs = mutableListOf<Pair<SecurityGroup, SecurityGroup>>()
desired.forEach { d ->
val key = "${d.accountName}/${d.region}/${d.name}"
currentState.forEach { c ->
if ("${c.accountName}/${c.region}/${c.name}" == key) {
statePairs.add(Pair(c, d))
}
}
if (currentState == null) {
return false
}

if (statePairs.size != desiredState.regions.size) return false

val stateInspector = StateInspector(objectMapper)
val diff = statePairs.flatMap {
stateInspector.getDiff(
intentId = intentId,
currentState = it.first,
desiredState = it.second,
modelClass = SecurityGroup::class,
specClass = SecurityGroupSpec::class,
ignoreKeys = setOf("type", "id", "moniker", "summary", "description")
)
}.toSet()
val diff = StateInspector(objectMapper).getDiff(
intentId = intentId,
currentState = currentState,
desiredState = securityGroupConverter.convertToState(desiredState),
modelClass = SecurityGroup::class,
specClass = SecurityGroupSpec::class,
ignoreKeys = setOf("type", "id", "moniker", "summary", "description")
)
changeSummary.diff = diff
return diff.isEmpty()
}
Expand All @@ -162,27 +142,25 @@ class SecurityGroupIntentProcessor
.filter {
spec.name != it.name
}
.flatMap {
spec.regions.map { region ->
if (spec is AmazonSecurityGroupSpec) {
try {
cloudDriverService.getSecurityGroup(
spec.accountName,
"aws",
it.name,
region,
clouddriverCache.networkBy(spec.vpcName!!, spec.accountName, region).id
)
} catch (e: RetrofitError) {
if (e.notFound()) {
return@map it.name
}
.map {
if (spec is AmazonSecurityGroupSpec) {
try {
cloudDriverService.getSecurityGroup(
spec.accountName,
"aws",
it.name,
spec.region,
clouddriverCache.networkBy(spec.vpcName!!, spec.accountName, spec.region).id
)
} catch (e: RetrofitError) {
if (e.notFound()) {
return@map it.name
}
} else {
log.error("${spec.javaClass.simpleName} is not supported yet")
}
return@map null
} else {
log.error("${spec.javaClass.simpleName} is not supported yet")
}
return@map null
}
.filterNotNull()
.distinct()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ import javax.annotation.PostConstruct
class SecurityGroupConverter(
private val clouddriverCache: CloudDriverCache,
private val objectMapper: ObjectMapper
) : SpecConverter<SecurityGroupSpec, Set<SecurityGroup>> {
) : SpecConverter<SecurityGroupSpec, SecurityGroup> {

private val log = LoggerFactory.getLogger(javaClass)

Expand All @@ -46,70 +46,61 @@ class SecurityGroupConverter(
)
}

override fun convertToState(spec: SecurityGroupSpec): Set<SecurityGroup> {
override fun convertToState(spec: SecurityGroupSpec): SecurityGroup {
if (spec is AmazonSecurityGroupSpec) {
return spec.regions.map { region ->
SecurityGroup(
type = "aws",
name = spec.name,
description = spec.description,
accountName = spec.accountName,
region = region,
// TODO rz - do we even want to mess with EC2-classic support?
vpcId = clouddriverCache.networkBy(spec.vpcName!!, spec.accountName, region).id,
inboundRules = spec.inboundRules.map {
when (it) {
is ReferenceSecurityGroupRule -> SecurityGroup.SecurityGroupRule(
protocol = it.protocol,
portRanges = it.portRanges.map { SecurityGroup.SecurityGroupRulePortRange(it.startPort, it.endPort) },
securityGroup = SecurityGroup.SecurityGroupRuleReference(
name = it.name,
accountName = spec.accountName,
region = region
)
return SecurityGroup(
type = "aws",
name = spec.name,
description = spec.description,
accountName = spec.accountName,
region = spec.region,
// TODO rz - do we even want to mess with EC2-classic support?
vpcId = clouddriverCache.networkBy(spec.vpcName!!, spec.accountName, spec.region).id,
inboundRules = spec.inboundRules.map {
when (it) {
is ReferenceSecurityGroupRule -> SecurityGroup.SecurityGroupRule(
protocol = it.protocol,
portRanges = it.portRanges.map { SecurityGroup.SecurityGroupRulePortRange(it.startPort, it.endPort) },
securityGroup = SecurityGroup.SecurityGroupRuleReference(
name = it.name,
accountName = spec.accountName,
region = spec.region
)
is CrossAccountReferenceSecurityGroupRule -> SecurityGroup.SecurityGroupRule(
protocol = it.protocol,
portRanges = it.portRanges.map { SecurityGroup.SecurityGroupRulePortRange(it.startPort, it.endPort) },
securityGroup = SecurityGroup.SecurityGroupRuleReference(
name = it.name,
accountName = it.account,
region = it.region
)
)
is CrossAccountReferenceSecurityGroupRule -> SecurityGroup.SecurityGroupRule(
protocol = it.protocol,
portRanges = it.portRanges.map { SecurityGroup.SecurityGroupRulePortRange(it.startPort, it.endPort) },
securityGroup = SecurityGroup.SecurityGroupRuleReference(
name = it.name,
accountName = it.account,
region = spec.region
)
else -> TODO(reason = "${it.javaClass.simpleName} has not been implemented yet")
}
}.toSet(),
id = null,
// TODO rz - fix so not bad
moniker = Moniker(spec.name)
)
}.toSet()
)
else -> TODO(reason = "${it.javaClass.simpleName} has not been implemented yet")
}
}.toSet(),
id = null,
moniker = Moniker(spec.name)
)
}
throw NotImplementedError("Only AWS security groups are supported at the moment")
}

override fun convertFromState(state: Set<SecurityGroup>): SecurityGroupSpec? {
if (state.isEmpty()) {
return null
}

state.first().let {
if (it.type == "aws") {
return AmazonSecurityGroupSpec(
cloudProvider = "aws",
application = it.moniker.app,
name = it.name,
description = it.description!!,
accountName = it.accountName,
regions = state.map { s -> s.region }.toSet(),
vpcName = clouddriverCache.networkBy(it.vpcId!!).name,
inboundRules = it.inboundRules.map {
objectMapper.convertValue(it, SecurityGroupRule::class.java)
}.toSet(),
outboundRules = setOf()
)
}
override fun convertFromState(state: SecurityGroup): SecurityGroupSpec? {
if (state.type == "aws") {
return AmazonSecurityGroupSpec(
cloudProvider = "aws",
application = state.moniker.app,
name = state.name,
description = state.description!!,
accountName = state.accountName,
region = state.region,
vpcName = clouddriverCache.networkBy(state.vpcId!!).name,
inboundRules = state.inboundRules.map {
objectMapper.convertValue(state, SecurityGroupRule::class.java)
}.toSet(),
outboundRules = setOf()
)
}
throw NotImplementedError("Only AWS security groups are supported at the moment")
}
Expand All @@ -125,7 +116,7 @@ class SecurityGroupConverter(
"credentials" to spec.accountName,
"cloudProvider" to "aws",
"name" to spec.name,
"regions" to spec.regions,
"regions" to listOf(spec.region),
"vpcId" to spec.vpcName,
"description" to spec.description,
"securityGroupIngress" to spec.inboundRules.flatMap {
Expand All @@ -142,7 +133,7 @@ class SecurityGroupConverter(
changeSummary.addMessage("Adding cross account reference support account ${it.account}")
m["accountName"] = it.account
m["crossAccountEnabled"] = true
m["vpcId"] = clouddriverCache.networkBy(it.vpcName, spec.accountName, it.region)
m["vpcId"] = clouddriverCache.networkBy(it.vpcName, spec.accountName, spec.region)
}
m
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,3 @@ interface SpecConverter<I : IntentSpec, S : Any> {
fun convertFromState(state: S): I?
fun convertToJob(spec: I, changeSummary: ChangeSummary): List<Job>
}

const val COMPUTED_VALUE = "<computed>"
Loading

0 comments on commit 9be18df

Please sign in to comment.