provisioners: Allow provisioning over IPv6
This commit is contained in:
parent
d772389518
commit
bc5518f993
|
@ -0,0 +1,17 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
)
|
||||
|
||||
// IpFormat formats the IP correctly, so we don't provide IPv6 address in an IPv4 format during node communication. We return the ip parameter as is if it's an IPv4 address or a hostname.
|
||||
func IpFormat(ip string) string {
|
||||
ipObj := net.ParseIP(ip)
|
||||
// Return the ip/host as is if it's either a hostname or an IPv4 address.
|
||||
if ipObj == nil || ipObj.To4() != nil {
|
||||
return ip
|
||||
}
|
||||
|
||||
return fmt.Sprintf("[%s]", ip)
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package shared
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIpFormatting_Ipv4(t *testing.T) {
|
||||
formatted := IpFormat("127.0.0.1")
|
||||
if formatted != "127.0.0.1" {
|
||||
t.Fatal("expected", "127.0.0.1", "got", formatted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIpFormatting_Hostname(t *testing.T) {
|
||||
formatted := IpFormat("example.com")
|
||||
if formatted != "example.com" {
|
||||
t.Fatal("expected", "example.com", "got", formatted)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIpFormatting_Ipv6(t *testing.T) {
|
||||
formatted := IpFormat("::1")
|
||||
if formatted != "[::1]" {
|
||||
t.Fatal("expected", "[::1]", "got", formatted)
|
||||
}
|
||||
}
|
|
@ -8,6 +8,7 @@ import (
|
|||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/communicator/shared"
|
||||
"github.com/hashicorp/terraform/helper/pathorcontents"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
|
@ -84,6 +85,11 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
if connInfo.User == "" {
|
||||
connInfo.User = DefaultUser
|
||||
}
|
||||
|
||||
// Format the host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.Host = shared.IpFormat(connInfo.Host)
|
||||
|
||||
if connInfo.Port == 0 {
|
||||
connInfo.Port = DefaultPort
|
||||
}
|
||||
|
@ -107,6 +113,10 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
|
||||
// Default all bastion config attrs to their non-bastion counterparts
|
||||
if connInfo.BastionHost != "" {
|
||||
// Format the bastion host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.BastionHost = shared.IpFormat(connInfo.BastionHost)
|
||||
|
||||
if connInfo.BastionUser == "" {
|
||||
connInfo.BastionUser = connInfo.User
|
||||
}
|
||||
|
|
|
@ -66,6 +66,68 @@ func TestProvisioner_connInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoIpv6(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "ssh",
|
||||
"user": "root",
|
||||
"password": "supersecret",
|
||||
"private_key": "someprivatekeycontents",
|
||||
"host": "::1",
|
||||
"port": "22",
|
||||
"timeout": "30s",
|
||||
|
||||
"bastion_host": "::1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.Host != "[::1]" {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
|
||||
if conf.BastionHost != "[::1]" {
|
||||
t.Fatalf("bad %v", conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoHostname(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "ssh",
|
||||
"user": "root",
|
||||
"password": "supersecret",
|
||||
"private_key": "someprivatekeycontents",
|
||||
"host": "example.com",
|
||||
"port": "22",
|
||||
"timeout": "30s",
|
||||
|
||||
"bastion_host": "example.com",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.Host != "example.com" {
|
||||
t.Fatalf("bad: %v", conf)
|
||||
}
|
||||
|
||||
if conf.BastionHost != "example.com" {
|
||||
t.Fatalf("bad %v", conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoLegacy(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/terraform/communicator/shared"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
)
|
||||
|
@ -72,6 +73,11 @@ func parseConnectionInfo(s *terraform.InstanceState) (*connectionInfo, error) {
|
|||
if connInfo.User == "" {
|
||||
connInfo.User = DefaultUser
|
||||
}
|
||||
|
||||
// Format the host if needed.
|
||||
// Needed for IPv6 support.
|
||||
connInfo.Host = shared.IpFormat(connInfo.Host)
|
||||
|
||||
if connInfo.Port == 0 {
|
||||
connInfo.Port = DefaultPort
|
||||
}
|
||||
|
|
|
@ -49,6 +49,92 @@ func TestProvisioner_connInfo(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoIpv6(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "winrm",
|
||||
"user": "Administrator",
|
||||
"password": "supersecret",
|
||||
"host": "::1",
|
||||
"port": "5985",
|
||||
"https": "true",
|
||||
"timeout": "30s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.User != "Administrator" {
|
||||
t.Fatalf("expected: %v: got: %v", "Administrator", conf)
|
||||
}
|
||||
if conf.Password != "supersecret" {
|
||||
t.Fatalf("expected: %v: got: %v", "supersecret", conf)
|
||||
}
|
||||
if conf.Host != "[::1]" {
|
||||
t.Fatalf("expected: %v: got: %v", "[::1]", conf)
|
||||
}
|
||||
if conf.Port != 5985 {
|
||||
t.Fatalf("expected: %v: got: %v", 5985, conf)
|
||||
}
|
||||
if conf.HTTPS != true {
|
||||
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||
}
|
||||
if conf.Timeout != "30s" {
|
||||
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
||||
}
|
||||
if conf.ScriptPath != DefaultScriptPath {
|
||||
t.Fatalf("expected: %v: got: %v", DefaultScriptPath, conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_connInfoHostname(t *testing.T) {
|
||||
r := &terraform.InstanceState{
|
||||
Ephemeral: terraform.EphemeralState{
|
||||
ConnInfo: map[string]string{
|
||||
"type": "winrm",
|
||||
"user": "Administrator",
|
||||
"password": "supersecret",
|
||||
"host": "example.com",
|
||||
"port": "5985",
|
||||
"https": "true",
|
||||
"timeout": "30s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
conf, err := parseConnectionInfo(r)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
if conf.User != "Administrator" {
|
||||
t.Fatalf("expected: %v: got: %v", "Administrator", conf)
|
||||
}
|
||||
if conf.Password != "supersecret" {
|
||||
t.Fatalf("expected: %v: got: %v", "supersecret", conf)
|
||||
}
|
||||
if conf.Host != "example.com" {
|
||||
t.Fatalf("expected: %v: got: %v", "example.com", conf)
|
||||
}
|
||||
if conf.Port != 5985 {
|
||||
t.Fatalf("expected: %v: got: %v", 5985, conf)
|
||||
}
|
||||
if conf.HTTPS != true {
|
||||
t.Fatalf("expected: %v: got: %v", true, conf)
|
||||
}
|
||||
if conf.Timeout != "30s" {
|
||||
t.Fatalf("expected: %v: got: %v", "30s", conf)
|
||||
}
|
||||
if conf.ScriptPath != DefaultScriptPath {
|
||||
t.Fatalf("expected: %v: got: %v", DefaultScriptPath, conf)
|
||||
}
|
||||
}
|
||||
|
||||
func TestProvisioner_formatDuration(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
InstanceState *terraform.InstanceState
|
||||
|
|
Loading…
Reference in New Issue