When using "win_command: mklink softlinkfile destfile" can not locate mklink.exe\" - command

I'm using ansible to manage several windows hosts on the cloud, I need to create a log file and link it to another file, so I use the follow playbook
- name: init the directory structure of windows
hosts: '{{windows_hosts}}'
tasks:
- name: create log file and link it to log directory
win_command: mklink log D:\prod\log
args:
chdir: D:\prod\project
when running this playbook, the hosts can be found successfully, but I got the following error report
> TASK [Gathering Facts]
> ********* ok: [111.111.2.40]
>
> TASK [create log file and link it to log directory]
> ********* fatal: [111.231.76.40]: FAILED! => {"changed": false, "cmd": "mklink log
> D:\\prod\\log", "msg": "Exception calling \"SearchPath\" with \"1\"
> argument(s): \"Could not locate the following executable
> mklink.exe\"", "rc": 2}
and I tryed this command on the remote host in the same directory, it can be execute successfully. I don't know what to do......

win_command is for running executables directly. Hence the user's environment isn't applied and you aren't running inside a dos box or powershell window
so 'mklink' isn't actually an executable - its a built-in feature of the cmd.exe program. So to run mklink via win_command, you'd have to run the cmd.exe program and pass it an argument to tell it do what 'mklink' does, like this:
win_command: cmd.exe /k mklink log D:\prod\log

Do the following way:
---
- name: Run Windows Command
hosts: windows
gather_facts: False
tasks:
- name: win command
win_shell: cmd /k mklink log D:\prod\log
args:
chdir: D:\prod\project

Related

Prevent Gitlab adding -NoProfile to PowerShell when starting a docker container

