Add the winRM communicator to Oracle Classic builder.
update oracle classic docs with a minimal working windows example
This commit is contained in:
parent
36179c5a1d
commit
df45e0916d
|
@ -99,10 +99,6 @@ func NewConfig(raws ...interface{}) (*Config, error) {
|
||||||
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
|
if es := c.Comm.Prepare(&c.ctx); len(es) > 0 {
|
||||||
errs = packer.MultiErrorAppend(errs, es...)
|
errs = packer.MultiErrorAppend(errs, es...)
|
||||||
}
|
}
|
||||||
if c.Comm.Type == "winrm" {
|
|
||||||
err = fmt.Errorf("winRM is not supported with the oracle-classic builder yet.")
|
|
||||||
errs = packer.MultiErrorAppend(errs, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if errs != nil && len(errs.Errors) > 0 {
|
if errs != nil && len(errs.Errors) > 0 {
|
||||||
return nil, errs
|
return nil, errs
|
||||||
|
|
|
@ -19,6 +19,11 @@ func (s *stepAddKeysToAPI) Run(_ context.Context, state multistep.StateBag) mult
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
|
|
||||||
|
if config.Comm.Type != "ssh" {
|
||||||
|
ui.Say("Not using SSH communicator; skip generating SSH keys...")
|
||||||
|
return multistep.ActionContinue
|
||||||
|
}
|
||||||
|
|
||||||
// grab packer-generated key from statebag context.
|
// grab packer-generated key from statebag context.
|
||||||
sshPublicKey := strings.TrimSpace(state.Get("publicKey").(string))
|
sshPublicKey := strings.TrimSpace(state.Get("publicKey").(string))
|
||||||
|
|
||||||
|
@ -49,10 +54,14 @@ func (s *stepAddKeysToAPI) Run(_ context.Context, state multistep.StateBag) mult
|
||||||
|
|
||||||
func (s *stepAddKeysToAPI) Cleanup(state multistep.StateBag) {
|
func (s *stepAddKeysToAPI) Cleanup(state multistep.StateBag) {
|
||||||
// Delete the keys we created during this run
|
// Delete the keys we created during this run
|
||||||
keyName := state.Get("key_name").(string)
|
keyName, ok := state.GetOk("key_name")
|
||||||
|
if !ok {
|
||||||
|
// No keys were generated; none need to be cleaned up.
|
||||||
|
return
|
||||||
|
}
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
ui.Say("Deleting SSH keys...")
|
ui.Say("Deleting SSH keys...")
|
||||||
deleteInput := compute.DeleteSSHKeyInput{Name: keyName}
|
deleteInput := compute.DeleteSSHKeyInput{Name: keyName.(string)}
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
deleteClient := client.SSHKeys()
|
deleteClient := client.SSHKeys()
|
||||||
err := deleteClient.DeleteSSHKey(&deleteInput)
|
err := deleteClient.DeleteSSHKey(&deleteInput)
|
||||||
|
|
|
@ -18,7 +18,6 @@ func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu
|
||||||
|
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
keyName := state.Get("key_name").(string)
|
|
||||||
ipAddName := state.Get("ipres_name").(string)
|
ipAddName := state.Get("ipres_name").(string)
|
||||||
secListName := state.Get("security_list").(string)
|
secListName := state.Get("security_list").(string)
|
||||||
|
|
||||||
|
@ -35,10 +34,13 @@ func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu
|
||||||
Name: config.ImageName,
|
Name: config.ImageName,
|
||||||
Shape: config.Shape,
|
Shape: config.Shape,
|
||||||
ImageList: config.SourceImageList,
|
ImageList: config.SourceImageList,
|
||||||
SSHKeys: []string{keyName},
|
|
||||||
Networking: map[string]compute.NetworkingInfo{"eth0": netInfo},
|
Networking: map[string]compute.NetworkingInfo{"eth0": netInfo},
|
||||||
Attributes: config.attribs,
|
Attributes: config.attribs,
|
||||||
}
|
}
|
||||||
|
if config.Comm.Type == "ssh" {
|
||||||
|
keyName := state.Get("key_name").(string)
|
||||||
|
input.SSHKeys = []string{keyName}
|
||||||
|
}
|
||||||
|
|
||||||
instanceInfo, err := instanceClient.CreateInstance(input)
|
instanceInfo, err := instanceClient.CreateInstance(input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -48,6 +50,7 @@ func (s *stepCreateInstance) Run(_ context.Context, state multistep.StateBag) mu
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.Put("instance_info", instanceInfo)
|
||||||
state.Put("instance_id", instanceInfo.ID)
|
state.Put("instance_id", instanceInfo.ID)
|
||||||
ui.Message(fmt.Sprintf("Created instance: %s.", instanceInfo.ID))
|
ui.Message(fmt.Sprintf("Created instance: %s.", instanceInfo.ID))
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
|
|
|
@ -3,10 +3,10 @@ package classic
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||||
|
"github.com/hashicorp/packer/common/uuid"
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
)
|
)
|
||||||
|
@ -15,53 +15,101 @@ type stepSecurity struct{}
|
||||||
|
|
||||||
func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
|
||||||
ui.Say("Configuring security lists and rules to enable SSH access...")
|
|
||||||
|
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
|
||||||
|
|
||||||
secListName := fmt.Sprintf("/Compute-%s/%s/Packer_SSH_Allow_%s",
|
commType := ""
|
||||||
config.IdentityDomain, config.Username, config.ImageName)
|
if config.Comm.Type == "ssh" {
|
||||||
|
commType = "SSH"
|
||||||
|
} else if config.Comm.Type == "winrm" {
|
||||||
|
commType = "WINRM"
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.Say(fmt.Sprintf("Configuring security lists and rules to enable %s access...", commType))
|
||||||
|
|
||||||
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
|
runUUID := uuid.TimeOrderedUUID()
|
||||||
|
|
||||||
|
namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
|
||||||
|
secListName := fmt.Sprintf("Packer_%s_Allow_%s_%s", commType, config.ImageName, runUUID)
|
||||||
secListClient := client.SecurityLists()
|
secListClient := client.SecurityLists()
|
||||||
secListInput := compute.CreateSecurityListInput{
|
secListInput := compute.CreateSecurityListInput{
|
||||||
Description: "Packer-generated security list to give packer ssh access",
|
Description: fmt.Sprintf("Packer-generated security list to give packer %s access", commType),
|
||||||
Name: secListName,
|
Name: namePrefix + secListName,
|
||||||
}
|
}
|
||||||
_, err := secListClient.CreateSecurityList(&secListInput)
|
_, err := secListClient.CreateSecurityList(&secListInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !strings.Contains(err.Error(), "already exists") {
|
if !strings.Contains(err.Error(), "already exists") {
|
||||||
err = fmt.Errorf("Error creating security List to"+
|
err = fmt.Errorf("Error creating security List to"+
|
||||||
" allow Packer to connect to Oracle instance via SSH: %s", err)
|
" allow Packer to connect to Oracle instance via %s: %s", commType, err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// DOCS NOTE: user must have Compute_Operations role
|
// DOCS NOTE: user must have Compute_Operations role
|
||||||
// Create security rule that allows Packer to connect via SSH
|
// Create security rule that allows Packer to connect via SSH or winRM
|
||||||
secRulesClient := client.SecRules()
|
var application string
|
||||||
secRulesInput := compute.CreateSecRuleInput{
|
if commType == "SSH" {
|
||||||
Action: "PERMIT",
|
application = "/oracle/public/ssh"
|
||||||
Application: "/oracle/public/ssh",
|
} else if commType == "WINRM" {
|
||||||
Description: "Packer-generated security rule to allow ssh",
|
// Check to see whether a winRM security protocol is already defined;
|
||||||
DestinationList: fmt.Sprintf("seclist:%s", secListName),
|
// don't need to do this for SSH becasue it is built into the Oracle API.
|
||||||
Name: fmt.Sprintf("Packer-allow-SSH-Rule_%s", config.ImageName),
|
protocolClient := client.SecurityProtocols()
|
||||||
SourceList: config.SSHSourceList,
|
winrmProtocol := fmt.Sprintf("WINRM_%s", runUUID)
|
||||||
}
|
input := compute.CreateSecurityProtocolInput{
|
||||||
|
Name: winrmProtocol,
|
||||||
secRuleName := fmt.Sprintf("/Compute-%s/%s/Packer-allow-SSH-Rule_%s",
|
Description: "packer-generated protocol to allow winRM communicator",
|
||||||
config.IdentityDomain, config.Username, config.ImageName)
|
DstPortSet: []string{"5985", "5986", "443"}, // TODO make configurable
|
||||||
_, err = secRulesClient.CreateSecRule(&secRulesInput)
|
IPProtocol: "tcp",
|
||||||
if err != nil {
|
}
|
||||||
log.Printf("Error creating security rule to allow SSH: %s", err.Error())
|
_, err = protocolClient.CreateSecurityProtocol(&input)
|
||||||
if !strings.Contains(err.Error(), "already exists") {
|
if err != nil {
|
||||||
err = fmt.Errorf("Error creating security rule to"+
|
err = fmt.Errorf("Error creating security protocol to"+
|
||||||
" allow Packer to connect to Oracle instance via SSH: %s", err)
|
" allow Packer to connect to Oracle instance via %s: %s", commType, err)
|
||||||
ui.Error(err.Error())
|
ui.Error(err.Error())
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
state.Put("winrm_protocol", winrmProtocol)
|
||||||
|
|
||||||
|
// Check to see whether a winRM security application is already defined
|
||||||
|
applicationClient := client.SecurityApplications()
|
||||||
|
application = fmt.Sprintf("packer_winRM_%s", runUUID)
|
||||||
|
applicationInput := compute.CreateSecurityApplicationInput{
|
||||||
|
Description: "Allows Packer to connect to instance via winRM",
|
||||||
|
DPort: "5985-5986",
|
||||||
|
Name: application,
|
||||||
|
Protocol: "TCP",
|
||||||
|
}
|
||||||
|
_, err = applicationClient.CreateSecurityApplication(&applicationInput)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error creating security application to"+
|
||||||
|
" allow Packer to connect to Oracle instance via %s: %s", commType, err)
|
||||||
|
ui.Error(err.Error())
|
||||||
|
state.Put("error", err)
|
||||||
|
return multistep.ActionHalt
|
||||||
|
}
|
||||||
|
state.Put("winrm_application", application)
|
||||||
|
}
|
||||||
|
secRulesClient := client.SecRules()
|
||||||
|
secRuleName := fmt.Sprintf("Packer-allow-%s-Rule_%s_%s", commType,
|
||||||
|
config.ImageName, runUUID)
|
||||||
|
secRulesInput := compute.CreateSecRuleInput{
|
||||||
|
Action: "PERMIT",
|
||||||
|
Application: application,
|
||||||
|
Description: "Packer-generated security rule to allow ssh/winrm",
|
||||||
|
DestinationList: "seclist:" + namePrefix + secListName,
|
||||||
|
Name: namePrefix + secRuleName,
|
||||||
|
SourceList: config.SSHSourceList,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = secRulesClient.CreateSecRule(&secRulesInput)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Error creating security rule to"+
|
||||||
|
" allow Packer to connect to Oracle instance: %s", err)
|
||||||
|
ui.Error(err.Error())
|
||||||
|
state.Put("error", err)
|
||||||
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
state.Put("security_rule_name", secRuleName)
|
state.Put("security_rule_name", secRuleName)
|
||||||
state.Put("security_list", secListName)
|
state.Put("security_list", secListName)
|
||||||
|
@ -71,12 +119,15 @@ func (s *stepSecurity) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
func (s *stepSecurity) Cleanup(state multistep.StateBag) {
|
func (s *stepSecurity) Cleanup(state multistep.StateBag) {
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
config := state.Get("config").(*Config)
|
||||||
|
|
||||||
ui.Say("Deleting temporary rules and lists...")
|
ui.Say("Deleting temporary rules and lists...")
|
||||||
|
|
||||||
|
namePrefix := fmt.Sprintf("/Compute-%s/%s/", config.IdentityDomain, config.Username)
|
||||||
// delete security rules that Packer generated
|
// delete security rules that Packer generated
|
||||||
secRuleName := state.Get("security_rule_name").(string)
|
secRuleName := state.Get("security_rule_name").(string)
|
||||||
secRulesClient := client.SecRules()
|
secRulesClient := client.SecRules()
|
||||||
ruleInput := compute.DeleteSecRuleInput{Name: secRuleName}
|
ruleInput := compute.DeleteSecRuleInput{Name: namePrefix + secRuleName}
|
||||||
err := secRulesClient.DeleteSecRule(&ruleInput)
|
err := secRulesClient.DeleteSecRule(&ruleInput)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+
|
ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+
|
||||||
|
@ -86,10 +137,38 @@ func (s *stepSecurity) Cleanup(state multistep.StateBag) {
|
||||||
// delete security list that Packer generated
|
// delete security list that Packer generated
|
||||||
secListName := state.Get("security_list").(string)
|
secListName := state.Get("security_list").(string)
|
||||||
secListClient := client.SecurityLists()
|
secListClient := client.SecurityLists()
|
||||||
input := compute.DeleteSecurityListInput{Name: secListName}
|
input := compute.DeleteSecurityListInput{Name: namePrefix + secListName}
|
||||||
err = secListClient.DeleteSecurityList(&input)
|
err = secListClient.DeleteSecurityList(&input)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+
|
ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+
|
||||||
"please delete manually. (error : %s)", secListName, err.Error()))
|
"please delete manually. (error : %s)", secListName, err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Some extra cleanup if we used the winRM communicator
|
||||||
|
if config.Comm.Type == "winrm" {
|
||||||
|
// Delete the packer-generated protocol
|
||||||
|
protocol := state.Get("winrm_protocol").(string)
|
||||||
|
protocolClient := client.SecurityProtocols()
|
||||||
|
deleteProtocolInput := compute.DeleteSecurityProtocolInput{
|
||||||
|
Name: namePrefix + protocol,
|
||||||
|
}
|
||||||
|
err = protocolClient.DeleteSecurityProtocol(&deleteProtocolInput)
|
||||||
|
if err != nil {
|
||||||
|
ui.Say(fmt.Sprintf("Error deleting the packer-generated winrm security protocol %s; "+
|
||||||
|
"please delete manually. (error : %s)", protocol, err.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete the packer-generated application
|
||||||
|
application := state.Get("winrm_application").(string)
|
||||||
|
applicationClient := client.SecurityApplications()
|
||||||
|
deleteApplicationInput := compute.DeleteSecurityApplicationInput{
|
||||||
|
Name: namePrefix + application,
|
||||||
|
}
|
||||||
|
err = applicationClient.DeleteSecurityApplication(&deleteApplicationInput)
|
||||||
|
if err != nil {
|
||||||
|
ui.Say(fmt.Sprintf("Error deleting the packer-generated winrm security application %s; "+
|
||||||
|
"please delete manually. (error : %s)", application, err.Error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,20 @@ package classic
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/go-oracle-terraform/compute"
|
"github.com/hashicorp/go-oracle-terraform/compute"
|
||||||
"github.com/hashicorp/packer/helper/multistep"
|
"github.com/hashicorp/packer/helper/multistep"
|
||||||
"github.com/hashicorp/packer/packer"
|
"github.com/hashicorp/packer/packer"
|
||||||
)
|
)
|
||||||
|
|
||||||
type stepSnapshot struct{}
|
type stepSnapshot struct {
|
||||||
|
cleanupSnap bool
|
||||||
|
}
|
||||||
|
|
||||||
func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||||
// get variables from state
|
// get variables from state
|
||||||
|
s.cleanupSnap = false
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
ui.Say("Creating Snapshot...")
|
ui.Say("Creating Snapshot...")
|
||||||
config := state.Get("config").(*Config)
|
config := state.Get("config").(*Config)
|
||||||
|
@ -26,6 +30,7 @@ func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
snapshotInput := &compute.CreateSnapshotInput{
|
snapshotInput := &compute.CreateSnapshotInput{
|
||||||
Instance: fmt.Sprintf("%s/%s", config.ImageName, instanceID),
|
Instance: fmt.Sprintf("%s/%s", config.ImageName, instanceID),
|
||||||
MachineImage: config.ImageName,
|
MachineImage: config.ImageName,
|
||||||
|
Timeout: time.Minute * 20,
|
||||||
}
|
}
|
||||||
|
|
||||||
snap, err := snapshotClient.CreateSnapshot(snapshotInput)
|
snap, err := snapshotClient.CreateSnapshot(snapshotInput)
|
||||||
|
@ -35,7 +40,7 @@ func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
state.Put("error", err)
|
state.Put("error", err)
|
||||||
return multistep.ActionHalt
|
return multistep.ActionHalt
|
||||||
}
|
}
|
||||||
|
s.cleanupSnap = true
|
||||||
state.Put("snapshot", snap)
|
state.Put("snapshot", snap)
|
||||||
ui.Message(fmt.Sprintf("Created snapshot: %s.", snap.Name))
|
ui.Message(fmt.Sprintf("Created snapshot: %s.", snap.Name))
|
||||||
return multistep.ActionContinue
|
return multistep.ActionContinue
|
||||||
|
@ -44,6 +49,9 @@ func (s *stepSnapshot) Run(_ context.Context, state multistep.StateBag) multiste
|
||||||
func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
|
func (s *stepSnapshot) Cleanup(state multistep.StateBag) {
|
||||||
// Delete the snapshot
|
// Delete the snapshot
|
||||||
ui := state.Get("ui").(packer.Ui)
|
ui := state.Get("ui").(packer.Ui)
|
||||||
|
if !s.cleanupSnap {
|
||||||
|
return
|
||||||
|
}
|
||||||
ui.Say("Deleting Snapshot...")
|
ui.Say("Deleting Snapshot...")
|
||||||
client := state.Get("client").(*compute.ComputeClient)
|
client := state.Get("client").(*compute.ComputeClient)
|
||||||
snap := state.Get("snapshot").(*compute.Snapshot)
|
snap := state.Get("snapshot").(*compute.Snapshot)
|
||||||
|
|
|
@ -114,3 +114,62 @@ obfuscated; you will need to add a working `username`, `password`,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Basic Example -- Windows
|
||||||
|
|
||||||
|
Attributes file is optional for connecting via ssh, but required for winrm.
|
||||||
|
|
||||||
|
The following file contains the bare minimum necessary to get winRM working;
|
||||||
|
you have to give it the password to give to the "Administrator" user, which
|
||||||
|
will be the one winrm connects to. You must also whitelist your computer
|
||||||
|
to connect via winRM -- the empty braces below whitelist any computer to access
|
||||||
|
winRM but you can make it more secure by only allowing your build machine
|
||||||
|
access. See the [docs](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/automating-instance-initialization-using-opc-init.html#GUID-A0A107D6-3B38-47F4-8FC8-96D50D99379B)
|
||||||
|
for more details on how to define a trusted host.
|
||||||
|
|
||||||
|
Save this file as `windows_attributes.json`:
|
||||||
|
|
||||||
|
```{.json}
|
||||||
|
{
|
||||||
|
"userdata": {
|
||||||
|
"administrator_password": "password",
|
||||||
|
"winrm": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Following is a minimal but working Packer config that references this attributes
|
||||||
|
file:
|
||||||
|
```{.json}
|
||||||
|
{
|
||||||
|
"variables": {
|
||||||
|
"opc_username": "{{ env `OPC_USERNAME`}}",
|
||||||
|
"opc_password": "{{ env `OPC_PASSWORD`}}",
|
||||||
|
"opc_identity_domain": "{{env `OPC_IDENTITY_DOMAIN`}}",
|
||||||
|
"opc_api_endpoint": "{{ env `OPC_ENDPOINT`}}"
|
||||||
|
},
|
||||||
|
"builders": [
|
||||||
|
{
|
||||||
|
"type": "oracle-classic",
|
||||||
|
"username": "{{ user `opc_username`}}",
|
||||||
|
"password": "{{ user `opc_password`}}",
|
||||||
|
"identity_domain": "{{ user `opc_identity_domain`}}",
|
||||||
|
"api_endpoint": "{{ user `opc_api_endpoint`}}",
|
||||||
|
"source_image_list": "/Compute-{{ user `opc_identity_domain` }}/{{ user opc_username`}}/Microsoft_Windows_Server_2012_R2-17.3.6-20170930-124649",
|
||||||
|
"attributes_file": "./windows_attributes.json",
|
||||||
|
"shape": "oc3",
|
||||||
|
"image_name": "Packer_Windows_Demo_{{timestamp}}",
|
||||||
|
"dest_image_list": "Packer_Windows_Demo",
|
||||||
|
"communicator": "winrm",
|
||||||
|
"winrm_username": "Administrator",
|
||||||
|
"winrm_password": "password"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"provisioners": [
|
||||||
|
{
|
||||||
|
"type": "powershell",
|
||||||
|
"inline": "Write-Output(\"HELLO WORLD\")"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
Loading…
Reference in New Issue