Skip to content

Commit 384e331

Browse files
feat(plugins): Binary publish proxy endpoint (#1066)
* refactor(plugins): Rename gate-deck-plugins module to gate-plugins * refactor(plugins): Move deck plugin proxy code to new package * feat(plugins): Add endpoint to proxy plugin binary publishing Co-authored-by: mergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
1 parent 8e51ed1 commit 384e331

File tree

16 files changed

+135
-22
lines changed

16 files changed

+135
-22
lines changed

.editorconfig

-1
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,3 @@ insert_final_newline = true
77
trim_trailing_whitespace = true
88
indent_style = space
99
indent_size = 2
10-
continuation_indent_size = 4

gate-api/gate-api.gradle

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2020 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+
apply plugin: 'java-library'
17+
18+
dependencies {
19+
implementation platform("com.netflix.spinnaker.kork:kork-bom:$korkVersion")
20+
api "com.netflix.spinnaker.kork:kork-plugins-api"
21+
}

gate-core/src/main/groovy/com/netflix/spinnaker/gate/services/internal/Front50Service.groovy

+10
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package com.netflix.spinnaker.gate.services.internal
1919
import com.netflix.spinnaker.fiat.model.resources.ServiceAccount
2020
import retrofit.client.Response
2121
import retrofit.http.*
22+
import retrofit.mime.TypedInput
2223

2324
interface Front50Service {
2425
@GET("/credentials")
@@ -160,4 +161,13 @@ interface Front50Service {
160161
// Plugins related
161162
@GET('/pluginInfo')
162163
List<Map> getPluginInfo(@Query("service") String service)
164+
165+
@POST("/pluginBinaries/{id}/{version}")
166+
@Headers(["Content-Type: application/zip,application/octet-stream"])
167+
Response uploadPluginBinary(
168+
@Path("id") String pluginId,
169+
@Path("version") String pluginVersion,
170+
@Query("sha512sum") String sha512sum,
171+
@Body TypedInput pluginBinary
172+
);
163173
}

gate-deck-plugins/gate-deck-plugins.gradle gate-plugins/gate-plugins.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ apply from: "${project.rootDir}/gradle/kotlin.gradle"
1818
apply from: "${project.rootDir}/gradle/kotlin-test.gradle"
1919

2020
dependencies {
21+
implementation project(":gate-api")
2122
implementation project(":gate-core")
2223

2324
implementation "com.netflix.spinnaker.kork:kork-plugins"

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/CacheNotReadyException.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/CacheNotReadyException.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spinnaker.kork.exceptions.SystemException
1919

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginCache.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginCache.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spectator.api.Id
1919
import com.netflix.spectator.api.Registry

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginConfiguration.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginConfiguration.kt

+4-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spectator.api.Registry
1919
import com.netflix.spinnaker.kork.plugins.bundle.PluginBundleExtractor
@@ -26,15 +26,15 @@ import org.springframework.scheduling.annotation.EnableScheduling
2626

2727
@Configuration
2828
@ConditionalOnProperty("spinnaker.extensibility.deck-proxy.enabled", matchIfMissing = true)
29-
@ComponentScan("com.netflix.spinnaker.gate.plugins")
29+
@ComponentScan("com.netflix.spinnaker.gate.plugins.deck")
3030
@EnableScheduling
3131
open class DeckPluginConfiguration {
3232
@Bean
3333
open fun deckPluginCache(
3434
updateManager: SpinnakerUpdateManager,
3535
registry: Registry
3636
): DeckPluginCache =
37-
DeckPluginCache(updateManager, PluginBundleExtractor(), registry)
37+
DeckPluginCache(updateManager, PluginBundleExtractor(), registry)
3838

3939
@Bean
4040
open fun deckPluginService(
@@ -44,5 +44,5 @@ open class DeckPluginConfiguration {
4444

4545
@Bean
4646
open fun deckPluginsController(pluginService: DeckPluginService): DeckPluginsController =
47-
DeckPluginsController(pluginService)
47+
DeckPluginsController(pluginService)
4848
}

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginService.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginService.kt

+10-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spectator.api.Registry
1919
import org.slf4j.LoggerFactory
@@ -78,9 +78,15 @@ class DeckPluginService(
7878
fun from(file: File): PluginAsset {
7979
return PluginAsset(
8080
contentType = when {
81-
file.toString().endsWith(".js") -> { "application/javascript" }
82-
file.toString().endsWith(".css") -> { "text/css" }
83-
file.toString().endsWith(".html") -> { "text/html" }
81+
file.toString().endsWith(".js") -> {
82+
"application/javascript"
83+
}
84+
file.toString().endsWith(".css") -> {
85+
"text/css"
86+
}
87+
file.toString().endsWith(".html") -> {
88+
"text/html"
89+
}
8490
else -> {
8591
log.warn("Unhandled file extension to content-type mapping for file `{}`, falling back to text/plain", file.toString())
8692
"text/plain"

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginVersion.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginVersion.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
/**
1919
* A plugin manifest used by Deck to know what plugins should be installed and at what version.

gate-deck-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginsController.kt gate-plugins/src/main/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginsController.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spinnaker.kork.web.exceptions.NotFoundException
1919
import io.swagger.annotations.ApiOperation
@@ -26,7 +26,6 @@ import org.springframework.web.bind.annotation.PathVariable
2626
import org.springframework.web.bind.annotation.RequestMapping
2727
import org.springframework.web.bind.annotation.RestController
2828
import java.util.concurrent.TimeUnit
29-
import javax.servlet.http.HttpServletRequest
3029
import javax.servlet.http.HttpServletResponse
3130

3231
@RestController
@@ -65,8 +64,7 @@ class DeckPluginsController(
6564
@ExceptionHandler(CacheNotReadyException::class)
6665
fun handleCacheNotReadyException(
6766
e: Exception,
68-
response: HttpServletResponse,
69-
request: HttpServletRequest?
67+
response: HttpServletResponse
7068
) {
7169
response.sendError(HttpStatus.SERVICE_UNAVAILABLE.value(), e.message)
7270
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright 2020 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+
package com.netflix.spinnaker.gate.plugins.publish
17+
18+
import com.netflix.spinnaker.gate.services.internal.Front50Service
19+
import io.swagger.annotations.ApiOperation
20+
import org.springframework.web.bind.annotation.PathVariable
21+
import org.springframework.web.bind.annotation.PostMapping
22+
import org.springframework.web.bind.annotation.RequestBody
23+
import org.springframework.web.bind.annotation.RequestMapping
24+
import org.springframework.web.bind.annotation.RequestParam
25+
import org.springframework.web.bind.annotation.RestController
26+
import retrofit.mime.TypedByteArray
27+
import java.io.InputStream
28+
29+
@RestController
30+
@RequestMapping("/plugins/upload")
31+
class PluginBinaryController(
32+
private val front50Service: Front50Service
33+
) {
34+
35+
@ApiOperation(value = "Upload a plugin binary")
36+
@PostMapping(
37+
"/{pluginId}/{pluginVersion}",
38+
consumes = ["application/zip", "application/octet-stream"]
39+
)
40+
fun publishBinary(
41+
@RequestBody body: InputStream,
42+
@PathVariable pluginId: String,
43+
@PathVariable pluginVersion: String,
44+
@RequestParam sha512sum: String
45+
) {
46+
front50Service.uploadPluginBinary(
47+
pluginId,
48+
pluginVersion,
49+
sha512sum,
50+
TypedByteArray("application/octet-stream", body.readBytes())
51+
)
52+
}
53+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2020 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+
package com.netflix.spinnaker.gate.plugins.publish
17+
18+
import org.springframework.context.annotation.ComponentScan
19+
import org.springframework.context.annotation.Configuration
20+
21+
@Configuration
22+
@ComponentScan("com.netflix.spinnaker.gate.plugins.publish")
23+
open class PluginPublishConfiguration

gate-deck-plugins/src/test/kotlin/com/netflix/spinnaker/gate/plugins/DeckPluginCacheTest.kt gate-plugins/src/test/kotlin/com/netflix/spinnaker/gate/plugins/deck/DeckPluginCacheTest.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* See the License for the specific language governing permissions and
1414
* limitations under the License.
1515
*/
16-
package com.netflix.spinnaker.gate.plugins
16+
package com.netflix.spinnaker.gate.plugins.deck
1717

1818
import com.netflix.spectator.api.NoopRegistry
1919
import com.netflix.spectator.api.Registry

gate-web/gate-web.gradle

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repositories {
2020
dependencies {
2121
implementation project(":gate-core")
2222
implementation project(":gate-proxy")
23-
implementation project(":gate-deck-plugins")
23+
implementation project(":gate-plugins")
2424
implementation project(":gate-integrations-gremlin")
2525

2626
implementation "com.squareup.retrofit:retrofit"

gate-web/src/main/groovy/com/netflix/spinnaker/gate/config/GateConfig.groovy

+3-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ import com.netflix.spinnaker.filters.AuthenticatedRequestFilter
3333
import com.netflix.spinnaker.gate.config.PostConnectionConfiguringJedisConnectionFactory.ConnectionPostProcessor
3434
import com.netflix.spinnaker.gate.converters.JsonHttpMessageConverter
3535
import com.netflix.spinnaker.gate.converters.YamlHttpMessageConverter
36-
import com.netflix.spinnaker.gate.plugins.DeckPluginConfiguration
36+
import com.netflix.spinnaker.gate.plugins.deck.DeckPluginConfiguration
37+
import com.netflix.spinnaker.gate.plugins.publish.PluginPublishConfiguration
3738
import com.netflix.spinnaker.gate.retrofit.Slf4jRetrofitLogger
3839
import com.netflix.spinnaker.gate.services.EurekaLookupService
3940
import com.netflix.spinnaker.gate.services.internal.*
@@ -83,7 +84,7 @@ import static retrofit.Endpoints.newFixedEndpoint
8384
@Configuration
8485
@Slf4j
8586
@EnableConfigurationProperties([FiatClientConfigurationProperties, DynamicRoutingConfigProperties])
86-
@Import([PluginsAutoConfiguration, DeckPluginConfiguration])
87+
@Import([PluginsAutoConfiguration, DeckPluginConfiguration, PluginPublishConfiguration])
8788
class GateConfig extends RedisHttpSessionConfiguration {
8889

8990
@Value('${server.session.timeout-in-seconds:3600}')

settings.gradle

+3-2
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@
1616

1717
rootProject.name = "gate"
1818

19-
include "gate-core",
20-
"gate-deck-plugins",
19+
include "gate-api",
20+
"gate-core",
21+
"gate-plugins",
2122
"gate-basic",
2223
"gate-bom",
2324
"gate-iap",

0 commit comments

Comments
 (0)