1. How can I prevent Gitlab from adding -NoProfile when creating the docker container?
2. What's the difference between using powershell with -NoProfile and without it?
3. Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
And now the story behind these questions:
MSBuild (Visual Studio build tool command) fails to build Xamarin app when used in docker container started by Gitlab with Powershell -NoProfile.
I created a docker image for CI purspose and everything is working properly if I run the container manually, but when it is run during Gitlab runner job, it fails (more exactly msbuild /t:SignAndroidPackage fails, because of some file does not gets generated). I inspected this (put a sleep of 1 hour in gitlab-ci.yml and attached to the container on the runner machine) and found out that Gitlab starts the container with PowerShell -NoProfile...I tried that manually(start the container with -NoProfile) and I reproduced the issue.
the error is:
Could not find a part of the path 'C:\builds\gitlab\HMI.Framework\KDI\sub\HostApplicationToolkit\sub\KBle\KBle\sub\XamarinBluetooth\Source\Plugin.BLE.Android\Resources\Resource.Designer.cs'
Here the Resource.Designer.cs is missing (and it should be auto-generated during the build process)
This is the dockerFile:
# escape=`
# Use the latest Windows Server Core image with .NET Framework 4.8.
FROM mcr.microsoft.com/dotnet/framework/sdk:3.5-windowsservercore-ltsc2019
ENV VS_STUDIO_INSTALL_LINK=https://download.visualstudio.microsoft.com/download/pr/befdb1f9-8676-4693-b031-65ee44835915/c541feeaa77b97681f7693fc5bed2ff82b331b168c678af1a95bdb1138a99802/vs_Community.exe
ENV VS_INSTALLER_PATH=C:\TEMP\vs2019.exe
ENV ANDROID_COMPILE_SDK=29
# Restore the default Windows shell for correct batch processing.
SHELL ["cmd", "/S", "/C"]
ADD $VS_STUDIO_INSTALL_LINK $VS_INSTALLER_PATH
RUN %VS_INSTALLER_PATH% --quiet --wait --norestart --nocache --includeRecommended --includeOptional`
--add Microsoft.VisualStudio.Workload.NetCrossPlat `
--add Microsoft.VisualStudio.Workload.XamarinBuildTools `
|| IF "%ERRORLEVEL%"=="3010" EXIT 0
RUN del %VS_INSTALLER_PATH%
# set some util paths
RUN setx JAVA_HOME "c:\Program Files\Android\jdk\microsoft_dist_openjdk_1.8.0.25\"
RUN setx path "%path%;c:\Program Files (x86)\Android\android-sdk\tools\bin;c:\Program Files (x86)\Android\android-sdk\platform-tools"
# update android SDK with API 29
RUN echo y| sdkmanager "platforms;android-%ANDROID_COMPILE_SDK%"
#ENTRYPOINT ["powershell.exe", "-NoLogo", "-ExecutionPolicy", "Bypass"]
This is the gitlab-ci.yml
image: visualstudio2019-xamarin-ci:1.0-windowsservercore-ltsc2019
stages:
- build
- test
variables:
GIT_SUBMODULE_STRATEGY: 'recursive'
build_kdi:
stage: build
only:
- CI_CD
tags:
- docker-windows
script:
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" ./src/KDI/KDI.sln /t:Restore /p:AndroidBuildApplicationPackage=true /p:Configuration=Release'
- '& "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\MSBuild\Current\Bin\MSBuild.exe" /p:Configuration=Release /t:SignAndroidPackage /property:SolutionDir="C:\builds\gitlab\HMI.Framework\KDI\src\KDI\" /p:AndroidSigningKeyStore="C:\builds\gitlab\HMI.Framework\KDI\distribution\Android\KrohneAndroidKeystore.keystore" .\src\KDI\KDI\KDI.Android\KDI.Android.csproj'
run_bb_tests:
stage: test
only:
- CI_CD
tags:
- docker-windows
script:
- docker-ci/install_and_run_bb_tests.bat "phone_ip" "5555" arg1 arg2 || true
- adb pull /storage/emulated/0/Android/data/myApp/files/Exports/BBT_Exports/BBTests_CI C:\test_results
artifacts:
paths:
- c:\test_results\BBTests_CI #expire in 1 month by default
If I start this image using : docker run -it myImage powershell everything works well, but if I run it docker run -it myImage powershell -NoProfile, msbuild fails at some step in building the xamarin app
How can I prevent Gitlab from adding -NoProfile when creating the docker container?
Apparently you can't...yet but there is a feature request in place
What's the difference between using powershell with -NoProfile and without it?
A PowerShell profile is just a file that contains things, like custom functions, for a specific user. For instance, if I were to have Function Banana(){Write-Host "Awesome"} in my PowerShell profile e.g $Home[My ]Documents\PowerShell\Profile.ps1. Whenever I open up PowerShell, it loads that function automatically. So I can open PowerShell, type banana and have the string Awesome written to stdout. If I were to start powershell with -NoProfile, and enter banana, I'd get CommandNotFoundException.
source
Is there any way if I run powershell -NoProfile to somehow load/run the default profile and to revert the effect of setting -NoProfile flag?
Maybe. And I only say maybe because I haven't personally tested it, but in theory it should work. If the profile is in the container, all you have to do is dot source it.
. "C:\path\to\powershell\profile.ps1"
dot sourcing the .ps1 file will run anything within it, inside the current scope, which includes loading functions, if any are present.
dot source docs
My expertise on Gitlab is limited, but due to my overall experience with Windows containers, PowerShell, as well as the nature of PowerShell profiles, I have doubts that the profiling is the root cause of this issue, but I don't have enough information/evidence to definitively say. Hope this helps in some way!

Writing the build.ps1 console output to a specific log file

I am using cake script to build my application. While the build process all the logging informations are displayed in the console. I want to write all the console output into a specific log file in the same path where the build.ps1 is located.
Build process is like, from gitlab-ci a particular bat file will be called. That bat file will get necessary build informations and build.ps1 will be called as below.
call start /wait /i cmd /c powershell.exe -Command %PSFILE_PATH% --rebrand="app_name"
pause
[PSFILE_PATH - will have the build.ps1 file path with file name.
eg: "F:\Build\app_name\build.ps1"]
Info: I have tried using ".\build.ps1 > output.log" this works while running the build in my local machine. But, in my application build process(via gitlab-ci runner) I'm unable to use this command.
Please suggest a way(other than ".\build.ps1 > output.log") to log all the outputs printed in the console into a file while running build.ps1.
Thanks in advance.
You can persist this information from the Gitlab-ci build by saving it as an artifact. Just add this to your job's description in the gitlab-ci.yml:
artifacts:
name: 'Build output' # or whatever
when: always # or on_success/on_failure depending on your use case
paths:
- output.log
expire_in: 1 day # or 4 hours or however long you want to keep it stored
This way you can look at the output.log file via pipelines > your pipeline > artifacts.

Start a Windows web server in the background with Ansible

I am looking to start a Go web server (a single .exe) on Windows Server via Ansible.
The equivalent in Linux that works great looks like:
- name: Start web server
become: true
become_user: root
shell:
cmd: nohup /home/centos/webserver </dev/null >/dev/null 2>&1 &
I can do it in PowerShell using Start-Process -FilePath -NoNewWindow .\webserver.exe but it terminates when I close the PowerShell window.
I have also looked into doing it with Start-Job { & C:\Path\to\webserver.exe } and Get-Job shows it completed, but not sure what that means since it's a web server and should just keep running until it's killed.
I need something that will star the webserver but not be tied to the shell so Ansible can do it via the win_shell module. I would have hoped this would work, but no luck:
- name: Start the webserver processes
win_shell: Start-Process -FilePath .\webserver.exe
args:
chdir: C:\Users\Administrator
Any and all suggestions much appreciated!
Looks like I was trying to find a more complicated way to do it with PowerShell when Ansible had built in functionality all along. This achieves exactly what I want:
- name: Start webserver
win_shell: .\webserver.exe
args:
chdir: C:\Users\Administrator
async: 180
poll: 0

Ansible command wont output as playbook

Im using ansible 2.7.5 and a windows 10 host over winRM.
If I execute:
ansible win -I hosts -m win_command -a "PowerShell.exe ipconfig"
I get an output and it works fine.
But I want to write it inside a playbook and not as an ansible command but I won't get any output so I tried to use stdout but it wont work:
- hosts: win
gather_facts: no
tasks:
- name: PowerShell Command
win_command: powershell.exe
register: shell_result
args:
stdin: ipconfig
-debug:
var: shell_result.stdout_lines
Any suggestions how to get the first command working as a playbook?
Your - debug task isn't indented properly and doesn't have the right spacing. I'm not sure if that's just from posting here or if it's in your original file.
Your call to powershell.exe left out the - parameter which is what tells it to accept input on stdin. So it should be win_command: powershell.exe -.
That said, ipconfig is actually ipconfig.exe so instead of trying to run a shell with win_command just run ipconfig.exe directly:
- hosts: win
gather_facts: no
tasks:
- name: ipconfig
win_command: ipconfig.exe
register: shell_result
- debug:
var: shell_result.stdout_lines

Timeout when trying to have ansible delete a file on cisco routers

Im having errors in my playbook when I try to delete files from the flash of my cisco IOS router. Below is the code and underneath is the error I am getting
- ios_command:
commands: "delete flash:c1900-universalk9-mz.SPA.155-3.M.bin\r"
FAILED! => {"changed": false, "msg": "timeout trying to send command: delete flash:c1900-universalk9-mz.SPA.155-3.M.bin", "rc": 1}
So the command is asking for confirmation and /r is not working. According to Ansible's documentation you can use the "prompt" parameter with the ios_command module.
Example from Documentation
http://docs.ansible.com/ansible/latest/modules/ios_command_module.html
- name: run command that requires answering a prompt
ios_command:
commands:
- command: 'clear counters GigabitEthernet0/2'
prompt: 'Clear "show interface" counters on this interface [confirm]'
answer: c
And in your case, you should run the command manually to see what the prompt is and the required answer, then fill in the prompt and answer parameters.
Example delete from flash (Update with correct parameters)
- name: run command that requires answering a prompt
ios_command:
commands:
- command: 'delete flash:c1900-universalk9-mz.SPA.155-3.M.bin'
prompt: 'Delete "flash:c1900-universalk9-mz.SPA.155-3.M.bin" from flash [confirm]'
answer: c
Wanted to post this in-case someone else stumbles here in the future. The typical file prompt dialog is as follows and actually requires response for two separate prompts.
switch_name#delete c2960s-universalk9-mz.152-7.E2.bin
Delete filename [c2960s-universalk9-mz.152-7.E2.bin]?
Delete flash:/c2960s-universalk9-mz.152-7.E2.bin? [confirm]
Dealing with two prompts in ansible proved difficult, so I configured "file prompt quiet" on the network switch.
This configuration will make the switch prompt only for confirmation and its easy to confirm in your playbook.
- command: Delete {{ old_image_path }}
prompt: Delete {{ old_image_path }}\? \[confirm\]
answer: 'y'