Merge pull request #3 from YuSungDuk/support_ncloud

Support ncloud
This commit is contained in:
Yu SungDuk 2018-01-29 17:32:08 +09:00 committed by GitHub
commit 9c0f50d29c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 102 additions and 21 deletions

View File

@ -8,8 +8,6 @@ import (
"github.com/mitchellh/multistep" "github.com/mitchellh/multistep"
) )
const version = "1.0.0"
// Builder assume this implements packer.Builder // Builder assume this implements packer.Builder
type Builder struct { type Builder struct {
config *Config config *Config
@ -30,8 +28,6 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
} }
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) { func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
ui.Say("Running builder for Naver Cloud Platform (version: " + version + ") ...")
ui.Message("Creating Naver Cloud Platform Connection ...") ui.Message("Creating Naver Cloud Platform Connection ...")
conn := ncloud.NewConnection(b.config.AccessKey, b.config.SecretKey) conn := ncloud.NewConnection(b.config.AccessKey, b.config.SecretKey)
@ -42,7 +38,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
steps = []multistep.Step{} steps = []multistep.Step{}
if b.config.OSType == "Linux" { if b.config.Comm.Type == "ssh" {
steps = []multistep.Step{ steps = []multistep.Step{
NewStepValidateTemplate(conn, ui, b.config), NewStepValidateTemplate(conn, ui, b.config),
NewStepCreateLoginKey(conn, ui), NewStepCreateLoginKey(conn, ui),
@ -63,7 +59,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
NewStepDeleteLoginKey(conn, ui), NewStepDeleteLoginKey(conn, ui),
NewStepDeletePublicIPInstance(conn, ui), NewStepDeletePublicIPInstance(conn, ui),
} }
} else if b.config.OSType == "Windows" { } else if b.config.Comm.Type == "Windows" {
steps = []multistep.Step{ steps = []multistep.Step{
NewStepValidateTemplate(conn, ui, b.config), NewStepValidateTemplate(conn, ui, b.config),
NewStepCreateLoginKey(conn, ui), NewStepCreateLoginKey(conn, ui),
@ -94,7 +90,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
} }
// Run! // Run!
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui) b.runner = common.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, b.stateBag)
b.runner.Run(b.stateBag) b.runner.Run(b.stateBag)
// If there was an error, return that // If there was an error, return that

View File

@ -16,13 +16,13 @@ type Config struct {
AccessKey string `mapstructure:"access_key"` AccessKey string `mapstructure:"access_key"`
SecretKey string `mapstructure:"secret_key"` SecretKey string `mapstructure:"secret_key"`
OSType string `mapstructure:"os_type"`
ServerImageProductCode string `mapstructure:"server_image_product_code"` ServerImageProductCode string `mapstructure:"server_image_product_code"`
ServerProductCode string `mapstructure:"server_product_code"` ServerProductCode string `mapstructure:"server_product_code"`
MemberServerImageNo string `mapstructure:"member_server_image_no"` MemberServerImageNo string `mapstructure:"member_server_image_no"`
ServerImageName string `mapstructure:"server_image_name"` ServerImageName string `mapstructure:"server_image_name"`
ServerImageDescription string `mapstructure:"server_image_description"` ServerImageDescription string `mapstructure:"server_image_description"`
UserData string `mapstructure:"user_data"` UserData string `mapstructure:"user_data"`
UserDataFile string `mapstructure:"user_data_file"`
BlockStorageSize int `mapstructure:"block_storage_size"` BlockStorageSize int `mapstructure:"block_storage_size"`
Region string `mapstructure:"region"` Region string `mapstructure:"region"`
AccessControlGroupConfigurationNo string `mapstructure:"access_control_group_configuration_no"` AccessControlGroupConfigurationNo string `mapstructure:"access_control_group_configuration_no"`
@ -60,10 +60,6 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, errors.New("secret_key is required")) errs = packer.MultiErrorAppend(errs, errors.New("secret_key is required"))
} }
if c.OSType != "Linux" && c.OSType != "Windows" {
errs = packer.MultiErrorAppend(errs, errors.New("os_type is required. ('Linux' or 'Windows')"))
}
if c.MemberServerImageNo == "" && c.ServerImageProductCode == "" { if c.MemberServerImageNo == "" && c.ServerImageProductCode == "" {
errs = packer.MultiErrorAppend(errs, errors.New("server_image_product_code or member_server_image_no is required")) errs = packer.MultiErrorAppend(errs, errors.New("server_image_product_code or member_server_image_no is required"))
} }
@ -100,8 +96,8 @@ func NewConfig(raws ...interface{}) (*Config, []string, error) {
errs = packer.MultiErrorAppend(errs, errors.New("If user_data field is set, length of UserData should be max 21847")) errs = packer.MultiErrorAppend(errs, errors.New("If user_data field is set, length of UserData should be max 21847"))
} }
if c.OSType == "Windows" && c.AccessControlGroupConfigurationNo == "" { if c.Comm.Type == "wrinrm" && c.AccessControlGroupConfigurationNo == "" {
errs = packer.MultiErrorAppend(errs, errors.New("If os_type is Windows, access_control_group_configuration_no is required")) errs = packer.MultiErrorAppend(errs, errors.New("If Communicator is winrm, access_control_group_configuration_no is required"))
} }
c.FeeSystemTypeCode = "MTRAT" c.FeeSystemTypeCode = "MTRAT"

