Skip to content

Commit

Permalink
Create computed result_conn (#14)
Browse files Browse the repository at this point in the history
  • Loading branch information
tenstad authored Aug 29, 2021
1 parent 0001084 commit 0f20724
Show file tree
Hide file tree
Showing 7 changed files with 84 additions and 37 deletions.
1 change: 1 addition & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ default: testacc
.PHONY: testacc
testacc:
docker rm -f remotehost
docker rm -f remotehost2
docker network rm remote || true
docker network create remote
docker build -t remotehost tests
Expand Down
16 changes: 16 additions & 0 deletions docs/data-sources/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ data "remote_file" "server2_hosts" {
### Read-Only

- **content** (String) Content of file.
- **result_conn** (List of Object) Result of applying provider's `conn` as default to optional `conn` (see [below for nested schema](#nestedatt--result_conn))

<a id="nestedblock--conn"></a>
### Nested Schema for `conn`
Expand All @@ -71,3 +72,18 @@ Optional:
- **sudo** (Boolean) Use sudo to gain access to file. Defaults to `false`.


<a id="nestedatt--result_conn"></a>
### Nested Schema for `result_conn`

Read-Only:

- **host** (String)
- **password** (String)
- **port** (Number)
- **private_key** (String)
- **private_key_env_var** (String)
- **private_key_path** (String)
- **sudo** (Boolean)
- **user** (String)


19 changes: 19 additions & 0 deletions docs/resources/file.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ resource "remote_file" "server2_bashrc" {
- **id** (String) The ID of this resource.
- **permissions** (String) Permissions of file. Defaults to `0644`.

### Read-Only

- **result_conn** (List of Object) Computed conn for handling default functionality. (see [below for nested schema](#nestedatt--result_conn))

<a id="nestedblock--conn"></a>
### Nested Schema for `conn`

Expand All @@ -75,3 +79,18 @@ Optional:
- **sudo** (Boolean) Use sudo to gain access to file. Defaults to `false`.


<a id="nestedatt--result_conn"></a>
### Nested Schema for `result_conn`

Read-Only:

- **host** (String)
- **password** (String)
- **port** (Number)
- **private_key** (String)
- **private_key_env_var** (String)
- **private_key_path** (String)
- **sudo** (Boolean)
- **user** (String)


14 changes: 7 additions & 7 deletions internal/provider/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,22 +60,22 @@ var connectionSchemaResource = &schema.Resource{
}

func ConnectionFromResourceData(d *schema.ResourceData) (string, *ssh.ClientConfig, error) {
_, ok := d.GetOk("conn")
_, ok := d.GetOk("result_conn")
if !ok {
return "", nil, fmt.Errorf("resouce does not have a connection configured")
}

clientConfig := ssh.ClientConfig{
User: d.Get("conn.0.user").(string),
User: d.Get("result_conn.0.user").(string),
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
}

password, ok := d.GetOk("conn.0.password")
password, ok := d.GetOk("result_conn.0.password")
if ok {
clientConfig.Auth = append(clientConfig.Auth, ssh.Password(password.(string)))
}

private_key, ok := d.GetOk("conn.0.private_key")
private_key, ok := d.GetOk("result_conn.0.private_key")
if ok {
signer, err := ssh.ParsePrivateKey([]byte(private_key.(string)))
if err != nil {
Expand All @@ -84,7 +84,7 @@ func ConnectionFromResourceData(d *schema.ResourceData) (string, *ssh.ClientConf
clientConfig.Auth = append(clientConfig.Auth, ssh.PublicKeys(signer))
}

private_key_path, ok := d.GetOk("conn.0.private_key_path")
private_key_path, ok := d.GetOk("result_conn.0.private_key_path")
if ok {
content, err := ioutil.ReadFile(private_key_path.(string))
if err != nil {
Expand All @@ -97,7 +97,7 @@ func ConnectionFromResourceData(d *schema.ResourceData) (string, *ssh.ClientConf
clientConfig.Auth = append(clientConfig.Auth, ssh.PublicKeys(signer))
}

private_key_env_var, ok := d.GetOk("conn.0.private_key_env_var")
private_key_env_var, ok := d.GetOk("result_conn.0.private_key_env_var")
if ok {
private_key := os.Getenv(private_key_env_var.(string))
signer, err := ssh.ParsePrivateKey([]byte(private_key))
Expand All @@ -107,6 +107,6 @@ func ConnectionFromResourceData(d *schema.ResourceData) (string, *ssh.ClientConf
clientConfig.Auth = append(clientConfig.Auth, ssh.PublicKeys(signer))
}

host := fmt.Sprintf("%s:%d", d.Get("conn.0.host").(string), d.Get("conn.0.port").(int))
host := fmt.Sprintf("%s:%d", d.Get("result_conn.0.host").(string), d.Get("result_conn.0.port").(int))
return host, &clientConfig, nil
}
6 changes: 6 additions & 0 deletions internal/provider/data_source_remote_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ func dataSourceRemoteFile() *schema.Resource {
Description: "Connection to host where files are located.",
Elem: connectionSchemaResource,
},
"result_conn": {
Type: schema.TypeList,
Computed: true,
Description: "Result of applying provider's `conn` as default to optional `conn`",
Elem: connectionSchemaResource,
},
"path": {
Description: "Path to file on remote host.",
Type: schema.TypeString,
Expand Down
38 changes: 15 additions & 23 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,27 +83,24 @@ func configure(version string, p *schema.Provider) func(context.Context, *schema
}
}

func (c *apiClient) connectionResourceData(d *schema.ResourceData) (*schema.ResourceData, error) {
_, ok := d.GetOk("conn")
func (c *apiClient) applyResultConn(d *schema.ResourceData) (*schema.ResourceData, error) {
conn, ok := d.GetOk("conn")
if ok {
d.Set("result_conn", conn)
return d, nil
}

_, ok = c.resourceData.GetOk("conn")
conn, ok = c.resourceData.GetOk("conn")
if ok {
return c.resourceData, nil
d.Set("result_conn", conn)
return d, nil
}

return nil, errors.New("neither the provider nor the resource/data source have a configured connection")
}

func (c *apiClient) getRemoteClient(d *schema.ResourceData) (*RemoteClient, error) {
resourceData, err := c.connectionResourceData(d)
if err != nil {
return nil, err
}

connectionID := resourceConnectionHash(resourceData)
connectionID := resourceConnectionHash(d)
defer c.mux.Unlock()
for {
c.mux.Lock()
Expand All @@ -119,7 +116,7 @@ func (c *apiClient) getRemoteClient(d *schema.ResourceData) (*RemoteClient, erro
return client, nil
}

client, err = remoteClientFromResourceData(resourceData)
client, err := remoteClientFromResourceData(d)
if err != nil {
return nil, err
}
Expand All @@ -139,12 +136,7 @@ func remoteClientFromResourceData(d *schema.ResourceData) (*RemoteClient, error)
}

func (c *apiClient) closeRemoteClient(d *schema.ResourceData) error {
resourceData, err := c.connectionResourceData(d)
if err != nil {
return err
}

connectionID := resourceConnectionHash(resourceData)
connectionID := resourceConnectionHash(d)
c.mux.Lock()
defer c.mux.Unlock()

Expand All @@ -160,12 +152,12 @@ func (c *apiClient) closeRemoteClient(d *schema.ResourceData) error {

func resourceConnectionHash(d *schema.ResourceData) string {
elements := []string{
d.Get("conn.0.host").(string),
d.Get("conn.0.user").(string),
strconv.Itoa(d.Get("conn.0.port").(int)),
resourceStringWithDefault(d, "conn.0.password", ""),
resourceStringWithDefault(d, "conn.0.private_key", ""),
resourceStringWithDefault(d, "conn.0.private_key_path", ""),
d.Get("result_conn.0.host").(string),
d.Get("result_conn.0.user").(string),
strconv.Itoa(d.Get("result_conn.0.port").(int)),
resourceStringWithDefault(d, "result_conn.0.password", ""),
resourceStringWithDefault(d, "result_conn.0.private_key", ""),
resourceStringWithDefault(d, "result_conn.0.private_key_path", ""),
}
return strings.Join(elements, "::")
}
Expand Down
27 changes: 20 additions & 7 deletions internal/provider/resource_remote_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ func resourceRemoteFile() *schema.Resource {
Description: "Connection to host where files are located.",
Elem: connectionSchemaResource,
},
"result_conn": {
Type: schema.TypeList,
Computed: true,
Description: "Computed conn for handling default functionality.",
Elem: connectionSchemaResource,
},
"path": {
Description: "Path to file on remote host.",
Type: schema.TypeString,
Expand All @@ -50,18 +56,19 @@ func resourceRemoteFile() *schema.Resource {
}

func resourceRemoteFileCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
connectionResourceData, err := meta.(*apiClient).connectionResourceData(d)
d, err := meta.(*apiClient).applyResultConn(d)
if err != nil {
return diag.Errorf(err.Error())
}
d.SetId(fmt.Sprintf("%s:%s", connectionResourceData.Get("conn.0.host").(string), d.Get("path").(string)))

d.SetId(fmt.Sprintf("%s:%s", d.Get("result_conn.0.host").(string), d.Get("path").(string)))

client, err := meta.(*apiClient).getRemoteClient(d)
if err != nil {
return diag.Errorf("error while opening remote client: %s", err.Error())
}

sudo, ok := d.GetOk("conn.0.sudo")
sudo, ok := d.GetOk("result_conn.0.sudo")
if ok && sudo.(bool) {
err := client.WriteFileSudo(d)
if err != nil {
Expand All @@ -87,18 +94,19 @@ func resourceRemoteFileCreate(ctx context.Context, d *schema.ResourceData, meta
}

func resourceRemoteFileRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
connectionResourceData, err := meta.(*apiClient).connectionResourceData(d)
d, err := meta.(*apiClient).applyResultConn(d)
if err != nil {
return diag.Errorf(err.Error())
}
d.SetId(fmt.Sprintf("%s:%s", connectionResourceData.Get("conn.0.host").(string), d.Get("path").(string)))

d.SetId(fmt.Sprintf("%s:%s", d.Get("result_conn.0.host").(string), d.Get("path").(string)))

client, err := meta.(*apiClient).getRemoteClient(d)
if err != nil {
return diag.Errorf("error while opening remote client: %s", err.Error())
}

sudo, ok := d.GetOk("conn.0.sudo")
sudo, ok := d.GetOk("result_conn.0.sudo")
if ok && sudo.(bool) {
exists, err := client.FileExistsSudo(d)
if err != nil {
Expand Down Expand Up @@ -132,12 +140,17 @@ func resourceRemoteFileUpdate(ctx context.Context, d *schema.ResourceData, meta
}

func resourceRemoteFileDelete(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
d, err := meta.(*apiClient).applyResultConn(d)
if err != nil {
return diag.Errorf(err.Error())
}

client, err := meta.(*apiClient).getRemoteClient(d)
if err != nil {
return diag.Errorf("error while opening remote client: %s", err.Error())
}

sudo, ok := d.GetOk("conn.0.sudo")
sudo, ok := d.GetOk("result_conn.0.sudo")
if ok && sudo.(bool) {
exists, err := client.FileExistsSudo(d)
if err != nil {
Expand Down

0 comments on commit 0f20724

Please sign in to comment.