diff --git a/builder/oracle/classic/artifact.go b/builder/oracle/classic/artifact.go deleted file mode 100644 index 7a73acec8..000000000 --- a/builder/oracle/classic/artifact.go +++ /dev/null @@ -1,49 +0,0 @@ -package classic - -import ( - "fmt" -) - -// Artifact is an artifact implementation that contains Image List -// and Machine Image info. -type Artifact struct { - MachineImageName string - MachineImageFile string - ImageListVersion int - - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -// BuilderId uniquely identifies the builder. -func (a *Artifact) BuilderId() string { - return BuilderId -} - -// Files lists the files associated with an artifact. We don't have any files -// as the custom image is stored server side. -func (a *Artifact) Files() []string { - return nil -} - -func (a *Artifact) Id() string { - return a.MachineImageName -} - -func (a *Artifact) String() string { - return fmt.Sprintf("An image list entry was created: \n"+ - "Name: %s\n"+ - "File: %s\n"+ - "Version: %d", - a.MachineImageName, a.MachineImageFile, a.ImageListVersion) -} - -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -// Destroy deletes the custom image associated with the artifact. -func (a *Artifact) Destroy() error { - return nil -} diff --git a/builder/oracle/classic/builder.go b/builder/oracle/classic/builder.go deleted file mode 100644 index 4c975dec1..000000000 --- a/builder/oracle/classic/builder.go +++ /dev/null @@ -1,206 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config - -package classic - -import ( - "context" - "fmt" - "os" - - "github.com/hashicorp/go-cleanhttp" - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/go-oracle-terraform/opc" - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - ocommon "github.com/hashicorp/packer/builder/oracle/common" -) - -// BuilderId uniquely identifies the builder -const BuilderId = "packer.oracle.classic" - -// Builder is a builder implementation that creates Oracle OCI custom images. -type Builder struct { - config Config - runner multistep.Runner -} - -func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } - -func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { - err := b.config.Prepare(raws...) - if err != nil { - return nil, nil, err - } - - var errs *packersdk.MultiError - - errs = packersdk.MultiErrorAppend(errs, b.config.PVConfig.Prepare(&b.config.ctx)) - - if errs != nil && len(errs.Errors) > 0 { - return nil, nil, errs - } - return nil, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - loggingEnabled := os.Getenv("PACKER_OCI_CLASSIC_LOGGING") != "" - httpClient := cleanhttp.DefaultClient() - config := &opc.Config{ - Username: opc.String(b.config.Username), - Password: opc.String(b.config.Password), - IdentityDomain: opc.String(b.config.IdentityDomain), - APIEndpoint: b.config.apiEndpointURL, - LogLevel: opc.LogDebug, - Logger: &Logger{loggingEnabled}, - // Logger: # Leave blank to use the default logger, or provide your own - HTTPClient: httpClient, - } - // Create the Compute Client - client, err := compute.NewComputeClient(config) - if err != nil { - return nil, fmt.Errorf("Error creating OPC Compute Client: %s", err) - } - - runID := fmt.Sprintf("%s_%s", b.config.ImageName, os.Getenv("PACKER_RUN_UUID")) - // Populate the state bag - state := new(multistep.BasicStateBag) - state.Put("config", &b.config) - state.Put("hook", hook) - state.Put("ui", ui) - state.Put("client", client) - state.Put("run_id", runID) - - var steps []multistep.Step - if b.config.IsPV() { - steps = []multistep.Step{ - &ocommon.StepKeyPair{ - Debug: b.config.PackerDebug, - Comm: &b.config.Comm, - DebugKeyPath: fmt.Sprintf("oci_classic_%s.pem", b.config.PackerBuildName), - }, - &stepCreateIPReservation{}, - &stepAddKeysToAPI{ - KeyName: fmt.Sprintf("packer-generated-key_%s", runID), - }, - &stepSecurity{ - CommType: b.config.Comm.Type, - SecurityListKey: "security_list_master", - }, - &stepCreatePersistentVolume{ - VolumeSize: fmt.Sprintf("%d", b.config.PersistentVolumeSize), - VolumeName: fmt.Sprintf("master-storage_%s", runID), - ImageList: b.config.SourceImageList, - ImageListEntry: b.config.SourceImageListEntry, - Bootable: true, - }, - &stepCreatePVMaster{ - Name: fmt.Sprintf("master-instance_%s", runID), - VolumeName: fmt.Sprintf("master-storage_%s", runID), - SecurityListKey: "security_list_master", - }, - &communicator.StepConnect{ - Config: &b.config.Comm, - Host: communicator.CommHost(b.config.Comm.Host(), "instance_ip"), - SSHConfig: b.config.Comm.SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &stepTerminatePVMaster{}, - &stepSecurity{ - SecurityListKey: "security_list_builder", - CommType: "ssh", - }, - &stepCreatePersistentVolume{ - // We double the master volume size because we need room to - // tarball the disk image. We also need to chunk the tar ball, - // but we can remove the original disk image first. - VolumeSize: fmt.Sprintf("%d", b.config.PersistentVolumeSize*2), - VolumeName: fmt.Sprintf("builder-storage_%s", runID), - }, - &stepCreatePVBuilder{ - Name: fmt.Sprintf("builder-instance_%s", runID), - BuilderVolumeName: fmt.Sprintf("builder-storage_%s", runID), - SecurityListKey: "security_list_builder", - }, - &stepAttachVolume{ - VolumeName: fmt.Sprintf("master-storage_%s", runID), - Index: 2, - InstanceInfoKey: "builder_instance_info", - }, - &stepConnectBuilder{ - KeyName: fmt.Sprintf("packer-generated-key_%s", runID), - StepConnectSSH: &communicator.StepConnectSSH{ - Config: &b.config.BuilderComm, - Host: communicator.CommHost(b.config.Comm.Host(), "instance_ip"), - SSHConfig: b.config.BuilderComm.SSHConfigFunc(), - }, - }, - &stepUploadImage{ - UploadImageCommand: b.config.BuilderUploadImageCommand, - }, - &stepCreateImage{}, - &stepListImages{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - } - } else { - // Build the steps - steps = []multistep.Step{ - &ocommon.StepKeyPair{ - Debug: b.config.PackerDebug, - Comm: &b.config.Comm, - DebugKeyPath: fmt.Sprintf("oci_classic_%s.pem", b.config.PackerBuildName), - }, - &stepCreateIPReservation{}, - &stepAddKeysToAPI{ - Skip: b.config.Comm.Type != "ssh", - KeyName: fmt.Sprintf("packer-generated-key_%s", runID), - }, - &stepSecurity{ - SecurityListKey: "security_list", - CommType: b.config.Comm.Type, - }, - &stepCreateInstance{}, - &communicator.StepConnect{ - Config: &b.config.Comm, - Host: communicator.CommHost(b.config.Comm.Host(), "instance_ip"), - SSHConfig: b.config.Comm.SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - &stepSnapshot{}, - &stepListImages{}, - } - } - - // Run the steps - b.runner = commonsteps.NewRunner(steps, b.config.PackerConfig, ui) - b.runner.Run(ctx, state) - - // If there was an error, return that - if rawErr, ok := state.GetOk("error"); ok { - return nil, rawErr.(error) - } - - // If there is no snapshot, then just return - if _, ok := state.GetOk("machine_image_name"); !ok { - return nil, nil - } - - // Build the artifact and return it - artifact := &Artifact{ - ImageListVersion: state.Get("image_list_version").(int), - MachineImageName: state.Get("machine_image_name").(string), - MachineImageFile: state.Get("machine_image_file").(string), - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - - return artifact, nil -} - -// Cancel terminates a running build. diff --git a/builder/oracle/classic/builder.hcl2spec.go b/builder/oracle/classic/builder.hcl2spec.go deleted file mode 100644 index 93e5432d8..000000000 --- a/builder/oracle/classic/builder.hcl2spec.go +++ /dev/null @@ -1,184 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package classic - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/zclconf/go-cty/cty" -) - -// FlatConfig is an auto-generated flat version of Config. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"` - PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` - PersistentVolumeSize *int `mapstructure:"persistent_volume_size" cty:"persistent_volume_size" hcl:"persistent_volume_size"` - BuilderUploadImageCommand *string `mapstructure:"builder_upload_image_command" cty:"builder_upload_image_command" hcl:"builder_upload_image_command"` - BuilderShape *string `mapstructure:"builder_shape" cty:"builder_shape" hcl:"builder_shape"` - BuilderImageList *string `mapstructure:"builder_image_list" cty:"builder_image_list" hcl:"builder_image_list"` - BuilderImageListEntry *int `mapstructure:"builder_image_list_entry" cty:"builder_image_list_entry" hcl:"builder_image_list_entry"` - BuilderComm *communicator.FlatConfig `mapstructure:"builder_communicator" cty:"builder_communicator" hcl:"builder_communicator"` - Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"` - PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"` - SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"` - SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"` - SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"` - SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"` - SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"` - SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"` - SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"` - SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"` - SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"` - SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"` - SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"` - SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"` - SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"` - SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"` - SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"` - SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"` - SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"` - SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"` - SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"` - SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"` - SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"` - SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"` - SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"` - SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"` - SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"` - SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"` - SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"` - SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"` - SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"` - SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"` - SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"` - SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"` - SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"` - SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"` - SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"` - SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"` - SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"` - SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"` - WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"` - WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"` - WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"` - WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"` - WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"` - WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"` - WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"` - WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"` - WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"` - Username *string `mapstructure:"username" cty:"username" hcl:"username"` - Password *string `mapstructure:"password" cty:"password" hcl:"password"` - IdentityDomain *string `mapstructure:"identity_domain" cty:"identity_domain" hcl:"identity_domain"` - APIEndpoint *string `mapstructure:"api_endpoint" cty:"api_endpoint" hcl:"api_endpoint"` - ImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"` - Shape *string `mapstructure:"shape" cty:"shape" hcl:"shape"` - SourceImageList *string `mapstructure:"source_image_list" cty:"source_image_list" hcl:"source_image_list"` - SourceImageListEntry *int `mapstructure:"source_image_list_entry" cty:"source_image_list_entry" hcl:"source_image_list_entry"` - SnapshotTimeout *string `mapstructure:"snapshot_timeout" cty:"snapshot_timeout" hcl:"snapshot_timeout"` - DestImageList *string `mapstructure:"dest_image_list" cty:"dest_image_list" hcl:"dest_image_list"` - Attributes *string `mapstructure:"attributes" cty:"attributes" hcl:"attributes"` - AttributesFile *string `mapstructure:"attributes_file" cty:"attributes_file" hcl:"attributes_file"` - DestImageListDescription *string `mapstructure:"image_description" cty:"image_description" hcl:"image_description"` - SSHSourceList *string `mapstructure:"ssh_source_list" cty:"ssh_source_list" hcl:"ssh_source_list"` -} - -// FlatMapstructure returns a new FlatConfig. -// FlatConfig is an auto-generated flat version of Config. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatConfig) -} - -// HCL2Spec returns the hcl spec of a Config. -// This spec is used by HCL to read the fields of Config. -// The decoded values from this spec will then be applied to a FlatConfig. -func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "persistent_volume_size": &hcldec.AttrSpec{Name: "persistent_volume_size", Type: cty.Number, Required: false}, - "builder_upload_image_command": &hcldec.AttrSpec{Name: "builder_upload_image_command", Type: cty.String, Required: false}, - "builder_shape": &hcldec.AttrSpec{Name: "builder_shape", Type: cty.String, Required: false}, - "builder_image_list": &hcldec.AttrSpec{Name: "builder_image_list", Type: cty.String, Required: false}, - "builder_image_list_entry": &hcldec.AttrSpec{Name: "builder_image_list_entry", Type: cty.Number, Required: false}, - "builder_communicator": &hcldec.BlockSpec{TypeName: "builder_communicator", Nested: hcldec.ObjectSpec((*communicator.FlatConfig)(nil).HCL2Spec())}, - "communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false}, - "pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false}, - "ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false}, - "ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false}, - "ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false}, - "ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false}, - "ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false}, - "temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false}, - "temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false}, - "temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false}, - "ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false}, - "ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false}, - "ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false}, - "ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false}, - "ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false}, - "ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false}, - "ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false}, - "ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false}, - "ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false}, - "ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false}, - "ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false}, - "ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false}, - "ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false}, - "ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false}, - "ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false}, - "ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false}, - "ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false}, - "ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false}, - "ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false}, - "ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false}, - "ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false}, - "ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false}, - "ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false}, - "ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false}, - "ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false}, - "ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false}, - "ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false}, - "ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false}, - "ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false}, - "ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false}, - "winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false}, - "winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false}, - "winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false}, - "winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false}, - "winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false}, - "winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false}, - "winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false}, - "winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false}, - "winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false}, - "username": &hcldec.AttrSpec{Name: "username", Type: cty.String, Required: false}, - "password": &hcldec.AttrSpec{Name: "password", Type: cty.String, Required: false}, - "identity_domain": &hcldec.AttrSpec{Name: "identity_domain", Type: cty.String, Required: false}, - "api_endpoint": &hcldec.AttrSpec{Name: "api_endpoint", Type: cty.String, Required: false}, - "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, - "shape": &hcldec.AttrSpec{Name: "shape", Type: cty.String, Required: false}, - "source_image_list": &hcldec.AttrSpec{Name: "source_image_list", Type: cty.String, Required: false}, - "source_image_list_entry": &hcldec.AttrSpec{Name: "source_image_list_entry", Type: cty.Number, Required: false}, - "snapshot_timeout": &hcldec.AttrSpec{Name: "snapshot_timeout", Type: cty.String, Required: false}, - "dest_image_list": &hcldec.AttrSpec{Name: "dest_image_list", Type: cty.String, Required: false}, - "attributes": &hcldec.AttrSpec{Name: "attributes", Type: cty.String, Required: false}, - "attributes_file": &hcldec.AttrSpec{Name: "attributes_file", Type: cty.String, Required: false}, - "image_description": &hcldec.AttrSpec{Name: "image_description", Type: cty.String, Required: false}, - "ssh_source_list": &hcldec.AttrSpec{Name: "ssh_source_list", Type: cty.String, Required: false}, - } - return s -} diff --git a/builder/oracle/classic/config.go b/builder/oracle/classic/config.go deleted file mode 100644 index cdc7159b2..000000000 --- a/builder/oracle/classic/config.go +++ /dev/null @@ -1,155 +0,0 @@ -package classic - -import ( - "encoding/json" - "fmt" - "io/ioutil" - "net/url" - "os" - "regexp" - "time" - - "github.com/hashicorp/packer-plugin-sdk/common" - "github.com/hashicorp/packer-plugin-sdk/communicator" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - PVConfig `mapstructure:",squash"` - Comm communicator.Config `mapstructure:",squash"` - attribs map[string]interface{} - - // Access config overrides - Username string `mapstructure:"username"` - Password string `mapstructure:"password"` - IdentityDomain string `mapstructure:"identity_domain"` - APIEndpoint string `mapstructure:"api_endpoint"` - apiEndpointURL *url.URL - - // Image - ImageName string `mapstructure:"image_name"` - Shape string `mapstructure:"shape"` - SourceImageList string `mapstructure:"source_image_list"` - SourceImageListEntry int `mapstructure:"source_image_list_entry"` - SnapshotTimeout time.Duration `mapstructure:"snapshot_timeout"` - DestImageList string `mapstructure:"dest_image_list"` - // Attributes and Attributes file are both optional and mutually exclusive. - Attributes string `mapstructure:"attributes"` - AttributesFile string `mapstructure:"attributes_file"` - // Optional; if you don't enter anything, the image list description - // will read "Packer-built image list" - DestImageListDescription string `mapstructure:"image_description"` - // Optional. Describes what computers are allowed to reach your instance - // via SSH. This whitelist must contain the computer you're running Packer - // from. It defaults to public-internet, meaning that you can SSH into your - // instance from anywhere as long as you have the right keys - SSHSourceList string `mapstructure:"ssh_source_list"` - - ctx interpolate.Context -} - -func (c *Config) Identifier(s string) string { - return fmt.Sprintf("/Compute-%s/%s/%s", c.IdentityDomain, c.Username, s) -} - -func (c *Config) Prepare(raws ...interface{}) error { - - // Decode from template - err := config.Decode(c, &config.DecodeOpts{ - Interpolate: true, - InterpolateContext: &c.ctx, - }, raws...) - if err != nil { - return fmt.Errorf("Failed to mapstructure Config: %+v", err) - } - - c.apiEndpointURL, err = url.Parse(c.APIEndpoint) - if err != nil { - return fmt.Errorf("Error parsing API Endpoint: %s", err) - } - // Set default source list - if c.SSHSourceList == "" { - c.SSHSourceList = "seciplist:/oracle/public/public-internet" - } - - if c.SnapshotTimeout == 0 { - c.SnapshotTimeout = 20 * time.Minute - } - - // Validate that all required fields are present - var errs *packersdk.MultiError - required := map[string]string{ - "username": c.Username, - "password": c.Password, - "api_endpoint": c.APIEndpoint, - "identity_domain": c.IdentityDomain, - "source_image_list": c.SourceImageList, - "dest_image_list": c.DestImageList, - "shape": c.Shape, - } - for k, v := range required { - if v == "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("You must specify a %s.", k)) - } - } - - // Object names can contain only alphanumeric characters, hyphens, underscores, and periods - reValidObject := regexp.MustCompile("^[a-zA-Z0-9-._/]+$") - var objectValidation = []struct { - name string - value string - }{ - {"dest_image_list", c.DestImageList}, - {"image_name", c.ImageName}, - } - for _, ov := range objectValidation { - if !reValidObject.MatchString(ov.value) { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("%s can contain only alphanumeric characters, hyphens, underscores, and periods.", ov.name)) - } - } - - if c.Attributes != "" && c.AttributesFile != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified.")) - } else if c.AttributesFile != "" { - if _, err := os.Stat(c.AttributesFile); err != nil { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("attributes_file not found: %s", c.AttributesFile)) - } - } - - if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { - errs = packersdk.MultiErrorAppend(errs, es...) - } - - // unpack attributes from json into config - var data map[string]interface{} - - if c.Attributes != "" { - err := json.Unmarshal([]byte(c.Attributes), &data) - if err != nil { - err = fmt.Errorf("Problem parsing json from attributes: %s", err) - errs = packersdk.MultiErrorAppend(errs, err) - } - c.attribs = data - } else if c.AttributesFile != "" { - fidata, err := ioutil.ReadFile(c.AttributesFile) - if err != nil { - err = fmt.Errorf("Problem reading attributes_file: %s", err) - errs = packersdk.MultiErrorAppend(errs, err) - } - err = json.Unmarshal(fidata, &data) - c.attribs = data - if err != nil { - err = fmt.Errorf("Problem parsing json from attributes_file: %s", err) - errs = packersdk.MultiErrorAppend(errs, err) - } - c.attribs = data - } - - if errs != nil && len(errs.Errors) > 0 { - return errs - } - return nil -} diff --git a/builder/oracle/classic/config_test.go b/builder/oracle/classic/config_test.go deleted file mode 100644 index 8d55a1626..000000000 --- a/builder/oracle/classic/config_test.go +++ /dev/null @@ -1,82 +0,0 @@ -package classic - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func testConfig() map[string]interface{} { - return map[string]interface{}{ - "identity_domain": "abc12345", - "username": "test@hashicorp.com", - "password": "testpassword123", - "api_endpoint": "https://api-test.compute.test.oraclecloud.com/", - "dest_image_list": "/Config-thing/myuser/myimage", - "source_image_list": "/oracle/public/whatever", - "shape": "oc3", - "image_name": "TestImageName", - "ssh_username": "opc", - } -} - -func TestConfigAutoFillsSourceList(t *testing.T) { - tc := testConfig() - var conf Config - err := conf.Prepare(tc) - if err != nil { - t.Fatalf("Should not have error: %s", err.Error()) - } - if conf.SSHSourceList != "seciplist:/oracle/public/public-internet" { - t.Fatalf("conf.SSHSourceList should have been "+ - "\"seciplist:/oracle/public/public-internet\" but is \"%s\"", - conf.SSHSourceList) - } -} - -func TestConfigValidationCatchesMissing(t *testing.T) { - required := []string{ - "username", - "password", - "api_endpoint", - "identity_domain", - "dest_image_list", - "source_image_list", - "shape", - "ssh_username", - } - for _, key := range required { - tc := testConfig() - delete(tc, key) - var c Config - err := c.Prepare(tc) - if err == nil { - t.Fatalf("Test should have failed when config lacked %s!", key) - } - } -} - -func TestConfigValidatesObjects(t *testing.T) { - var objectTests = []struct { - object string - valid bool - }{ - {"foo-BAR.0_9", true}, - {"%", false}, - {"Matt...?", false}, - {"/Config-thing/myuser/myimage", true}, - } - for _, s := range []string{"dest_image_list", "image_name"} { - for _, tt := range objectTests { - tc := testConfig() - tc[s] = tt.object - var c Config - err := c.Prepare(tc) - if tt.valid { - assert.NoError(t, err, tt.object) - } else { - assert.Error(t, err, tt.object) - } - } - } -} diff --git a/builder/oracle/classic/log.go b/builder/oracle/classic/log.go deleted file mode 100644 index 7389dc057..000000000 --- a/builder/oracle/classic/log.go +++ /dev/null @@ -1,14 +0,0 @@ -package classic - -import "log" - -type Logger struct { - Enabled bool -} - -func (l *Logger) Log(input ...interface{}) { - if !l.Enabled { - return - } - log.Println(input...) -} diff --git a/builder/oracle/classic/pv_config.go b/builder/oracle/classic/pv_config.go deleted file mode 100644 index f69f1d197..000000000 --- a/builder/oracle/classic/pv_config.go +++ /dev/null @@ -1,140 +0,0 @@ -package classic - -import ( - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/communicator" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -const imageListDefault = "/oracle/public/OL_7.2_UEKR4_x86_64" -const imageListEntryDefault = 5 -const usernameDefault = "opc" -const shapeDefault = "oc3" -const uploadImageCommandDefault = ` -# https://www.oracle.com/webfolder/technetwork/tutorials/obe/cloud/objectstorage/upload_files_gt_5GB_REST_API/upload_files_gt_5GB_REST_API.html - -# Split diskimage in to 100mb chunks -split -b 100m diskimage.tar.gz segment_ -printf "Split diskimage into %s segments\n" $(ls segment_* | wc -l) - -# Download jq tool -curl -OLs https://github.com/stedolan/jq/releases/download/jq-1.5/jq-linux64 -mv jq-linux64 jq -chmod u+x jq - -# Create manifest file -( -for i in segment_*; do - ./jq -n --arg path "{{.SegmentPath}}/$i" \ - --arg etag $(md5sum $i | cut -f1 -d' ') \ - --arg size_bytes $(stat --printf "%s" $i) \ - '{path: $path, etag: $etag, size_bytes: $size_bytes}' -done -) | ./jq -s . > manifest.json - -# Authenticate -curl -D auth-headers -s -X GET \ - -H "X-Storage-User: Storage-{{.AccountID}}:{{.Username}}" \ - -H "X-Storage-Pass: {{.Password}}" \ - https://{{.AccountID}}.storage.oraclecloud.com/auth/v1.0 - -export AUTH_TOKEN=$(awk 'BEGIN {FS=": "; RS="\r\n"}/^X-Auth-Token/{print $2}' auth-headers) -export STORAGE_URL=$(awk 'BEGIN {FS=": "; RS="\r\n"}/^X-Storage-Url/{print $2}' auth-headers) - -# Upload segments -for i in segment_*; do - echo "Uploading segment $i" - - curl -s -X PUT -T $i \ - -H "X-Auth-Token: $AUTH_TOKEN" ${STORAGE_URL}/{{.SegmentPath}}/$i; -done - -# Create machine image from manifest -curl -s -X PUT \ - -H "X-Auth-Token: $AUTH_TOKEN" \ - "${STORAGE_URL}/compute_images/{{.ImageFile}}?multipart-manifest=put" \ - -T ./manifest.json - -# Get uploaded image description -echo "Details of ${STORAGE_URL}/compute_images/{{.ImageFile}}:" -curl -I -X HEAD \ - -H "X-Auth-Token: $AUTH_TOKEN" \ - "${STORAGE_URL}/compute_images/{{.ImageFile}}" -` - -type PVConfig struct { - // PersistentVolumeSize lets us control the volume size by using persistent boot storage - PersistentVolumeSize int `mapstructure:"persistent_volume_size"` - BuilderUploadImageCommand string `mapstructure:"builder_upload_image_command"` - - // Builder Image - BuilderShape string `mapstructure:"builder_shape"` - BuilderImageList string `mapstructure:"builder_image_list"` - BuilderImageListEntry *int `mapstructure:"builder_image_list_entry"` - - BuilderComm communicator.Config `mapstructure:"builder_communicator"` -} - -// IsPV tells us if we're using a persistent volume for this build -func (c *PVConfig) IsPV() bool { - return c.PersistentVolumeSize > 0 -} - -func (c *PVConfig) Prepare(ctx *interpolate.Context) (errs *packersdk.MultiError) { - if !c.IsPV() { - if c.BuilderShape != "" { - errs = packersdk.MultiErrorAppend(errs, - fmt.Errorf("`builder_shape` has no meaning when `persistent_volume_size` is not set.")) - } - if c.BuilderImageList != "" { - errs = packersdk.MultiErrorAppend(errs, - fmt.Errorf("`builder_image_list` has no meaning when `persistent_volume_size` is not set.")) - } - - if c.BuilderImageListEntry != nil { - errs = packersdk.MultiErrorAppend(errs, - fmt.Errorf("`builder_image_list_entry` has no meaning when `persistent_volume_size` is not set.")) - } - return errs - } - - c.BuilderComm.SSHPty = true - if c.BuilderComm.Type == "winrm" { - errs = packersdk.MultiErrorAppend(errs, - fmt.Errorf("`ssh` is the only valid builder communicator type.")) - } - - if c.BuilderShape == "" { - c.BuilderShape = shapeDefault - } - - if c.BuilderComm.SSHUsername == "" { - c.BuilderComm.SSHUsername = usernameDefault - } - - if c.BuilderImageList == "" { - c.BuilderImageList = imageListDefault - } - - // Set to known working default if this is unset and we're using the - // default image list - if c.BuilderImageListEntry == nil { - var entry int - if c.BuilderImageList == imageListDefault { - entry = imageListEntryDefault - } - c.BuilderImageListEntry = &entry - } - - if c.BuilderUploadImageCommand == "" { - c.BuilderUploadImageCommand = uploadImageCommandDefault - } - - if es := c.BuilderComm.Prepare(ctx); len(es) > 0 { - errs = packersdk.MultiErrorAppend(errs, es...) - } - - return -} diff --git a/builder/oracle/classic/pv_config_test.go b/builder/oracle/classic/pv_config_test.go deleted file mode 100644 index c99bb30b4..000000000 --- a/builder/oracle/classic/pv_config_test.go +++ /dev/null @@ -1,31 +0,0 @@ -package classic - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestPVConfigEntry(t *testing.T) { - entry := 1 - var entryTests = []struct { - imageList string - imageListEntry *int - expected int - }{ - {"x", nil, 0}, - {"x", &entry, 1}, - {imageListDefault, nil, 5}, - {imageListDefault, &entry, 1}, - } - for _, tt := range entryTests { - tc := &PVConfig{ - PersistentVolumeSize: 1, - BuilderImageList: tt.imageList, - BuilderImageListEntry: tt.imageListEntry, - } - errs := tc.Prepare(nil) - assert.Nil(t, errs, "Didn't expect any errors") - assert.Equal(t, tt.expected, *tc.BuilderImageListEntry) - } -} diff --git a/builder/oracle/classic/step_add_keys.go b/builder/oracle/classic/step_add_keys.go deleted file mode 100644 index a2279f775..000000000 --- a/builder/oracle/classic/step_add_keys.go +++ /dev/null @@ -1,75 +0,0 @@ -package classic - -import ( - "bytes" - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepAddKeysToAPI struct { - Skip bool - KeyName string -} - -func (s *stepAddKeysToAPI) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - - if s.Skip { - ui.Say("Skipping generating SSH keys...") - return multistep.ActionContinue - } - // grab packer-generated key from statebag context. - // Always check configured communicator for keys - sshPublicKey := bytes.TrimSpace(config.Comm.SSHPublicKey) - - // form API call to add key to compute cloud - - ui.Say(fmt.Sprintf("Creating temporary key: %s", s.KeyName)) - - sshKeysClient := client.SSHKeys() - sshKeysInput := compute.CreateSSHKeyInput{ - Name: s.KeyName, - Key: string(sshPublicKey), - Enabled: true, - } - - // Load the packer-generated SSH key into the Oracle Compute cloud. - keyInfo, err := sshKeysClient.CreateSSHKey(&sshKeysInput) - if err != nil { - err = fmt.Errorf("Problem adding Public SSH key through Oracle's API: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - config.Comm.SSHKeyPairName = keyInfo.Name - return multistep.ActionContinue -} - -func (s *stepAddKeysToAPI) Cleanup(state multistep.StateBag) { - if s.Skip { - return - } - config := state.Get("config").(*Config) - // Delete the keys we created during this run - if len(config.Comm.SSHKeyPairName) == 0 { - // No keys were generated; none need to be cleaned up. - return - } - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Deleting SSH keys...") - deleteInput := compute.DeleteSSHKeyInput{Name: config.Comm.SSHKeyPairName} - client := state.Get("client").(*compute.Client) - deleteClient := client.SSHKeys() - err := deleteClient.DeleteSSHKey(&deleteInput) - if err != nil { - ui.Error(fmt.Sprintf("Error deleting SSH keys: %s", err.Error())) - } - return -} diff --git a/builder/oracle/classic/step_attach_volume.go b/builder/oracle/classic/step_attach_volume.go deleted file mode 100644 index b3f81a9c2..000000000 --- a/builder/oracle/classic/step_attach_volume.go +++ /dev/null @@ -1,63 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepAttachVolume struct { - Index int - VolumeName string - InstanceInfoKey string -} - -func (s *stepAttachVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - client := state.Get("client").(*compute.Client) - ui := state.Get("ui").(packersdk.Ui) - instanceInfo := state.Get(s.InstanceInfoKey).(*compute.InstanceInfo) - - saClient := client.StorageAttachments() - saInput := &compute.CreateStorageAttachmentInput{ - Index: s.Index, - InstanceName: instanceInfo.Name + "/" + instanceInfo.ID, - StorageVolumeName: s.VolumeName, - } - - sa, err := saClient.CreateStorageAttachment(saInput) - if err != nil { - err = fmt.Errorf("Problem attaching master volume: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - state.Put(s.InstanceInfoKey+"/attachment", sa) - - ui.Message("Volume attached to instance.") - return multistep.ActionContinue -} - -func (s *stepAttachVolume) Cleanup(state multistep.StateBag) { - sa, ok := state.GetOk(s.InstanceInfoKey + "/attachment") - if !ok { - return - } - client := state.Get("client").(*compute.Client) - ui := state.Get("ui").(packersdk.Ui) - - saClient := client.StorageAttachments() - saI := &compute.DeleteStorageAttachmentInput{ - Name: sa.(*compute.StorageAttachmentInfo).Name, - } - - if err := saClient.DeleteStorageAttachment(saI); err != nil { - err = fmt.Errorf("Problem detaching storage volume: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } -} diff --git a/builder/oracle/classic/step_connect_builder.go b/builder/oracle/classic/step_connect_builder.go deleted file mode 100644 index 94385229f..000000000 --- a/builder/oracle/classic/step_connect_builder.go +++ /dev/null @@ -1,22 +0,0 @@ -package classic - -import ( - "context" - - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/multistep" -) - -type stepConnectBuilder struct { - *communicator.StepConnectSSH - KeyName string -} - -func (s *stepConnectBuilder) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - s.Config.SSHKeyPairName = s.KeyName - return s.StepConnectSSH.Run(ctx, state) -} - -func (s *stepConnectBuilder) Cleanup(state multistep.StateBag) { - s.StepConnectSSH.Cleanup(state) -} diff --git a/builder/oracle/classic/step_create_image.go b/builder/oracle/classic/step_create_image.go deleted file mode 100644 index 6f6a14381..000000000 --- a/builder/oracle/classic/step_create_image.go +++ /dev/null @@ -1,72 +0,0 @@ -package classic - -import ( - "context" - "fmt" - "log" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreateImage struct { -} - -func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - client := state.Get("client").(*compute.Client) - config := state.Get("config").(*Config) - imageFile := state.Get("image_file").(string) - - // Image uploaded, let's register it - machineImageClient := client.MachineImages() - createMI := &compute.CreateMachineImageInput{ - // Two-part name of the account - Account: fmt.Sprintf("/Compute-%s/cloud_storage", config.IdentityDomain), - Description: "Packer generated Machine Image.", - // The three-part name of the object - Name: config.ImageName, - // image_file.tar.gz, where image_file is the .tar.gz name of the - // machine image file that you have uploaded to Oracle Cloud - // Infrastructure Object Storage Classic. - File: imageFile, - } - mi, err := machineImageClient.CreateMachineImage(createMI) - if err != nil { - err = fmt.Errorf("Error creating machine image: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - log.Println("Registered machine image.") - state.Put("machine_image", mi.Name) - - return multistep.ActionContinue -} - -func (s *stepCreateImage) Cleanup(state multistep.StateBag) { - _, cancelled := state.GetOk(multistep.StateCancelled) - _, halted := state.GetOk(multistep.StateHalted) - if !cancelled && !halted { - return - } - - client := state.Get("client").(*compute.Client) - config := state.Get("config").(*Config) - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Cleaning up Image...") - - machineImageClient := client.MachineImages() - deleteMI := &compute.DeleteMachineImageInput{ - Name: config.ImageName, - } - - if err := machineImageClient.DeleteMachineImage(deleteMI); err != nil { - ui.Error(fmt.Sprintf("Error cleaning up machine image: %s", err)) - return - } - - ui.Message(fmt.Sprintf("Deleted Image: %s", config.ImageName)) -} diff --git a/builder/oracle/classic/step_create_instance.go b/builder/oracle/classic/step_create_instance.go deleted file mode 100644 index 5884755ef..000000000 --- a/builder/oracle/classic/step_create_instance.go +++ /dev/null @@ -1,86 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreateInstance struct{} - -func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating Instance...") - - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - ipAddName := state.Get("ipres_name").(string) - secListName := state.Get("security_list").(string) - - netInfo := compute.NetworkingInfo{ - Nat: []string{ipAddName}, - SecLists: []string{secListName}, - } - - // get instances client - instanceClient := client.Instances() - - // Instances Input - input := &compute.CreateInstanceInput{ - Name: config.ImageName, - Shape: config.Shape, - ImageList: config.SourceImageList, - Entry: config.SourceImageListEntry, - Networking: map[string]compute.NetworkingInfo{"eth0": netInfo}, - Attributes: config.attribs, - } - if config.Comm.Type == "ssh" { - input.SSHKeys = []string{config.Comm.SSHKeyPairName} - } - - instanceInfo, err := instanceClient.CreateInstance(input) - if err != nil { - err = fmt.Errorf("Problem creating instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - state.Put("instance_info", instanceInfo) - state.Put("instance_id", instanceInfo.ID) - ui.Message(fmt.Sprintf("Created instance: %s.", instanceInfo.ID)) - return multistep.ActionContinue -} - -func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { - instanceID, ok := state.GetOk("instance_id") - if !ok { - return - } - - // terminate instance - ui := state.Get("ui").(packersdk.Ui) - client := state.Get("client").(*compute.Client) - config := state.Get("config").(*Config) - - ui.Say("Terminating source instance...") - - instanceClient := client.Instances() - input := &compute.DeleteInstanceInput{ - Name: config.ImageName, - ID: instanceID.(string), - } - - err := instanceClient.DeleteInstance(input) - if err != nil { - err = fmt.Errorf("Problem destroying instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } - ui.Say("Terminated instance.") -} diff --git a/builder/oracle/classic/step_create_ip_reservation.go b/builder/oracle/classic/step_create_ip_reservation.go deleted file mode 100644 index 546d33275..000000000 --- a/builder/oracle/classic/step_create_ip_reservation.go +++ /dev/null @@ -1,61 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/uuid" -) - -type stepCreateIPReservation struct{} - -func (s *stepCreateIPReservation) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - iprClient := client.IPReservations() - // TODO: add optional Name and Tags - - ipresName := fmt.Sprintf("ipres_%s_%s", config.ImageName, uuid.TimeOrderedUUID()) - ui.Message(fmt.Sprintf("Creating temporary IP reservation: %s", ipresName)) - - IPInput := &compute.CreateIPReservationInput{ - ParentPool: compute.PublicReservationPool, - Permanent: true, - Name: ipresName, - } - ipRes, err := iprClient.CreateIPReservation(IPInput) - - if err != nil { - err := fmt.Errorf("Error creating IP Reservation: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - state.Put("instance_ip", ipRes.IP) - state.Put("ipres_name", ipresName) - return multistep.ActionContinue -} - -func (s *stepCreateIPReservation) Cleanup(state multistep.StateBag) { - ipResName, ok := state.GetOk("ipres_name") - if !ok { - return - } - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Cleaning up IP reservations...") - client := state.Get("client").(*compute.Client) - - input := compute.DeleteIPReservationInput{Name: ipResName.(string)} - ipClient := client.IPReservations() - err := ipClient.DeleteIPReservation(&input) - if err != nil { - fmt.Printf("error deleting IP reservation: %s", err.Error()) - } - -} diff --git a/builder/oracle/classic/step_create_persistent_volume.go b/builder/oracle/classic/step_create_persistent_volume.go deleted file mode 100644 index 07321ad99..000000000 --- a/builder/oracle/classic/step_create_persistent_volume.go +++ /dev/null @@ -1,67 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreatePersistentVolume struct { - VolumeSize string - VolumeName string - Bootable bool - ImageList string - ImageListEntry int -} - -func (s *stepCreatePersistentVolume) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - client := state.Get("client").(*compute.Client) - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating Volume...") - - c := &compute.CreateStorageVolumeInput{ - Name: s.VolumeName, - Size: s.VolumeSize, - ImageList: s.ImageList, - ImageListEntry: s.ImageListEntry, - Properties: []string{"/oracle/public/storage/default"}, - Bootable: s.Bootable, - } - - sc := client.StorageVolumes() - cc, err := sc.CreateStorageVolume(c) - - if err != nil { - err = fmt.Errorf("Error creating persistent storage volume: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - ui.Message(fmt.Sprintf("Created volume: %s", cc.Name)) - return multistep.ActionContinue -} - -func (s *stepCreatePersistentVolume) Cleanup(state multistep.StateBag) { - client := state.Get("client").(*compute.Client) - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Cleaning up Volume...") - - c := &compute.DeleteStorageVolumeInput{ - Name: s.VolumeName, - } - - sc := client.StorageVolumes() - - if err := sc.DeleteStorageVolume(c); err != nil { - ui.Error(fmt.Sprintf("Error cleaning up persistent storage volume: %s", err)) - return - } - - ui.Message(fmt.Sprintf("Deleted volume: %s", s.VolumeName)) -} diff --git a/builder/oracle/classic/step_create_pv_builder.go b/builder/oracle/classic/step_create_pv_builder.go deleted file mode 100644 index aff02d328..000000000 --- a/builder/oracle/classic/step_create_pv_builder.go +++ /dev/null @@ -1,96 +0,0 @@ -package classic - -import ( - "context" - "fmt" - "log" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreatePVBuilder struct { - Name string - BuilderVolumeName string - SecurityListKey string -} - -func (s *stepCreatePVBuilder) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating builder instance...") - - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - ipAddName := state.Get("ipres_name").(string) - secListName := state.Get(s.SecurityListKey).(string) - - // get instances client - instanceClient := client.Instances() - - // Instances Input - input := &compute.CreateInstanceInput{ - Name: s.Name, - Shape: config.BuilderShape, - Networking: map[string]compute.NetworkingInfo{ - "eth0": { - Nat: []string{ipAddName}, - SecLists: []string{secListName}, - }, - }, - Storage: []compute.StorageAttachmentInput{ - { - Volume: s.BuilderVolumeName, - Index: 1, - }, - }, - ImageList: config.BuilderImageList, - SSHKeys: []string{config.Comm.SSHKeyPairName}, - Entry: *config.BuilderImageListEntry, - } - - instanceInfo, err := instanceClient.CreateInstance(input) - if err != nil { - err = fmt.Errorf("Problem creating instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - log.Printf("Created instance %s", instanceInfo.Name) - - state.Put("builder_instance_info", instanceInfo) - state.Put("builder_instance_id", instanceInfo.ID) - - ui.Message(fmt.Sprintf("Created builder instance: %s.", instanceInfo.Name)) - return multistep.ActionContinue -} - -func (s *stepCreatePVBuilder) Cleanup(state multistep.StateBag) { - instanceID, ok := state.GetOk("builder_instance_id") - if !ok { - return - } - - // terminate instance - ui := state.Get("ui").(packersdk.Ui) - client := state.Get("client").(*compute.Client) - - ui.Say("Terminating builder instance...") - - instanceClient := client.Instances() - input := &compute.DeleteInstanceInput{ - Name: s.Name, - ID: instanceID.(string), - } - - err := instanceClient.DeleteInstance(input) - if err != nil { - err = fmt.Errorf("Problem destroying instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } - ui.Say("Terminated builder instance.") - -} diff --git a/builder/oracle/classic/step_create_pv_master.go b/builder/oracle/classic/step_create_pv_master.go deleted file mode 100644 index 6773506d0..000000000 --- a/builder/oracle/classic/step_create_pv_master.go +++ /dev/null @@ -1,97 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreatePVMaster struct { - Name string - VolumeName string - SecurityListKey string -} - -func (s *stepCreatePVMaster) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating master instance...") - - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - ipAddName := state.Get("ipres_name").(string) - secListName := state.Get(s.SecurityListKey).(string) - - // get instances client - instanceClient := client.Instances() - - // Instances Input - input := &compute.CreateInstanceInput{ - Name: s.Name, - Shape: config.Shape, - Networking: map[string]compute.NetworkingInfo{ - "eth0": { - Nat: []string{ipAddName}, - SecLists: []string{secListName}, - }, - }, - Storage: []compute.StorageAttachmentInput{ - { - Volume: s.VolumeName, - Index: 1, - }, - }, - BootOrder: []int{1}, - Attributes: config.attribs, - } - if config.Comm.Type == "ssh" { - input.SSHKeys = []string{config.Comm.SSHKeyPairName} - } - - instanceInfo, err := instanceClient.CreateInstance(input) - if err != nil { - err = fmt.Errorf("Problem creating instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - state.Put("master_instance_info", instanceInfo) - state.Put("master_instance_id", instanceInfo.ID) - ui.Message(fmt.Sprintf("Created master instance: %s.", instanceInfo.Name)) - return multistep.ActionContinue -} - -func (s *stepCreatePVMaster) Cleanup(state multistep.StateBag) { - if _, deleted := state.GetOk("master_instance_deleted"); deleted { - return - } - - instanceID, ok := state.GetOk("master_instance_id") - if !ok { - return - } - - // terminate instance - ui := state.Get("ui").(packersdk.Ui) - client := state.Get("client").(*compute.Client) - - ui.Say("Terminating builder instance...") - - instanceClient := client.Instances() - input := &compute.DeleteInstanceInput{ - Name: s.Name, - ID: instanceID.(string), - } - - err := instanceClient.DeleteInstance(input) - if err != nil { - err = fmt.Errorf("Problem destroying instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } - ui.Say("Terminated master instance.") -} diff --git a/builder/oracle/classic/step_list_images.go b/builder/oracle/classic/step_list_images.go deleted file mode 100644 index cf61ff4f5..000000000 --- a/builder/oracle/classic/step_list_images.go +++ /dev/null @@ -1,103 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepListImages struct{} - -func (s *stepListImages) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - ui.Say("Adding image to image list...") - - imageListClient := client.ImageList() - getInput := compute.GetImageListInput{ - Name: config.DestImageList, - } - imList, err := imageListClient.GetImageList(&getInput) - if err != nil { - // If the list didn't exist, create it. - ui.Say(fmt.Sprintf(err.Error())) - ui.Say(fmt.Sprintf("Destination image list %s does not exist; Creating it...", - config.DestImageList)) - - ilInput := compute.CreateImageListInput{ - Name: config.DestImageList, - Description: "Packer-built image list", - } - - imList, err = imageListClient.CreateImageList(&ilInput) - if err != nil { - err = fmt.Errorf("Problem creating image list: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - ui.Message(fmt.Sprintf("Image list %s created!", imList.URI)) - } - - // Now create and image list entry for the image into that list. - machineImage := state.Get("machine_image").(string) - version := len(imList.Entries) + 1 - entriesClient := client.ImageListEntries() - entriesInput := compute.CreateImageListEntryInput{ - Name: config.DestImageList, - MachineImages: []string{config.Identifier(machineImage)}, - Version: version, - } - entryInfo, err := entriesClient.CreateImageListEntry(&entriesInput) - if err != nil { - err = fmt.Errorf("Problem creating an image list entry: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - state.Put("image_list_entry", entryInfo) - ui.Message(fmt.Sprintf("created image list entry %s", entryInfo.Name)) - - machineImagesClient := client.MachineImages() - getImagesInput := compute.GetMachineImageInput{ - Name: config.ImageName, - } - - // Update image list default to use latest version - updateInput := compute.UpdateImageListInput{ - Default: version, - Description: config.DestImageListDescription, - Name: config.DestImageList, - } - _, err = imageListClient.UpdateImageList(&updateInput) - if err != nil { - err = fmt.Errorf("Problem updating default image list version: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - // Grab info about the machine image to return with the artifact - imInfo, err := machineImagesClient.GetMachineImage(&getImagesInput) - if err != nil { - err = fmt.Errorf("Problem getting machine image info: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - state.Put("machine_image_file", imInfo.File) - state.Put("machine_image_name", imInfo.Name) - state.Put("image_list_version", version) - - return multistep.ActionContinue -} - -func (s *stepListImages) Cleanup(state multistep.StateBag) { - // Nothing to do - return -} diff --git a/builder/oracle/classic/step_security.go b/builder/oracle/classic/step_security.go deleted file mode 100644 index 6098322b9..000000000 --- a/builder/oracle/classic/step_security.go +++ /dev/null @@ -1,161 +0,0 @@ -package classic - -import ( - "context" - "fmt" - "log" - "strings" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepSecurity struct { - CommType string - SecurityListKey string - secListName string - secRuleName string -} - -func (s *stepSecurity) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) - runID := state.Get("run_id").(string) - client := state.Get("client").(*compute.Client) - - commType := "" - if s.CommType == "ssh" { - commType = "SSH" - } else if s.CommType == "winrm" { - commType = "WINRM" - } - secListName := fmt.Sprintf("Packer_%s_Allow_%s", commType, runID) - - if _, ok := state.GetOk(secListName); ok { - log.Println("SecList created in earlier step, continuing") - // copy sec list name to proper key - state.Put(s.SecurityListKey, secListName) - return multistep.ActionContinue - } - - ui.Say(fmt.Sprintf("Configuring security lists and rules to enable %s access...", commType)) - log.Println(secListName) - - secListClient := client.SecurityLists() - secListInput := compute.CreateSecurityListInput{ - Description: fmt.Sprintf("Packer-generated security list to give packer %s access", commType), - Name: config.Identifier(secListName), - } - _, err := secListClient.CreateSecurityList(&secListInput) - if err != nil { - if !strings.Contains(err.Error(), "already exists") { - err = fmt.Errorf("Error creating security List to"+ - " allow Packer to connect to Oracle instance via %s: %s", commType, err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - } - // DOCS NOTE: user must have Compute_Operations role - // Create security rule that allows Packer to connect via SSH or winRM - var application string - if commType == "SSH" { - application = "/oracle/public/ssh" - } else if commType == "WINRM" { - // Check to see whether a winRM security application is already defined - applicationClient := client.SecurityApplications() - application = fmt.Sprintf("packer_winRM_%s", runID) - 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", commType, runID) - log.Println(secRuleName) - secRulesInput := compute.CreateSecRuleInput{ - Action: "PERMIT", - Application: application, - Description: "Packer-generated security rule to allow ssh/winrm", - DestinationList: "seclist:" + config.Identifier(secListName), - Name: config.Identifier(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(s.SecurityListKey, secListName) - state.Put(secListName, true) - s.secListName = secListName - s.secRuleName = secRuleName - return multistep.ActionContinue -} - -func (s *stepSecurity) Cleanup(state multistep.StateBag) { - if s.secListName == "" || s.secRuleName == "" { - return - } - - client := state.Get("client").(*compute.Client) - ui := state.Get("ui").(packersdk.Ui) - config := state.Get("config").(*Config) - - ui.Say("Deleting temporary rules and lists...") - - // delete security rules that Packer generated - secRulesClient := client.SecRules() - ruleInput := compute.DeleteSecRuleInput{ - Name: config.Identifier(s.secRuleName), - } - err := secRulesClient.DeleteSecRule(&ruleInput) - if err != nil { - ui.Say(fmt.Sprintf("Error deleting the packer-generated security rule %s; "+ - "please delete manually. (error: %s)", s.secRuleName, err.Error())) - } - - // delete security list that Packer generated - secListClient := client.SecurityLists() - input := compute.DeleteSecurityListInput{Name: config.Identifier(s.secListName)} - err = secListClient.DeleteSecurityList(&input) - if err != nil { - ui.Say(fmt.Sprintf("Error deleting the packer-generated security list %s; "+ - "please delete manually. (error : %s)", s.secListName, err.Error())) - } - - // Some extra cleanup if we used the winRM communicator - if s.CommType == "winrm" { - // Delete the packer-generated application - application, ok := state.GetOk("winrm_application") - if !ok { - return - } - applicationClient := client.SecurityApplications() - deleteApplicationInput := compute.DeleteSecurityApplicationInput{ - Name: config.Identifier(application.(string)), - } - 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.(string), err.Error())) - } - } - -} diff --git a/builder/oracle/classic/step_snapshot.go b/builder/oracle/classic/step_snapshot.go deleted file mode 100644 index 6a2a90cbd..000000000 --- a/builder/oracle/classic/step_snapshot.go +++ /dev/null @@ -1,72 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepSnapshot struct { - cleanupSnap bool -} - -func (s *stepSnapshot) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Creating Snapshot...") - config := state.Get("config").(*Config) - client := state.Get("client").(*compute.Client) - instanceID := state.Get("instance_id").(string) - - // get instances client - snapshotClient := client.Snapshots() - - // Instances Input - snapshotInput := &compute.CreateSnapshotInput{ - Instance: fmt.Sprintf("%s/%s", config.ImageName, instanceID), - MachineImage: config.ImageName, - Timeout: config.SnapshotTimeout, - } - - snap, err := snapshotClient.CreateSnapshot(snapshotInput) - if err != nil { - err = fmt.Errorf("Problem creating snapshot: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - state.Put("snapshot", snap) - state.Put("machine_image", snap.MachineImage) - ui.Message(fmt.Sprintf("Created snapshot: %s.", snap.Name)) - return multistep.ActionContinue -} - -func (s *stepSnapshot) Cleanup(state multistep.StateBag) { - // Delete the snapshot - var snap *compute.Snapshot - if snapshot, ok := state.GetOk("snapshot"); ok { - snap = snapshot.(*compute.Snapshot) - } else { - return - } - - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Deleting Snapshot...") - client := state.Get("client").(*compute.Client) - snapClient := client.Snapshots() - snapInput := compute.DeleteSnapshotInput{ - Snapshot: snap.Name, - MachineImage: snap.MachineImage, - } - - err := snapClient.DeleteSnapshotResourceOnly(&snapInput) - if err != nil { - err = fmt.Errorf("Problem deleting snapshot: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - } - return -} diff --git a/builder/oracle/classic/step_terminate_pv_master.go b/builder/oracle/classic/step_terminate_pv_master.go deleted file mode 100644 index 39de6afae..000000000 --- a/builder/oracle/classic/step_terminate_pv_master.go +++ /dev/null @@ -1,46 +0,0 @@ -package classic - -import ( - "context" - "fmt" - - "github.com/hashicorp/go-oracle-terraform/compute" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepTerminatePVMaster struct { -} - -func (s *stepTerminatePVMaster) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - // get variables from state - ui := state.Get("ui").(packersdk.Ui) - ui.Say("Deleting master Instance...") - - client := state.Get("client").(*compute.Client) - instanceInfo := state.Get("master_instance_info").(*compute.InstanceInfo) - - // get instances client - instanceClient := client.Instances() - - // Instances Input - input := &compute.DeleteInstanceInput{ - Name: instanceInfo.Name, - ID: instanceInfo.ID, - } - - err := instanceClient.DeleteInstance(input) - if err != nil { - err = fmt.Errorf("Problem creating instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - ui.Message(fmt.Sprintf("Deleted master instance: %s.", instanceInfo.ID)) - state.Put("master_instance_deleted", true) - return multistep.ActionContinue -} - -func (s *stepTerminatePVMaster) Cleanup(state multistep.StateBag) { -} diff --git a/builder/oracle/classic/step_upload_image.go b/builder/oracle/classic/step_upload_image.go deleted file mode 100644 index c0d47c9c1..000000000 --- a/builder/oracle/classic/step_upload_image.go +++ /dev/null @@ -1,95 +0,0 @@ -package classic - -import ( - "context" - "fmt" - "log" - "strings" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" -) - -type stepUploadImage struct { - UploadImageCommand string - segmentPath string -} - -type uploadCmdData struct { - Username string - Password string - AccountID string - ImageFile string - SegmentPath string -} - -func (s *stepUploadImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - comm := state.Get("communicator").(packersdk.Communicator) - config := state.Get("config").(*Config) - runID := state.Get("run_id").(string) - - imageFile := fmt.Sprintf("%s.tar.gz", config.ImageName) - state.Put("image_file", imageFile) - s.segmentPath = fmt.Sprintf("compute_images_segments/%s/_segment_/%s", imageFile, runID) - - config.ctx.Data = uploadCmdData{ - Username: config.Username, - Password: config.Password, - AccountID: config.IdentityDomain, - ImageFile: imageFile, - SegmentPath: s.segmentPath, - } - uploadImageCmd, err := interpolate.Render(s.UploadImageCommand, &config.ctx) - if err != nil { - err := fmt.Errorf("Error processing image upload command: %s", err) - state.Put("error", err) - ui.Error(err.Error()) - return multistep.ActionHalt - } - - command := fmt.Sprintf(`#!/bin/sh - set -e - mkdir /builder - mkfs -t ext3 /dev/xvdb - mount /dev/xvdb /builder - chown opc:opc /builder - cd /builder - dd if=/dev/xvdc bs=8M status=progress | cp --sparse=always /dev/stdin diskimage.raw - tar czSf ./diskimage.tar.gz ./diskimage.raw - rm diskimage.raw - %s`, uploadImageCmd) - - dest := "/tmp/create-packer-diskimage.sh" - comm.Upload(dest, strings.NewReader(command), nil) - cmd := &packersdk.RemoteCmd{ - Command: fmt.Sprintf("sudo /bin/sh %s", dest), - } - if err := cmd.RunWithUi(ctx, comm, ui); err != nil { - err = fmt.Errorf("Problem creating image`: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - if cmd.ExitStatus() != 0 { - err = fmt.Errorf("Create Disk Image command failed with exit code %d", cmd.ExitStatus()) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - ui.Say("Uploaded image to object storage.") - - return multistep.ActionContinue -} - -func (s *stepUploadImage) Cleanup(state multistep.StateBag) { - _, cancelled := state.GetOk(multistep.StateCancelled) - _, halted := state.GetOk(multistep.StateHalted) - if !cancelled && !halted { - return - } - log.Printf("Some segments may need to be manually cleaned at '%s'", s.segmentPath) -} diff --git a/builder/oracle/common/step_ssh_key_pair.go b/builder/oracle/common/step_ssh_key_pair.go deleted file mode 100644 index 4b42a0f00..000000000 --- a/builder/oracle/common/step_ssh_key_pair.go +++ /dev/null @@ -1,116 +0,0 @@ -package common - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "fmt" - "os" - "runtime" - - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "golang.org/x/crypto/ssh" -) - -type StepKeyPair struct { - Debug bool - Comm *communicator.Config - DebugKeyPath string -} - -func (s *StepKeyPair) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - ui := state.Get("ui").(packersdk.Ui) - - if s.Comm.SSHPrivateKeyFile != "" { - ui.Say("Using existing SSH private key") - privateKeyBytes, err := s.Comm.ReadSSHPrivateKeyFile() - if err != nil { - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - key, err := ssh.ParsePrivateKey(privateKeyBytes) - if err != nil { - err = fmt.Errorf("Error parsing 'ssh_private_key_file': %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - s.Comm.SSHPublicKey = ssh.MarshalAuthorizedKey(key.PublicKey()) - s.Comm.SSHPrivateKey = privateKeyBytes - - return multistep.ActionContinue - } - - ui.Say("Creating temporary ssh key for instance...") - - priv, err := rsa.GenerateKey(rand.Reader, 2048) - if err != nil { - err = fmt.Errorf("Error creating temporary SSH key: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - // ASN.1 DER encoded form - privDer := x509.MarshalPKCS1PrivateKey(priv) - privBlk := pem.Block{Type: "RSA PRIVATE KEY", Headers: nil, Bytes: privDer} - - // Set the private key in the statebag for later - state.Put("privateKey", string(pem.EncodeToMemory(&privBlk))) - - // Marshal the public key into SSH compatible format - pub, err := ssh.NewPublicKey(&priv.PublicKey) - if err != nil { - err = fmt.Errorf("Error marshaling temporary SSH public key: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - s.Comm.SSHPublicKey = ssh.MarshalAuthorizedKey(pub) - - // If we're in debug mode, output the private key to the working - // directory. - if s.Debug { - ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath)) - f, err := os.Create(s.DebugKeyPath) - if err != nil { - err = fmt.Errorf("Error saving debug key: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - defer f.Close() - - // Write the key out - if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil { - err = fmt.Errorf("Error saving debug key: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - // Chmod it so that it is SSH ready - if runtime.GOOS != "windows" { - if err := f.Chmod(0600); err != nil { - err = fmt.Errorf("Error setting permissions of debug key: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - } - } - - return multistep.ActionContinue -} - -func (s *StepKeyPair) Cleanup(state multistep.StateBag) { - // Nothing to do -} diff --git a/builder/oracle/oci/LICENSE b/builder/oracle/oci/LICENSE deleted file mode 100644 index 0ddc33c23..000000000 --- a/builder/oracle/oci/LICENSE +++ /dev/null @@ -1,375 +0,0 @@ -Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved. - -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at http://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/builder/oracle/oci/artifact.go b/builder/oracle/oci/artifact.go deleted file mode 100644 index b5784d9a6..000000000 --- a/builder/oracle/oci/artifact.go +++ /dev/null @@ -1,57 +0,0 @@ -package oci - -import ( - "context" - "fmt" - - "github.com/oracle/oci-go-sdk/v36/core" -) - -// Artifact is an artifact implementation that contains a built Custom Image. -type Artifact struct { - Image core.Image - Region string - driver Driver - - // StateData should store data such as GeneratedData - // to be shared with post-processors - StateData map[string]interface{} -} - -// BuilderId uniquely identifies the builder. -func (a *Artifact) BuilderId() string { - return BuilderId -} - -// Files lists the files associated with an artifact. We don't have any files -// as the custom image is stored server side. -func (a *Artifact) Files() []string { - return nil -} - -// Id returns the OCID of the associated Image. -func (a *Artifact) Id() string { - return *a.Image.Id -} - -func (a *Artifact) String() string { - var displayName string - if a.Image.DisplayName != nil { - displayName = *a.Image.DisplayName - } - - return fmt.Sprintf( - "An image was created: '%v' (OCID: %v) in region '%v'", - displayName, *a.Image.Id, a.Region, - ) -} - -// State ... -func (a *Artifact) State(name string) interface{} { - return a.StateData[name] -} - -// Destroy deletes the custom image associated with the artifact. -func (a *Artifact) Destroy() error { - return a.driver.DeleteImage(context.TODO(), *a.Image.Id) -} diff --git a/builder/oracle/oci/artifact_test.go b/builder/oracle/oci/artifact_test.go deleted file mode 100644 index 366d1267c..000000000 --- a/builder/oracle/oci/artifact_test.go +++ /dev/null @@ -1,41 +0,0 @@ -package oci - -import ( - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestArtifactImpl(t *testing.T) { - var raw interface{} - raw = &Artifact{} - if _, ok := raw.(packersdk.Artifact); !ok { - t.Fatalf("Artifact should be artifact") - } -} - -func TestArtifactState_StateData(t *testing.T) { - expectedData := "this is the data" - artifact := &Artifact{ - StateData: map[string]interface{}{"state_data": expectedData}, - } - - // Valid state - result := artifact.State("state_data") - if result != expectedData { - t.Fatalf("Bad: State data was %s instead of %s", result, expectedData) - } - - // Invalid state - result = artifact.State("invalid_key") - if result != nil { - t.Fatalf("Bad: State should be nil for invalid state data name") - } - - // Nil StateData should not fail and should return nil - artifact = &Artifact{} - result = artifact.State("key") - if result != nil { - t.Fatalf("Bad: State should be nil for nil StateData") - } -} diff --git a/builder/oracle/oci/builder.go b/builder/oracle/oci/builder.go deleted file mode 100644 index 7ed18c761..000000000 --- a/builder/oracle/oci/builder.go +++ /dev/null @@ -1,110 +0,0 @@ -// Package oci contains a packersdk.Builder implementation that builds Oracle -// Bare Metal Cloud Services (OCI) images. -package oci - -import ( - "context" - "fmt" - - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/multistep" - "github.com/hashicorp/packer-plugin-sdk/multistep/commonsteps" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - ocommon "github.com/hashicorp/packer/builder/oracle/common" - "github.com/oracle/oci-go-sdk/v36/core" -) - -// BuilderId uniquely identifies the builder -const BuilderId = "packer.oracle.oci" - -// OCI API version -const ociAPIVersion = "20160918" - -// Builder is a builder implementation that creates Oracle OCI custom images. -type Builder struct { - config Config - runner multistep.Runner -} - -func (b *Builder) ConfigSpec() hcldec.ObjectSpec { return b.config.FlatMapstructure().HCL2Spec() } - -func (b *Builder) Prepare(raws ...interface{}) ([]string, []string, error) { - err := b.config.Prepare(raws...) - if err != nil { - return nil, nil, err - } - - return nil, nil, nil -} - -func (b *Builder) Run(ctx context.Context, ui packersdk.Ui, hook packersdk.Hook) (packersdk.Artifact, error) { - driver, err := NewDriverOCI(&b.config) - if err != nil { - return nil, err - } - - // Populate the state bag - state := new(multistep.BasicStateBag) - state.Put("config", &b.config) - state.Put("driver", driver) - state.Put("hook", hook) - state.Put("ui", ui) - - // Build the steps - steps := []multistep.Step{ - &ocommon.StepKeyPair{ - Debug: b.config.PackerDebug, - Comm: &b.config.Comm, - DebugKeyPath: fmt.Sprintf("oci_%s.pem", b.config.PackerBuildName), - }, - &stepCreateInstance{}, - &stepInstanceInfo{}, - &stepGetDefaultCredentials{ - Debug: b.config.PackerDebug, - Comm: &b.config.Comm, - BuildName: b.config.PackerBuildName, - }, - &communicator.StepConnect{ - Config: &b.config.Comm, - Host: communicator.CommHost(b.config.Comm.Host(), "instance_ip"), - SSHConfig: b.config.Comm.SSHConfigFunc(), - }, - &commonsteps.StepProvision{}, - &commonsteps.StepCleanupTempKeys{ - Comm: &b.config.Comm, - }, - &stepImage{}, - } - - // Run the steps - b.runner = commonsteps.NewRunnerWithPauseFn(steps, b.config.PackerConfig, ui, state) - b.runner.Run(ctx, state) - - // If there was an error, return that - if rawErr, ok := state.GetOk("error"); ok { - return nil, rawErr.(error) - } - - region, err := b.config.configProvider.Region() - if err != nil { - return nil, err - } - - image, ok := state.GetOk("image") - if !ok { - return nil, err - } - - // Build the artifact and return it - artifact := &Artifact{ - Image: image.(core.Image), - Region: region, - driver: driver, - StateData: map[string]interface{}{"generated_data": state.Get("generated_data")}, - } - - return artifact, nil -} - -// Cancel terminates a running build. diff --git a/builder/oracle/oci/builder_test.go b/builder/oracle/oci/builder_test.go deleted file mode 100644 index bb4b0fb21..000000000 --- a/builder/oracle/oci/builder_test.go +++ /dev/null @@ -1,15 +0,0 @@ -package oci - -import ( - "testing" - - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestBuilder_ImplementsBuilder(t *testing.T) { - var raw interface{} - raw = &Builder{} - if _, ok := raw.(packersdk.Builder); !ok { - t.Fatalf("Builder should be a builder") - } -} diff --git a/builder/oracle/oci/config.go b/builder/oracle/oci/config.go deleted file mode 100644 index 55347813b..000000000 --- a/builder/oracle/oci/config.go +++ /dev/null @@ -1,415 +0,0 @@ -//go:generate packer-sdc mapstructure-to-hcl2 -type Config,CreateVNICDetails,ListImagesRequest,FlexShapeConfig - -package oci - -import ( - "encoding/base64" - "errors" - "fmt" - "io/ioutil" - "log" - "os" - "os/user" - "path/filepath" - "strings" - - "github.com/hashicorp/packer-plugin-sdk/common" - "github.com/hashicorp/packer-plugin-sdk/communicator" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" - "github.com/hashicorp/packer-plugin-sdk/pathing" - "github.com/hashicorp/packer-plugin-sdk/template/config" - "github.com/hashicorp/packer-plugin-sdk/template/interpolate" - ocicommon "github.com/oracle/oci-go-sdk/v36/common" - ociauth "github.com/oracle/oci-go-sdk/v36/common/auth" -) - -type CreateVNICDetails struct { - // fields that can be specified under "create_vnic_details" - AssignPublicIp *bool `mapstructure:"assign_public_ip" required:"false"` - DefinedTags map[string]map[string]interface{} `mapstructure:"defined_tags" required:"false"` - DisplayName *string `mapstructure:"display_name" required:"false"` - FreeformTags map[string]string `mapstructure:"tags" required:"false"` - HostnameLabel *string `mapstructure:"hostname_label" required:"false"` - NsgIds []string `mapstructure:"nsg_ids" required:"false"` - PrivateIp *string `mapstructure:"private_ip" required:"false"` - SkipSourceDestCheck *bool `mapstructure:"skip_source_dest_check" required:"false"` - SubnetId *string `mapstructure:"subnet_id" required:"false"` -} - -type ListImagesRequest struct { - // fields that can be specified under "base_image_filter" - CompartmentId *string `mapstructure:"compartment_id"` - DisplayName *string `mapstructure:"display_name"` - DisplayNameSearch *string `mapstructure:"display_name_search"` - OperatingSystem *string `mapstructure:"operating_system"` - OperatingSystemVersion *string `mapstructure:"operating_system_version"` - Shape *string `mapstructure:"shape"` -} - -type FlexShapeConfig struct { - Ocpus *float32 `mapstructure:"ocpus" required:"false"` - MemoryInGBs *float32 `mapstructure:"memory_in_gbs" required:"false"` -} - -type Config struct { - common.PackerConfig `mapstructure:",squash"` - Comm communicator.Config `mapstructure:",squash"` - - configProvider ocicommon.ConfigurationProvider - - // Instance Principals (OPTIONAL) - // If set to true the following can't have non empty values - // - AccessCfgFile - // - AccessCfgFileAccount - // - UserID - // - TenancyID - // - Region - // - Fingerprint - // - KeyFile - // - PassPhrase - InstancePrincipals bool `mapstructure:"use_instance_principals"` - - AccessCfgFile string `mapstructure:"access_cfg_file"` - AccessCfgFileAccount string `mapstructure:"access_cfg_file_account"` - - // Access config overrides - UserID string `mapstructure:"user_ocid"` - TenancyID string `mapstructure:"tenancy_ocid"` - Region string `mapstructure:"region"` - Fingerprint string `mapstructure:"fingerprint"` - KeyFile string `mapstructure:"key_file"` - PassPhrase string `mapstructure:"pass_phrase"` - UsePrivateIP bool `mapstructure:"use_private_ip"` - - AvailabilityDomain string `mapstructure:"availability_domain"` - CompartmentID string `mapstructure:"compartment_ocid"` - - // Image - BaseImageID string `mapstructure:"base_image_ocid"` - BaseImageFilter ListImagesRequest `mapstructure:"base_image_filter"` - ImageName string `mapstructure:"image_name"` - ImageCompartmentID string `mapstructure:"image_compartment_ocid"` - LaunchMode string `mapstructure:"image_launch_mode"` - - // Instance - InstanceName *string `mapstructure:"instance_name"` - InstanceTags map[string]string `mapstructure:"instance_tags"` - InstanceDefinedTags map[string]map[string]interface{} `mapstructure:"instance_defined_tags"` - Shape string `mapstructure:"shape"` - ShapeConfig FlexShapeConfig `mapstructure:"shape_config"` - BootVolumeSizeInGBs int64 `mapstructure:"disk_size"` - - // Metadata optionally contains custom metadata key/value pairs provided in the - // configuration. While this can be used to set metadata["user_data"] the explicit - // "user_data" and "user_data_file" values will have precedence. - // An instance's metadata can be obtained from at http://169.254.169.254 on the - // launched instance. - Metadata map[string]string `mapstructure:"metadata"` - - // UserData and UserDataFile file are both optional and mutually exclusive. - UserData string `mapstructure:"user_data"` - UserDataFile string `mapstructure:"user_data_file"` - - // Networking - SubnetID string `mapstructure:"subnet_ocid"` - CreateVnicDetails CreateVNICDetails `mapstructure:"create_vnic_details"` - - // Tagging - Tags map[string]string `mapstructure:"tags"` - DefinedTags map[string]map[string]interface{} `mapstructure:"defined_tags"` - - ctx interpolate.Context -} - -func (c *Config) ConfigProvider() ocicommon.ConfigurationProvider { - return c.configProvider -} - -func (c *Config) Prepare(raws ...interface{}) error { - - // Decode from template - err := config.Decode(c, &config.DecodeOpts{ - Interpolate: true, - InterpolateContext: &c.ctx, - }, raws...) - if err != nil { - return fmt.Errorf("Failed to mapstructure Config: %+v", err) - } - - var errs *packersdk.MultiError - if es := c.Comm.Prepare(&c.ctx); len(es) > 0 { - errs = packersdk.MultiErrorAppend(errs, es...) - } - - var tenancyOCID string - - if c.InstancePrincipals { - // We could go through all keys in one go and report that the below set - // of keys cannot coexist with use_instance_principals but decided to - // split them and report them seperately so that the user sees the specific - // key involved. - var message string = " cannot be present when use_instance_principals is set to true." - if c.AccessCfgFile != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("access_cfg_file"+message)) - } - if c.AccessCfgFileAccount != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("access_cfg_file_account"+message)) - } - if c.UserID != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("user_ocid"+message)) - } - if c.TenancyID != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("tenancy_ocid"+message)) - } - if c.Region != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("region"+message)) - } - if c.Fingerprint != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("fingerprint"+message)) - } - if c.KeyFile != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("key_file"+message)) - } - if c.PassPhrase != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("pass_phrase"+message)) - } - // This check is used to facilitate testing. During testing a Mock struct - // is assigned to c.configProvider otherwise testing fails because Instance - // Principals cannot be obtained. - if c.configProvider == nil { - // Even though the previous configuraion checks might fail we don't want - // to skip this step. It seems that the logic behind the checks in this - // file is to check everything even getting the configProvider. - c.configProvider, err = ociauth.InstancePrincipalConfigurationProvider() - if err != nil { - return err - } - } - tenancyOCID, err = c.configProvider.TenancyOCID() - if err != nil { - return err - } - } else { - // Determine where the SDK config is located - if c.AccessCfgFile == "" { - c.AccessCfgFile, err = getDefaultOCISettingsPath() - if err != nil { - log.Println("Default OCI settings file not found") - } - } - - if c.AccessCfgFileAccount == "" { - c.AccessCfgFileAccount = "DEFAULT" - } - - var keyContent []byte - if c.KeyFile != "" { - path, err := pathing.ExpandUser(c.KeyFile) - if err != nil { - return err - } - - // Read API signing key - keyContent, err = ioutil.ReadFile(path) - if err != nil { - return err - } - } - - fileProvider, _ := ocicommon.ConfigurationProviderFromFileWithProfile(c.AccessCfgFile, c.AccessCfgFileAccount, c.PassPhrase) - if c.Region == "" { - var region string - if fileProvider != nil { - region, _ = fileProvider.Region() - } - if region == "" { - c.Region = "us-phoenix-1" - } - } - - providers := []ocicommon.ConfigurationProvider{ - ocicommon.NewRawConfigurationProvider(c.TenancyID, c.UserID, c.Region, c.Fingerprint, string(keyContent), &c.PassPhrase), - } - - if fileProvider != nil { - providers = append(providers, fileProvider) - } - - // Load API access configuration from SDK - configProvider, err := ocicommon.ComposingConfigurationProvider(providers) - if err != nil { - return err - } - - if userOCID, _ := configProvider.UserOCID(); userOCID == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'user_ocid' must be specified")) - } - - tenancyOCID, _ = configProvider.TenancyOCID() - if tenancyOCID == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'tenancy_ocid' must be specified")) - } - - if fingerprint, _ := configProvider.KeyFingerprint(); fingerprint == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'fingerprint' must be specified")) - } - - if _, err := configProvider.PrivateRSAKey(); err != nil { - errs = packersdk.MultiErrorAppend( - errs, fmt.Errorf("'key_file' must be correctly specified. %w", err)) - } - - c.configProvider = configProvider - } - - if c.AvailabilityDomain == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'availability_domain' must be specified")) - } - - if c.CompartmentID == "" && tenancyOCID != "" { - c.CompartmentID = tenancyOCID - } - - if c.ImageCompartmentID == "" { - c.ImageCompartmentID = c.CompartmentID - } - - if c.Shape == "" { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'shape' must be specified")) - } - - if strings.HasSuffix(c.Shape, "Flex") { - if c.ShapeConfig.Ocpus == nil { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'Ocpus' must be specified when using flexible shapes")) - } - } - - if c.ShapeConfig.MemoryInGBs != nil && c.ShapeConfig.Ocpus == nil { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'Ocpus' must be specified if memory_in_gbs is specified")) - } - - if (c.SubnetID == "") && (c.CreateVnicDetails.SubnetId == nil) { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'subnet_ocid' must be specified")) - } - - if c.CreateVnicDetails.SubnetId == nil { - c.CreateVnicDetails.SubnetId = &c.SubnetID - } else if (*c.CreateVnicDetails.SubnetId != c.SubnetID) && (c.SubnetID != "") { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'create_vnic_details[subnet]' must match 'subnet_ocid' if both are specified")) - } - - if (c.BaseImageID == "") && (c.BaseImageFilter == ListImagesRequest{}) { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'base_image_ocid' or 'base_image_filter' must be specified")) - } - - if c.BaseImageFilter.CompartmentId == nil { - c.BaseImageFilter.CompartmentId = &c.CompartmentID - } - - if c.BaseImageFilter.Shape == nil { - c.BaseImageFilter.Shape = &c.Shape - } - - // Validate tag lengths. TODO (hlowndes) maximum number of tags allowed. - if c.Tags != nil { - for k, v := range c.Tags { - k = strings.TrimSpace(k) - v = strings.TrimSpace(v) - if len(k) > 100 { - errs = packersdk.MultiErrorAppend( - errs, fmt.Errorf("Tag key length too long. Maximum 100 but found %d. Key: %s", len(k), k)) - } - if len(k) == 0 { - errs = packersdk.MultiErrorAppend( - errs, errors.New("Tag key empty in config")) - } - if len(v) > 100 { - errs = packersdk.MultiErrorAppend( - errs, fmt.Errorf("Tag value length too long. Maximum 100 but found %d. Key: %s", len(v), k)) - } - if len(v) == 0 { - errs = packersdk.MultiErrorAppend( - errs, errors.New("Tag value empty in config")) - } - } - } - - if c.ImageName == "" { - name, err := interpolate.Render("packer-{{timestamp}}", nil) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, - fmt.Errorf("unable to parse image name: %s", err)) - } else { - c.ImageName = name - } - } - - // Optional UserData config - if c.UserData != "" && c.UserDataFile != "" { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Only one of user_data or user_data_file can be specified.")) - } else if c.UserDataFile != "" { - if _, err := os.Stat(c.UserDataFile); err != nil { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("user_data_file not found: %s", c.UserDataFile)) - } - } - // read UserDataFile into string. - if c.UserDataFile != "" { - fiData, err := ioutil.ReadFile(c.UserDataFile) - if err != nil { - errs = packersdk.MultiErrorAppend(errs, fmt.Errorf("Problem reading user_data_file: %s", err)) - } - c.UserData = string(fiData) - } - // Test if UserData is encoded already, and if not, encode it - if c.UserData != "" { - if _, err := base64.StdEncoding.DecodeString(c.UserData); err != nil { - log.Printf("[DEBUG] base64 encoding user data...") - c.UserData = base64.StdEncoding.EncodeToString([]byte(c.UserData)) - } - } - - // Set default boot volume size to 50 if not set - // Check if size set is allowed by OCI - if c.BootVolumeSizeInGBs == 0 { - c.BootVolumeSizeInGBs = 50 - } else if c.BootVolumeSizeInGBs < 50 || c.BootVolumeSizeInGBs > 16384 { - errs = packersdk.MultiErrorAppend( - errs, errors.New("'disk_size' must be between 50 and 16384 GBs")) - } - - if errs != nil && len(errs.Errors) > 0 { - return errs - } - - return nil -} - -// getDefaultOCISettingsPath uses os/user to compute the default -// config file location ($HOME/.oci/config). -func getDefaultOCISettingsPath() (string, error) { - u, err := user.Current() - if err != nil { - return "", err - } - - if u.HomeDir == "" { - return "", fmt.Errorf("Unable to determine the home directory for the current user.") - } - - path := filepath.Join(u.HomeDir, ".oci", "config") - if _, err := os.Stat(path); err != nil { - return "", err - } - - return path, nil -} diff --git a/builder/oracle/oci/config.hcl2spec.go b/builder/oracle/oci/config.hcl2spec.go deleted file mode 100644 index 84c3493c4..000000000 --- a/builder/oracle/oci/config.hcl2spec.go +++ /dev/null @@ -1,300 +0,0 @@ -// Code generated by "packer-sdc mapstructure-to-hcl2"; DO NOT EDIT. - -package oci - -import ( - "github.com/hashicorp/hcl/v2/hcldec" - "github.com/zclconf/go-cty/cty" -) - -// FlatConfig is an auto-generated flat version of Config. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatConfig struct { - PackerBuildName *string `mapstructure:"packer_build_name" cty:"packer_build_name" hcl:"packer_build_name"` - PackerBuilderType *string `mapstructure:"packer_builder_type" cty:"packer_builder_type" hcl:"packer_builder_type"` - PackerCoreVersion *string `mapstructure:"packer_core_version" cty:"packer_core_version" hcl:"packer_core_version"` - PackerDebug *bool `mapstructure:"packer_debug" cty:"packer_debug" hcl:"packer_debug"` - PackerForce *bool `mapstructure:"packer_force" cty:"packer_force" hcl:"packer_force"` - PackerOnError *string `mapstructure:"packer_on_error" cty:"packer_on_error" hcl:"packer_on_error"` - PackerUserVars map[string]string `mapstructure:"packer_user_variables" cty:"packer_user_variables" hcl:"packer_user_variables"` - PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables" hcl:"packer_sensitive_variables"` - Type *string `mapstructure:"communicator" cty:"communicator" hcl:"communicator"` - PauseBeforeConnect *string `mapstructure:"pause_before_connecting" cty:"pause_before_connecting" hcl:"pause_before_connecting"` - SSHHost *string `mapstructure:"ssh_host" cty:"ssh_host" hcl:"ssh_host"` - SSHPort *int `mapstructure:"ssh_port" cty:"ssh_port" hcl:"ssh_port"` - SSHUsername *string `mapstructure:"ssh_username" cty:"ssh_username" hcl:"ssh_username"` - SSHPassword *string `mapstructure:"ssh_password" cty:"ssh_password" hcl:"ssh_password"` - SSHKeyPairName *string `mapstructure:"ssh_keypair_name" undocumented:"true" cty:"ssh_keypair_name" hcl:"ssh_keypair_name"` - SSHTemporaryKeyPairName *string `mapstructure:"temporary_key_pair_name" undocumented:"true" cty:"temporary_key_pair_name" hcl:"temporary_key_pair_name"` - SSHTemporaryKeyPairType *string `mapstructure:"temporary_key_pair_type" cty:"temporary_key_pair_type" hcl:"temporary_key_pair_type"` - SSHTemporaryKeyPairBits *int `mapstructure:"temporary_key_pair_bits" cty:"temporary_key_pair_bits" hcl:"temporary_key_pair_bits"` - SSHCiphers []string `mapstructure:"ssh_ciphers" cty:"ssh_ciphers" hcl:"ssh_ciphers"` - SSHClearAuthorizedKeys *bool `mapstructure:"ssh_clear_authorized_keys" cty:"ssh_clear_authorized_keys" hcl:"ssh_clear_authorized_keys"` - SSHKEXAlgos []string `mapstructure:"ssh_key_exchange_algorithms" cty:"ssh_key_exchange_algorithms" hcl:"ssh_key_exchange_algorithms"` - SSHPrivateKeyFile *string `mapstructure:"ssh_private_key_file" undocumented:"true" cty:"ssh_private_key_file" hcl:"ssh_private_key_file"` - SSHCertificateFile *string `mapstructure:"ssh_certificate_file" cty:"ssh_certificate_file" hcl:"ssh_certificate_file"` - SSHPty *bool `mapstructure:"ssh_pty" cty:"ssh_pty" hcl:"ssh_pty"` - SSHTimeout *string `mapstructure:"ssh_timeout" cty:"ssh_timeout" hcl:"ssh_timeout"` - SSHWaitTimeout *string `mapstructure:"ssh_wait_timeout" undocumented:"true" cty:"ssh_wait_timeout" hcl:"ssh_wait_timeout"` - SSHAgentAuth *bool `mapstructure:"ssh_agent_auth" undocumented:"true" cty:"ssh_agent_auth" hcl:"ssh_agent_auth"` - SSHDisableAgentForwarding *bool `mapstructure:"ssh_disable_agent_forwarding" cty:"ssh_disable_agent_forwarding" hcl:"ssh_disable_agent_forwarding"` - SSHHandshakeAttempts *int `mapstructure:"ssh_handshake_attempts" cty:"ssh_handshake_attempts" hcl:"ssh_handshake_attempts"` - SSHBastionHost *string `mapstructure:"ssh_bastion_host" cty:"ssh_bastion_host" hcl:"ssh_bastion_host"` - SSHBastionPort *int `mapstructure:"ssh_bastion_port" cty:"ssh_bastion_port" hcl:"ssh_bastion_port"` - SSHBastionAgentAuth *bool `mapstructure:"ssh_bastion_agent_auth" cty:"ssh_bastion_agent_auth" hcl:"ssh_bastion_agent_auth"` - SSHBastionUsername *string `mapstructure:"ssh_bastion_username" cty:"ssh_bastion_username" hcl:"ssh_bastion_username"` - SSHBastionPassword *string `mapstructure:"ssh_bastion_password" cty:"ssh_bastion_password" hcl:"ssh_bastion_password"` - SSHBastionInteractive *bool `mapstructure:"ssh_bastion_interactive" cty:"ssh_bastion_interactive" hcl:"ssh_bastion_interactive"` - SSHBastionPrivateKeyFile *string `mapstructure:"ssh_bastion_private_key_file" cty:"ssh_bastion_private_key_file" hcl:"ssh_bastion_private_key_file"` - SSHBastionCertificateFile *string `mapstructure:"ssh_bastion_certificate_file" cty:"ssh_bastion_certificate_file" hcl:"ssh_bastion_certificate_file"` - SSHFileTransferMethod *string `mapstructure:"ssh_file_transfer_method" cty:"ssh_file_transfer_method" hcl:"ssh_file_transfer_method"` - SSHProxyHost *string `mapstructure:"ssh_proxy_host" cty:"ssh_proxy_host" hcl:"ssh_proxy_host"` - SSHProxyPort *int `mapstructure:"ssh_proxy_port" cty:"ssh_proxy_port" hcl:"ssh_proxy_port"` - SSHProxyUsername *string `mapstructure:"ssh_proxy_username" cty:"ssh_proxy_username" hcl:"ssh_proxy_username"` - SSHProxyPassword *string `mapstructure:"ssh_proxy_password" cty:"ssh_proxy_password" hcl:"ssh_proxy_password"` - SSHKeepAliveInterval *string `mapstructure:"ssh_keep_alive_interval" cty:"ssh_keep_alive_interval" hcl:"ssh_keep_alive_interval"` - SSHReadWriteTimeout *string `mapstructure:"ssh_read_write_timeout" cty:"ssh_read_write_timeout" hcl:"ssh_read_write_timeout"` - SSHRemoteTunnels []string `mapstructure:"ssh_remote_tunnels" cty:"ssh_remote_tunnels" hcl:"ssh_remote_tunnels"` - SSHLocalTunnels []string `mapstructure:"ssh_local_tunnels" cty:"ssh_local_tunnels" hcl:"ssh_local_tunnels"` - SSHPublicKey []byte `mapstructure:"ssh_public_key" undocumented:"true" cty:"ssh_public_key" hcl:"ssh_public_key"` - SSHPrivateKey []byte `mapstructure:"ssh_private_key" undocumented:"true" cty:"ssh_private_key" hcl:"ssh_private_key"` - WinRMUser *string `mapstructure:"winrm_username" cty:"winrm_username" hcl:"winrm_username"` - WinRMPassword *string `mapstructure:"winrm_password" cty:"winrm_password" hcl:"winrm_password"` - WinRMHost *string `mapstructure:"winrm_host" cty:"winrm_host" hcl:"winrm_host"` - WinRMNoProxy *bool `mapstructure:"winrm_no_proxy" cty:"winrm_no_proxy" hcl:"winrm_no_proxy"` - WinRMPort *int `mapstructure:"winrm_port" cty:"winrm_port" hcl:"winrm_port"` - WinRMTimeout *string `mapstructure:"winrm_timeout" cty:"winrm_timeout" hcl:"winrm_timeout"` - WinRMUseSSL *bool `mapstructure:"winrm_use_ssl" cty:"winrm_use_ssl" hcl:"winrm_use_ssl"` - WinRMInsecure *bool `mapstructure:"winrm_insecure" cty:"winrm_insecure" hcl:"winrm_insecure"` - WinRMUseNTLM *bool `mapstructure:"winrm_use_ntlm" cty:"winrm_use_ntlm" hcl:"winrm_use_ntlm"` - InstancePrincipals *bool `mapstructure:"use_instance_principals" cty:"use_instance_principals" hcl:"use_instance_principals"` - AccessCfgFile *string `mapstructure:"access_cfg_file" cty:"access_cfg_file" hcl:"access_cfg_file"` - AccessCfgFileAccount *string `mapstructure:"access_cfg_file_account" cty:"access_cfg_file_account" hcl:"access_cfg_file_account"` - UserID *string `mapstructure:"user_ocid" cty:"user_ocid" hcl:"user_ocid"` - TenancyID *string `mapstructure:"tenancy_ocid" cty:"tenancy_ocid" hcl:"tenancy_ocid"` - Region *string `mapstructure:"region" cty:"region" hcl:"region"` - Fingerprint *string `mapstructure:"fingerprint" cty:"fingerprint" hcl:"fingerprint"` - KeyFile *string `mapstructure:"key_file" cty:"key_file" hcl:"key_file"` - PassPhrase *string `mapstructure:"pass_phrase" cty:"pass_phrase" hcl:"pass_phrase"` - UsePrivateIP *bool `mapstructure:"use_private_ip" cty:"use_private_ip" hcl:"use_private_ip"` - AvailabilityDomain *string `mapstructure:"availability_domain" cty:"availability_domain" hcl:"availability_domain"` - CompartmentID *string `mapstructure:"compartment_ocid" cty:"compartment_ocid" hcl:"compartment_ocid"` - BaseImageID *string `mapstructure:"base_image_ocid" cty:"base_image_ocid" hcl:"base_image_ocid"` - BaseImageFilter *FlatListImagesRequest `mapstructure:"base_image_filter" cty:"base_image_filter" hcl:"base_image_filter"` - ImageName *string `mapstructure:"image_name" cty:"image_name" hcl:"image_name"` - ImageCompartmentID *string `mapstructure:"image_compartment_ocid" cty:"image_compartment_ocid" hcl:"image_compartment_ocid"` - LaunchMode *string `mapstructure:"image_launch_mode" cty:"image_launch_mode" hcl:"image_launch_mode"` - InstanceName *string `mapstructure:"instance_name" cty:"instance_name" hcl:"instance_name"` - InstanceTags map[string]string `mapstructure:"instance_tags" cty:"instance_tags" hcl:"instance_tags"` - InstanceDefinedTags map[string]map[string]interface{} `mapstructure:"instance_defined_tags" cty:"instance_defined_tags" hcl:"instance_defined_tags"` - Shape *string `mapstructure:"shape" cty:"shape" hcl:"shape"` - ShapeConfig *FlatFlexShapeConfig `mapstructure:"shape_config" cty:"shape_config" hcl:"shape_config"` - BootVolumeSizeInGBs *int64 `mapstructure:"disk_size" cty:"disk_size" hcl:"disk_size"` - Metadata map[string]string `mapstructure:"metadata" cty:"metadata" hcl:"metadata"` - UserData *string `mapstructure:"user_data" cty:"user_data" hcl:"user_data"` - UserDataFile *string `mapstructure:"user_data_file" cty:"user_data_file" hcl:"user_data_file"` - SubnetID *string `mapstructure:"subnet_ocid" cty:"subnet_ocid" hcl:"subnet_ocid"` - CreateVnicDetails *FlatCreateVNICDetails `mapstructure:"create_vnic_details" cty:"create_vnic_details" hcl:"create_vnic_details"` - Tags map[string]string `mapstructure:"tags" cty:"tags" hcl:"tags"` - DefinedTags map[string]map[string]interface{} `mapstructure:"defined_tags" cty:"defined_tags" hcl:"defined_tags"` -} - -// FlatMapstructure returns a new FlatConfig. -// FlatConfig is an auto-generated flat version of Config. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*Config) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatConfig) -} - -// HCL2Spec returns the hcl spec of a Config. -// This spec is used by HCL to read the fields of Config. -// The decoded values from this spec will then be applied to a FlatConfig. -func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "packer_build_name": &hcldec.AttrSpec{Name: "packer_build_name", Type: cty.String, Required: false}, - "packer_builder_type": &hcldec.AttrSpec{Name: "packer_builder_type", Type: cty.String, Required: false}, - "packer_core_version": &hcldec.AttrSpec{Name: "packer_core_version", Type: cty.String, Required: false}, - "packer_debug": &hcldec.AttrSpec{Name: "packer_debug", Type: cty.Bool, Required: false}, - "packer_force": &hcldec.AttrSpec{Name: "packer_force", Type: cty.Bool, Required: false}, - "packer_on_error": &hcldec.AttrSpec{Name: "packer_on_error", Type: cty.String, Required: false}, - "packer_user_variables": &hcldec.AttrSpec{Name: "packer_user_variables", Type: cty.Map(cty.String), Required: false}, - "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, - "communicator": &hcldec.AttrSpec{Name: "communicator", Type: cty.String, Required: false}, - "pause_before_connecting": &hcldec.AttrSpec{Name: "pause_before_connecting", Type: cty.String, Required: false}, - "ssh_host": &hcldec.AttrSpec{Name: "ssh_host", Type: cty.String, Required: false}, - "ssh_port": &hcldec.AttrSpec{Name: "ssh_port", Type: cty.Number, Required: false}, - "ssh_username": &hcldec.AttrSpec{Name: "ssh_username", Type: cty.String, Required: false}, - "ssh_password": &hcldec.AttrSpec{Name: "ssh_password", Type: cty.String, Required: false}, - "ssh_keypair_name": &hcldec.AttrSpec{Name: "ssh_keypair_name", Type: cty.String, Required: false}, - "temporary_key_pair_name": &hcldec.AttrSpec{Name: "temporary_key_pair_name", Type: cty.String, Required: false}, - "temporary_key_pair_type": &hcldec.AttrSpec{Name: "temporary_key_pair_type", Type: cty.String, Required: false}, - "temporary_key_pair_bits": &hcldec.AttrSpec{Name: "temporary_key_pair_bits", Type: cty.Number, Required: false}, - "ssh_ciphers": &hcldec.AttrSpec{Name: "ssh_ciphers", Type: cty.List(cty.String), Required: false}, - "ssh_clear_authorized_keys": &hcldec.AttrSpec{Name: "ssh_clear_authorized_keys", Type: cty.Bool, Required: false}, - "ssh_key_exchange_algorithms": &hcldec.AttrSpec{Name: "ssh_key_exchange_algorithms", Type: cty.List(cty.String), Required: false}, - "ssh_private_key_file": &hcldec.AttrSpec{Name: "ssh_private_key_file", Type: cty.String, Required: false}, - "ssh_certificate_file": &hcldec.AttrSpec{Name: "ssh_certificate_file", Type: cty.String, Required: false}, - "ssh_pty": &hcldec.AttrSpec{Name: "ssh_pty", Type: cty.Bool, Required: false}, - "ssh_timeout": &hcldec.AttrSpec{Name: "ssh_timeout", Type: cty.String, Required: false}, - "ssh_wait_timeout": &hcldec.AttrSpec{Name: "ssh_wait_timeout", Type: cty.String, Required: false}, - "ssh_agent_auth": &hcldec.AttrSpec{Name: "ssh_agent_auth", Type: cty.Bool, Required: false}, - "ssh_disable_agent_forwarding": &hcldec.AttrSpec{Name: "ssh_disable_agent_forwarding", Type: cty.Bool, Required: false}, - "ssh_handshake_attempts": &hcldec.AttrSpec{Name: "ssh_handshake_attempts", Type: cty.Number, Required: false}, - "ssh_bastion_host": &hcldec.AttrSpec{Name: "ssh_bastion_host", Type: cty.String, Required: false}, - "ssh_bastion_port": &hcldec.AttrSpec{Name: "ssh_bastion_port", Type: cty.Number, Required: false}, - "ssh_bastion_agent_auth": &hcldec.AttrSpec{Name: "ssh_bastion_agent_auth", Type: cty.Bool, Required: false}, - "ssh_bastion_username": &hcldec.AttrSpec{Name: "ssh_bastion_username", Type: cty.String, Required: false}, - "ssh_bastion_password": &hcldec.AttrSpec{Name: "ssh_bastion_password", Type: cty.String, Required: false}, - "ssh_bastion_interactive": &hcldec.AttrSpec{Name: "ssh_bastion_interactive", Type: cty.Bool, Required: false}, - "ssh_bastion_private_key_file": &hcldec.AttrSpec{Name: "ssh_bastion_private_key_file", Type: cty.String, Required: false}, - "ssh_bastion_certificate_file": &hcldec.AttrSpec{Name: "ssh_bastion_certificate_file", Type: cty.String, Required: false}, - "ssh_file_transfer_method": &hcldec.AttrSpec{Name: "ssh_file_transfer_method", Type: cty.String, Required: false}, - "ssh_proxy_host": &hcldec.AttrSpec{Name: "ssh_proxy_host", Type: cty.String, Required: false}, - "ssh_proxy_port": &hcldec.AttrSpec{Name: "ssh_proxy_port", Type: cty.Number, Required: false}, - "ssh_proxy_username": &hcldec.AttrSpec{Name: "ssh_proxy_username", Type: cty.String, Required: false}, - "ssh_proxy_password": &hcldec.AttrSpec{Name: "ssh_proxy_password", Type: cty.String, Required: false}, - "ssh_keep_alive_interval": &hcldec.AttrSpec{Name: "ssh_keep_alive_interval", Type: cty.String, Required: false}, - "ssh_read_write_timeout": &hcldec.AttrSpec{Name: "ssh_read_write_timeout", Type: cty.String, Required: false}, - "ssh_remote_tunnels": &hcldec.AttrSpec{Name: "ssh_remote_tunnels", Type: cty.List(cty.String), Required: false}, - "ssh_local_tunnels": &hcldec.AttrSpec{Name: "ssh_local_tunnels", Type: cty.List(cty.String), Required: false}, - "ssh_public_key": &hcldec.AttrSpec{Name: "ssh_public_key", Type: cty.List(cty.Number), Required: false}, - "ssh_private_key": &hcldec.AttrSpec{Name: "ssh_private_key", Type: cty.List(cty.Number), Required: false}, - "winrm_username": &hcldec.AttrSpec{Name: "winrm_username", Type: cty.String, Required: false}, - "winrm_password": &hcldec.AttrSpec{Name: "winrm_password", Type: cty.String, Required: false}, - "winrm_host": &hcldec.AttrSpec{Name: "winrm_host", Type: cty.String, Required: false}, - "winrm_no_proxy": &hcldec.AttrSpec{Name: "winrm_no_proxy", Type: cty.Bool, Required: false}, - "winrm_port": &hcldec.AttrSpec{Name: "winrm_port", Type: cty.Number, Required: false}, - "winrm_timeout": &hcldec.AttrSpec{Name: "winrm_timeout", Type: cty.String, Required: false}, - "winrm_use_ssl": &hcldec.AttrSpec{Name: "winrm_use_ssl", Type: cty.Bool, Required: false}, - "winrm_insecure": &hcldec.AttrSpec{Name: "winrm_insecure", Type: cty.Bool, Required: false}, - "winrm_use_ntlm": &hcldec.AttrSpec{Name: "winrm_use_ntlm", Type: cty.Bool, Required: false}, - "use_instance_principals": &hcldec.AttrSpec{Name: "use_instance_principals", Type: cty.Bool, Required: false}, - "access_cfg_file": &hcldec.AttrSpec{Name: "access_cfg_file", Type: cty.String, Required: false}, - "access_cfg_file_account": &hcldec.AttrSpec{Name: "access_cfg_file_account", Type: cty.String, Required: false}, - "user_ocid": &hcldec.AttrSpec{Name: "user_ocid", Type: cty.String, Required: false}, - "tenancy_ocid": &hcldec.AttrSpec{Name: "tenancy_ocid", Type: cty.String, Required: false}, - "region": &hcldec.AttrSpec{Name: "region", Type: cty.String, Required: false}, - "fingerprint": &hcldec.AttrSpec{Name: "fingerprint", Type: cty.String, Required: false}, - "key_file": &hcldec.AttrSpec{Name: "key_file", Type: cty.String, Required: false}, - "pass_phrase": &hcldec.AttrSpec{Name: "pass_phrase", Type: cty.String, Required: false}, - "use_private_ip": &hcldec.AttrSpec{Name: "use_private_ip", Type: cty.Bool, Required: false}, - "availability_domain": &hcldec.AttrSpec{Name: "availability_domain", Type: cty.String, Required: false}, - "compartment_ocid": &hcldec.AttrSpec{Name: "compartment_ocid", Type: cty.String, Required: false}, - "base_image_ocid": &hcldec.AttrSpec{Name: "base_image_ocid", Type: cty.String, Required: false}, - "base_image_filter": &hcldec.BlockSpec{TypeName: "base_image_filter", Nested: hcldec.ObjectSpec((*FlatListImagesRequest)(nil).HCL2Spec())}, - "image_name": &hcldec.AttrSpec{Name: "image_name", Type: cty.String, Required: false}, - "image_compartment_ocid": &hcldec.AttrSpec{Name: "image_compartment_ocid", Type: cty.String, Required: false}, - "image_launch_mode": &hcldec.AttrSpec{Name: "image_launch_mode", Type: cty.String, Required: false}, - "instance_name": &hcldec.AttrSpec{Name: "instance_name", Type: cty.String, Required: false}, - "instance_tags": &hcldec.AttrSpec{Name: "instance_tags", Type: cty.Map(cty.String), Required: false}, - "instance_defined_tags": &hcldec.AttrSpec{Name: "instance_defined_tags", Type: cty.Map(cty.String), Required: false}, - "shape": &hcldec.AttrSpec{Name: "shape", Type: cty.String, Required: false}, - "shape_config": &hcldec.BlockSpec{TypeName: "shape_config", Nested: hcldec.ObjectSpec((*FlatFlexShapeConfig)(nil).HCL2Spec())}, - "disk_size": &hcldec.AttrSpec{Name: "disk_size", Type: cty.Number, Required: false}, - "metadata": &hcldec.AttrSpec{Name: "metadata", Type: cty.Map(cty.String), Required: false}, - "user_data": &hcldec.AttrSpec{Name: "user_data", Type: cty.String, Required: false}, - "user_data_file": &hcldec.AttrSpec{Name: "user_data_file", Type: cty.String, Required: false}, - "subnet_ocid": &hcldec.AttrSpec{Name: "subnet_ocid", Type: cty.String, Required: false}, - "create_vnic_details": &hcldec.BlockSpec{TypeName: "create_vnic_details", Nested: hcldec.ObjectSpec((*FlatCreateVNICDetails)(nil).HCL2Spec())}, - "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, - "defined_tags": &hcldec.AttrSpec{Name: "defined_tags", Type: cty.Map(cty.String), Required: false}, - } - return s -} - -// FlatCreateVNICDetails is an auto-generated flat version of CreateVNICDetails. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatCreateVNICDetails struct { - AssignPublicIp *bool `mapstructure:"assign_public_ip" required:"false" cty:"assign_public_ip" hcl:"assign_public_ip"` - DefinedTags map[string]map[string]interface{} `mapstructure:"defined_tags" required:"false" cty:"defined_tags" hcl:"defined_tags"` - DisplayName *string `mapstructure:"display_name" required:"false" cty:"display_name" hcl:"display_name"` - FreeformTags map[string]string `mapstructure:"tags" required:"false" cty:"tags" hcl:"tags"` - HostnameLabel *string `mapstructure:"hostname_label" required:"false" cty:"hostname_label" hcl:"hostname_label"` - NsgIds []string `mapstructure:"nsg_ids" required:"false" cty:"nsg_ids" hcl:"nsg_ids"` - PrivateIp *string `mapstructure:"private_ip" required:"false" cty:"private_ip" hcl:"private_ip"` - SkipSourceDestCheck *bool `mapstructure:"skip_source_dest_check" required:"false" cty:"skip_source_dest_check" hcl:"skip_source_dest_check"` - SubnetId *string `mapstructure:"subnet_id" required:"false" cty:"subnet_id" hcl:"subnet_id"` -} - -// FlatMapstructure returns a new FlatCreateVNICDetails. -// FlatCreateVNICDetails is an auto-generated flat version of CreateVNICDetails. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*CreateVNICDetails) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatCreateVNICDetails) -} - -// HCL2Spec returns the hcl spec of a CreateVNICDetails. -// This spec is used by HCL to read the fields of CreateVNICDetails. -// The decoded values from this spec will then be applied to a FlatCreateVNICDetails. -func (*FlatCreateVNICDetails) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "assign_public_ip": &hcldec.AttrSpec{Name: "assign_public_ip", Type: cty.Bool, Required: false}, - "defined_tags": &hcldec.AttrSpec{Name: "defined_tags", Type: cty.Map(cty.String), Required: false}, - "display_name": &hcldec.AttrSpec{Name: "display_name", Type: cty.String, Required: false}, - "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.Map(cty.String), Required: false}, - "hostname_label": &hcldec.AttrSpec{Name: "hostname_label", Type: cty.String, Required: false}, - "nsg_ids": &hcldec.AttrSpec{Name: "nsg_ids", Type: cty.List(cty.String), Required: false}, - "private_ip": &hcldec.AttrSpec{Name: "private_ip", Type: cty.String, Required: false}, - "skip_source_dest_check": &hcldec.AttrSpec{Name: "skip_source_dest_check", Type: cty.Bool, Required: false}, - "subnet_id": &hcldec.AttrSpec{Name: "subnet_id", Type: cty.String, Required: false}, - } - return s -} - -// FlatFlexShapeConfig is an auto-generated flat version of FlexShapeConfig. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatFlexShapeConfig struct { - Ocpus *float32 `mapstructure:"ocpus" required:"false" cty:"ocpus" hcl:"ocpus"` - MemoryInGBs *float32 `mapstructure:"memory_in_gbs" required:"false" cty:"memory_in_gbs" hcl:"memory_in_gbs"` -} - -// FlatMapstructure returns a new FlatFlexShapeConfig. -// FlatFlexShapeConfig is an auto-generated flat version of FlexShapeConfig. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*FlexShapeConfig) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatFlexShapeConfig) -} - -// HCL2Spec returns the hcl spec of a FlexShapeConfig. -// This spec is used by HCL to read the fields of FlexShapeConfig. -// The decoded values from this spec will then be applied to a FlatFlexShapeConfig. -func (*FlatFlexShapeConfig) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "ocpus": &hcldec.AttrSpec{Name: "ocpus", Type: cty.Number, Required: false}, - "memory_in_gbs": &hcldec.AttrSpec{Name: "memory_in_gbs", Type: cty.Number, Required: false}, - } - return s -} - -// FlatListImagesRequest is an auto-generated flat version of ListImagesRequest. -// Where the contents of a field with a `mapstructure:,squash` tag are bubbled up. -type FlatListImagesRequest struct { - CompartmentId *string `mapstructure:"compartment_id" cty:"compartment_id" hcl:"compartment_id"` - DisplayName *string `mapstructure:"display_name" cty:"display_name" hcl:"display_name"` - DisplayNameSearch *string `mapstructure:"display_name_search" cty:"display_name_search" hcl:"display_name_search"` - OperatingSystem *string `mapstructure:"operating_system" cty:"operating_system" hcl:"operating_system"` - OperatingSystemVersion *string `mapstructure:"operating_system_version" cty:"operating_system_version" hcl:"operating_system_version"` - Shape *string `mapstructure:"shape" cty:"shape" hcl:"shape"` -} - -// FlatMapstructure returns a new FlatListImagesRequest. -// FlatListImagesRequest is an auto-generated flat version of ListImagesRequest. -// Where the contents a fields with a `mapstructure:,squash` tag are bubbled up. -func (*ListImagesRequest) FlatMapstructure() interface{ HCL2Spec() map[string]hcldec.Spec } { - return new(FlatListImagesRequest) -} - -// HCL2Spec returns the hcl spec of a ListImagesRequest. -// This spec is used by HCL to read the fields of ListImagesRequest. -// The decoded values from this spec will then be applied to a FlatListImagesRequest. -func (*FlatListImagesRequest) HCL2Spec() map[string]hcldec.Spec { - s := map[string]hcldec.Spec{ - "compartment_id": &hcldec.AttrSpec{Name: "compartment_id", Type: cty.String, Required: false}, - "display_name": &hcldec.AttrSpec{Name: "display_name", Type: cty.String, Required: false}, - "display_name_search": &hcldec.AttrSpec{Name: "display_name_search", Type: cty.String, Required: false}, - "operating_system": &hcldec.AttrSpec{Name: "operating_system", Type: cty.String, Required: false}, - "operating_system_version": &hcldec.AttrSpec{Name: "operating_system_version", Type: cty.String, Required: false}, - "shape": &hcldec.AttrSpec{Name: "shape", Type: cty.String, Required: false}, - } - return s -} diff --git a/builder/oracle/oci/config_test.go b/builder/oracle/oci/config_test.go deleted file mode 100644 index 631acef5d..000000000 --- a/builder/oracle/oci/config_test.go +++ /dev/null @@ -1,412 +0,0 @@ -package oci - -import ( - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "encoding/pem" - "io/ioutil" - "os" - "strings" - "testing" - - "github.com/go-ini/ini" -) - -func testConfig(accessConfFile *os.File) map[string]interface{} { - return map[string]interface{}{ - - "availability_domain": "aaaa:PHX-AD-3", - "access_cfg_file": accessConfFile.Name(), - - // Image - "base_image_ocid": "ocd1...", - "image_name": "HelloWorld", - - // Networking - "subnet_ocid": "ocd1...", - - // Comm - "ssh_username": "opc", - "use_private_ip": false, - "metadata": map[string]string{ - "key": "value", - }, - "defined_tags": map[string]map[string]interface{}{ - "namespace": {"key": "value"}, - }, - - // Instance Details - "instance_name": "hello-world", - "instance_tags": map[string]string{ - "key": "value", - }, - "create_vnic_details": map[string]interface{}{ - "nsg_ids": []string{"ocd1..."}, - }, - "shape": "VM.Standard1.1", - "disk_size": 60, - } -} - -func TestConfig(t *testing.T) { - // Shared set-up and deferred deletion - - cfg, keyFile, err := baseTestConfigWithTmpKeyFile() - if err != nil { - t.Fatal(err) - } - defer os.Remove(keyFile.Name()) - - cfgFile, err := writeTestConfig(cfg) - if err != nil { - t.Fatal(err) - } - defer os.Remove(cfgFile.Name()) - - // Temporarily set $HOME to temp directory to bypass default - // access config loading. - - tmpHome, err := ioutil.TempDir("", "packer_config_test") - if err != nil { - t.Fatalf("Unexpected error when creating temporary directory: %+v", err) - } - defer os.Remove(tmpHome) - - home := os.Getenv("HOME") - os.Setenv("HOME", tmpHome) - defer os.Setenv("HOME", home) - - // Config tests - t.Run("BaseConfig", func(t *testing.T) { - raw := testConfig(cfgFile) - var c Config - errs := c.Prepare(raw) - - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - }) - - t.Run("BaseImageFilterWithoutOCID", func(t *testing.T) { - raw := testConfig(cfgFile) - raw["base_image_ocid"] = "" - raw["base_image_filter"] = map[string]interface{}{ - "display_name": "hello_world", - } - - var c Config - errs := c.Prepare(raw) - - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - }) - - t.Run("BaseImageFilterDefault", func(t *testing.T) { - raw := testConfig(cfgFile) - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - if *c.BaseImageFilter.Shape != raw["shape"] { - t.Fatalf("Default base_image_filter shape %v does not equal config shape %v", - *c.BaseImageFilter.Shape, raw["shape"]) - } - }) - - t.Run("LaunchMode", func(t *testing.T) { - raw := testConfig(cfgFile) - raw["image_launch_mode"] = "NATIVE" - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - }) - - t.Run("NoAccessConfig", func(t *testing.T) { - raw := testConfig(cfgFile) - raw["access_cfg_file"] = "/tmp/random/access/config/file/should/not/exist" - - var c Config - errs := c.Prepare(raw) - - expectedErrors := []string{ - "'user_ocid'", "'tenancy_ocid'", "'fingerprint'", "'key_file'", - } - - if errs == nil { - t.Fatalf("Expected errors %q but got none", expectedErrors) - } - - s := errs.Error() - for _, expected := range expectedErrors { - if !strings.Contains(s, expected) { - t.Errorf("Expected %q to contain '%s'", s, expected) - } - } - }) - - t.Run("AccessConfigTemplateOnly", func(t *testing.T) { - raw := testConfig(cfgFile) - delete(raw, "access_cfg_file") - raw["user_ocid"] = "ocid1..." - raw["tenancy_ocid"] = "ocid1..." - raw["fingerprint"] = "00:00..." - raw["key_file"] = keyFile.Name() - - var c Config - errs := c.Prepare(raw) - - if errs != nil { - t.Fatalf("err: %+v", errs) - } - - }) - - t.Run("TenancyReadFromAccessCfgFile", func(t *testing.T) { - raw := testConfig(cfgFile) - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - tenancy, err := c.configProvider.TenancyOCID() - if err != nil { - t.Fatalf("Unexpected error getting tenancy ocid: %v", err) - } - - expected := "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" - if tenancy != expected { - t.Errorf("Expected tenancy: %s, got %s.", expected, tenancy) - } - - }) - - t.Run("RegionNotDefaultedToPHXWhenSetInOCISettings", func(t *testing.T) { - raw := testConfig(cfgFile) - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - region, err := c.configProvider.Region() - if err != nil { - t.Fatalf("Unexpected error getting region: %v", err) - } - - expected := "us-ashburn-1" - if region != expected { - t.Errorf("Expected region: %s, got %s.", expected, region) - } - - }) - - // Test the correct errors are produced when required template keys are - // omitted. - requiredKeys := []string{"availability_domain", "base_image_ocid", "shape", "subnet_ocid"} - for _, k := range requiredKeys { - t.Run(k+"_required", func(t *testing.T) { - raw := testConfig(cfgFile) - delete(raw, k) - - var c Config - errs := c.Prepare(raw) - - if !strings.Contains(errs.Error(), k) { - t.Errorf("Expected '%s' to contain '%s'", errs.Error(), k) - } - }) - } - - t.Run("ImageNameDefaultedIfEmpty", func(t *testing.T) { - raw := testConfig(cfgFile) - delete(raw, "image_name") - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - if !strings.Contains(c.ImageName, "packer-") { - t.Errorf("got default ImageName %q, want image name 'packer-{{timestamp}}'", c.ImageName) - } - }) - - t.Run("user_ocid_overridden", func(t *testing.T) { - expected := "override" - raw := testConfig(cfgFile) - raw["user_ocid"] = expected - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - user, _ := c.configProvider.UserOCID() - if user != expected { - t.Errorf("Expected ConfigProvider.UserOCID: %s, got %s", expected, user) - } - }) - - t.Run("tenancy_ocid_overidden", func(t *testing.T) { - expected := "override" - raw := testConfig(cfgFile) - raw["tenancy_ocid"] = expected - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - tenancy, _ := c.configProvider.TenancyOCID() - if tenancy != expected { - t.Errorf("Expected ConfigProvider.TenancyOCID: %s, got %s", expected, tenancy) - } - }) - - t.Run("region_overidden", func(t *testing.T) { - expected := "override" - raw := testConfig(cfgFile) - raw["region"] = expected - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration %+v", errs) - } - - region, _ := c.configProvider.Region() - if region != expected { - t.Errorf("Expected ConfigProvider.Region: %s, got %s", expected, region) - } - }) - - t.Run("fingerprint_overidden", func(t *testing.T) { - expected := "override" - raw := testConfig(cfgFile) - raw["fingerprint"] = expected - - var c Config - errs := c.Prepare(raw) - if errs != nil { - t.Fatalf("Unexpected error in configuration: %+v", errs) - } - - fingerprint, _ := c.configProvider.KeyFingerprint() - if fingerprint != expected { - t.Errorf("Expected ConfigProvider.KeyFingerprint: %s, got %s", expected, fingerprint) - } - }) - - // Test the correct errors are produced when certain template keys - // are present alongside use_instance_principals key. - invalidKeys := []string{ - "access_cfg_file", - "access_cfg_file_account", - "user_ocid", - "tenancy_ocid", - "region", - "fingerprint", - "key_file", - "pass_phrase", - } - for _, k := range invalidKeys { - t.Run(k+"_mixed_with_use_instance_principals", func(t *testing.T) { - raw := testConfig(cfgFile) - raw["use_instance_principals"] = "true" - raw[k] = "some_random_value" - - var c Config - - c.configProvider = instancePrincipalConfigurationProviderMock{} - - errs := c.Prepare(raw) - - if !strings.Contains(errs.Error(), k) { - t.Errorf("Expected '%s' to contain '%s'", errs.Error(), k) - } - }) - } -} - -// BaseTestConfig creates the base (DEFAULT) config including a temporary key -// file. -// NOTE: Caller is responsible for removing temporary key file. -func baseTestConfigWithTmpKeyFile() (*ini.File, *os.File, error) { - keyFile, err := generateRSAKeyFile() - if err != nil { - return nil, keyFile, err - } - // Build ini - cfg := ini.Empty() - section, _ := cfg.NewSection("DEFAULT") - section.NewKey("region", "us-ashburn-1") - section.NewKey("tenancy", "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - section.NewKey("user", "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - section.NewKey("fingerprint", "70:04:5z:b3:19:ab:90:75:a4:1f:50:d4:c7:c3:33:20") - section.NewKey("key_file", keyFile.Name()) - - return cfg, keyFile, nil -} - -// WriteTestConfig writes a ini.File to a temporary file for use in unit tests. -// NOTE: Caller is responsible for removing temporary file. -func writeTestConfig(cfg *ini.File) (*os.File, error) { - confFile, err := ioutil.TempFile("", "config_file") - if err != nil { - return nil, err - } - - if _, err := confFile.Write([]byte("[DEFAULT]\n")); err != nil { - os.Remove(confFile.Name()) - return nil, err - } - - if _, err := cfg.WriteTo(confFile); err != nil { - os.Remove(confFile.Name()) - return nil, err - } - return confFile, nil -} - -// generateRSAKeyFile generates an RSA key file for use in unit tests. -// NOTE: The caller is responsible for deleting the temporary file. -func generateRSAKeyFile() (*os.File, error) { - // Create temporary file for the key - f, err := ioutil.TempFile("", "key") - if err != nil { - return nil, err - } - - // Generate key - priv, err := rsa.GenerateKey(rand.Reader, 2014) - if err != nil { - return nil, err - } - - // ASN.1 DER encoded form - privDer := x509.MarshalPKCS1PrivateKey(priv) - privBlk := pem.Block{ - Type: "RSA PRIVATE KEY", - Headers: nil, - Bytes: privDer, - } - - // Write the key out - if _, err := f.Write(pem.EncodeToMemory(&privBlk)); err != nil { - return nil, err - } - - return f, nil -} diff --git a/builder/oracle/oci/driver.go b/builder/oracle/oci/driver.go deleted file mode 100644 index cdad1c4e6..000000000 --- a/builder/oracle/oci/driver.go +++ /dev/null @@ -1,18 +0,0 @@ -package oci - -import ( - "context" - - "github.com/oracle/oci-go-sdk/v36/core" -) - -// Driver interfaces between the builder steps and the OCI SDK. -type Driver interface { - CreateInstance(ctx context.Context, publicKey string) (string, error) - CreateImage(ctx context.Context, id string) (core.Image, error) - DeleteImage(ctx context.Context, id string) error - GetInstanceIP(ctx context.Context, id string) (string, error) - TerminateInstance(ctx context.Context, id string) error - WaitForImageCreation(ctx context.Context, id string) error - WaitForInstanceState(ctx context.Context, id string, waitStates []string, terminalState string) error -} diff --git a/builder/oracle/oci/driver_mock.go b/builder/oracle/oci/driver_mock.go deleted file mode 100644 index 708067193..000000000 --- a/builder/oracle/oci/driver_mock.go +++ /dev/null @@ -1,96 +0,0 @@ -package oci - -import ( - "context" - - "github.com/oracle/oci-go-sdk/v36/core" -) - -// driverMock implements the Driver interface and communicates with Oracle -// OCI. -type driverMock struct { - CreateInstanceID string - CreateInstanceErr error - - CreateImageID string - CreateImageErr error - - DeleteImageID string - DeleteImageErr error - - GetInstanceIPErr error - - TerminateInstanceID string - TerminateInstanceErr error - - WaitForImageCreationErr error - - WaitForInstanceStateErr error - - cfg *Config -} - -// CreateInstance creates a new compute instance. -func (d *driverMock) CreateInstance(ctx context.Context, publicKey string) (string, error) { - if d.CreateInstanceErr != nil { - return "", d.CreateInstanceErr - } - - d.CreateInstanceID = "ocid1..." - - return d.CreateInstanceID, nil -} - -// CreateImage creates a new custom image. -func (d *driverMock) CreateImage(ctx context.Context, id string) (core.Image, error) { - if d.CreateImageErr != nil { - return core.Image{}, d.CreateImageErr - } - d.CreateImageID = id - return core.Image{Id: &id}, nil -} - -// DeleteImage mocks deleting a custom image. -func (d *driverMock) DeleteImage(ctx context.Context, id string) error { - if d.DeleteImageErr != nil { - return d.DeleteImageErr - } - - d.DeleteImageID = id - - return nil -} - -// GetInstanceIP returns the public or private IP corresponding to the given instance id. -func (d *driverMock) GetInstanceIP(ctx context.Context, id string) (string, error) { - if d.GetInstanceIPErr != nil { - return "", d.GetInstanceIPErr - } - if d.cfg.UsePrivateIP { - return "private_ip", nil - } - return "ip", nil -} - -// TerminateInstance terminates a compute instance. -func (d *driverMock) TerminateInstance(ctx context.Context, id string) error { - if d.TerminateInstanceErr != nil { - return d.TerminateInstanceErr - } - - d.TerminateInstanceID = id - - return nil -} - -// WaitForImageCreation waits for a provisioning custom image to reach the -// "AVAILABLE" state. -func (d *driverMock) WaitForImageCreation(ctx context.Context, id string) error { - return d.WaitForImageCreationErr -} - -// WaitForInstanceState waits for an instance to reach the a given terminal -// state. -func (d *driverMock) WaitForInstanceState(ctx context.Context, id string, waitStates []string, terminalState string) error { - return d.WaitForInstanceStateErr -} diff --git a/builder/oracle/oci/driver_oci.go b/builder/oracle/oci/driver_oci.go deleted file mode 100644 index 1b8f978d3..000000000 --- a/builder/oracle/oci/driver_oci.go +++ /dev/null @@ -1,339 +0,0 @@ -package oci - -import ( - "context" - "errors" - "fmt" - "math" - "math/rand" - "net/http" - "regexp" - "sync/atomic" - "time" - - "github.com/oracle/oci-go-sdk/v36/common" - core "github.com/oracle/oci-go-sdk/v36/core" -) - -// driverOCI implements the Driver interface and communicates with Oracle -// OCI. -type driverOCI struct { - computeClient core.ComputeClient - vcnClient core.VirtualNetworkClient - cfg *Config - context context.Context -} - -var retryPolicy = &common.RetryPolicy{ - MaximumNumberAttempts: 10, - ShouldRetryOperation: func(res common.OCIOperationResponse) bool { - var e common.ServiceError - if errors.As(res.Error, &e) { - switch e.GetHTTPStatusCode() { - case http.StatusTooManyRequests, http.StatusInternalServerError, http.StatusServiceUnavailable: - return true - } - } - return false - }, - NextDuration: func(res common.OCIOperationResponse) time.Duration { - x := uint64(res.AttemptNumber) - d := time.Duration(math.Pow(2, float64(atomic.LoadUint64(&x)))) * time.Second - j := time.Duration(rand.Float64()*(2000)) * time.Millisecond - w := d + j - return w - }, -} - -var requestMetadata = common.RequestMetadata{ - RetryPolicy: retryPolicy, -} - -// NewDriverOCI Creates a new driverOCI with a connected compute client and a connected vcn client. -func NewDriverOCI(cfg *Config) (Driver, error) { - coreClient, err := core.NewComputeClientWithConfigurationProvider(cfg.configProvider) - if err != nil { - return nil, err - } - - vcnClient, err := core.NewVirtualNetworkClientWithConfigurationProvider(cfg.configProvider) - if err != nil { - return nil, err - } - - return &driverOCI{ - computeClient: coreClient, - vcnClient: vcnClient, - cfg: cfg, - }, nil -} - -// CreateInstance creates a new compute instance. -func (d *driverOCI) CreateInstance(ctx context.Context, publicKey string) (string, error) { - metadata := map[string]string{ - "ssh_authorized_keys": publicKey, - } - if d.cfg.Metadata != nil { - for key, value := range d.cfg.Metadata { - metadata[key] = value - } - } - if d.cfg.UserData != "" { - metadata["user_data"] = d.cfg.UserData - } - - // Create VNIC details for instance - CreateVnicDetails := core.CreateVnicDetails{ - AssignPublicIp: d.cfg.CreateVnicDetails.AssignPublicIp, - DisplayName: d.cfg.CreateVnicDetails.DisplayName, - HostnameLabel: d.cfg.CreateVnicDetails.HostnameLabel, - NsgIds: d.cfg.CreateVnicDetails.NsgIds, - PrivateIp: d.cfg.CreateVnicDetails.PrivateIp, - SkipSourceDestCheck: d.cfg.CreateVnicDetails.SkipSourceDestCheck, - SubnetId: d.cfg.CreateVnicDetails.SubnetId, - DefinedTags: d.cfg.CreateVnicDetails.DefinedTags, - FreeformTags: d.cfg.CreateVnicDetails.FreeformTags, - } - - // Determine base image ID - var imageId *string - if d.cfg.BaseImageID != "" { - imageId = &d.cfg.BaseImageID - } else { - // Pull images and determine which image ID to use, if BaseImageId not specified - response, err := d.computeClient.ListImages(ctx, core.ListImagesRequest{ - CompartmentId: d.cfg.BaseImageFilter.CompartmentId, - DisplayName: d.cfg.BaseImageFilter.DisplayName, - OperatingSystem: d.cfg.BaseImageFilter.OperatingSystem, - OperatingSystemVersion: d.cfg.BaseImageFilter.OperatingSystemVersion, - Shape: d.cfg.BaseImageFilter.Shape, - LifecycleState: "AVAILABLE", - SortBy: "TIMECREATED", - SortOrder: "DESC", - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", err - } - if len(response.Items) == 0 { - return "", errors.New("base_image_filter returned no images") - } - if d.cfg.BaseImageFilter.DisplayNameSearch != nil { - // Return most recent image that matches regex - imageNameRegex, err := regexp.Compile(*d.cfg.BaseImageFilter.DisplayNameSearch) - if err != nil { - return "", err - } - for _, image := range response.Items { - if imageNameRegex.MatchString(*image.DisplayName) { - imageId = image.Id - break - } - } - if imageId == nil { - return "", errors.New("No image matched display_name_search criteria") - } - } else { - // If no regex provided, simply return most recent image pulled - imageId = response.Items[0].Id - } - } - - // Create Source details which will be used to Launch Instance - InstanceSourceDetails := core.InstanceSourceViaImageDetails{ - ImageId: imageId, - BootVolumeSizeInGBs: &d.cfg.BootVolumeSizeInGBs, - } - - // Build instance details - instanceDetails := core.LaunchInstanceDetails{ - AvailabilityDomain: &d.cfg.AvailabilityDomain, - CompartmentId: &d.cfg.CompartmentID, - CreateVnicDetails: &CreateVnicDetails, - DefinedTags: d.cfg.InstanceDefinedTags, - DisplayName: d.cfg.InstanceName, - FreeformTags: d.cfg.InstanceTags, - Shape: &d.cfg.Shape, - SourceDetails: InstanceSourceDetails, - Metadata: metadata, - } - - if d.cfg.ShapeConfig.Ocpus != nil { - LaunchInstanceShapeConfigDetails := core.LaunchInstanceShapeConfigDetails{ - Ocpus: d.cfg.ShapeConfig.Ocpus, - MemoryInGBs: d.cfg.ShapeConfig.MemoryInGBs, - } - instanceDetails.ShapeConfig = &LaunchInstanceShapeConfigDetails - } - - instance, err := d.computeClient.LaunchInstance(context.TODO(), core.LaunchInstanceRequest{ - LaunchInstanceDetails: instanceDetails, - RequestMetadata: requestMetadata, - }) - - if err != nil { - return "", err - } - - return *instance.Id, nil -} - -// CreateImage creates a new custom image. -func (d *driverOCI) CreateImage(ctx context.Context, id string) (core.Image, error) { - res, err := d.computeClient.CreateImage(ctx, core.CreateImageRequest{CreateImageDetails: core.CreateImageDetails{ - CompartmentId: &d.cfg.ImageCompartmentID, - InstanceId: &id, - DisplayName: &d.cfg.ImageName, - FreeformTags: d.cfg.Tags, - DefinedTags: d.cfg.DefinedTags, - LaunchMode: core.CreateImageDetailsLaunchModeEnum(d.cfg.LaunchMode), - }, - RequestMetadata: requestMetadata, - }) - - if err != nil { - return core.Image{}, err - } - - return res.Image, nil -} - -// DeleteImage deletes a custom image. -func (d *driverOCI) DeleteImage(ctx context.Context, id string) error { - _, err := d.computeClient.DeleteImage(ctx, core.DeleteImageRequest{ - ImageId: &id, - RequestMetadata: requestMetadata, - }) - return err -} - -// GetInstanceIP returns the public or private IP corresponding to the given instance id. -func (d *driverOCI) GetInstanceIP(ctx context.Context, id string) (string, error) { - vnics, err := d.computeClient.ListVnicAttachments(ctx, core.ListVnicAttachmentsRequest{ - InstanceId: &id, - CompartmentId: &d.cfg.CompartmentID, - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", err - } - - if len(vnics.Items) == 0 { - return "", errors.New("instance has zero VNICs") - } - - vnic, err := d.vcnClient.GetVnic(ctx, core.GetVnicRequest{ - VnicId: vnics.Items[0].VnicId, - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", fmt.Errorf("Error getting VNIC details: %s", err) - } - - if d.cfg.UsePrivateIP { - return *vnic.PrivateIp, nil - } - - if vnic.PublicIp == nil { - return "", fmt.Errorf("Error getting VNIC Public Ip for: %s", id) - } - - return *vnic.PublicIp, nil -} - -func (d *driverOCI) GetInstanceInitialCredentials(ctx context.Context, id string) (string, string, error) { - credentials, err := d.computeClient.GetWindowsInstanceInitialCredentials(ctx, core.GetWindowsInstanceInitialCredentialsRequest{ - InstanceId: &id, - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", "", err - } - - return *credentials.InstanceCredentials.Username, *credentials.InstanceCredentials.Password, err -} - -// TerminateInstance terminates a compute instance. -func (d *driverOCI) TerminateInstance(ctx context.Context, id string) error { - _, err := d.computeClient.TerminateInstance(ctx, core.TerminateInstanceRequest{ - InstanceId: &id, - RequestMetadata: requestMetadata, - }) - return err -} - -// WaitForImageCreation waits for a provisioning custom image to reach the -// "AVAILABLE" state. -func (d *driverOCI) WaitForImageCreation(ctx context.Context, id string) error { - return waitForResourceToReachState( - func(string) (string, error) { - image, err := d.computeClient.GetImage(ctx, core.GetImageRequest{ - ImageId: &id, - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", err - } - return string(image.LifecycleState), nil - }, - id, - []string{"PROVISIONING"}, - "AVAILABLE", - 0, //Unlimited Retries - 5*time.Second, //5 second wait between retries - ) -} - -// WaitForInstanceState waits for an instance to reach the a given terminal -// state. -func (d *driverOCI) WaitForInstanceState(ctx context.Context, id string, waitStates []string, terminalState string) error { - return waitForResourceToReachState( - func(string) (string, error) { - instance, err := d.computeClient.GetInstance(ctx, core.GetInstanceRequest{ - InstanceId: &id, - RequestMetadata: requestMetadata, - }) - if err != nil { - return "", err - } - return string(instance.LifecycleState), nil - }, - id, - waitStates, - terminalState, - 0, //Unlimited Retries - 5*time.Second, //5 second wait between retries - ) -} - -// WaitForResourceToReachState checks the response of a request through a -// polled get and waits until the desired state or until the max retried has -// been reached. -func waitForResourceToReachState(getResourceState func(string) (string, error), id string, waitStates []string, terminalState string, maxRetries int, waitDuration time.Duration) error { - for i := 0; maxRetries == 0 || i < maxRetries; i++ { - state, err := getResourceState(id) - if err != nil { - return err - } - - if stringSliceContains(waitStates, state) { - time.Sleep(waitDuration) - continue - } else if state == terminalState { - return nil - } - return fmt.Errorf("Unexpected resource state %q, expecting a waiting state %s or terminal state %q ", state, waitStates, terminalState) - } - return fmt.Errorf("Maximum number of retries (%d) exceeded; resource did not reach state %q", maxRetries, terminalState) -} - -// stringSliceContains loops through a slice of strings returning a boolean -// based on whether a given value is contained in the slice. -func stringSliceContains(slice []string, value string) bool { - for _, elem := range slice { - if elem == value { - return true - } - } - return false -} diff --git a/builder/oracle/oci/instance_principal_configuration_provider_mock.go b/builder/oracle/oci/instance_principal_configuration_provider_mock.go deleted file mode 100644 index f4eb5db99..000000000 --- a/builder/oracle/oci/instance_principal_configuration_provider_mock.go +++ /dev/null @@ -1,43 +0,0 @@ -package oci - -import ( - "crypto/rand" - "crypto/rsa" - - "github.com/oracle/oci-go-sdk/v36/common" -) - -// Mock struct to be used during testing to obtain Instance Principals. -type instancePrincipalConfigurationProviderMock struct { -} - -func (p instancePrincipalConfigurationProviderMock) PrivateRSAKey() (*rsa.PrivateKey, error) { - return rsa.GenerateKey(rand.Reader, 1024) -} - -func (p instancePrincipalConfigurationProviderMock) KeyID() (string, error) { - return "some_random_key_id", nil -} - -func (p instancePrincipalConfigurationProviderMock) TenancyOCID() (string, error) { - return "some_random_tenancy", nil -} - -func (p instancePrincipalConfigurationProviderMock) UserOCID() (string, error) { - return "", nil -} - -func (p instancePrincipalConfigurationProviderMock) KeyFingerprint() (string, error) { - return "", nil -} - -func (p instancePrincipalConfigurationProviderMock) Region() (string, error) { - return "some_random_region", nil -} - -func (p instancePrincipalConfigurationProviderMock) AuthType() (common.AuthConfig, error) { - return common.AuthConfig{ - AuthType: common.InstancePrincipal, - IsFromConfigFile: false, - OboToken: nil}, nil -} diff --git a/builder/oracle/oci/step_create_instance.go b/builder/oracle/oci/step_create_instance.go deleted file mode 100644 index 0f9aedda0..000000000 --- a/builder/oracle/oci/step_create_instance.go +++ /dev/null @@ -1,76 +0,0 @@ -package oci - -import ( - "context" - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepCreateInstance struct{} - -func (s *stepCreateInstance) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - var ( - driver = state.Get("driver").(Driver) - ui = state.Get("ui").(packersdk.Ui) - config = state.Get("config").(*Config) - ) - - ui.Say("Creating instance...") - - instanceID, err := driver.CreateInstance(ctx, string(config.Comm.SSHPublicKey)) - if err != nil { - err = fmt.Errorf("Problem creating instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - state.Put("instance_id", instanceID) - - ui.Say(fmt.Sprintf("Created instance (%s).", instanceID)) - - ui.Say("Waiting for instance to enter 'RUNNING' state...") - - if err = driver.WaitForInstanceState(ctx, instanceID, []string{"STARTING", "PROVISIONING"}, "RUNNING"); err != nil { - err = fmt.Errorf("Error waiting for instance to start: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - ui.Say("Instance 'RUNNING'.") - - return multistep.ActionContinue -} - -func (s *stepCreateInstance) Cleanup(state multistep.StateBag) { - driver := state.Get("driver").(Driver) - ui := state.Get("ui").(packersdk.Ui) - - idRaw, ok := state.GetOk("instance_id") - if !ok { - return - } - id := idRaw.(string) - - ui.Say(fmt.Sprintf("Terminating instance (%s)...", id)) - - if err := driver.TerminateInstance(context.TODO(), id); err != nil { - err = fmt.Errorf("Error terminating instance. Please terminate manually: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } - - err := driver.WaitForInstanceState(context.TODO(), id, []string{"TERMINATING"}, "TERMINATED") - if err != nil { - err = fmt.Errorf("Error terminating instance. Please terminate manually: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return - } - - ui.Say("Terminated instance.") -} diff --git a/builder/oracle/oci/step_create_instance_test.go b/builder/oracle/oci/step_create_instance_test.go deleted file mode 100644 index 746e53536..000000000 --- a/builder/oracle/oci/step_create_instance_test.go +++ /dev/null @@ -1,131 +0,0 @@ -package oci - -import ( - "context" - "errors" - "testing" - - "github.com/hashicorp/packer-plugin-sdk/multistep" -) - -func TestStepCreateInstance(t *testing.T) { - state := testState() - state.Put("publicKey", "key") - - step := new(stepCreateInstance) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - instanceIDRaw, ok := state.GetOk("instance_id") - if !ok { - t.Fatalf("should have machine") - } - - step.Cleanup(state) - - if driver.TerminateInstanceID != instanceIDRaw.(string) { - t.Fatalf( - "should've deleted instance (%s != %s)", - driver.TerminateInstanceID, instanceIDRaw.(string)) - } -} - -func TestStepCreateInstance_CreateInstanceErr(t *testing.T) { - state := testState() - state.Put("publicKey", "key") - - step := new(stepCreateInstance) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - driver.CreateInstanceErr = errors.New("error") - - if action := step.Run(context.Background(), state); action != multistep.ActionHalt { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } - - if _, ok := state.GetOk("instance_id"); ok { - t.Fatalf("should NOT have instance_id") - } - - step.Cleanup(state) - - if driver.TerminateInstanceID != "" { - t.Fatalf("Should not have tried to terminate an instance") - } -} - -func TestStepCreateInstance_WaitForInstanceStateErr(t *testing.T) { - state := testState() - state.Put("publicKey", "key") - - step := new(stepCreateInstance) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - driver.WaitForInstanceStateErr = errors.New("error") - - if action := step.Run(context.Background(), state); action != multistep.ActionHalt { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } -} - -func TestStepCreateInstance_TerminateInstanceErr(t *testing.T) { - state := testState() - state.Put("publicKey", "key") - - step := new(stepCreateInstance) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - _, ok := state.GetOk("instance_id") - if !ok { - t.Fatalf("should have machine") - } - - driver.TerminateInstanceErr = errors.New("error") - step.Cleanup(state) - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } -} - -func TestStepCreateInstanceCleanup_WaitForInstanceStateErr(t *testing.T) { - state := testState() - state.Put("publicKey", "key") - - step := new(stepCreateInstance) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - driver.WaitForInstanceStateErr = errors.New("error") - step.Cleanup(state) - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } -} diff --git a/builder/oracle/oci/step_get_default_credentials.go b/builder/oracle/oci/step_get_default_credentials.go deleted file mode 100644 index 3499221c1..000000000 --- a/builder/oracle/oci/step_get_default_credentials.go +++ /dev/null @@ -1,61 +0,0 @@ -package oci - -import ( - "context" - "fmt" - "log" - - "github.com/hashicorp/packer-plugin-sdk/communicator" - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepGetDefaultCredentials struct { - Debug bool - Comm *communicator.Config - BuildName string -} - -func (s *stepGetDefaultCredentials) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - var ( - driver = state.Get("driver").(*driverOCI) - ui = state.Get("ui").(packersdk.Ui) - id = state.Get("instance_id").(string) - ) - - // Skip if we're not using winrm - if s.Comm.Type != "winrm" { - log.Printf("[INFO] Not using winrm communicator, skipping get password...") - return multistep.ActionContinue - } - - // If we already have a password, skip it - if s.Comm.WinRMPassword != "" { - ui.Say("Skipping waiting for password since WinRM password set...") - return multistep.ActionContinue - } - - username, password, err := driver.GetInstanceInitialCredentials(ctx, id) - if err != nil { - err = fmt.Errorf("Error getting instance's credentials: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - s.Comm.WinRMPassword = password - s.Comm.WinRMUser = username - - if s.Debug { - ui.Message(fmt.Sprintf( - "[DEBUG] (OCI default credentials): Credentials (since debug is enabled): %s", password)) - } - - // store so that we can access this later during provisioning - state.Put("winrm_password", s.Comm.WinRMPassword) - packersdk.LogSecretFilter.Set(s.Comm.WinRMPassword) - return multistep.ActionContinue -} - -func (s *stepGetDefaultCredentials) Cleanup(state multistep.StateBag) { - // no cleanup -} diff --git a/builder/oracle/oci/step_image.go b/builder/oracle/oci/step_image.go deleted file mode 100644 index fb4814b59..000000000 --- a/builder/oracle/oci/step_image.go +++ /dev/null @@ -1,49 +0,0 @@ -package oci - -import ( - "context" - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepImage struct{} - -func (s *stepImage) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - var ( - driver = state.Get("driver").(Driver) - ui = state.Get("ui").(packersdk.Ui) - instanceID = state.Get("instance_id").(string) - ) - - ui.Say("Creating image from instance...") - - image, err := driver.CreateImage(ctx, instanceID) - if err != nil { - err = fmt.Errorf("Error creating image from instance: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - err = driver.WaitForImageCreation(ctx, *image.Id) - if err != nil { - err = fmt.Errorf("Error waiting for image creation to finish: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - // TODO(apryde): This is stale as .LifecycleState has changed to - // AVAILABLE at this point. Does it matter? - state.Put("image", image) - - ui.Say("Image created.") - - return multistep.ActionContinue -} - -func (s *stepImage) Cleanup(state multistep.StateBag) { - // Nothing to do -} diff --git a/builder/oracle/oci/step_image_test.go b/builder/oracle/oci/step_image_test.go deleted file mode 100644 index 52bb321b0..000000000 --- a/builder/oracle/oci/step_image_test.go +++ /dev/null @@ -1,71 +0,0 @@ -package oci - -import ( - "context" - "errors" - "testing" - - "github.com/hashicorp/packer-plugin-sdk/multistep" -) - -func TestStepImage(t *testing.T) { - state := testState() - state.Put("instance_id", "ocid1...") - - step := new(stepImage) - defer step.Cleanup(state) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("image"); !ok { - t.Fatalf("should have image") - } -} - -func TestStepImage_CreateImageErr(t *testing.T) { - state := testState() - state.Put("instance_id", "ocid1...") - - step := new(stepImage) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - driver.CreateImageErr = errors.New("error") - - if action := step.Run(context.Background(), state); action != multistep.ActionHalt { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } - - if _, ok := state.GetOk("image"); ok { - t.Fatalf("should NOT have image") - } -} - -func TestStepImage_WaitForImageCreationErr(t *testing.T) { - state := testState() - state.Put("instance_id", "ocid1...") - - step := new(stepImage) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - driver.WaitForImageCreationErr = errors.New("error") - - if action := step.Run(context.Background(), state); action != multistep.ActionHalt { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } - - if _, ok := state.GetOk("image"); ok { - t.Fatalf("should not have image") - } -} diff --git a/builder/oracle/oci/step_instance_info.go b/builder/oracle/oci/step_instance_info.go deleted file mode 100644 index 78b3a00fe..000000000 --- a/builder/oracle/oci/step_instance_info.go +++ /dev/null @@ -1,37 +0,0 @@ -package oci - -import ( - "context" - "fmt" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -type stepInstanceInfo struct{} - -func (s *stepInstanceInfo) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction { - var ( - driver = state.Get("driver").(Driver) - ui = state.Get("ui").(packersdk.Ui) - id = state.Get("instance_id").(string) - ) - - ip, err := driver.GetInstanceIP(ctx, id) - if err != nil { - err = fmt.Errorf("Error getting instance's IP: %s", err) - ui.Error(err.Error()) - state.Put("error", err) - return multistep.ActionHalt - } - - state.Put("instance_ip", ip) - - ui.Say(fmt.Sprintf("Instance has IP: %s.", ip)) - - return multistep.ActionContinue -} - -func (s *stepInstanceInfo) Cleanup(state multistep.StateBag) { - // no cleanup -} diff --git a/builder/oracle/oci/step_instance_info_test.go b/builder/oracle/oci/step_instance_info_test.go deleted file mode 100644 index 5625dc78c..000000000 --- a/builder/oracle/oci/step_instance_info_test.go +++ /dev/null @@ -1,85 +0,0 @@ -package oci - -import ( - "bytes" - "context" - "errors" - "testing" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -func TestInstanceInfo(t *testing.T) { - state := testState() - state.Put("instance_id", "ocid1...") - - step := new(stepInstanceInfo) - defer step.Cleanup(state) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - instanceIPRaw, ok := state.GetOk("instance_ip") - if !ok { - t.Fatalf("should have instance_ip") - } - - if instanceIPRaw.(string) != "ip" { - t.Fatalf("should've got ip ('%s' != 'ip')", instanceIPRaw.(string)) - } -} - -func TestInstanceInfoPrivateIP(t *testing.T) { - baseTestConfig := baseTestConfig() - baseTestConfig.UsePrivateIP = true - state := new(multistep.BasicStateBag) - state.Put("config", baseTestConfig) - state.Put("driver", &driverMock{cfg: baseTestConfig}) - state.Put("hook", &packersdk.MockHook{}) - state.Put("ui", &packersdk.BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - }) - state.Put("instance_id", "ocid1...") - - step := new(stepInstanceInfo) - defer step.Cleanup(state) - - if action := step.Run(context.Background(), state); action != multistep.ActionContinue { - t.Fatalf("bad action: %#v", action) - } - - instanceIPRaw, ok := state.GetOk("instance_ip") - if !ok { - t.Fatalf("should have instance_ip") - } - - if instanceIPRaw.(string) != "private_ip" { - t.Fatalf("should've got ip ('%s' != 'private_ip')", instanceIPRaw.(string)) - } -} - -func TestInstanceInfo_GetInstanceIPErr(t *testing.T) { - state := testState() - state.Put("instance_id", "ocid1...") - - step := new(stepInstanceInfo) - defer step.Cleanup(state) - - driver := state.Get("driver").(*driverMock) - driver.GetInstanceIPErr = errors.New("error") - - if action := step.Run(context.Background(), state); action != multistep.ActionHalt { - t.Fatalf("bad action: %#v", action) - } - - if _, ok := state.GetOk("error"); !ok { - t.Fatalf("should have error") - } - - if _, ok := state.GetOk("instance_ip"); ok { - t.Fatalf("should NOT have instance_ip") - } -} diff --git a/builder/oracle/oci/step_test.go b/builder/oracle/oci/step_test.go deleted file mode 100644 index f4c6a0569..000000000 --- a/builder/oracle/oci/step_test.go +++ /dev/null @@ -1,64 +0,0 @@ -package oci - -import ( - "bytes" - "os" - - "github.com/hashicorp/packer-plugin-sdk/multistep" - packersdk "github.com/hashicorp/packer-plugin-sdk/packer" -) - -// TODO(apryde): It would be good not to have to write a key file to disk to -// load the config. -func baseTestConfig() *Config { - _, keyFile, err := baseTestConfigWithTmpKeyFile() - if err != nil { - panic(err) - } - - var c Config - err = c.Prepare(map[string]interface{}{ - "availability_domain": "aaaa:US-ASHBURN-AD-1", - - // Image - "base_image_ocid": "ocid1.image.oc1.iad.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "shape": "VM.Standard1.1", - "image_name": "HelloWorld", - "region": "us-ashburn-1", - - // Networking - "subnet_ocid": "ocid1.subnet.oc1.iad.aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - - // AccessConfig - "user_ocid": "ocid1.user.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "tenancy_ocid": "ocid1.tenancy.oc1..aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "fingerprint": "70:04:5z:b3:19:ab:90:75:a4:1f:50:d4:c7:c3:33:20", - "key_file": keyFile.Name(), - - // Comm - "ssh_username": "opc", - "use_private_ip": false, - }) - - // Once we have a config object they key file isn't re-read so we can - // remove it now. - os.Remove(keyFile.Name()) - - if err != nil { - panic(err) - } - return &c -} - -func testState() multistep.StateBag { - baseTestConfig := baseTestConfig() - state := new(multistep.BasicStateBag) - state.Put("config", baseTestConfig) - state.Put("driver", &driverMock{cfg: baseTestConfig}) - state.Put("hook", &packersdk.MockHook{}) - state.Put("ui", &packersdk.BasicUi{ - Reader: new(bytes.Buffer), - Writer: new(bytes.Buffer), - }) - return state -} diff --git a/builder/oracle/version/version.go b/builder/oracle/version/version.go deleted file mode 100644 index 27d0da1c4..000000000 --- a/builder/oracle/version/version.go +++ /dev/null @@ -1,13 +0,0 @@ -package version - -import ( - "github.com/hashicorp/packer-plugin-sdk/version" - packerVersion "github.com/hashicorp/packer/version" -) - -var OraclePluginVersion *version.PluginVersion - -func init() { - OraclePluginVersion = version.InitializePluginVersion( - packerVersion.Version, packerVersion.VersionPrerelease) -} diff --git a/command/plugin.go b/command/plugin.go index 96fbe34d3..a300b335c 100644 --- a/command/plugin.go +++ b/command/plugin.go @@ -22,8 +22,6 @@ import ( lxdbuilder "github.com/hashicorp/packer/builder/lxd" nullbuilder "github.com/hashicorp/packer/builder/null" oneandonebuilder "github.com/hashicorp/packer/builder/oneandone" - oracleclassicbuilder "github.com/hashicorp/packer/builder/oracle/classic" - oracleocibuilder "github.com/hashicorp/packer/builder/oracle/oci" profitbricksbuilder "github.com/hashicorp/packer/builder/profitbricks" tencentcloudcvmbuilder "github.com/hashicorp/packer/builder/tencentcloud/cvm" tritonbuilder "github.com/hashicorp/packer/builder/triton" @@ -62,8 +60,6 @@ var Builders = map[string]packersdk.Builder{ "lxd": new(lxdbuilder.Builder), "null": new(nullbuilder.Builder), "oneandone": new(oneandonebuilder.Builder), - "oracle-classic": new(oracleclassicbuilder.Builder), - "oracle-oci": new(oracleocibuilder.Builder), "profitbricks": new(profitbricksbuilder.Builder), "tencentcloud-cvm": new(tencentcloudcvmbuilder.Builder), "triton": new(tritonbuilder.Builder), diff --git a/command/vendored_plugins.go b/command/vendored_plugins.go index 7e7b66ab6..099f35e5a 100644 --- a/command/vendored_plugins.go +++ b/command/vendored_plugins.go @@ -40,6 +40,8 @@ import ( linodebuilder "github.com/hashicorp/packer-plugin-linode/builder/linode" ncloudbuilder "github.com/hashicorp/packer-plugin-ncloud/builder/ncloud" openstackbuilder "github.com/hashicorp/packer-plugin-openstack/builder/openstack" + oracleclassicbuilder "github.com/hashicorp/packer-plugin-oracle/builder/classic" + oracleocibuilder "github.com/hashicorp/packer-plugin-oracle/builder/oci" oscbsubuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsu" oscbsusurrogatebuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsusurrogate" oscbsuvolumebuilder "github.com/hashicorp/packer-plugin-outscale/builder/osc/bsuvolume" @@ -95,6 +97,8 @@ var VendoredBuilders = map[string]packersdk.Builder{ "linode": new(linodebuilder.Builder), "ncloud": new(ncloudbuilder.Builder), "openstack": new(openstackbuilder.Builder), + "oracle-classic": new(oracleclassicbuilder.Builder), + "oracle-oci": new(oracleocibuilder.Builder), "proxmox": new(proxmoxiso.Builder), "proxmox-iso": new(proxmoxiso.Builder), "proxmox-clone": new(proxmoxclone.Builder), diff --git a/go.mod b/go.mod index 3a9fd0af4..e8e6131f6 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/digitalocean/godo v1.60.0 github.com/dsnet/compress v0.0.1 github.com/exoscale/packer-plugin-exoscale v0.1.1 - github.com/go-ini/ini v1.25.4 + github.com/go-ini/ini v1.62.0 github.com/go-resty/resty/v2 v2.3.0 github.com/gobwas/glob v0.2.3 github.com/google/go-cmp v0.5.5 @@ -33,7 +33,7 @@ require ( github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840 github.com/hashicorp/go-getter/v2 v2.0.0-20200604122502-a6995fa1edad github.com/hashicorp/go-multierror v1.1.1 - github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79 + github.com/hashicorp/go-oracle-terraform v0.17.0 github.com/hashicorp/go-uuid v1.0.2 github.com/hashicorp/go-version v1.3.0 github.com/hashicorp/hcl/v2 v2.10.0 @@ -52,6 +52,7 @@ require ( github.com/hashicorp/packer-plugin-linode v0.0.2 github.com/hashicorp/packer-plugin-ncloud v0.0.2 github.com/hashicorp/packer-plugin-openstack v0.0.2 + github.com/hashicorp/packer-plugin-oracle v0.0.3 // indirect github.com/hashicorp/packer-plugin-outscale v0.0.1 github.com/hashicorp/packer-plugin-parallels v0.0.1 github.com/hashicorp/packer-plugin-proxmox v0.0.2 diff --git a/go.sum b/go.sum index 4bf9f789d..ecaa3897b 100644 --- a/go.sum +++ b/go.sum @@ -262,6 +262,7 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-ini/ini v1.25.4 h1:Mujh4R/dH6YL8bxuISne3xX2+qcQ9p0IxKAP6ExWoUo= github.com/go-ini/ini v1.25.4/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= +github.com/go-ini/ini v1.62.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= github.com/go-ldap/ldap v3.0.2+incompatible/go.mod h1:qfd9rJvER9Q0/D/Sqn1DfHRoBp40uXYvFoEVrNEPqRc= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= @@ -439,6 +440,8 @@ github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+l github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79 h1:RKu7yAXZTaQsxj1K9GDsh+QVw0+Wu1SWHxtbFN0n+hE= github.com/hashicorp/go-oracle-terraform v0.0.0-20181016190316-007121241b79/go.mod h1:09jT3Y/OIsjTjQ2+3bkVNPDKqWcGIYYvjB2BEKVUdvc= +github.com/hashicorp/go-oracle-terraform v0.17.0 h1:gFiaeKf9MXLobhv7uqzPuDFULL6ymJpw1NJCXwSOgJ4= +github.com/hashicorp/go-oracle-terraform v0.17.0/go.mod h1:09jT3Y/OIsjTjQ2+3bkVNPDKqWcGIYYvjB2BEKVUdvc= github.com/hashicorp/go-plugin v1.0.1/go.mod h1:++UyYGoz3o5w9ZzAdZxtQKrWWP+iqPBn3cQptSMzBuY= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= github.com/hashicorp/go-retryablehttp v0.5.4 h1:1BZvpawXoJCWX6pNtow9+rpEj+3itIlutiqnntI6jOE= @@ -520,6 +523,8 @@ github.com/hashicorp/packer-plugin-ncloud v0.0.2 h1:MGvGkOVfzeosqOSs5dteghLwv9VR github.com/hashicorp/packer-plugin-ncloud v0.0.2/go.mod h1:Hud2R1pkky96TQy3TPTTrr9Kej4b/4dqC/v+uEE0VDY= github.com/hashicorp/packer-plugin-openstack v0.0.2 h1:wGNE8es3Bn9auuIoX+gqT9chXzYY9GlM55eSpM4uwtU= github.com/hashicorp/packer-plugin-openstack v0.0.2/go.mod h1:rHAdd4+JmI+1z98Zx+lVOehgzLZT1Rjo2YgtS0NNvwM= +github.com/hashicorp/packer-plugin-oracle v0.0.3 h1:yQEAfCD+TQqEWjrHLJTfdJis7axhwknzCKB07gnTZDA= +github.com/hashicorp/packer-plugin-oracle v0.0.3/go.mod h1:EfUBTOzh5WtQu6PbcBcylKXiZSyyNw5XbzJ2/CUxay8= github.com/hashicorp/packer-plugin-outscale v0.0.1 h1:BrL8hKypNYrvP3NR+d+xX03SZKB08yTgXPRnH9piUI8= github.com/hashicorp/packer-plugin-outscale v0.0.1/go.mod h1:6jEWfJO7TgAbaL3e+St1bN5PoIC/MmDIsYqNUzAHF1w= github.com/hashicorp/packer-plugin-parallels v0.0.1 h1:fcaaiGWdU1+X4IGadXdUhJ2si1ZA3apXS9tMNJXln2A= diff --git a/website/content/docs/builders/oracle/classic.mdx b/website/content/docs/builders/oracle/classic.mdx deleted file mode 100644 index 0fe26eddd..000000000 --- a/website/content/docs/builders/oracle/classic.mdx +++ /dev/null @@ -1,320 +0,0 @@ ---- -description: | - The oracle-classic builder is able to create new custom images for use with - Oracle Cloud Infrastructure Classic Compute. -page_title: Oracle Cloud Infrastructure Classic - Builders ---- - -# Oracle Cloud Infrastructure Classic Compute Builder - -Type: `oracle-classic` -Artifact BuilderId: `packer.oracle.classic` - -The `oracle-classic` Packer builder is able to create custom images for use -with [Oracle Cloud Infrastructure Classic -Compute](https://cloud.oracle.com/compute-classic). The builder takes a base -image, runs any provisioning necessary on the base image after launching it, -and finally snapshots it creating a reusable custom image. - -It is recommended that you familiarise yourself with the [Key Concepts and -Terminology](https://docs.oracle.com/en/cloud/iaas-classic/compute-iaas-cloud/stcsg/getting-started-oracle-compute-cloud-service.html#GUID-6CB9D494-4F3C-4B78-BD03-127983FEC357) -prior to using this builder if you have not done so already. - -The builder _does not_ manage images. Once it creates an image, it is up to you -to use it or delete it. - -## Authorization - -This builder authenticates API calls to Oracle Cloud Infrastructure Classic -Compute using basic authentication (user name and password). To read more, see -the [authentication -documentation](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsa/Authentication.html) - -## Configuration Reference - -There are many configuration options available for the `oracle-classic` -builder. This builder currently only works with the SSH communicator. - -### Required - -- `api_endpoint` (string) - This is your custom API endpoint for sending - requests. Instructions for determining your API endpoint can be found - [here](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsa/SendRequests.html) - -- `dest_image_list` (string) - Where to save the machine image to once you've - provisioned it. If the provided image list does not exist, Packer will - create it. - -- `identity_domain` (string) - This is your customer-specific identity domain - as generated by Oracle. If you don't know what your identity domain is, ask - your account administrator. For a little more information, see the Oracle - [documentation](https://docs.oracle.com/en/cloud/get-started/subscriptions-cloud/ocuid/identity-domain-overview.html#GUID-7969F881-5F4D-443E-B86C-9044C8085B8A). - -- `source_image_list` (string) - This is what image you want to use as your - base image. See the - [documentation](https://docs.oracle.com/en/cloud/iaas-classic/compute-iaas-cloud/stcsg/managing-machine-images.html#GUID-652E6797-A5B8-40A7-860F-F27FF3E42471) - for more details. You may use either a public image list, or a private - image list. To see what public image lists are available, you can use the - CLI, as described - [here](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stopc/image-lists-stclr-and-nmcli.html#GUID-DB7E75FE-F752-4FF7-AB70-3C8DCDFCA0FA) - -- `source_image_list_entry` (string) - The entry identifying the machine - image to use in the image list. Defaults to the latest available entry. - -- `password` (string) - Your account password. - -- `shape` (string) - The template that determines the number of CPUs, amount - of memory, and other resources allocated to a newly created instance. For - more information about shapes, see the documentation - [here](https://docs.oracle.com/en/cloud/iaas-classic/compute-iaas-cloud/stcsg/creating-instances.html#GUID-1DD0FA71-AC7B-461C-B8C1-14892725AA69). - -- `username` (string) - Your account username. - -### Optional - -- `attributes` (string) - (string) - Attributes to apply when launching the - instance. Note that you need to be careful about escaping characters due to - the templates being JSON. It is often more convenient to use - `attributes_file`, instead. You may only define either `attributes` or - `attributes_file`, not both. - -- `attributes_file` (string) - Path to a json file that will be used for the - attributes when launching the instance. You may only define either - `attributes` or `attributes_file`, not both. - -- `image_description` (string) - a description for your destination image - list. If you don't provide one, Packer will provide a generic description. - -- `ssh_username` (string) - The username that Packer will use to SSH into the - instance; required if using SSH. The default oracle user with sudo - privileges is `opc`, so you may set `ssh_username` to `opc` if you have not - yet configured users on your machine. If you have already configured users - on your machine, you may prompt Packer to use one of those instead. For - more detail, see the - [documentation](https://docs.oracle.com/en/cloud/iaas/compute-iaas-cloud/stcsg/accessing-oracle-linux-instance-using-ssh.html). - -- `image_name` (string) - The name to assign to the resulting custom image. - -- `persistent_volume_size` (int) - Size in gigabytes of the persistent boot - storage volume to build the image on. Use this if you want a bigger volume - than what instance storage provides. Note that using this option puts the - builder into a "persistent volume" mode, which is substantially different - than the default snapshot mode. Please see the configuration section below - for additional configuration options. - -- `snapshot_timeout` (string) - How long to wait for a snapshot to be - created. Expects a positive golang Time.Duration string, which is a - sequence of decimal numbers and a unit suffix; valid suffixes are `ns` - (nanoseconds), `us` (microseconds), `ms` (milliseconds), `s` (seconds), `m` - (minutes), and `h` (hours). Examples of valid inputs: `100ms`, `250ms`, - `1s`, `2.5s`, `2.5m`, `1m30s`. Example: `"snapshot_timeout": "15m"`. - Default: `20m`. - -### Persistent Volume Build - -You will use this type of build if you've set the `persistent_volume_size` -option. If you need a bigger disk than what you normally get with instance -storage, you'll want to set this. - -In the _persistent volume_ mode, things are built a little differently. -Normally, we launch an instance, then provision it and take a snapshot, which -becomes your machine image. This relies on the disk of the created instance -being large enough to perform your entire provisioning process. If that disk -size isn't sufficient, we can build with a persistent volume of arbitrary size. - -First, we create a persistent volume of the requested size. This volume is -bootable and initialized with your image list. We start an instance with this -volume as the boot volume. After this instance launches, we provision and -terminate it, leaving the persistent volume around. - -Next, we create a second instance, the "builder", this time booting from -instance storage. We also attach a new persistent volume, making it twice the -size of the original. We connect to this instance and copy the contents of the -first volume into a tarball file on the second volume. We then upload this file -to Object Storage Classic, and create a new machine image with it. - -If this is set, a few more options become available. - -- `builder_communicator` (communicator) - This represents an - [`ssh communicator`](/docs/communicators/ssh), - and can be configured as such. If you use a different builder image, you - may need to change the `ssh_username`, for example. That might look like - this: - - ```json - { - "builders": [ - { - "builder_communicator": { - "ssh_username": "soandso" - }, - "type": "oracle-classic" - } - ] - } - ``` - - See below for more details on configuring this communicator. - -- `builder_image_list` (string) - This is the image to use for the builder - instance. This _must_ be a linux image, and Oracle Linux is recommended. - Default: `/oracle/public/OL_7.2_UEKR4_x86_64`. - -- `builder_image_list_entry` (string) - The entry identifying the machine - image to use in the image list. If `builder_image_list` is unset, this - defaults to `5`, which is a working image as of this time. Otherwise, it - defaults to the latest entry. Set this to `0` to force it to use the latest - entry when using the default `builder_image_list`. - -- `builder_shape` (string) - The template that determines the number of CPUs, - amount of memory, and other resources allocated to the builder instance. - Default: `oc3`. - -- `builder_upload_image_command` (string) - The command to run to upload the - image to Object Storage Classic. This is for advanced users only, and you - should consult the default in code to decide on the changes to make. For - most users the default should suffice. If you choose to write your own, - this command is a template engine and can make use of the following - variables: `{{ .Username }}`, `{{ .Password }}`, `{{ .AccountID }}`, - `{{ .ImageFile }}`, and `{{ .SegmentPath }}`. - -### Communicator Configuration - -The `builder_communicator` has the following options: - -#### Optional: - -@include 'packer-plugin-sdk/communicator/Config-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSH-not-required.mdx' - -@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx' - -## Basic Example - -Here is a basic example. Note that account specific configuration has been -obfuscated; you will need to add a working `username`, `password`, -`identity_domain`, and `api_endpoint` in order for the example to work. - -```json -{ - "builders": [ - { - "type": "oracle-classic", - "username": "myuser@myaccount.com", - "password": "supersecretpasswordhere", - "identity_domain": "#######", - "api_endpoint": "https://api-###.compute.###.oraclecloud.com/", - "source_image_list": "/oracle/public/OL_7.2_UEKR4_x86_64", - "shape": "oc3", - "image_name": "Packer_Builder_Test_{{timestamp}}", - "attributes": "{\"userdata\": {\"pre-bootstrap\": {\"script\": [\"...\"]}}}", - "dest_image_list": "Packer_Builder_Test_List" - } - ], - "provisioners": [ - { - "type": "shell", - "inline": ["echo hello"] - } - ] -} -``` - -## 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\")" - } - ] -} -``` - -## Persistent Volume Example - -Here is an example using a persistent volume. Note the `persistent_volume_size` -setting. - -```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": "/oracle/public/OL_7.2_UEKR4_x86_64", - "persistent_volume_size": 15, - "image_name": "Packer_Builder_Test_{{timestamp}}", - "dest_image_list": "Packer_Builder_Test_List", - "ssh_username": "opc", - "shape": "oc3" - } - ], - "provisioners": [ - { - "type": "shell", - "inline": ["echo hello"] - } - ] -} -``` diff --git a/website/content/docs/builders/oracle/index.mdx b/website/content/docs/builders/oracle/index.mdx deleted file mode 100644 index b598fb462..000000000 --- a/website/content/docs/builders/oracle/index.mdx +++ /dev/null @@ -1,19 +0,0 @@ ---- -description: Packer is able to create custom images using Oracle Cloud Infrastructure. -page_title: Oracle - Builders ---- - -# Oracle Builder - -Packer is able to create custom images on both Oracle Cloud Infrastructure and -Oracle Cloud Infrastructure Classic Compute. Packer comes with builders -designed to support both platforms. Please choose the one that's right for you: - -- [oracle-classic](/docs/builders/oracle-classic) - Create custom images - in Oracle Cloud Infrastructure Classic Compute by launching a source - instance and creating an image list from a snapshot of it after - provisioning. - -- [oracle-oci](/docs/builders/oracle-oci) - Create custom images in - Oracle Cloud Infrastructure (OCI) by launching a base instance and creating - an image from it after provisioning. diff --git a/website/content/docs/builders/oracle/oci.mdx b/website/content/docs/builders/oracle/oci.mdx deleted file mode 100644 index acca95055..000000000 --- a/website/content/docs/builders/oracle/oci.mdx +++ /dev/null @@ -1,362 +0,0 @@ ---- -description: | - The oracle-oci builder is able to create new custom images for use with Oracle - Cloud Infrastructure (OCI). -page_title: Oracle OCI - Builders ---- - -# Oracle Cloud Infrastructure (OCI) Builder - -Type: `oracle-oci` -Artifact BuilderId: `packer.oracle.oci` - -The `oracle-oci` Packer builder is able to create new custom images for use -with [Oracle Cloud Infrastructure](https://cloud.oracle.com) (OCI). The builder -takes a base image, runs any provisioning necessary on the base image after -launching it, and finally snapshots it creating a reusable custom image. - -It is recommended that you familiarise yourself with the [Key Concepts and -Terminology](https://docs.us-phoenix-1.oraclecloud.com/Content/GSG/Concepts/concepts.htm) -prior to using this builder if you have not done so already. - -The builder _does not_ manage images. Once it creates an image, it is up to you -to use it or delete it. - -## Authorization - -The Oracle OCI API requires that requests be signed with the RSA public key -associated with your -[IAM](https://docs.us-phoenix-1.oraclecloud.com/Content/Identity/Concepts/overview.htm) -user account. For a comprehensive example of how to configure the required -authentication see the documentation on [Required Keys and -OCIDs](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/apisigningkey.htm) -([Oracle Cloud -IDs](https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/identifiers.htm)). -Alternatively you can use [Instance -Principals](https://docs.cloud.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm) -in which case you don't need the above user authorization. - -## Configuration Reference - -There are many configuration options available for the `oracle-oci` builder. In -addition to the options listed here, a -[communicator](/docs/templates/legacy_json_templates/communicator) can be configured for this -builder. - -In addition to the options defined there, a private key file -can also be supplied to override the typical auto-generated key: - -@include 'packer-plugin-sdk/communicator/SSH-Private-Key-File-not-required.mdx' - -### Required - -- `availability_domain` (string) - The name of the [Availability - Domain](https://docs.us-phoenix-1.oraclecloud.com/Content/General/Concepts/regions.htm) - within which a new instance is launched and provisioned. The names of the - Availability Domains have a prefix that is specific to your - [tenancy](https://docs.us-phoenix-1.oraclecloud.com/Content/GSG/Concepts/concepts.htm#two). - - To get a list of the Availability Domains, use the - [ListAvailabilityDomains](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/identity/latest/AvailabilityDomain/ListAvailabilityDomains) - operation, which is available in the IAM Service API. - -- `base_image_ocid` (string) - The OCID of the [base - image](https://docs.us-phoenix-1.oraclecloud.com/Content/Compute/References/images.htm) - to use. This is the unique identifier of the image that will be used to - launch a new instance and provision it. - - To get a list of the accepted image OCIDs, use the - [ListImages](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/iaas/latest/Image/ListImages) - operation available in the Core Services API. - -- `base_image_filter` (map of strings) - As an alternative to providing `base_image_ocid`, - the user can supply search criteria, and Packer will use the the most recent image that meets - all search criteria. If no image meets all search criteria, Packer returns an error. The - following fields, if specified, must match exactly: - - - `compartment_id` - The OCID of the compartment to find the image. If not specified, will use `compartment_ocid` - used for the instance. - - `display_name` - The full name of the image, e.g., `Oracle-Linux-7.8-2020.05.26-0` - - `operating_system` - The operating system used on the image, e.g., `Oracle Linux` - - `operating_system_version` - The version of the operating system on the image, e.g., `7.8` - - `shape` - A shape that the image supports. If not specified, will use `shape` used for the instance - - Additionally, the following field takes a regular expression: - - - `display_name_search` - a regular expression for the display name, e.g., `^Oracle-Linux`. This - is ignored if `display_name` is also specified under `base_image_filter`. If no images match - the expression, Packer returns an error. If multiple images match, the most recent is used. - - `base_image_filter` is ignored if `base_image_ocid` is also specified. - -- `compartment_ocid` (string) - The OCID of the - [compartment](https://docs.us-phoenix-1.oraclecloud.com/Content/GSG/Tasks/choosingcompartments.htm) that the instance will run in. - -- `shape` (string) - The template that determines the number of CPUs, amount - of memory, and other resources allocated to a newly created instance. - - To get a list of the available shapes, use the - [ListShapes](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/iaas/20160918/Shape/ListShapes) - operation available in the Core Services API. - - When using flexible shapes, ocpus must be set. - -- `subnet_ocid` (string) - The name of the subnet within which a new instance - is launched and provisioned. - - To get a list of your subnets, use the - [ListSubnets](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/iaas/latest/Subnet/ListSubnets) - operation available in the Core Services API. - - Note: the subnet must be configured to allow access via your chosen - [communicator](/docs/communicators) (communicator defaults to - [SSH tcp/22](/docs/communicators/ssh#ssh_port)). - -### Optional - -- `use_instance_principals` (boolean) - Whether to use [Instance - Principals](https://docs.cloud.oracle.com/en-us/iaas/Content/Identity/Tasks/callingservicesfrominstances.htm) - instead of User Principals. If this key is set to true, setting any one of the `access_cfg_file`, - `access_cfg_file_account`, `region`, `tenancy_ocid`, `user_ocid`, `key_file`, `fingerprint`, - `pass_phrase` will result in configuration validation errors. - Defaults to `false`. - -- `access_cfg_file` (string) - The path to the [OCI config - file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm). - This cannot be used along with the `use_instance_principals` key. - Defaults to `$HOME/.oci/config`. - -- `access_cfg_file_account` (string) - The specific account in the [OCI config - file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) to use. - This cannot be used along with the `use_instance_principals` key. - Defaults to `DEFAULT`. - -- `region` (string) - An Oracle Cloud Infrastructure region. Overrides value provided by the - [OCI config file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) - if present. This cannot be used along with the `use_instance_principals` key. - -- `tenancy_ocid` (string) - The OCID of your tenancy. Overrides value provided by the [OCI config - file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) if present. - This cannot be used along with the `use_instance_principals` key. - -- `user_ocid` (string) - The OCID of the user calling the OCI API. Overrides value provided by the - [OCI config file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) - if present. This cannot be used along with the `use_instance_principals` key. - -- `key_file` (string) - Full path and filename of the OCI API signing key. Overrides value provided - by the [OCI config file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) - if present. This cannot be used along with the `use_instance_principals` key. - -- `fingerprint` (string) - Fingerprint for the OCI API signing key. Overrides value provided by the - [OCI config file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) if - present. This cannot be used along with the `use_instance_principals` key. - -- `pass_phrase` (string) - Pass phrase used to decrypt the OCI API signing key. Overrides value provided - by the [OCI config file](https://docs.us-phoenix-1.oraclecloud.com/Content/API/Concepts/sdkconfig.htm) - if present. This cannot be used along with the `use_instance_principals` key. - -- `image_name` (string) - The name to assign to the resulting custom image. - -- `image_compartment_ocid` (string) - The OCID of the target compartment for the resulting image. Defaults to `compartment_ocid`. - -- `instance_name` (string) - The name to assign to the instance used for the image creation process. - If not set a name of the form `instanceYYYYMMDDhhmmss` will be used. - -- `instance_tags` (map of strings) - Add one or more freeform tags to the instance used for the - image creation process. - -- `instance_defined_tags` (map of maps of strings) - Add one or more defined tags for a given namespace - to the instance used for the image creation process. - -- `create_vnic_details` (map of strings) - Specify details for the virtual network interface card (VNIC) - that is attached to the instance. Possible keys (all optional) are: `assign_public_ip` (bool), - `display_name` (string), `hostname_lable` (string), `nsg_ids` (list), `private_ip` (string), - `skip_source_dest_check` (bool), `subnet_id` (string), `tags` (map of string), and `defined_tags` - (map of maps of strings). See - [the Oracle docs](https://docs.cloud.oracle.com/en-us/iaas/Content/Network/Tasks/managingVNICs.htm) - for more information about VNICs. - -- `disk_size` (int64) - The size of the boot volume in GBs. Minimum value is 50 and maximum value is 16384 (16TB). - Sets the [BootVolumeSizeInGBs](https://godoc.org/github.com/oracle/oci-go-sdk/core#InstanceConfigurationInstanceSourceViaImageDetails) - when launching the instance. Defaults to `50`. - -- `image_launch_mode` (string) - Specifies the configuration mode for launching instances. - Valid values are `"NATIVE"`, `"EMULATED"`, `"PARAVIRTUALIZED"`, and `"CUSTOM"`. See the - [Oracle CLI docs](https://docs.cloud.oracle.com/en-us/iaas/tools/oci-cli/2.12.5/oci_cli_docs/cmdref/compute/image/create.html#cmdoption-launch-mode) - for more information about these modes. - -- `use_private_ip` (boolean) - Use private ip addresses to connect to the - instance via ssh. - -- `shape_config` (object) - The shape configuration for an instance. The shape configuration determines the resources - allocated to an instance. Options: - - `ocpus` (required when using flexible shapes or memory_in_gbs is set) (float32) - The total number of OCPUs available to the instance. - - `memory_in_gbs` (optional) (float32) - The total amount of memory, in gigabytes, available to the instance. - - - -- `metadata` (map of strings) - Metadata optionally contains custom metadata -key/value pairs provided in the configuration. While this can be used to -set metadata\["user_data"\] the explicit "user_data" and -"user_data_file" values will have precedence. An instance's metadata can -be obtained from at [http://169.254.169.254](http://169.254.169.254) on -the launched instance. - - -- `user_data` (string) - User data to be used by cloud-init. See [the Oracle - docs](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/iaas/20160918/LaunchInstanceDetails) - for more details. Generally speaking, it is easier to use the - `user_data_file`, but you can use this option to put either the plaintext - data or the base64 encoded data directly into your Packer config. Packer - will not automatically wait for a user script to finish before shutting - down the instance this must be handled in a provisioner. - -- `user_data_file` (string) - Path to a file to be used as user data by - cloud-init. See [the Oracle - docs](https://docs.us-phoenix-1.oraclecloud.com/api/#/en/iaas/20160918/LaunchInstanceDetails) - for more details. Example: `"user_data_file": "./boot_config/myscript.sh"` - -- `tags` (map of strings) - Add one or more freeform tags to the resulting - custom image. See [the Oracle - docs](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/taggingoverview.htm) - for more details. Example: - -```yaml -'tags': - 'tag1': 'value1' - 'tag2': 'value2' -``` - -- `defined_tags` (map of map of strings) - Add one or more defined tags for a given namespace to the resulting - custom image. See [the Oracle - docs](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/taggingoverview.htm) - for more details. Example: - -```yaml -'tags': - 'namespace': { 'tag1': 'value1', 'tag2': 'value2' } -``` - -## Basic Example - -Here is a basic example. Note that account specific configuration has been -substituted with the letter `a` and OCIDS have been shortened for brevity. - -```json -{ - "availability_domain": "aaaa:PHX-AD-1", - "base_image_ocid": "ocid1.image.oc1.phx.aaaaaaaa5yu6pw3riqtuhxzov7fdngi4tsteganmao54nq3pyxu3hxcuzmoa", - "compartment_ocid": "ocid1.compartment.oc1..aaa", - "image_name": "ExampleImage", - "shape": "VM.Standard1.1", - "ssh_username": "opc", - "subnet_ocid": "ocid1.subnet.oc1..aaa", - "type": "oracle-oci" -} -``` - -## Using Instance Principals - -Here is a basic example. Note that account specific configuration has been -substituted with the letter `a` and OCIDS have been shortened for brevity. - -```json -{ - "use_instance_principals": "true", - "availability_domain": "aaaa:PHX-AD-1", - "base_image_ocid": "ocid1.image.oc1.phx.aaaaaaaa5yu6pw3riqtuhxzov7fdngi4tsteganmao54nq3pyxu3hxcuzmoa", - "compartment_ocid": "ocid1.compartment.oc1..aaa", - "image_name": "ExampleImage", - "shape": "VM.Standard2.1", - "ssh_username": "opc", - "subnet_ocid": "ocid1.subnet.oc1..aaa", - "type": "oracle-oci" -} -``` - -```shell-session -[opc@packerhost ~]$ packer build packer.json -oracle-oci: output will be in this color. - -==> oracle-oci: Creating temporary ssh key for instance... -==> oracle-oci: Creating instance... -==> oracle-oci: Created instance (ocid1.instance.oc1.phx.aaa). -==> oracle-oci: Waiting for instance to enter 'RUNNING' state... -==> oracle-oci: Instance 'RUNNING'. -==> oracle-oci: Instance has IP: 10.10.10.10. -==> oracle-oci: Using ssh communicator to connect: 10.10.10.10 -==> oracle-oci: Waiting for SSH to become available... -==> oracle-oci: Connected to SSH! -==> oracle-oci: Creating image from instance... -==> oracle-oci: Image created. -==> oracle-oci: Terminating instance (ocid1.instance.oc1.phx.aaa)... -==> oracle-oci: Terminated instance. -Build 'oracle-oci' finished. - -==> Builds finished. The artifacts of successful builds are: ---> oracle-oci: An image was created: 'ExampleImage' (OCID: ocid1.image.oc1.phx.aaa) in region 'us-phoenix-1' -[opc@packerhost ~]$ -``` - -## Assigning Tags and Network Security Groups to the Instance - -Tags are useful for breaking down costs and usage. The keys `instance_tags` -and `instance_defined_tags` are assigned to the temporary instance, -whereas `tags` and `defined_tags` are assigned to the resulting image. - -Network Security Groups (NSGs) are used for granting networking permissions -to the instance. Depending on network (VCN and subnet) setup, this may be -required for Packer to successfully SSH into the instance. NSGs are a property -of the virtual network interface card (VNIC) attached to the instance, and -are listed in `nsg_ids` under `create_vnic_details`. - -```json -{ - "name": "base-image-{{isotime \"20060102030405\"}}", - "type": "oracle-oci", - "availability_domain": "aaaa:PHX-AD-1", - "base_image_ocid": "ocid1.image.oc1.iad.aaa", - "compartment_ocid": "ocid1.compartment.oc1..aaa", - "image_name": "my-image-{{isotime \"20060102030405\"}}", - "shape": "VM.Standard.E2.1", - "subnet_ocid": "ocid1.subnet.oc1.iad.aaa", - "use_private_ip": "true", - "instance_name": "packer-build-{{isotime \"20060102030405\"}}", - "instance_tags": { "testing": "yes" }, - "instance_defined_tags": { - "Operations": { - "Team": "CostCenter", - "Environment": "prod" - } - }, - "create_vnic_details": { - "assign_public_ip": "false", - "display_name": "testing-123", - "nsg_ids": ["ocid1.networksecuritygroup.oc1.iad.aaa"] - }, - "tags": { - "CreationDate": "{{isotime \"20060102 03:04:05 MST\"}}" - } -} -``` - -## Base Image Filter Example - -Note that `base_image_filter` gets passed as a string, then interpreted as a -regular expression. This means that all back-slashes must be doubled, e.g., -use `\\w+` to mean `\w+`, and `\\\\` to create the regular expression equivalent -of `\\` (which will search for a literal back-slash). - -```json -{ - "name": "base-image-{{isotime \"20060102030405\"}}", - "type": "oracle-oci", - "availability_domain": "aaaa:PHX-AD-1", - "base_image_filter": { - "operating_system": "Oracle Linux", - "operating_system_version": "7.8", - "display_name_search": "^Oracle-Linux-7\\.8-2020\\.\\d+" - } - ... -} -``` diff --git a/website/data/docs-nav-data.json b/website/data/docs-nav-data.json index 0bfa97aae..0810b70f3 100644 --- a/website/data/docs-nav-data.json +++ b/website/data/docs-nav-data.json @@ -720,23 +720,6 @@ "title": "1&1", "path": "builders/oneandone" }, - { - "title": "Oracle", - "routes": [ - { - "title": "Overview", - "path": "builders/oracle" - }, - { - "title": "Oracle Classic", - "path": "builders/oracle/classic" - }, - { - "title": "Oracle OCI", - "path": "builders/oracle/oci" - } - ] - }, { "title": "ProfitBricks", "path": "builders/profitbricks" diff --git a/website/data/docs-remote-plugins.json b/website/data/docs-remote-plugins.json index d694b8062..4ce525036 100644 --- a/website/data/docs-remote-plugins.json +++ b/website/data/docs-remote-plugins.json @@ -100,6 +100,12 @@ "pluginTier": "community", "version": "latest" }, + { + "title": "Oracle", + "path": "oracle", + "repo": "hashicorp/packer-plugin-oracle", + "version": "latest" + }, { "title": "Outscale", "path": "outscale",