View File

@ -9,7 +9,6 @@ func testConfig() map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
"access_key": "access_key", "access_key": "access_key",
"secret_key": "secret_key", "secret_key": "secret_key",
"os_type": "Windows",
"server_image_product_code": "SPSW0WINNT000016", "server_image_product_code": "SPSW0WINNT000016",
"server_product_code": "SPSVRSSD00000011", "server_product_code": "SPSVRSSD00000011",
"server_image_name": "packer-test {{timestamp}}", "server_image_name": "packer-test {{timestamp}}",
@ -27,7 +26,6 @@ func testConfigForMemberServerImage() map[string]interface{} {
return map[string]interface{}{ return map[string]interface{}{
"access_key": "access_key", "access_key": "access_key",
"secret_key": "secret_key", "secret_key": "secret_key",
"os_type": "Windows",
"server_product_code": "SPSVRSSD00000011", "server_product_code": "SPSVRSSD00000011",
"member_server_image_no": "2440", "member_server_image_no": "2440",
"server_image_name": "packer-test {{timestamp}}", "server_image_name": "packer-test {{timestamp}}",
@ -135,7 +133,6 @@ func TestExistsBothServerImageProductCodeAndMemberServerImageNoConfig(t *testing
raw := map[string]interface{}{ raw := map[string]interface{}{
"access_key": "access_key", "access_key": "access_key",
"secret_key": "secret_key", "secret_key": "secret_key",
"os_type": "Windows",
"server_image_product_code": "SPSW0WINNT000016", "server_image_product_code": "SPSW0WINNT000016",
"server_product_code": "SPSVRSSD00000011", "server_product_code": "SPSVRSSD00000011",
"member_server_image_no": "2440", "member_server_image_no": "2440",

View File

@ -91,10 +91,10 @@ func (s *StepCreatePublicIPInstance) Run(state multistep.StateBag) multistep.Ste
publicIPInstance, err := s.CreatePublicIPInstance(serverInstanceNo) publicIPInstance, err := s.CreatePublicIPInstance(serverInstanceNo)
if err == nil { if err == nil {
switch s.Config.OSType { switch s.Config.Comm.Type {
case "Linux": case "ssh":
state.Put("SSHHost", publicIPInstance.PublicIP) state.Put("SSHHost", publicIPInstance.PublicIP)
case "Windows": case "winrm":
state.Put("WinRMHost", publicIPInstance.PublicIP) state.Put("WinRMHost", publicIPInstance.PublicIP)
} }

View File

@ -31,13 +31,17 @@ func TestStepCreatePublicIPInstanceShouldFailIfOperationCreatePublicIPInstanceFa
} }
func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePasses(t *testing.T) { func TestStepCreatePublicIPInstanceShouldPassIfOperationCreatePublicIPInstancePasses(t *testing.T) {
c := new(Config)
c.Comm.Prepare(nil)
c.Comm.Type = "ssh"
var testSubject = &StepCreatePublicIPInstance{ var testSubject = &StepCreatePublicIPInstance{
CreatePublicIPInstance: func(serverInstanceNo string) (*ncloud.PublicIPInstance, error) { CreatePublicIPInstance: func(serverInstanceNo string) (*ncloud.PublicIPInstance, error) {
return &ncloud.PublicIPInstance{PublicIPInstanceNo: "a", PublicIP: "b"}, nil return &ncloud.PublicIPInstance{PublicIPInstanceNo: "a", PublicIP: "b"}, nil
}, },
Say: func(message string) {}, Say: func(message string) {},
Error: func(e error) {}, Error: func(e error) {},
Config: &Config{OSType: "Windows"}, Config: c,
} }
stateBag := createTestStateBagStepCreatePublicIPInstance() stateBag := createTestStateBagStepCreatePublicIPInstance()

View File

@ -0,0 +1,88 @@
---
description: |
As Packer allows users to develop a custom builder as a plugin, NAVER CLOUD PLATFORM provides its own Packer builder for your convenience.
You can use NAVER CLOUD PLATFORM's Packer builder to easily create your server images.
layout: docs
page_title: 'Naver Cloud Platform - Builders'
sidebar_current: 'docs-builders-ncloud'
---
# NAVER CLOUD PLATFORM Builder
As Packer allows users to develop a custom builder as a plugin, NAVER CLOUD PLATFORM provides its own Packer builder for your convenience.
You can use NAVER CLOUD PLATFORM's Packer builder to easily create your server images.
#### Sample code of template.json
```
{
"variables": {
"ncloud_access_key": "FRxhOQRNjKVMqIz3sRLY",
"ncloud_secret_key": "xd6kTO5iNcLookBx0D8TDKmpLj2ikxqEhc06MQD2"
},
"builders": [
{
"type": "ncloud",
"access_key": "{{user `ncloud_access_key`}}",
"secret_key": "{{user `ncloud_secret_key`}}",
"server_image_product_code": "SPSW0WINNT000016",
"server_product_code": "SPSVRSSD00000011",
"member_server_image_no": "4223",
"server_image_name": "packer-test {{timestamp}}",
"server_description": "server description",
"user_data": "CreateObject(\"WScript.Shell\").run(\"cmd.exe /c powershell Set-ExecutionPolicy RemoteSigned & winrm quickconfig -q & sc config WinRM start= auto & winrm set winrm/config/service/auth @{Basic=\"\"true\"\"} & winrm set winrm/config/service @{AllowUnencrypted=\"\"true\"\"} & winrm get winrm/config/service\")",
"region": "US-West"
}
]
}
```
#### Description
* type(required): "ncloud"
* ncloud_access_key (required): User's access key. Go to [[Account Management > Authentication Key]](https://www.ncloud.com/mypage/manage/authkey) to create and view your authentication key.
* ncloud_secret_key (required): User's secret key paired with the access key. Go to [[Account Management > Authentication Key]](https://www.ncloud.com/mypage/manage/authkey) to create and view your authentication key.
* server_image_product_code: Product code of an image to create. (member_server_image_no is required if not specified)
* server_product_code (required): Product (spec) code to create.
* member_server_image_no: Previous image code. If there is an image previously created, it can be used to create a new image. (server_image_product_code is required if not specified)
* server_image_name (option): Name of an image to create.
* server_image_description (option): Description of an image to create.
* block_storage_size (option): You can add block storage ranging from 10 GB to 2000 GB, in increments of 10 GB.
* access_control_group_configuration_no: This is used to allow winrm access when you create a Windows server. An ACG that specifies an access source ("0.0.0.0/0") and allowed port (5985) must be created in advance.
* user_data (option): Init script to run when an instance is created.
* For Linux servers, Python, Perl, and Shell scripts can be used. The path of the script to run should be included at the beginning of the script, like #!/usr/bin/env python, #!/bin/perl, or #!/bin/bash.
* For Windows servers, only Visual Basic scripts can be used.
* All scripts must be written in English.
* region (option): Name of the region where you want to create an image. (default: Korea)
* values: Korea / US-West / HongKong / Singapore / Japan / Germany
### Requirements for creating Windows images
You should include the following code in the packer configuration file for provision when creating a Windows server.
```
"builders": [
{
"type": "ncloud",
...
"user_data":
"CreateObject(\"WScript.Shell\").run(\"cmd.exe /c powershell Set-ExecutionPolicy RemoteSigned & winrm set winrm/config/service/auth @{Basic=\"\"true\"\"} & winrm set winrm/config/service @{AllowUnencrypted=\"\"true\"\"} & winrm quickconfig -q & sc config WinRM start= auto & winrm get winrm/config/service\")",
"communicator": "winrm",
"winrm_username": "Administrator"
}
],
"provisioners": [
{
"type": "powershell",
"inline": [
"$Env:SystemRoot\\System32\\Sysprep\\Sysprep.exe /oobe /generalize /shutdown /quiet \"/unattend:C:\\Program Files (x86)\\NBP\\nserver64.xml\" "
]
}
]
```
### Note
* You can only create as many public IP addresses as the number of server instances you own. Before running Packer, please make sure that the number of public IP addresses previously created is not larger than the number of server instances (including those to be used to create server images).
* When you forcibly terminate the packer process or close the terminal (command) window where the process is running, the resources may not be cleaned up as the packer process no longer runs. In this case, you should manually clean up the resources associated with the process.