├── CODEOWNERS
├── docs
├── delete.png
├── marking.png
├── swabbie-work-items.png
└── swabbie-services-config.png
├── gradle
├── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── dokka.gradle
├── license.gradle
├── junit5.gradle
└── kotlin.gradle
├── .editorconfig
├── .gitignore
├── .github
├── dependabot.yml
└── workflows
│ └── release_info.sh
├── swabbie-web
├── src
│ ├── logback-test.xml
│ └── main
│ │ ├── resources
│ │ └── logback-defaults.xml
│ │ └── kotlin
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ └── swabbie
│ │ ├── controllers
│ │ ├── ControllerUtils.kt
│ │ └── AdminController.kt
│ │ └── Main.kt
├── config
│ └── swabbie.yml
└── swabbie-web.gradle
├── swabbie-test
├── swabbie-test.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── netflix
│ └── spinnaker
│ └── swabbie
│ └── test
│ ├── NoopCacheStatus.kt
│ ├── InMemoryNotificationQueue.kt
│ ├── InMemoryWorkQueue.kt
│ ├── TestResource.kt
│ └── WorkConfigurationTestHelper.kt
├── Dockerfile.compile
├── swabbie-core
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── netflix
│ │ │ └── spinnaker
│ │ │ ├── swabbie
│ │ │ ├── model
│ │ │ │ ├── EddaEndpoint.kt
│ │ │ │ ├── SwabbieNamespace.kt
│ │ │ │ ├── OnDemandMarkData.kt
│ │ │ │ ├── Application.kt
│ │ │ │ ├── Rule.kt
│ │ │ │ ├── AlwaysCleanRule.kt
│ │ │ │ └── Account.kt
│ │ │ ├── CachedViewProvider.kt
│ │ │ ├── notifications
│ │ │ │ ├── NotificationTask.kt
│ │ │ │ ├── NotificationQueue.kt
│ │ │ │ └── Notifier.kt
│ │ │ ├── AccountProvider.kt
│ │ │ ├── EndpointProvider.kt
│ │ │ ├── exclusions
│ │ │ │ ├── ExclusionsSupplier.kt
│ │ │ │ ├── LiteralExclusionPolicy.kt
│ │ │ │ ├── AccountExclusionPolicy.kt
│ │ │ │ ├── NaiveExclusionPolicy.kt
│ │ │ │ └── AllowListExclusionPolicy.kt
│ │ │ ├── tagging
│ │ │ │ ├── TaggingService.kt
│ │ │ │ ├── ResourceTagger.kt
│ │ │ │ ├── TemporalTags.kt
│ │ │ │ └── EntityTag.kt
│ │ │ ├── exception
│ │ │ │ ├── SwabbieException.kt
│ │ │ │ ├── CacheSizeException.kt
│ │ │ │ └── StaleCacheException.kt
│ │ │ ├── repository
│ │ │ │ ├── ResourceStateRepository.kt
│ │ │ │ ├── UsedResourceRepository.kt
│ │ │ │ ├── ResourceTrackingRepository.kt
│ │ │ │ ├── TaskTrackingRepository.kt
│ │ │ │ └── ResourceUseTrackingRepository.kt
│ │ │ ├── work
│ │ │ │ └── WorkQueue.kt
│ │ │ ├── utils
│ │ │ │ └── ApplicationUtils.kt
│ │ │ ├── events
│ │ │ │ ├── ResourceTrackingManager.kt
│ │ │ │ └── Event.kt
│ │ │ ├── CacheStatus.kt
│ │ │ ├── Cacheable.kt
│ │ │ └── rules
│ │ │ │ └── Rules.kt
│ │ │ └── config
│ │ │ ├── LockingConfigurationProperties.kt
│ │ │ └── TestingConfiguration.kt
│ └── test
│ │ └── kotlin
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ └── swabbie
│ │ ├── ScheduleTest.kt
│ │ ├── rules
│ │ └── AgeRuleTest.kt
│ │ ├── events
│ │ └── ResourceTrackingManagerTest.kt
│ │ ├── model
│ │ └── WorkConfigurationTest.kt
│ │ └── exclusions
│ │ └── LiteralExclusionPolicyTest.kt
└── swabbie-core.gradle
├── .detekt.yml
├── Dockerfile.ubuntu
├── Dockerfile.slim
├── swabbie-aws
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── netflix
│ │ │ └── spinnaker
│ │ │ └── swabbie
│ │ │ └── aws
│ │ │ ├── edda
│ │ │ ├── providers
│ │ │ │ └── EddaEndpointProvider.kt
│ │ │ ├── EddaEndpointsService.kt
│ │ │ └── caches
│ │ │ │ └── EddaEndpointCache.kt
│ │ │ ├── Parameters.kt
│ │ │ ├── exclusions
│ │ │ ├── TemporalTagExclusionSupplier.kt
│ │ │ └── AmazonTagExclusionPolicy.kt
│ │ │ ├── loadbalancers
│ │ │ ├── AmazonElasticLoadBalancer.kt
│ │ │ └── Rules.kt
│ │ │ ├── AmazonTagOwnerResolutionStrategy.kt
│ │ │ ├── securitygroups
│ │ │ └── AmazonSecurityGroup.kt
│ │ │ ├── instances
│ │ │ └── AmazonInstance.kt
│ │ │ ├── launchtemplates
│ │ │ ├── AmazonLaunchTemplate.kt
│ │ │ └── AmazonLaunchTemplateVersion.kt
│ │ │ ├── images
│ │ │ ├── AmazonImage.kt
│ │ │ └── Rules.kt
│ │ │ ├── launchconfigurations
│ │ │ └── LaunchConfiguration.kt
│ │ │ ├── caches
│ │ │ ├── AmazonImagesUsedByInstancesInMemoryCache.kt
│ │ │ ├── AmazonLaunchConfigurationCache.kt
│ │ │ ├── AmazonLaunchTemplateVersionCache.kt
│ │ │ └── ImagesUsedByInstancesProvider.kt
│ │ │ ├── ExpiredResourceRule.kt
│ │ │ ├── snapshots
│ │ │ ├── SnapshotRules.kt
│ │ │ └── AmazonSnapshot.kt
│ │ │ └── model
│ │ │ └── AmazonResource.kt
│ └── test
│ │ └── java
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ └── swabbie
│ │ └── aws
│ │ ├── autoscalinggroups
│ │ ├── ZeroLoadBalancerRuleTest.kt
│ │ ├── ZeroInstanceRuleTest.kt
│ │ ├── DisabledLoadBalancerRuleTest.kt
│ │ └── ZeroInstanceDisabledServerGroupRuleTest.kt
│ │ ├── AmazonTagOwnerResolutionStrategyTest.kt
│ │ └── ExpiredResourceRuleTest.kt
└── swabbie-aws.gradle
├── gradle.properties
├── swabbie-front50
├── src
│ ├── main
│ │ └── kotlin
│ │ │ └── com
│ │ │ └── netflix
│ │ │ └── spinnaker
│ │ │ ├── swabbie
│ │ │ └── front50
│ │ │ │ ├── Front50Service.kt
│ │ │ │ ├── Front50ApplicationCache.kt
│ │ │ │ └── Front50ApplicationExclusionPolicy.kt
│ │ │ └── config
│ │ │ └── Front50Configuration.kt
│ └── test
│ │ └── kotlin
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ └── swabbie
│ │ └── front50
│ │ └── ApplicationResourceOwnerResolutionStrategyTest.kt
└── swabbie-front50.gradle
├── swabbie-bom
└── swabbie-bom.gradle
├── swabbie-clouddriver
├── src
│ └── main
│ │ └── kotlin
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ ├── swabbie
│ │ └── clouddriver
│ │ │ ├── CloudDriverService.kt
│ │ │ └── ClouddriverAccountProvider.kt
│ │ └── config
│ │ └── ClouddriverConfiguration.kt
└── swabbie-clouddriver.gradle
├── swabbie-retrofit
└── swabbie-retrofit.gradle
├── swabbie-redis
├── swabbie-redis.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── netflix
│ └── spinnaker
│ ├── config
│ └── RedisConfiguration.kt
│ └── swabbie
│ └── redis
│ ├── RedisClientDelegateSupport.kt
│ ├── RedisNotificationQueue.kt
│ ├── RedisUsedResourceRepository.kt
│ ├── LockingConfiguration.kt
│ └── RedisWorkQueue.kt
├── swabbie-echo
├── swabbie-echo.gradle
└── src
│ ├── main
│ └── kotlin
│ │ └── com
│ │ └── netflix
│ │ └── spinnaker
│ │ ├── swabbie
│ │ └── echo
│ │ │ ├── EchoService.kt
│ │ │ └── EchoNotifier.kt
│ │ └── config
│ │ └── EchoConfiguration.kt
│ └── test
│ └── kotlin
│ └── com
│ └── netflix
│ └── spinnaker
│ └── swabbie
│ └── echo
│ └── EchoNotifierTest.kt
├── swabbie-orca
├── swabbie-orca.gradle
└── src
│ └── main
│ └── kotlin
│ └── com
│ └── netflix
│ └── spinnaker
│ └── config
│ └── OrcaConfiguration.kt
├── settings.gradle
└── .mergify.yml
/CODEOWNERS:
--------------------------------------------------------------------------------
1 | * @jeyrschabu @aravindmd
2 |
--------------------------------------------------------------------------------
/docs/delete.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spinnaker/swabbie/HEAD/docs/delete.png
--------------------------------------------------------------------------------
/docs/marking.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spinnaker/swabbie/HEAD/docs/marking.png
--------------------------------------------------------------------------------
/docs/swabbie-work-items.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spinnaker/swabbie/HEAD/docs/swabbie-work-items.png
--------------------------------------------------------------------------------
/docs/swabbie-services-config.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spinnaker/swabbie/HEAD/docs/swabbie-services-config.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/spinnaker/swabbie/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | end_of_line = lf
6 | insert_final_newline = true
7 | trim_trailing_whitespace = true
8 | indent_style = space
9 | indent_size = 2
--------------------------------------------------------------------------------
/gradle/dokka.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: "org.jetbrains.dokka"
2 |
3 | dokkaHtml {
4 | dokkaSourceSets {
5 | configureEach {
6 | jdkVersion.set(17)
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /classes/
2 | /.gradle/
3 | /.idea/
4 | build/
5 | /.gradletasknamecache
6 | *.iml
7 | *.ipr
8 | *.iws
9 | out/
10 | .DS_Store
11 | /json/
12 | *.rdb
13 | /.shelf/
14 | **/*/out/*
--------------------------------------------------------------------------------
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | # Maintain dependencies for GitHub Actions
4 | - package-ecosystem: "github-actions"
5 | directory: "/"
6 | schedule:
7 | interval: "monthly"
8 |
--------------------------------------------------------------------------------
/swabbie-web/src/logback-test.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-bin.zip
4 | networkTimeout=10000
5 | zipStoreBase=GRADLE_USER_HOME
6 | zipStorePath=wrapper/dists
7 |
--------------------------------------------------------------------------------
/swabbie-test/swabbie-test.gradle:
--------------------------------------------------------------------------------
1 | dependencies {
2 | implementation project(":swabbie-core")
3 | implementation "com.natpryce:hamkrest"
4 | implementation "io.strikt:strikt-core"
5 | implementation "org.slf4j:jcl-over-slf4j"
6 | implementation "com.fasterxml.jackson.core:jackson-annotations"
7 | }
8 |
--------------------------------------------------------------------------------
/Dockerfile.compile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:jammy
2 | RUN apt-get update && apt-get install -y \
3 | openjdk-17-jdk \
4 | && rm -rf /var/lib/apt/lists/*
5 | LABEL maintainer="sig-platform@spinnaker.io"
6 | ENV GRADLE_USER_HOME /workspace/.gradle
7 | ENV GRADLE_OPTS -Xmx4g
8 | CMD ./gradlew --no-daemon swabbie-web:installDist -x test
9 |
--------------------------------------------------------------------------------
/gradle/license.gradle:
--------------------------------------------------------------------------------
1 | def licenseExtension = project.extensions.findByName("license")
2 | if (licenseExtension != null) {
3 | licenseExtension.exclude "**/*.json"
4 | licenseExtension.exclude "**/*.md"
5 | licenseExtension.exclude "**/*.yml"
6 | licenseExtension.mapping {
7 | java = "SLASHSTAR_STYLE"
8 | kt = "SLASHSTAR_STYLE"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/model/EddaEndpoint.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.model
2 |
3 | import com.netflix.spinnaker.swabbie.Cacheable
4 |
5 | data class EddaEndpoint(
6 | val region: String,
7 | val accountId: String,
8 | val environment: String,
9 | val endpoint: String,
10 | override val name: String
11 | ) : Cacheable
12 |
--------------------------------------------------------------------------------
/swabbie-web/config/swabbie.yml:
--------------------------------------------------------------------------------
1 | server:
2 | port: 8092
3 |
4 | front50:
5 | baseUrl: ${services.front50.baseUrl:http://localhost:8080}
6 |
7 | orca:
8 | baseUrl: ${services.orca.baseUrl:http://localhost:8083}
9 |
10 | clouddriver:
11 | baseUrl: ${services.clouddriver.baseUrl:http://localhost:7002}
12 |
13 | echo:
14 | baseUrl: ${services.echo.baseUrl:http://localhost:8089}
15 |
--------------------------------------------------------------------------------
/.detekt.yml:
--------------------------------------------------------------------------------
1 | complexity:
2 | TooManyFunctions:
3 | active: false
4 |
5 | style:
6 | ThrowsCount:
7 | active: false
8 | MaxLineLength:
9 | active: false
10 | ReturnCount:
11 | active: false
12 |
13 | performance:
14 | SpreadOperator:
15 | active: false
16 |
17 | comments:
18 | UndocumentedPublicClass:
19 | active: true
20 | UndocumentedPublicFunction:
21 | active: true
22 | UndocumentedPublicProperty:
23 | active: true
24 |
--------------------------------------------------------------------------------
/Dockerfile.ubuntu:
--------------------------------------------------------------------------------
1 | FROM ubuntu:jammy
2 | LABEL maintainer="sig-platform@spinnaker.io"
3 | RUN apt-get update && apt-get -y install curl openjdk-17-jre-headless wget
4 | RUN adduser --system --uid 10111 --group spinnaker
5 | COPY swabbie-web/build/install/swabbie /opt/swabbie
6 | RUN mkdir -p /opt/swabbie/plugins && chown -R spinnaker:nogroup /opt/swabbie/plugins
7 | USER spinnaker
8 | HEALTHCHECK CMD curl --fail http://localhost:8092/health
9 | CMD ["/opt/swabbie/bin/swabbie"]
10 |
--------------------------------------------------------------------------------
/Dockerfile.slim:
--------------------------------------------------------------------------------
1 | FROM alpine:3.20
2 | LABEL maintainer="sig-platform@spinnaker.io"
3 | RUN apk --no-cache add --update bash curl openjdk17-jre
4 | RUN addgroup -S -g 10111 spinnaker
5 | RUN adduser -S -G spinnaker -u 10111 spinnaker
6 | COPY swabbie-web/build/install/swabbie /opt/swabbie
7 | RUN mkdir -p /opt/swabbie/plugins && chown -R spinnaker:nogroup /opt/swabbie/plugins
8 | USER spinnaker
9 | HEALTHCHECK CMD curl --fail http://localhost:8092/health
10 | CMD ["/opt/swabbie/bin/swabbie"]
11 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/edda/providers/EddaEndpointProvider.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.aws.edda.providers
2 |
3 | import com.netflix.spinnaker.swabbie.EndpointProvider
4 | import com.netflix.spinnaker.swabbie.InMemoryCache
5 | import com.netflix.spinnaker.swabbie.model.EddaEndpoint
6 |
7 | class EddaEndpointProvider(
8 | private val endpointCache: InMemoryCache
9 | ) : EndpointProvider {
10 | override fun getEndpoints(): Set {
11 | return endpointCache.get()
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/model/SwabbieNamespace.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.model
2 |
3 | data class SwabbieNamespace(
4 | val cloudProvider: String,
5 | val accountName: String,
6 | val region: String,
7 | val resourceType: String
8 | ) {
9 | companion object {
10 | fun namespaceParser(namespace: String): SwabbieNamespace {
11 | namespace.split(":").let {
12 | return SwabbieNamespace(it[0], it[1], it[2], it[3])
13 | }
14 | }
15 | }
16 |
17 | override fun toString(): String {
18 | return "$cloudProvider:$accountName:$region:$resourceType"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/model/OnDemandMarkData.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.model
2 |
3 | import com.netflix.spinnaker.swabbie.notifications.Notifier
4 | import com.netflix.spinnaker.swabbie.repository.LastSeenInfo
5 |
6 | data class OnDemandMarkData(
7 | var projectedDeletionStamp: Long,
8 | var markTs: Long? = null,
9 | var resourceOwner: String = "swabbie@spinnaker.io",
10 | var notificationInfo: NotificationInfo? = NotificationInfo(
11 | recipient = resourceOwner,
12 | notificationType = Notifier.NotificationType.EMAIL.name
13 | ),
14 | var lastSeenInfo: LastSeenInfo? = null,
15 | val resourceId: String? = null
16 | )
17 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | korkVersion=7.254.0
2 | kotlinVersion=1.6.21
3 | org.gradle.parallel=true
4 | spinnakerGradleVersion=8.32.1
5 | targetJava17=true
6 |
7 | org.gradle.jvmargs=-Xmx2g
8 | # To enable a composite reference to a project, set the
9 | # project property `'Composite=true'`.
10 | #
11 | # This can be done either as
12 | # * a command line flag, e.g. `-PkorkComposite=true`
13 | # * a project property via gradle.properties
14 | # * a global project property via ~/.gradle/gradle.properties
15 | #
16 | # The composite project must checked out in a sibling directory
17 | # to this project, matching the name of the project
18 | # e.g. '../kork'
19 | #
20 | #korkComposite=true
21 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/CachedViewProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie
18 |
19 | interface CachedViewProvider {
20 | fun load(): T
21 | }
22 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/notifications/NotificationTask.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.notifications
18 |
19 | data class NotificationTask(
20 | val resourceType: String,
21 | val namespace: String
22 | )
23 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/AccountProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie
18 |
19 | import com.netflix.spinnaker.swabbie.model.Account
20 |
21 | interface AccountProvider {
22 | fun getAccounts(): Set
23 | }
24 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/Parameters.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.aws
18 |
19 | data class Parameters(
20 | val region: String,
21 | val account: String,
22 | val environment: String,
23 | val id: String = ""
24 | )
25 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/EndpointProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie
18 |
19 | import com.netflix.spinnaker.swabbie.model.EddaEndpoint
20 |
21 | interface EndpointProvider {
22 | fun getEndpoints(): Set
23 | }
24 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exclusions/ExclusionsSupplier.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.exclusions
18 |
19 | import com.netflix.spinnaker.config.Exclusion
20 |
21 | interface ExclusionsSupplier {
22 | fun get(): List
23 | }
24 |
--------------------------------------------------------------------------------
/swabbie-test/src/main/kotlin/com/netflix/spinnaker/swabbie/test/NoopCacheStatus.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright 2018 Netflix, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License")
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.swabbie.test
20 |
21 | import com.netflix.spinnaker.swabbie.CacheStatus
22 |
23 | class NoopCacheStatus : CacheStatus {
24 | override fun cachesLoaded() = true
25 | }
26 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/tagging/TaggingService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.tagging
18 |
19 | interface TaggingService {
20 | fun entityTag(tagRequest: TagRequest)
21 | fun removeEntityTag(tagRequest: TagRequest)
22 | }
23 |
24 | interface TagRequest
25 | interface Tag
26 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exception/SwabbieException.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.exception
18 |
19 | class SwabbieException : RuntimeException {
20 | constructor(message: String) : super(message)
21 | constructor(message: String, cause: Throwable) : super(message, cause)
22 | }
23 |
--------------------------------------------------------------------------------
/swabbie-front50/src/main/kotlin/com/netflix/spinnaker/swabbie/front50/Front50Service.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.front50
18 |
19 | import com.netflix.spinnaker.swabbie.model.Application
20 | import retrofit.http.GET
21 |
22 | interface Front50Service {
23 | @GET("/v2/applications?restricted=false")
24 | fun getApplications(): Set
25 | }
26 |
--------------------------------------------------------------------------------
/swabbie-bom/swabbie-bom.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: "java-platform"
18 |
19 | javaPlatform {
20 | allowDependencies()
21 | }
22 |
23 | dependencies {
24 | api(platform("io.spinnaker.kork:kork-bom:$korkVersion"))
25 |
26 | constraints {
27 | rootProject
28 | .subprojects
29 | .findAll { it != project }
30 | .each { api(project(it.path)) }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/swabbie-clouddriver/src/main/kotlin/com/netflix/spinnaker/swabbie/clouddriver/CloudDriverService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.clouddriver
18 |
19 | import com.netflix.spinnaker.swabbie.model.SpinnakerAccount
20 | import retrofit.http.GET
21 |
22 | interface CloudDriverService {
23 | @GET("/credentials?expand=true")
24 | fun getAccounts(): Set
25 | }
26 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exception/CacheSizeException.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2018 Netflix, Inc.
4 | * *
5 | * * Licensed under the Apache License, Version 2.0 (the "License")
6 | * * you may not use this file except in compliance with the License.
7 | * * You may obtain a copy of the License at
8 | * *
9 | * * http://www.apache.org/licenses/LICENSE-2.0
10 | * *
11 | * * Unless required by applicable law or agreed to in writing, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS,
13 | * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * * See the License for the specific language governing permissions and
15 | * * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.swabbie.exception
20 |
21 | class CacheSizeException : RuntimeException {
22 | constructor(message: String) : super(message)
23 | constructor(message: String, cause: Throwable) : super(message, cause)
24 | }
25 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exception/StaleCacheException.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2018 Netflix, Inc.
4 | * *
5 | * * Licensed under the Apache License, Version 2.0 (the "License")
6 | * * you may not use this file except in compliance with the License.
7 | * * You may obtain a copy of the License at
8 | * *
9 | * * http://www.apache.org/licenses/LICENSE-2.0
10 | * *
11 | * * Unless required by applicable law or agreed to in writing, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS,
13 | * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * * See the License for the specific language governing permissions and
15 | * * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.swabbie.exception
20 |
21 | class StaleCacheException : RuntimeException {
22 | constructor(message: String) : super(message)
23 | constructor(message: String, cause: Throwable) : super(message, cause)
24 | }
25 |
--------------------------------------------------------------------------------
/swabbie-retrofit/swabbie-retrofit.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client"
19 | implementation "com.squareup.retrofit:retrofit"
20 | implementation "com.squareup.retrofit:converter-jackson"
21 | implementation "io.spinnaker.kork:kork-web"
22 | implementation "io.reactivex:rxjava"
23 | implementation project(":swabbie-core")
24 | }
25 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/notifications/NotificationQueue.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.notifications
18 |
19 | /**
20 | * A queue for storing notification tasks
21 | */
22 | interface NotificationQueue {
23 | fun add(notificationTask: NotificationTask)
24 | fun popAll(): List
25 | fun isEmpty(): Boolean
26 | fun size(): Int
27 | }
28 |
--------------------------------------------------------------------------------
/swabbie-redis/swabbie-redis.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation project(":swabbie-core")
19 |
20 | implementation "redis.clients:jedis"
21 | implementation "io.spinnaker.kork:kork-jedis"
22 | implementation "io.spinnaker.kork:kork-test"
23 | implementation "com.fasterxml.jackson.module:jackson-module-kotlin"
24 |
25 | testImplementation "io.spinnaker.kork:kork-jedis-test"
26 | testImplementation project(":swabbie-test")
27 | testImplementation("io.strikt:strikt-core")
28 | }
29 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/config/LockingConfigurationProperties.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.config
18 |
19 | import org.springframework.boot.context.properties.ConfigurationProperties
20 |
21 | @ConfigurationProperties("locking")
22 | open class LockingConfigurationProperties {
23 | var enabled: Boolean? = false
24 | var maximumLockDurationMillis: Long? = 60 * 60 * 1000L // 1hour
25 | var heartbeatRateMillis: Long = 6000
26 | var leaseDurationMillis: Long = 10000
27 | }
28 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/tagging/ResourceTagger.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.tagging
18 |
19 | import com.netflix.spinnaker.swabbie.model.MarkedResource
20 | import com.netflix.spinnaker.swabbie.model.WorkConfiguration
21 |
22 | interface ResourceTagger {
23 | fun tag(markedResource: MarkedResource, workConfiguration: WorkConfiguration, description: String)
24 | fun unTag(markedResource: MarkedResource, workConfiguration: WorkConfiguration, description: String)
25 | }
26 |
--------------------------------------------------------------------------------
/swabbie-echo/swabbie-echo.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation project(":swabbie-core")
19 | implementation project(":swabbie-retrofit")
20 | implementation "io.spinnaker.kork:kork-core"
21 | implementation "io.spinnaker.kork:kork-web"
22 | implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client"
23 | implementation "com.squareup.retrofit:retrofit"
24 | implementation "com.squareup.retrofit:converter-jackson"
25 |
26 | testImplementation project(":swabbie-test")
27 | testImplementation "io.strikt:strikt-core"
28 | }
29 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/repository/ResourceStateRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.repository
18 |
19 | import com.netflix.spinnaker.swabbie.model.ResourceState
20 |
21 | interface ResourceStateRepository {
22 | fun get(resourceId: String, namespace: String): ResourceState?
23 | fun upsert(resourceState: ResourceState): ResourceState
24 | fun getAll(): List
25 | fun getByStatus(status: String): List
26 | fun remove(resourceId: String, namespace: String)
27 | }
28 |
--------------------------------------------------------------------------------
/swabbie-front50/src/main/kotlin/com/netflix/spinnaker/swabbie/front50/Front50ApplicationCache.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.front50
18 |
19 | import com.netflix.spinnaker.security.AuthenticatedRequest
20 | import com.netflix.spinnaker.swabbie.InMemoryCache
21 | import com.netflix.spinnaker.swabbie.model.Application
22 | import org.springframework.stereotype.Component
23 |
24 | @Component
25 | class Front50ApplicationCache(front50Service: Front50Service) : InMemoryCache({ AuthenticatedRequest.allowAnonymous(front50Service::getApplications) })
26 |
--------------------------------------------------------------------------------
/swabbie-front50/swabbie-front50.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation project(":swabbie-core")
19 | implementation project(":swabbie-retrofit")
20 | implementation "io.spinnaker.kork:kork-core"
21 | implementation "io.spinnaker.kork:kork-web"
22 | implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client"
23 | implementation "com.squareup.retrofit:retrofit"
24 | implementation "com.squareup.retrofit:converter-jackson"
25 |
26 | testImplementation project(":swabbie-test")
27 | testImplementation "com.squareup.retrofit:retrofit-mock"
28 | }
29 |
--------------------------------------------------------------------------------
/swabbie-orca/swabbie-orca.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation project(":swabbie-core")
19 | implementation project(":swabbie-retrofit")
20 | implementation "io.spinnaker.kork:kork-core"
21 | implementation "io.spinnaker.kork:kork-web"
22 | implementation "io.spinnaker.kork:kork-moniker"
23 | implementation "net.logstash.logback:logstash-logback-encoder"
24 | implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client"
25 | implementation "com.squareup.retrofit:retrofit"
26 | implementation "com.squareup.retrofit:converter-jackson"
27 | }
28 |
--------------------------------------------------------------------------------
/gradle/junit5.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | testImplementation "org.junit.platform:junit-platform-runner"
19 | testImplementation "org.mockito.kotlin:mockito-kotlin:4.0.0"
20 | testImplementation "com.natpryce:hamkrest"
21 | testImplementation "org.junit.jupiter:junit-jupiter-api"
22 | testImplementation "org.junit.jupiter:junit-jupiter-params"
23 |
24 | testRuntimeOnly "org.junit.platform:junit-platform-launcher"
25 | testRuntimeOnly "org.junit.jupiter:junit-jupiter-engine"
26 | }
27 |
28 | test {
29 | useJUnitPlatform {
30 | includeEngines("junit-jupiter")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/swabbie-redis/src/main/kotlin/com/netflix/spinnaker/config/RedisConfiguration.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.config
18 |
19 | import com.netflix.spinnaker.kork.jedis.JedisClientConfiguration
20 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
21 | import org.springframework.context.annotation.Configuration
22 | import org.springframework.context.annotation.Import
23 |
24 | @Configuration
25 | @ConditionalOnExpression("\${redis.enabled:false}")
26 | @Import(JedisClientConfiguration::class)
27 | open class RedisConfiguration
28 |
29 | const val REDIS_CHUNK_SIZE = 100
30 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/work/WorkQueue.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.work
18 |
19 | import com.netflix.spinnaker.swabbie.model.WorkItem
20 |
21 | interface WorkQueue {
22 | /**
23 | * For initializing the queue with a list of [WorkItem]
24 | */
25 | fun seed()
26 | fun pop(): WorkItem?
27 | fun push(workItem: WorkItem)
28 | fun isEmpty(): Boolean
29 |
30 | /**
31 | * Empties the queue
32 | */
33 | fun clear() {
34 | var tmp = pop()
35 | while (tmp != null) {
36 | tmp = pop()
37 | }
38 | }
39 |
40 | fun size(): Int
41 | }
42 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exclusions/LiteralExclusionPolicy.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.exclusions
18 |
19 | import com.netflix.spinnaker.config.Exclusion
20 | import com.netflix.spinnaker.config.ExclusionType
21 | import org.springframework.stereotype.Component
22 |
23 | @Component
24 | class LiteralExclusionPolicy : ResourceExclusionPolicy {
25 | override fun getType(): ExclusionType = ExclusionType.Literal
26 | override fun apply(excludable: Excludable, exclusions: List): String? {
27 | return byPropertyMatchingResult(exclusions, excludable)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/model/Application.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.model
18 |
19 | import com.netflix.spinnaker.swabbie.Cacheable
20 | import com.netflix.spinnaker.swabbie.exclusions.Excludable
21 |
22 | data class Application(
23 | val email: String?,
24 | override val name: String
25 | ) : HasDetails(), Cacheable, Excludable {
26 | override val resourceId: String
27 | get() = name
28 | override val resourceType: String
29 | get() = "application"
30 | override val cloudProvider: String
31 | get() = "*"
32 | override val grouping: Grouping?
33 | get() = Grouping(name, GroupingType.APPLICATION)
34 | }
35 |
--------------------------------------------------------------------------------
/swabbie-web/src/main/resources/logback-defaults.xml:
--------------------------------------------------------------------------------
1 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | %clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(%5p) %clr(${PID:- }){magenta} %clr(---){faint}
23 | %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} [%X{X-SPINNAKER-USER}] %m%n
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/edda/EddaEndpointsService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.aws.edda
18 |
19 | import retrofit.http.GET
20 |
21 | /**
22 | * This is a service for discovering which edda endpoints are available.
23 | */
24 | interface EddaEndpointsService {
25 | @GET("/api/v1/edda/endpoints.json")
26 | fun getEddaEndpoints(): EddaEndpointsContainer
27 |
28 | data class EddaEndpointsContainer(
29 | val edda_endpoints: EddaEndpoints
30 | ) {
31 | data class EddaEndpoints(
32 | val by_account: List?,
33 | val by_cluster: List?
34 | )
35 |
36 | fun get(): List = edda_endpoints.by_account ?: emptyList()
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exclusions/AccountExclusionPolicy.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.exclusions
18 |
19 | import com.netflix.spinnaker.config.Exclusion
20 | import com.netflix.spinnaker.config.ExclusionType
21 | import com.netflix.spinnaker.swabbie.model.Account
22 | import org.springframework.stereotype.Component
23 |
24 | @Component
25 | class AccountExclusionPolicy : BasicExclusionPolicy {
26 | override fun getType(): ExclusionType = ExclusionType.Account
27 | override fun apply(excludable: Excludable, exclusions: List): String? {
28 | if (excludable is Account) {
29 | return byPropertyMatchingResult(exclusions, excludable)
30 | }
31 |
32 | return null
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/repository/UsedResourceRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * Copyright 2018 Netflix, Inc.
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License")
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.swabbie.repository
20 |
21 | /**
22 | * Track a resource that is in use by another type of resource.
23 | * This repository provides a way to collect information about use from one resource and query that while processing
24 | * another resource. For example, AWS provides some one way mappings about use (image -> snapshot). This repository
25 | * is used to record if a snapshot is in use by an image.
26 | */
27 | interface UsedResourceRepository {
28 | fun recordUse(resourceType: String, id: String, namespace: String)
29 | fun isUsed(resourceType: String, id: String, namespace: String): Boolean
30 | }
31 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/notifications/Notifier.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.notifications
18 |
19 | import com.netflix.spinnaker.config.NotificationConfiguration
20 |
21 | interface Notifier {
22 | fun notify(
23 | recipient: String,
24 | notificationContext: Map,
25 | notificationConfiguration: NotificationConfiguration
26 | ): NotificationResult
27 |
28 | enum class NotificationType {
29 | EMAIL,
30 | NONE
31 | }
32 |
33 | enum class NotificationSeverity {
34 | NORMAL,
35 | HIGH
36 | }
37 |
38 | data class NotificationResult(
39 | val recipient: String,
40 | val notificationType: NotificationType = NotificationType.NONE,
41 | val success: Boolean = false
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/config/TestingConfiguration.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2018 Netflix, Inc.
4 | * *
5 | * * Licensed under the Apache License, Version 2.0 (the "License")
6 | * * you may not use this file except in compliance with the License.
7 | * * You may obtain a copy of the License at
8 | * *
9 | * * http://www.apache.org/licenses/LICENSE-2.0
10 | * *
11 | * * Unless required by applicable law or agreed to in writing, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS,
13 | * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * * See the License for the specific language governing permissions and
15 | * * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.config
20 |
21 | import com.netflix.spinnaker.swabbie.model.AlwaysCleanRule
22 | import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression
23 | import org.springframework.context.annotation.Bean
24 | import org.springframework.context.annotation.Configuration
25 |
26 | @Configuration
27 | @ConditionalOnExpression("\${swabbie.testing.enabled:false}")
28 | open class TestingConfiguration {
29 |
30 | @ConditionalOnExpression("\${swabbie.testing.always-clean-rule-config.enabled:false}")
31 | @Bean
32 | open fun alwaysCleanRule(swabbieProperties: SwabbieProperties) =
33 | AlwaysCleanRule(swabbieProperties)
34 | }
35 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | ['kork'].each { prj ->
18 | String propName = "${prj}Composite"
19 | String projectPath = "../$prj"
20 | if (settings.ext.has(propName) && Boolean.parseBoolean(settings.ext.get(propName) as String)) {
21 | includeBuild projectPath
22 | }
23 | }
24 |
25 | rootProject.name = 'swabbie'
26 |
27 | include 'swabbie-test',
28 | 'swabbie-core',
29 | 'swabbie-retrofit',
30 | 'swabbie-redis',
31 | 'swabbie-aws',
32 | 'swabbie-echo',
33 | 'swabbie-orca',
34 | 'swabbie-clouddriver',
35 | 'swabbie-front50',
36 | 'swabbie-web',
37 | 'swabbie-bom'
38 |
39 | def setBuildFile(project) {
40 | project.buildFileName = "${project.name}.gradle"
41 | project.children.each {
42 | setBuildFile(it)
43 | }
44 | }
45 |
46 | rootProject.children.each {
47 | setBuildFile it
48 | }
49 |
--------------------------------------------------------------------------------
/swabbie-clouddriver/swabbie-clouddriver.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation project(":swabbie-retrofit")
19 | implementation project(":swabbie-core")
20 | implementation "io.spinnaker.kork:kork-core"
21 | implementation "io.spinnaker.kork:kork-web"
22 | implementation "com.fasterxml.jackson.core:jackson-annotations"
23 | implementation "com.fasterxml.jackson.core:jackson-core"
24 | implementation "com.fasterxml.jackson.core:jackson-databind"
25 | implementation "io.spinnaker.kork:kork-moniker"
26 | implementation "com.jakewharton.retrofit:retrofit1-okhttp3-client"
27 | implementation "com.squareup.retrofit:retrofit"
28 | implementation "com.squareup.retrofit:converter-jackson"
29 |
30 | testImplementation project(":swabbie-test")
31 | testImplementation "com.squareup.retrofit:retrofit-mock"
32 | }
33 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/model/Rule.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.model
18 |
19 | import com.netflix.spinnaker.config.ResourceTypeConfiguration.RuleDefinition
20 |
21 | /**
22 | * A resource specific rule
23 | * If the rule finds the resource to be invalid, it will return a violation summary
24 | * Rules should be kept to simple logic and not perform any I/O operations
25 | */
26 | interface Rule {
27 | fun applicableForType(clazz: Class): Boolean = false
28 | fun apply(resource: T, ruleDefinition: RuleDefinition? = null): Result
29 | fun name(): String = this.javaClass.simpleName
30 | }
31 |
32 | data class Result(
33 | val summary: Summary?
34 | )
35 |
36 | data class Summary(
37 | val description: String,
38 | val ruleName: String
39 | )
40 |
--------------------------------------------------------------------------------
/gradle/kotlin.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2017 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | apply plugin: "kotlin"
18 | apply plugin: "io.gitlab.arturbosch.detekt"
19 |
20 | compileKotlin {
21 | kotlinOptions {
22 | languageVersion = "1.6"
23 | jvmTarget = "17"
24 | }
25 | }
26 |
27 | compileTestKotlin {
28 | kotlinOptions {
29 | languageVersion = "1.6"
30 | jvmTarget = "17"
31 | }
32 | }
33 |
34 | configurations.all {
35 | resolutionStrategy {
36 | eachDependency { details ->
37 | if (details.requested.group == "org.jetbrains.kotlin") {
38 | details.useVersion kotlinVersion
39 | }
40 | }
41 | }
42 | }
43 |
44 | detekt {
45 | parallel = false
46 | config = files("$rootDir/.detekt.yml")
47 | buildUponDefaultConfig = true
48 | ignoreFailures = true
49 | reports {
50 | xml {
51 | enabled = false
52 | }
53 | txt {
54 | enabled = false
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/exclusions/NaiveExclusionPolicy.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.exclusions
18 |
19 | import com.netflix.spinnaker.config.Exclusion
20 | import com.netflix.spinnaker.config.ExclusionType
21 | import com.netflix.spinnaker.swabbie.model.NAIVE_EXCLUSION
22 | import com.netflix.spinnaker.swabbie.model.Resource
23 | import org.springframework.stereotype.Component
24 |
25 | @Component
26 | class NaiveExclusionPolicy : ResourceExclusionPolicy {
27 | override fun getType(): ExclusionType = ExclusionType.Naive
28 | override fun apply(excludable: Excludable, exclusions: List): String? {
29 | if (excludable is Resource) {
30 | (excludable.details[NAIVE_EXCLUSION] as? Boolean)?.let {
31 | if (it) {
32 | return "Naive exclusion of ${excludable.name}"
33 | }
34 | }
35 | }
36 |
37 | return null
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/swabbie-clouddriver/src/main/kotlin/com/netflix/spinnaker/swabbie/clouddriver/ClouddriverAccountProvider.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.clouddriver
18 |
19 | import com.netflix.spinnaker.security.AuthenticatedRequest
20 | import com.netflix.spinnaker.swabbie.AccountProvider
21 | import com.netflix.spinnaker.swabbie.InMemoryCache
22 | import com.netflix.spinnaker.swabbie.model.Account
23 | import com.netflix.spinnaker.swabbie.model.SpinnakerAccount
24 | import org.springframework.stereotype.Component
25 |
26 | @Component
27 | class ClouddriverAccountProvider(
28 | private val accountCache: InMemoryCache
29 | ) : AccountProvider {
30 | override fun getAccounts(): Set = accountCache.get()
31 | }
32 |
33 | @Component
34 | class ClouddriverAccountCache(
35 | cloudDriverService: CloudDriverService
36 | ) : InMemoryCache({ AuthenticatedRequest.allowAnonymous(cloudDriverService::getAccounts) })
37 |
--------------------------------------------------------------------------------
/swabbie-core/src/main/kotlin/com/netflix/spinnaker/swabbie/repository/ResourceTrackingRepository.kt:
--------------------------------------------------------------------------------
1 | /*
2 | *
3 | * * Copyright 2018 Netflix, Inc.
4 | * *
5 | * * Licensed under the Apache License, Version 2.0 (the "License")
6 | * * you may not use this file except in compliance with the License.
7 | * * You may obtain a copy of the License at
8 | * *
9 | * * http://www.apache.org/licenses/LICENSE-2.0
10 | * *
11 | * * Unless required by applicable law or agreed to in writing, software
12 | * * distributed under the License is distributed on an "AS IS" BASIS,
13 | * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * * See the License for the specific language governing permissions and
15 | * * limitations under the License.
16 | *
17 | */
18 |
19 | package com.netflix.spinnaker.swabbie.repository
20 |
21 | import com.netflix.spinnaker.swabbie.model.MarkedResource
22 |
23 | interface ResourceTrackingRepository {
24 | fun upsert(markedResource: MarkedResource, deleteScore: Long = markedResource.projectedDeletionStamp)
25 | fun remove(markedResource: MarkedResource)
26 |
27 | fun getIdsOfMarkedResourcesToDelete(): Set
28 | fun getMarkedResourcesToDelete(): List
29 | fun getMarkedResources(): List
30 |
31 | fun getNumMarkedResources(): Long
32 |
33 | fun getDeleted(): List
34 |
35 | fun find(resourceId: String, namespace: String): MarkedResource?
36 | }
37 |
38 | data class DeleteInfo(
39 | val name: String,
40 | val resourceId: String,
41 | val namespace: String
42 | )
43 |
--------------------------------------------------------------------------------
/swabbie-echo/src/main/kotlin/com/netflix/spinnaker/swabbie/echo/EchoService.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.echo
18 |
19 | import com.fasterxml.jackson.annotation.JsonInclude
20 | import com.netflix.spinnaker.swabbie.notifications.Notifier
21 | import retrofit.client.Response
22 | import retrofit.http.Body
23 | import retrofit.http.POST
24 |
25 | interface EchoService {
26 | @POST("/notifications")
27 | fun create(@Body notification: Notification): Response
28 |
29 | @JsonInclude(JsonInclude.Include.NON_NULL)
30 | data class Notification(
31 | val notificationType: Notifier.NotificationType,
32 | val to: Collection,
33 | val cc: Collection = listOf(),
34 | val severity: Notifier.NotificationSeverity,
35 | val source: Source,
36 | val templateGroup: String,
37 | val additionalContext: Map = mapOf()
38 | ) {
39 |
40 | data class Source(val application: String)
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/swabbie-test/src/main/kotlin/com/netflix/spinnaker/swabbie/test/InMemoryNotificationQueue.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2019 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.test
18 |
19 | import com.netflix.spinnaker.swabbie.notifications.NotificationQueue
20 | import com.netflix.spinnaker.swabbie.notifications.NotificationTask
21 | import java.util.concurrent.LinkedBlockingDeque
22 |
23 | // For local testing. Implemented as a mere list
24 | class InMemoryNotificationQueue : NotificationQueue {
25 | private val _q = LinkedBlockingDeque()
26 | override fun popAll(): List {
27 | val list = mutableListOf()
28 | while (!_q.isEmpty()) {
29 | list += _q.pop()
30 | }
31 |
32 | return list
33 | }
34 |
35 | override fun isEmpty(): Boolean {
36 | return _q.isEmpty()
37 | }
38 |
39 | override fun add(notificationTask: NotificationTask) {
40 | _q.add(notificationTask)
41 | }
42 |
43 | override fun size(): Int {
44 | return _q.size
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/swabbie-core/swabbie-core.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | dependencies {
18 | implementation "org.slf4j:jcl-over-slf4j"
19 | implementation "io.spinnaker.kork:kork-core"
20 | implementation "io.spinnaker.kork:kork-web"
21 | implementation "io.spinnaker.kork:kork-moniker"
22 | implementation "net.logstash.logback:logstash-logback-encoder"
23 | implementation "com.squareup.retrofit:retrofit"
24 | implementation "com.fasterxml.jackson.core:jackson-annotations"
25 | implementation "com.fasterxml.jackson.core:jackson-core"
26 | implementation "com.fasterxml.jackson.core:jackson-databind"
27 | implementation "com.squareup.retrofit:converter-jackson"
28 | implementation "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
29 | implementation "com.fasterxml.jackson.module:jackson-module-kotlin"
30 | implementation "com.google.guava:guava"
31 |
32 | testImplementation project(":swabbie-test")
33 | testImplementation "io.spinnaker.kork:kork-test"
34 | testImplementation "io.strikt:strikt-core"
35 | }
36 |
--------------------------------------------------------------------------------
/swabbie-web/src/main/kotlin/com/netflix/spinnaker/swabbie/controllers/ControllerUtils.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.controllers
2 |
3 | import com.netflix.spinnaker.kork.web.exceptions.NotFoundException
4 | import com.netflix.spinnaker.swabbie.ResourceTypeHandler
5 | import com.netflix.spinnaker.swabbie.model.SwabbieNamespace
6 | import com.netflix.spinnaker.swabbie.model.WorkConfiguration
7 | import org.slf4j.LoggerFactory
8 | import org.springframework.stereotype.Component
9 |
10 | @Component
11 | class ControllerUtils(
12 | private val resourceTypeHandlers: List>,
13 | private val workConfigurations: List
14 | ) {
15 |
16 | private val log = LoggerFactory.getLogger(javaClass)
17 |
18 | init {
19 | log.info("Available resource type handlers are: $resourceTypeHandlers")
20 | }
21 |
22 | fun findWorkConfiguration(namespace: SwabbieNamespace): WorkConfiguration {
23 | return workConfigurations.find { workConfiguration ->
24 | workConfiguration.account.name == namespace.accountName &&
25 | workConfiguration.cloudProvider == namespace.cloudProvider &&
26 | workConfiguration.resourceType.equals(namespace.resourceType, true) &&
27 | workConfiguration.location == namespace.region
28 | } ?: throw NotFoundException("No configuration found for $namespace")
29 | }
30 |
31 | fun findHandler(workConfiguration: WorkConfiguration): ResourceTypeHandler<*> {
32 | return resourceTypeHandlers.find { handler ->
33 | handler.handles(workConfiguration)
34 | } ?: throw NotFoundException("No handlers for ${workConfiguration.namespace}")
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/swabbie-web/src/main/kotlin/com/netflix/spinnaker/swabbie/controllers/AdminController.kt:
--------------------------------------------------------------------------------
1 | package com.netflix.spinnaker.swabbie.controllers
2 |
3 | import com.netflix.spinnaker.swabbie.model.SwabbieNamespace
4 | import org.slf4j.LoggerFactory
5 | import org.springframework.web.bind.annotation.PathVariable
6 | import org.springframework.web.bind.annotation.RequestMapping
7 | import org.springframework.web.bind.annotation.RequestMethod
8 | import org.springframework.web.bind.annotation.RequestParam
9 | import org.springframework.web.bind.annotation.RestController
10 |
11 | @RestController
12 | @RequestMapping("/admin")
13 | class AdminController(
14 | private val controllerUtils: ControllerUtils
15 | ) {
16 |
17 | private val log = LoggerFactory.getLogger(javaClass)
18 |
19 | /**
20 | * Recalculate deletion timestamp to [retentionSeconds] seconds in the future for the
21 | * oldest [numResources] that are marked
22 | */
23 | @RequestMapping(value = ["/resources/recalculate/{namespace}/"], method = [RequestMethod.PUT])
24 | fun recalculate(
25 | @PathVariable namespace: String,
26 | @RequestParam(required = true) retentionSeconds: Long,
27 | @RequestParam(required = true) numResources: Int
28 | ) {
29 | log.info(
30 | "Recalculating deletion timestamp for oldest $numResources resources in $namespace. " +
31 | "Setting to ${retentionSeconds}s from now."
32 | )
33 | val workConfiguration = controllerUtils.findWorkConfiguration(SwabbieNamespace.namespaceParser(namespace))
34 | val handler = controllerUtils.findHandler(workConfiguration)
35 | handler.recalculateDeletionTimestamp(namespace, retentionSeconds, numResources)
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/exclusions/TemporalTagExclusionSupplier.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.aws.exclusions
18 |
19 | import com.netflix.spinnaker.config.Attribute
20 | import com.netflix.spinnaker.config.Exclusion
21 | import com.netflix.spinnaker.config.ExclusionType
22 | import com.netflix.spinnaker.swabbie.exclusions.ExclusionsSupplier
23 | import com.netflix.spinnaker.swabbie.tagging.TemporalTags
24 | import org.springframework.stereotype.Component
25 |
26 | @Component
27 | class TemporalTagExclusionSupplier : ExclusionsSupplier {
28 | override fun get(): List {
29 | return listOf(
30 | Exclusion()
31 | .withType(ExclusionType.Tag.toString())
32 | .withAttributes(
33 | TemporalTags.temporalTags.map { key ->
34 | Attribute()
35 | .withKey(key)
36 | .withValue(
37 | TemporalTags.supportedTemporalTagValues
38 | )
39 | }.toSet()
40 | )
41 | )
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/loadbalancers/AmazonElasticLoadBalancer.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.aws.loadbalancers
18 |
19 | import com.fasterxml.jackson.annotation.JsonTypeName
20 | import com.netflix.spinnaker.swabbie.aws.model.AmazonResource
21 | import com.netflix.spinnaker.swabbie.model.AWS
22 | import com.netflix.spinnaker.swabbie.model.LOAD_BALANCER
23 |
24 | @JsonTypeName("amazonElasticLoadBalancer")
25 | data class AmazonElasticLoadBalancer(
26 | private val loadBalancerName: String?, // TODO: stupid hack, fix this
27 | override val resourceType: String = LOAD_BALANCER,
28 | override val name: String = loadBalancerName!!,
29 | override val resourceId: String = loadBalancerName!!,
30 | override val cloudProvider: String = AWS,
31 | private val creationDate: String?
32 | ) : AmazonResource(creationDate) {
33 | override fun equals(other: Any?): Boolean {
34 | return super.equals(other)
35 | }
36 |
37 | override fun hashCode(): Int {
38 | return super.hashCode()
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/swabbie-aws/src/main/kotlin/com/netflix/spinnaker/swabbie/aws/AmazonTagOwnerResolutionStrategy.kt:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2018 Netflix, Inc.
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License")
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | package com.netflix.spinnaker.swabbie.aws
18 |
19 | import com.netflix.spinnaker.swabbie.ResourceOwnerResolutionStrategy
20 | import com.netflix.spinnaker.swabbie.model.Resource
21 | import org.springframework.stereotype.Component
22 |
23 | @Component
24 | class AmazonTagOwnerResolutionStrategy : ResourceOwnerResolutionStrategy {
25 |
26 | override fun primaryFor(): Set = emptySet()
27 |
28 | override fun resolve(resource: Resource): String? {
29 | if ("tags" in resource.details) {
30 | (resource.details["tags"] as? List