github.com/hazelops/ize@v1.1.12-0.20230915191306-97d7c0e48f11/internal/commands/tunnel_up_test.go (about)

     1  package commands
     2  
     3  import (
     4  	"fmt"
     5  	"io"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"testing"
    11  
    12  	"github.com/aws/aws-sdk-go/aws"
    13  	"github.com/aws/aws-sdk-go/aws/awserr"
    14  	"github.com/aws/aws-sdk-go/aws/credentials"
    15  	"github.com/aws/aws-sdk-go/aws/session"
    16  	"github.com/aws/aws-sdk-go/service/ssm"
    17  	"github.com/aws/aws-sdk-go/service/ssm/ssmiface"
    18  	"github.com/hazelops/ize/internal/config"
    19  )
    20  
    21  func TestUpOptions_getSSHCommandArgs(t *testing.T) {
    22  	temp, err := os.MkdirTemp("", "test")
    23  	if err != nil {
    24  		t.Error(err)
    25  		return
    26  	}
    27  	type fields struct {
    28  		Config                *config.Project
    29  		PrivateKeyFile        string
    30  		PublicKeyFile         string
    31  		BastionHostID         string
    32  		ForwardHost           []string
    33  		StrictHostKeyChecking bool
    34  	}
    35  	type args struct {
    36  		sshConfigPath string
    37  	}
    38  	tests := []struct {
    39  		name   string
    40  		fields fields
    41  		args   args
    42  		want   []string
    43  	}{
    44  		{name: "success",
    45  			fields: fields{
    46  				Config:                &config.Project{},
    47  				PrivateKeyFile:        "",
    48  				PublicKeyFile:         "",
    49  				BastionHostID:         "i-xxxxxxxxxxx",
    50  				ForwardHost:           nil,
    51  				StrictHostKeyChecking: true,
    52  			},
    53  			args: args{sshConfigPath: "./test/ssh.config"},
    54  			want: []string{"-M", "-t", "-S", "bastion.sock", "-fN", "ubuntu@i-xxxxxxxxxxx", "-F", "./test/ssh.config"},
    55  		},
    56  		{name: "success with StrictHostKeyChecking",
    57  			fields: fields{
    58  				Config:                &config.Project{},
    59  				PrivateKeyFile:        "",
    60  				PublicKeyFile:         "",
    61  				BastionHostID:         "i-xxxxxxxxxxx",
    62  				ForwardHost:           nil,
    63  				StrictHostKeyChecking: false,
    64  			},
    65  			args: args{sshConfigPath: "./test/ssh.config"},
    66  			want: []string{"-M", "-t", "-S", "bastion.sock", "-fN", "-o", "StrictHostKeyChecking=no", "ubuntu@i-xxxxxxxxxxx", "-F", "./test/ssh.config"},
    67  		},
    68  		{name: "success with private key file",
    69  			fields: fields{
    70  				Config:                &config.Project{},
    71  				PrivateKeyFile:        fmt.Sprintf("%s/.ssh/id_rsa", temp),
    72  				PublicKeyFile:         fmt.Sprintf("%s/.ssh/id_rsa.pub", temp),
    73  				BastionHostID:         "i-XXXXXXXXXXXXXXXXX",
    74  				ForwardHost:           nil,
    75  				StrictHostKeyChecking: true,
    76  			},
    77  			args: args{sshConfigPath: "./test/ssh.config"},
    78  			want: []string{"-M", "-t", "-S", "bastion.sock", "-fN", "ubuntu@i-XXXXXXXXXXXXXXXXX", "-F", "./test/ssh.config", "-i", fmt.Sprintf("%s/.ssh/id_rsa", temp)},
    79  		},
    80  	}
    81  	for _, tt := range tests {
    82  		t.Run(tt.name, func(t *testing.T) {
    83  			o := &TunnelUpOptions{
    84  				Config:                tt.fields.Config,
    85  				PrivateKeyFile:        tt.fields.PrivateKeyFile,
    86  				PublicKeyFile:         tt.fields.PublicKeyFile,
    87  				BastionHostID:         tt.fields.BastionHostID,
    88  				ForwardHost:           tt.fields.ForwardHost,
    89  				StrictHostKeyChecking: tt.fields.StrictHostKeyChecking,
    90  			}
    91  			os.MkdirAll(filepath.Join(temp, ".ssh"), 0777)
    92  			if len(o.PrivateKeyFile) != 0 {
    93  				_, err := makeSSHKeyPair(o.PublicKeyFile, o.PrivateKeyFile)
    94  				if err != nil {
    95  					t.Error(err)
    96  					return
    97  				}
    98  			}
    99  			if got := o.getSSHCommandArgs(tt.args.sshConfigPath); !reflect.DeepEqual(got, tt.want) {
   100  				t.Errorf("getSSHCommandArgs() = %v, want %v", got, tt.want)
   101  			}
   102  		})
   103  	}
   104  }
   105  
   106  type mockSSM struct {
   107  	ssmiface.SSMAPI
   108  	response string
   109  	err      error
   110  }
   111  
   112  func (sp mockSSM) GetParameter(*ssm.GetParameterInput) (*ssm.GetParameterOutput, error) {
   113  	output := new(ssm.GetParameterOutput)
   114  	output.Parameter = &ssm.Parameter{Value: aws.String(sp.response)}
   115  	return output, sp.err
   116  }
   117  
   118  func Test_getTerraformOutput(t *testing.T) {
   119  	type args struct {
   120  		wr  *SSMWrapper
   121  		env string
   122  	}
   123  	tests := []struct {
   124  		name    string
   125  		args    args
   126  		want    terraformOutput
   127  		wantErr bool
   128  	}{
   129  		{
   130  			name: "success", args: args{
   131  				wr: &SSMWrapper{Api: mockSSM{
   132  					SSMAPI:   nil,
   133  					response: "ew0KICAiYmFzdGlvbl9pbnN0YW5jZV9pZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiAic3RyaW5nIiwNCiAgICAidmFsdWUiOiAiaS1YWFhYWFhYWFhYWFhYWFhYWCINCiAgfSwNCiAgImNtZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAib2JqZWN0IiwNCiAgICAgIHsNCiAgICAgICAgInR1bm5lbCI6IFsNCiAgICAgICAgICAib2JqZWN0IiwNCiAgICAgICAgICB7DQogICAgICAgICAgICAiZG93biI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInN0YXR1cyI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInVwIjogInN0cmluZyINCiAgICAgICAgICB9DQogICAgICAgIF0NCiAgICAgIH0NCiAgICBdLA0KICAgICJ2YWx1ZSI6IHsNCiAgICAgICJ0dW5uZWwiOiB7DQogICAgICAgICJkb3duIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gZXhpdCB1YnVudHVAaS1YWFhYWFhYWFhYWFhYWFhYWCAiLA0KICAgICAgICAic3RhdHVzIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gY2hlY2sgdWJ1bnR1QGktWFhYWFhYWFhYWFhYWFhYWFgiLA0KICAgICAgICAidXAiOiAic3NoIC1NIC1TIGJhc3Rpb24uc29jayAtZk5UIHVidW50dUBpLVhYWFhYWFhYWFhYWFhYWFhYICINCiAgICAgIH0NCiAgICB9DQogIH0sDQogICJzc2hfZm9yd2FyZF9jb25maWciOiB7DQogICAgInNlbnNpdGl2ZSI6IGZhbHNlLA0KICAgICJ0eXBlIjogWw0KICAgICAgInR1cGxlIiwNCiAgICAgIFsNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciLA0KICAgICAgICAic3RyaW5nIiwNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAiIyBTU0ggb3ZlciBTZXNzaW9uIE1hbmFnZXIiLA0KICAgICAgImhvc3QgaS0qIG1pLSoiLA0KICAgICAgIlNlcnZlckFsaXZlSW50ZXJ2YWwgMTgwIiwNCiAgICAgICJQcm94eUNvbW1hbmQgc2ggLWMgXCJhd3Mgc3NtIHN0YXJ0LXNlc3Npb24gLS10YXJnZXQgJWggLS1kb2N1bWVudC1uYW1lIEFXUy1TdGFydFNTSFNlc3Npb24gLS1wYXJhbWV0ZXJzICdwb3J0TnVtYmVyPSVwJ1wiXG4iLA0KICAgICAgIkxvY2FsRm9yd2FyZCAzMjA4NCB0ZXN0LnRlc3QudGVzdDo4MCINCiAgICBdDQogIH0sDQogICJ2cGNfcHJpdmF0ZV9zdWJuZXRzIjogew0KICAgICJzZW5zaXRpdmUiOiBmYWxzZSwNCiAgICAidHlwZSI6IFsNCiAgICAgICJ0dXBsZSIsDQogICAgICBbDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAic3VibmV0LVhYWFhYWFhYWFhYWFhYWFhYIg0KICAgIF0NCiAgfSwNCiAgInZwY19wdWJsaWNfc3VibmV0cyI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAidHVwbGUiLA0KICAgICAgWw0KICAgICAgICAic3RyaW5nIg0KICAgICAgXQ0KICAgIF0sDQogICAgInZhbHVlIjogWw0KICAgICAgInN1Ym5ldC1YWFhYWFhYWFhYWFhYWFhYWCINCiAgICBdDQogIH0NCn0=",
   134  					err:      nil,
   135  				}},
   136  				env: "testnut",
   137  			},
   138  			want: terraformOutput{
   139  				BastionInstanceID: struct {
   140  					Value string `json:"value,omitempty"`
   141  				}{Value: "i-XXXXXXXXXXXXXXXXX"},
   142  				SSHForwardConfig: struct {
   143  					Value []string `json:"value,omitempty"`
   144  				}{Value: []string{"# SSH over Session Manager", "host i-* mi-*", "ServerAliveInterval 180", "ProxyCommand sh -c \"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'\"\n", "LocalForward 32084 test.test.test:80"}},
   145  			},
   146  			wantErr: false,
   147  		},
   148  		{
   149  			name: "incorrect json", args: args{
   150  				wr: &SSMWrapper{Api: mockSSM{
   151  					SSMAPI:   nil,
   152  					response: "ICAiYmFzdGlvbl9pbnN0YW5jZV9pZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiAic3RyaW5nIiwNCiAgICAidmFsdWUiOiAiaS1YWFhYWFhYWFhYWFhYWFhYWCINCiAgfSwNCiAgImNtZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAib2JqZWN0IiwNCiAgICAgIHsNCiAgICAgICAgInR1bm5lbCI6IFsNCiAgICAgICAgICAib2JqZWN0IiwNCiAgICAgICAgICB7DQogICAgICAgICAgICAiZG93biI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInN0YXR1cyI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInVwIjogInN0cmluZyINCiAgICAgICAgICB9DQogICAgICAgIF0NCiAgICAgIH0NCiAgICBdLA0KICAgICJ2YWx1ZSI6IHsNCiAgICAgICJ0dW5uZWwiOiB7DQogICAgICAgICJkb3duIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gZXhpdCB1YnVudHVAaS1YWFhYWFhYWFhYWFhYWFhYWCAiLA0KICAgICAgICAic3RhdHVzIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gY2hlY2sgdWJ1bnR1QGktWFhYWFhYWFhYWFhYWFhYWFgiLA0KICAgICAgICAidXAiOiAic3NoIC1NIC1TIGJhc3Rpb24uc29jayAtZk5UIHVidW50dUBpLVhYWFhYWFhYWFhYWFhYWFhYICINCiAgICAgIH0NCiAgICB9DQogIH0sDQogICJzc2hfZm9yd2FyZF9jb25maWciOiB7DQogICAgInNlbnNpdGl2ZSI6IGZhbHNlLA0KICAgICJ0eXBlIjogWw0KICAgICAgInR1cGxlIiwNCiAgICAgIFsNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciLA0KICAgICAgICAic3RyaW5nIiwNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAiIyBTU0ggb3ZlciBTZXNzaW9uIE1hbmFnZXIiLA0KICAgICAgImhvc3QgaS0qIG1pLSoiLA0KICAgICAgIlNlcnZlckFsaXZlSW50ZXJ2YWwgMTgwIiwNCiAgICAgICJQcm94eUNvbW1hbmQgc2ggLWMgXCJhd3Mgc3NtIHN0YXJ0LXNlc3Npb24gLS10YXJnZXQgJWggLS1kb2N1bWVudC1uYW1lIEFXUy1TdGFydFNTSFNlc3Npb24gLS1wYXJhbWV0ZXJzICdwb3J0TnVtYmVyPSVwJ1wiXG4iLA0KICAgICAgIkxvY2FsRm9yd2FyZCAzMjA4NCB0ZXN0LnRlc3QudGVzdDo4MCINCiAgICBdDQogIH0sDQogICJ2cGNfcHJpdmF0ZV9zdWJuZXRzIjogew0KICAgICJzZW5zaXRpdmUiOiBmYWxzZSwNCiAgICAidHlwZSI6IFsNCiAgICAgICJ0dXBsZSIsDQogICAgICBbDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAic3VibmV0LVhYWFhYWFhYWFhYWFhYWFhYIg0KICAgIF0NCiAgfSwNCiAgInZwY19wdWJsaWNfc3VibmV0cyI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAidHVwbGUiLA0KICAgICAgWw0KICAgICAgICAic3RyaW5nIg0KICAgICAgXQ0KICAgIF0sDQogICAgInZhbHVlIjogWw0KICAgICAgInN1Ym5ldC1YWFhYWFhYWFhYWFhYWFhYWCINCiAgICBdDQogIH0NCn0",
   153  					err:      nil,
   154  				}},
   155  				env: "testnut",
   156  			},
   157  			want:    terraformOutput{},
   158  			wantErr: true,
   159  		},
   160  		{
   161  			name: "incorrect base64", args: args{
   162  				wr: &SSMWrapper{Api: mockSSM{
   163  					SSMAPI:   nil,
   164  					response: "0a2a-67c5-7a30-a153-b88f-81ac-8898-b766",
   165  					err:      nil,
   166  				}},
   167  				env: "testnut",
   168  			},
   169  			want:    terraformOutput{},
   170  			wantErr: true,
   171  		},
   172  		{
   173  			name: "incorrect path", args: args{
   174  				wr: &SSMWrapper{Api: mockSSM{
   175  					SSMAPI:   nil,
   176  					response: "",
   177  					err:      awserr.New(ssm.ErrCodeParameterNotFound, "", nil),
   178  				}},
   179  				env: "incorrectPath",
   180  			},
   181  			want:    terraformOutput{},
   182  			wantErr: true,
   183  		},
   184  	}
   185  	for _, tt := range tests {
   186  		t.Run(tt.name, func(t *testing.T) {
   187  			got, err := getTerraformOutput(tt.args.wr, tt.args.env)
   188  			if (err != nil) != tt.wantErr {
   189  				t.Errorf("getTerraformOutput() error = %v, wantErr %v", err, tt.wantErr)
   190  				return
   191  			}
   192  			if !reflect.DeepEqual(got, tt.want) {
   193  				t.Errorf("getTerraformOutput() got = %v, want %v", got, tt.want)
   194  			}
   195  		})
   196  	}
   197  }
   198  
   199  func Test_writeSSHConfigFromConfig(t *testing.T) {
   200  	tmp := os.TempDir()
   201  
   202  	type args struct {
   203  		forwardHost []string
   204  		dir         string
   205  	}
   206  	tests := []struct {
   207  		name    string
   208  		args    args
   209  		want    string
   210  		wantErr bool
   211  	}{
   212  		{
   213  			name: "success",
   214  			args: args{
   215  				forwardHost: []string{"11.11.11.11:22:36002", "11.11.11.11:23:36001"},
   216  				dir:         tmp,
   217  			},
   218  			want:    "# SSH over Session Manager\nhost i-* mi-*\nServerAliveInterval 180\nProxyCommand sh -c \"aws ssm start-session --target %h --document-name AWS-StartSSHSession --parameters 'portNumber=%p'\"\n\nLocalForward 36002 11.11.11.11:22\nLocalForward 36001 11.11.11.11:23\n\n",
   219  			wantErr: false,
   220  		},
   221  		{
   222  			name: "incorrect forward host 1",
   223  			args: args{
   224  				forwardHost: []string{"11.11.11.11", "11.11.11.11:23:36001"},
   225  				dir:         tmp,
   226  			},
   227  			want:    "",
   228  			wantErr: true,
   229  		},
   230  		{
   231  			name: "incorrect forward host 2",
   232  			args: args{
   233  				forwardHost: []string{"11.11.11.11:22:", "11.11.11.11:23:36001"},
   234  				dir:         tmp,
   235  			},
   236  			want:    "",
   237  			wantErr: true,
   238  		},
   239  	}
   240  	for _, tt := range tests {
   241  		t.Run(tt.name, func(t *testing.T) {
   242  			if err := writeSSHConfigFromConfig(tt.args.forwardHost, tt.args.dir); (err != nil) != tt.wantErr {
   243  				t.Errorf("writeSSHConfigFromConfig() error = %v, wantErr %v", err, tt.wantErr)
   244  				t.SkipNow()
   245  			}
   246  
   247  			file, err := os.ReadFile(filepath.Join(tmp, "ssh.config"))
   248  			if err != nil {
   249  				t.Error("writeSSHConfigFromConfig(): ssh.config not found")
   250  			}
   251  
   252  			fmt.Println(string(file))
   253  			if !reflect.DeepEqual(string(file), tt.want) {
   254  				t.Errorf("writeSSHConfigFromConfig() = %v, want %v", string(file), tt.want)
   255  			}
   256  		})
   257  	}
   258  }
   259  
   260  func Test_writeSSHConfigFromSSM(t *testing.T) {
   261  	tmp := os.TempDir()
   262  
   263  	type args struct {
   264  		wr  *SSMWrapper
   265  		env string
   266  		dir string
   267  	}
   268  	tests := []struct {
   269  		name    string
   270  		args    args
   271  		want    string
   272  		want1   []string
   273  		wantErr bool
   274  	}{
   275  		{
   276  			name: "success",
   277  			args: args{
   278  				wr: &SSMWrapper{Api: mockSSM{
   279  					SSMAPI:   nil,
   280  					response: "ew0KICAiYmFzdGlvbl9pbnN0YW5jZV9pZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiAic3RyaW5nIiwNCiAgICAidmFsdWUiOiAiaS1YWFhYWFhYWFhYWFhYWFhYWCINCiAgfSwNCiAgImNtZCI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAib2JqZWN0IiwNCiAgICAgIHsNCiAgICAgICAgInR1bm5lbCI6IFsNCiAgICAgICAgICAib2JqZWN0IiwNCiAgICAgICAgICB7DQogICAgICAgICAgICAiZG93biI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInN0YXR1cyI6ICJzdHJpbmciLA0KICAgICAgICAgICAgInVwIjogInN0cmluZyINCiAgICAgICAgICB9DQogICAgICAgIF0NCiAgICAgIH0NCiAgICBdLA0KICAgICJ2YWx1ZSI6IHsNCiAgICAgICJ0dW5uZWwiOiB7DQogICAgICAgICJkb3duIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gZXhpdCB1YnVudHVAaS1YWFhYWFhYWFhYWFhYWFhYWCAiLA0KICAgICAgICAic3RhdHVzIjogInNzaCAtUyBiYXN0aW9uLnNvY2sgLU8gY2hlY2sgdWJ1bnR1QGktWFhYWFhYWFhYWFhYWFhYWFgiLA0KICAgICAgICAidXAiOiAic3NoIC1NIC1TIGJhc3Rpb24uc29jayAtZk5UIHVidW50dUBpLVhYWFhYWFhYWFhYWFhYWFhYICINCiAgICAgIH0NCiAgICB9DQogIH0sDQogICJzc2hfZm9yd2FyZF9jb25maWciOiB7DQogICAgInNlbnNpdGl2ZSI6IGZhbHNlLA0KICAgICJ0eXBlIjogWw0KICAgICAgInR1cGxlIiwNCiAgICAgIFsNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciLA0KICAgICAgICAic3RyaW5nIiwNCiAgICAgICAgInN0cmluZyIsDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAiIyBTU0ggb3ZlciBTZXNzaW9uIE1hbmFnZXIiLA0KICAgICAgImhvc3QgaS0qIG1pLSoiLA0KICAgICAgIlNlcnZlckFsaXZlSW50ZXJ2YWwgMTgwIiwNCiAgICAgICJQcm94eUNvbW1hbmQgc2ggLWMgXCJhd3Mgc3NtIHN0YXJ0LXNlc3Npb24gLS10YXJnZXQgJWggLS1kb2N1bWVudC1uYW1lIEFXUy1TdGFydFNTSFNlc3Npb24gLS1wYXJhbWV0ZXJzICdwb3J0TnVtYmVyPSVwJ1wiXG4iLA0KICAgICAgIkxvY2FsRm9yd2FyZCAzMjA4NCB0ZXN0LnRlc3QudGVzdDo4MCINCiAgICBdDQogIH0sDQogICJ2cGNfcHJpdmF0ZV9zdWJuZXRzIjogew0KICAgICJzZW5zaXRpdmUiOiBmYWxzZSwNCiAgICAidHlwZSI6IFsNCiAgICAgICJ0dXBsZSIsDQogICAgICBbDQogICAgICAgICJzdHJpbmciDQogICAgICBdDQogICAgXSwNCiAgICAidmFsdWUiOiBbDQogICAgICAic3VibmV0LVhYWFhYWFhYWFhYWFhYWFhYIg0KICAgIF0NCiAgfSwNCiAgInZwY19wdWJsaWNfc3VibmV0cyI6IHsNCiAgICAic2Vuc2l0aXZlIjogZmFsc2UsDQogICAgInR5cGUiOiBbDQogICAgICAidHVwbGUiLA0KICAgICAgWw0KICAgICAgICAic3RyaW5nIg0KICAgICAgXQ0KICAgIF0sDQogICAgInZhbHVlIjogWw0KICAgICAgInN1Ym5ldC1YWFhYWFhYWFhYWFhYWFhYWCINCiAgICBdDQogIH0NCn0=",
   281  					err:      nil,
   282  				}},
   283  				env: "test",
   284  				dir: tmp,
   285  			},
   286  			want:    "i-XXXXXXXXXXXXXXXXX",
   287  			want1:   []string{"test.test.test:80:32084"},
   288  			wantErr: false,
   289  		},
   290  		{
   291  			name: "SSM error",
   292  			args: args{
   293  				wr: &SSMWrapper{Api: mockSSM{
   294  					SSMAPI: nil,
   295  					err:    awserr.New(ssm.ErrCodeParameterNotFound, "", nil),
   296  				}},
   297  				env: "test",
   298  				dir: tmp,
   299  			},
   300  			want:    "",
   301  			want1:   []string{},
   302  			wantErr: true,
   303  		},
   304  	}
   305  	for _, tt := range tests {
   306  		t.Run(tt.name, func(t *testing.T) {
   307  			got, got1, err := writeSSHConfigFromSSM(tt.args.wr, tt.args.env, tt.args.dir)
   308  			if (err != nil) != tt.wantErr {
   309  				t.Errorf("writeSSHConfigFromSSM() error = %v, wantErr %v", err, tt.wantErr)
   310  				return
   311  			}
   312  			if got != tt.want {
   313  				t.Errorf("writeSSHConfigFromSSM() got = %v, want %v", got, tt.want)
   314  			}
   315  			if !reflect.DeepEqual(got1, tt.want1) {
   316  				t.Errorf("writeSSHConfigFromSSM() got1 = %v, want %v", got1, tt.want1)
   317  			}
   318  		})
   319  	}
   320  }
   321  
   322  func Test_setAWSCredentials(t *testing.T) {
   323  	type args struct {
   324  		sess *session.Session
   325  	}
   326  	tests := []struct {
   327  		name    string
   328  		args    args
   329  		wantErr bool
   330  	}{
   331  		{name: "error", args: args{sess: getSession(true)}, wantErr: true},
   332  		{name: "success", args: args{sess: getSession(false)}, wantErr: false},
   333  	}
   334  	for _, tt := range tests {
   335  		t.Run(tt.name, func(t *testing.T) {
   336  			if err := setAWSCredentials(tt.args.sess); (err != nil) != tt.wantErr {
   337  				t.Errorf("setAWSCredentials() error = %v, wantErr %v", err, tt.wantErr)
   338  			}
   339  			if os.Getenv("AWS_SECRET_ACCESS_KEY") == "test" && os.Getenv("AWS_ACCESS_KEY_ID") == "test" {
   340  				return
   341  			}
   342  		})
   343  	}
   344  }
   345  
   346  func getSession(incorrect bool) *session.Session {
   347  	if incorrect {
   348  		return session.Must(session.NewSession(aws.NewConfig().WithCredentials(credentials.NewSharedCredentials(filepath.Join("incorrect", "credentials"), "test"))))
   349  	}
   350  
   351  	tmp := os.TempDir()
   352  
   353  	testCreds := `[test]
   354  aws_access_key_id = test
   355  aws_secret_access_key = test
   356  `
   357  
   358  	f, _ := os.Create(filepath.Join(tmp, "credentials"))
   359  	_, _ = io.WriteString(f, testCreds)
   360  
   361  	return session.Must(session.NewSession(aws.NewConfig().WithCredentials(credentials.NewSharedCredentials(filepath.Join(tmp, "credentials"), "test"))))
   362  }
   363  
   364  //func TestUpOptions_runSSH(t *testing.T) {
   365  //	type fields struct {
   366  //		Config                *config.Project
   367  //		PrivateKeyFile        string
   368  //		PublicKeyFile         string
   369  //		BastionHostID         string
   370  //		ForwardHost           []string
   371  //		StrictHostKeyChecking bool
   372  //	}
   373  //	type args struct {
   374  //		args []string
   375  //	}
   376  //	tests := []struct {
   377  //		name         string
   378  //		fields       fields
   379  //		args         args
   380  //		wantErr      bool
   381  //		wantNotFound bool
   382  //	}{
   383  //		{
   384  //			name: "success",
   385  //			fields: fields{
   386  //				Config: &config.Project{EnvDir: func() string {
   387  //					temp, _ := os.MkdirTemp("", "test")
   388  //					return temp
   389  //				}()},
   390  //			},
   391  //			args: args{args: []string{"-M", "-t", "-S", "bastion.sock", "git@github.com", "-fN", "-o", "StrictHostKeyChecking=no"}},
   392  //		},
   393  //		{
   394  //			name: "not found",
   395  //			fields: fields{
   396  //				Config: &config.Project{EnvDir: func() string {
   397  //					temp, _ := os.MkdirTemp("", "test")
   398  //					return temp
   399  //				}()},
   400  //			},
   401  //			args:         args{args: []string{"-M", "-t", "-S", "bastion.sock", "git@github.com", "-fN", "-o", "StrictHostKeyChecking=no"}},
   402  //			wantErr:      false,
   403  //			wantNotFound: true,
   404  //		},
   405  //		{
   406  //			name: "incorrect host",
   407  //			fields: fields{
   408  //				Config: &config.Project{EnvDir: func() string {
   409  //					temp, _ := os.MkdirTemp("", "test")
   410  //					return temp
   411  //				}()},
   412  //			},
   413  //			args:         args{args: []string{"-M", "-t", "-S", "bastion.sock", "git@incorrecthost.com", "-fN", "-o", "StrictHostKeyChecking=no"}},
   414  //			wantErr:      true,
   415  //			wantNotFound: true,
   416  //		},
   417  //	}
   418  //	for _, tt := range tests {
   419  //		t.Run(tt.name, func(t *testing.T) {
   420  //			o := &TunnelUpOptions{
   421  //				Config:                tt.fields.Config,
   422  //				PrivateKeyFile:        tt.fields.PrivateKeyFile,
   423  //				PublicKeyFile:         tt.fields.PublicKeyFile,
   424  //				BastionHostID:         tt.fields.BastionHostID,
   425  //				ForwardHost:           tt.fields.ForwardHost,
   426  //				StrictHostKeyChecking: tt.fields.StrictHostKeyChecking,
   427  //			}
   428  //
   429  //			if err := o.runSSH(tt.args.args); (err != nil) != tt.wantErr {
   430  //				t.Errorf("runSSH() error = %v, wantErr %v", err, tt.wantErr)
   431  //				return
   432  //			}
   433  //
   434  //			if tt.wantNotFound {
   435  //				tt.fields.Config.EnvDir = func() string {
   436  //					temp, _ := os.MkdirTemp("", "not_found")
   437  //					return temp
   438  //				}()
   439  //			}
   440  //
   441  //			_, err := os.Stat(filepath.Join(tt.fields.Config.EnvDir, "bastion.sock"))
   442  //			if os.IsNotExist(err) != tt.wantNotFound {
   443  //				t.Error("bastion.sock not found")
   444  //				return
   445  //			}
   446  //
   447  //			return
   448  //		})
   449  //	}
   450  //}
   451  
   452  func Test_getPublicKey(t *testing.T) {
   453  	tmp, _ := os.MkdirTemp("", "test")
   454  
   455  	type args struct {
   456  		path string
   457  	}
   458  	tests := []struct {
   459  		name    string
   460  		args    args
   461  		want    string
   462  		wantErr bool
   463  	}{
   464  		{name: "success", args: args{path: filepath.Join(tmp, "id_rsa.pub")}, want: func() string {
   465  			pk, err := makeSSHKeyPair(filepath.Join(tmp, "id_rsa.pub"), filepath.Join(tmp, "id_rsa"))
   466  			if err != nil {
   467  				t.Fail()
   468  			}
   469  			return pk
   470  		}(), wantErr: false},
   471  		{name: "incorrect path", args: args{path: filepath.Join(tmp, "incorrect_path.pub")}, want: "", wantErr: true},
   472  		{name: "invalid key", args: args{path: filepath.Join(tmp, "id_rsa.pub")}, want: "", wantErr: true},
   473  	}
   474  	for _, tt := range tests {
   475  		t.Run(tt.name, func(t *testing.T) {
   476  			if tt.name == "invalid key" {
   477  				err := ioutil.WriteFile(tt.args.path, []byte("invalid key"), os.ModeAppend)
   478  				if err != nil {
   479  					t.Fail()
   480  				}
   481  			}
   482  			got, err := getPublicKey(tt.args.path)
   483  			if (err != nil) != tt.wantErr {
   484  				t.Errorf("getPublicKey() error = %v, wantErr %v", err, tt.wantErr)
   485  				return
   486  			}
   487  			if got != tt.want {
   488  				t.Errorf("getPublicKey() got = %v, want %v", got, tt.want)
   489  			}
   490  		})
   491  	}
   492  }