-
Notifications
You must be signed in to change notification settings - Fork 643
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial commit providing openstack functionality for rosco (#97)
provider/openstack: Initial commit providing openstack functionality for rosco.
- Loading branch information
Showing
10 changed files
with
1,022 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,5 +47,4 @@ allprojects { | |
} | ||
} | ||
|
||
|
||
defaultTasks ':rosco-web:bootRun' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
150 changes: 150 additions & 0 deletions
150
...c/main/groovy/com/netflix/spinnaker/rosco/providers/openstack/OpenstackBakeHandler.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
/* | ||
* Copyright 2016 Target, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.spinnaker.rosco.providers.openstack | ||
|
||
import com.netflix.spinnaker.rosco.api.Bake | ||
import com.netflix.spinnaker.rosco.api.BakeOptions | ||
import com.netflix.spinnaker.rosco.api.BakeRequest | ||
import com.netflix.spinnaker.rosco.providers.CloudProviderBakeHandler | ||
import com.netflix.spinnaker.rosco.providers.openstack.config.RoscoOpenstackConfiguration | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.beans.factory.annotation.Value | ||
import org.springframework.stereotype.Component | ||
|
||
/** | ||
* TODO(drmaas): need to figure out the following: | ||
* 1) packer openstack variables - required vs optional (currently have a best guess for what is required for v3) | ||
* 2) openstack username/password management (currently will load via environment variable passed to java process) | ||
* 3) v2 vs. v3 apis (currently implemented for v3) | ||
*/ | ||
@Component | ||
public class OpenstackBakeHandler extends CloudProviderBakeHandler { | ||
|
||
private static final String BUILDER_TYPE = 'openstack' | ||
private static final String IMAGE_NAME_TOKEN = 'openstack: An image was created:' | ||
|
||
@Autowired | ||
RoscoOpenstackConfiguration.OpenstackBakeryDefaults openstackBakeryDefaults | ||
|
||
@Override | ||
def getBakeryDefaults() { | ||
return openstackBakeryDefaults | ||
} | ||
|
||
@Override | ||
BakeOptions getBakeOptions() { | ||
new BakeOptions( | ||
cloudProvider: BakeRequest.CloudProviderType.openstack, | ||
baseImages: openstackBakeryDefaults?.baseImages?.collect { it.baseImage } | ||
) | ||
} | ||
|
||
@Override | ||
String produceProviderSpecificBakeKeyComponent(String region, BakeRequest bakeRequest) { | ||
region | ||
} | ||
|
||
@Override | ||
def findVirtualizationSettings(String region, BakeRequest bakeRequest) { | ||
def openstackOperatingSystemVirtualizationSettings = openstackBakeryDefaults?.baseImages.find { | ||
it.baseImage.id == bakeRequest.base_os | ||
} | ||
|
||
if (!openstackOperatingSystemVirtualizationSettings) { | ||
throw new IllegalArgumentException("No virtualization settings found for '$bakeRequest.base_os'.") | ||
} | ||
|
||
def openstackVirtualizationSettings = openstackOperatingSystemVirtualizationSettings?.virtualizationSettings.find { | ||
it.region == region && it.instanceType == bakeRequest.instance_type | ||
} | ||
|
||
if (!openstackVirtualizationSettings) { | ||
throw new IllegalArgumentException("No virtualization settings found for region '$region', operating system '$bakeRequest.base_os', and instance_type '${bakeRequest.instance_type}'.") | ||
} | ||
|
||
if (bakeRequest.base_ami) { | ||
openstackVirtualizationSettings = openstackVirtualizationSettings.clone() | ||
openstackVirtualizationSettings.sourceImageName = bakeRequest.base_ami | ||
} | ||
|
||
return openstackVirtualizationSettings | ||
} | ||
|
||
@Override | ||
Map buildParameterMap(String region, def openstackVirtualizationSettings, String imageName, BakeRequest bakeRequest) { | ||
def parameterMap = [ | ||
openstack_identity_endpoint: openstackBakeryDefaults.identityEndpoint, | ||
openstack_region: region, | ||
openstack_ssh_username: openstackVirtualizationSettings.sshUserName, | ||
openstack_instance_type: openstackVirtualizationSettings.instanceType, | ||
openstack_source_image_name: openstackVirtualizationSettings.sourceImageName, | ||
openstack_image_name: imageName | ||
] | ||
|
||
if (openstackBakeryDefaults.username && openstackBakeryDefaults.password) { | ||
parameterMap.openstack_username = openstackBakeryDefaults.username | ||
parameterMap.openstack_password = openstackBakeryDefaults.password | ||
} | ||
|
||
if (openstackBakeryDefaults.domainName) { | ||
parameterMap.openstack_domain_name = openstackBakeryDefaults.domainName | ||
} | ||
|
||
if (openstackBakeryDefaults.floatingIpPool) { | ||
parameterMap.openstack_floating_ip_pool = openstackBakeryDefaults.floatingIpPool | ||
} | ||
|
||
if (openstackBakeryDefaults.insecure != null) { | ||
parameterMap.openstack_insecure = openstackBakeryDefaults.insecure | ||
} | ||
|
||
if (openstackBakeryDefaults.securityGroups != null) { | ||
parameterMap.openstack_security_groups = openstackBakeryDefaults.securityGroups | ||
} | ||
|
||
if (openstackBakeryDefaults.tenantName != null) { | ||
parameterMap.openstack_tenant_name = openstackBakeryDefaults.tenantName | ||
} | ||
|
||
return parameterMap | ||
} | ||
|
||
@Override | ||
String getTemplateFileName() { | ||
return openstackBakeryDefaults.templateFile | ||
} | ||
|
||
@Override | ||
boolean isProducerOf(String logsContentFirstLine) { | ||
logsContentFirstLine =~ BUILDER_TYPE | ||
} | ||
|
||
@Override | ||
Bake scrapeCompletedBakeResults(String region, String bakeId, String logsContent) { | ||
String imageName | ||
|
||
// TODO(duftler): Presently scraping the logs for the image name/id. Would be better to not be reliant on the log | ||
// format not changing. Resolve this by storing bake details in redis and querying oort for amiId from amiName. | ||
logsContent.eachLine { String line -> | ||
if (line =~ IMAGE_NAME_TOKEN) { | ||
imageName = line.split(" ").last() | ||
} | ||
} | ||
|
||
new Bake(id: bakeId, image_name: imageName) | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
...com/netflix/spinnaker/rosco/providers/openstack/config/RoscoOpenstackConfiguration.groovy
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
/* | ||
* Copyright 2016 Target, Inc. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
package com.netflix.spinnaker.rosco.providers.openstack.config | ||
|
||
import com.netflix.spinnaker.rosco.api.BakeOptions | ||
import com.netflix.spinnaker.rosco.api.BakeRequest | ||
import com.netflix.spinnaker.rosco.providers.openstack.OpenstackBakeHandler | ||
import com.netflix.spinnaker.rosco.providers.registry.CloudProviderBakeHandlerRegistry | ||
import groovy.transform.AutoClone | ||
import groovy.transform.AutoCloneStyle | ||
import org.springframework.beans.factory.annotation.Autowired | ||
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty | ||
import org.springframework.boot.context.properties.ConfigurationProperties | ||
import org.springframework.context.annotation.Bean | ||
import org.springframework.context.annotation.ComponentScan | ||
import org.springframework.context.annotation.Configuration | ||
|
||
import javax.annotation.PostConstruct | ||
|
||
@Configuration | ||
@ConditionalOnProperty('openstack.enabled') | ||
@ComponentScan('com.netflix.spinnaker.rosco.providers.openstack') | ||
class RoscoOpenstackConfiguration { | ||
|
||
@Autowired | ||
CloudProviderBakeHandlerRegistry cloudProviderBakeHandlerRegistry | ||
|
||
@Autowired | ||
OpenstackBakeHandler openstackBakeHandler | ||
|
||
@Bean | ||
@ConfigurationProperties('openstack.bakeryDefaults') | ||
OpenstackBakeryDefaults openstackBakeryDefaults() { | ||
new OpenstackBakeryDefaults() | ||
} | ||
|
||
static class OpenstackBakeryDefaults { | ||
String identityEndpoint | ||
String domainName | ||
String floatingIpPool | ||
String securityGroups | ||
String tenantName | ||
String templateFile | ||
Boolean insecure | ||
String username | ||
String password | ||
List<OpenstackOperatingSystemVirtualizationSettings> baseImages = [] | ||
} | ||
|
||
static class OpenstackOperatingSystemVirtualizationSettings { | ||
BakeOptions.BaseImage baseImage | ||
List<OpenstackVirtualizationSettings> virtualizationSettings = [] | ||
} | ||
|
||
@AutoClone(style = AutoCloneStyle.SIMPLE) | ||
static class OpenstackVirtualizationSettings { | ||
String region | ||
String instanceType | ||
String sourceImageName | ||
String sshUserName | ||
} | ||
|
||
@PostConstruct | ||
void init() { | ||
cloudProviderBakeHandlerRegistry.register(BakeRequest.CloudProviderType.openstack, openstackBakeHandler) | ||
} | ||
|
||
} |
Oops, something went wrong.