Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added basic support for ssh on Windows for raw script execution through Ansible #752

Merged
merged 11 commits into from
Jun 28, 2021
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

### ENHANCEMENTS

* Add basic support for ssh on Windows ([GH-751](https://github.com/ystia/yorc/issues/751))
* Add the ability to define OpenStack Compute Instance user_data ([GH-735](https://github.com/ystia/yorc/issues/735))

### BUG FIXES
Expand Down
2 changes: 2 additions & 0 deletions doc/tosca.rst
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ Currently Yorc supports as builtin implementations for operations:
* Python scripts
* Ansible Playbooks

Basic support for raws scripts execution through Ansible playbooks is also provided on Windows targets configured to use ssh.

New implementations can be plugged into Yorc using its plugin mechanism.

.. todo:
Expand Down
6 changes: 5 additions & 1 deletion helper/consulutil/consul_ratelimit_publisher.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,13 @@ package consulutil
import (
"context"
"encoding/json"
"github.com/ystia/yorc/v4/helper/collections"
"os"
"strings"
"sync"
"time"

"github.com/ystia/yorc/v4/helper/collections"

"github.com/hashicorp/consul/api"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -307,6 +308,9 @@ func (cs *consulStore) publishWithoutTx(key string, value []byte, flags uint64)
// Will block if the rateLimitedConsulPublisher is itself blocked by its semaphore
consulPub.publish(cs.ctx, func(kv *api.KV) error {
_, err := kv.Put(p, nil)
if err != nil {
log.Printf("Failed to store key %s value %s", key, string(value))
}
return errors.Wrap(err, ConsulGenericErrMsg)
})
}
Expand Down
13 changes: 13 additions & 0 deletions prov/ansible/execution.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ type hostConnection struct {
privateKeys map[string]*sshutil.PrivateKey
password string
bastion *sshutil.BastionHostConfig
osType string
}

type sshCredentials struct {
Expand Down Expand Up @@ -381,6 +382,14 @@ func (e *executionCommon) setHostConnection(ctx context.Context, host, instanceI
return errors.Wrapf(err, "Failed to convert port value:%q to int", port)
}
}
// Need to get the os type as Windows target hosts need specific ansible settings
osType, err := deployments.GetInstanceCapabilityAttributeValue(ctx, e.deploymentID, host, instanceID, "os", "type")
if err != nil {
return err
}
if osType != nil {
conn.osType = strings.ToLower(osType.RawString())
}
}
return nil
}
Expand Down Expand Up @@ -876,6 +885,10 @@ func (e *executionCommon) generateHostConnection(ctx context.Context, buffer *by
if host.port != 0 && host.port != 22 {
buffer.WriteString(fmt.Sprintf(" ansible_ssh_port=%d", host.port))
}
// Specific ansible connection settings are needed on windows targets
if strings.Contains(host.osType, "windows") {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know but maybe it worthwhile to be mentioned somehow in the documentation.
Maybe here https://yorc.readthedocs.io/en/stable/tosca.html#supported-operations-implementations
As it seems to be a very specific behavior.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes, proposign to add this:

Basic support for raws scripts execution through Ansible playbooks is also provided on Windows targets configured to use ssh.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

buffer.WriteString(" ansible_connection=ssh ansible_shell_type=cmd")
}
}
buffer.WriteString("\n")
return nil
Expand Down
12 changes: 11 additions & 1 deletion prov/ansible/execution_ansible.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ const uploadArtifactsPlaybook = `
hosts: all
strategy: free
tasks:
[[[ range $artName, $art := .Artifacts ]]] [[[printf "- file: path=\"{{ ansible_env.HOME}}/%s/%s\" state=directory mode=0755" $.OperationRemotePath (path $art)]]]
[[[ range $artName, $art := .Artifacts ]]]
[[[printf "- file: path=\"{{ ansible_env.HOME}}/%s/%s\" state=directory mode=0755" $.OperationRemotePath (path $art)]]]
[[[printf " when: ansible_os_family != 'Windows'"]]]
[[[printf "- ansible.windows.win_file: path=\"{{ ansible_env.HOME}}\\%s\\%s\" state=directory mode=0755" $.OperationRemotePath (path $art)]]]
[[[printf " when: ansible_os_family == 'Windows'"]]]
[[[printf "- copy: src=\"%s/%s\" dest=\"{{ ansible_env.HOME}}/%s/%s\"" $.OverlayPath $art $.OperationRemotePath (path $art)]]]
[[[end]]]
`
Expand All @@ -47,6 +51,9 @@ const ansiblePlaybook = `
strategy: free
tasks:
[[[printf "- file: path=\"{{ ansible_env.HOME}}/%s\" state=directory mode=0755" $.OperationRemotePath]]]
[[[printf " when: ansible_os_family != 'Windows'"]]]
[[[printf "- ansible.windows.win_file: path=\"{{ ansible_env.HOME}}\\%s\" state=directory mode=0755" $.OperationRemotePath]]]
[[[printf " when: ansible_os_family == 'Windows'"]]]
[[[printf "- template: src=\"outputs.csv.j2\" dest=\"{{ ansible_env.HOME}}/%s/out.csv\"" $.OperationRemotePath]]]
[[[printf "- fetch: src=\"{{ ansible_env.HOME}}/%s/out.csv\" dest={{dest_folder}}/{{ansible_host}}-out.csv flat=yes" $.OperationRemotePath]]]
[[[end]]]
Expand All @@ -56,6 +63,9 @@ const ansiblePlaybook = `
strategy: free
tasks:
- file: path="{{ ansible_env.HOME}}/[[[.OperationRemoteBaseDir]]]" state=absent
when: ansible_os_family != 'Windows'
- ansible.windows.win_file: path="{{ ansible_env.HOME}}\[[[.OperationRemoteBaseDir]]]" state=absent
when: ansible_os_family == 'Windows'
[[[end]]]
`

Expand Down
1 change: 1 addition & 0 deletions prov/terraform/commons/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ func AddConnectionCheckResource(ctx context.Context, deploymentID, nodeName stri
User: user,
Host: accessIP,
PrivateKey: "${var.private_key}",
Timeout: "15m",
}

bast, err := provutil.GetInstanceBastionHost(ctx, deploymentID, nodeName)
Expand Down