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

win_service - Cannot find an overload for "ToString" and the argument count: "0". #125

Closed
cruscio opened this issue Nov 5, 2020 · 4 comments · Fixed by #148
Closed

win_service - Cannot find an overload for "ToString" and the argument count: "0". #125

cruscio opened this issue Nov 5, 2020 · 4 comments · Fixed by #148

Comments

@cruscio
Copy link
Contributor

cruscio commented Nov 5, 2020

SUMMARY

win_service failures trying to stop and remove a service.

The below error happened on 41 of the first 1500 servers I ran the playbook against.
I reran it on just those servers and it kept happening.
The issue is infrequent, but consistent.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ansible.windows.win_service
module file /usr/local/lib/python3.6/site-packages/ansible_collections/ansible/windows/plugins/modules/win_service.ps1

ANSIBLE VERSION
ansible 2.10.3
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Apr 16 2020, 01:36:27) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]
CONFIGURATION
DEFAULT_CALLBACK_WHITELIST(/opt/ansible/ansible.cfg) = ['log_plays']
DEFAULT_FORKS(/opt/ansible/ansible.cfg) = 500
DEFAULT_LOG_PATH(env: ANSIBLE_LOG_PATH) = /var/log/ansible/20201105_175340/ansible.log
OS / ENVIRONMENT

Target:

"ansible_distribution": "Microsoft Windows Server 2012 R2 Datacenter",
"ansible_distribution_version": "6.3.9600.0",
$PSVersionTable
Name                           Value
----                           -----
PSRemotingProtocolVersion      2.3
BuildVersion                   10.0.10586.117
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
PSVersion                      5.0.10586.117
CLRVersion                     4.0.30319.36627
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
STEPS TO REPRODUCE

Run a playbook with a single task to remove the SaltStack minion service

---
- name: Remove Salt Minion Service
  hosts: all
  gather_facts: false
    - name: Saltstack Uninstall | Remove the salt-minion service
      win_service:
        name: salt-minion
        state: absent
EXPECTED RESULTS

On this server, the named service existed and was running.
The win_service task should have stop the service, removed it, and reported a change

ACTUAL RESULTS

Task failed

TASK [Saltstack Uninstall | Remove the salt-minion service] ***********************************************************************************************************************************************************************************************************************
task path: /my/playbook.yml:146
redirecting (type: modules) ansible.builtin.win_service to ansible.windows.win_service
Using module file /usr/local/lib/python3.6/site-packages/ansible_collections/ansible/windows/plugins/modules/win_service.ps1
Pipelining is enabled.
<some.windows.server.com> ESTABLISH WINRM CONNECTION FOR USER: ******** on PORT 5985 TO some.windows.server.com
EXEC (via pipeline wrapper)
The full traceback is:
Cannot find an overload for "ToString" and the argument count: "0".
At line:240 char:28
+ ... vice_type = ConvertTo-ServiceTypeDiff -ServiceType $Service.ServiceTy ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [ConvertTo-ServiceTypeDiff], MethodException
    + FullyQualifiedErrorId : MethodCountCouldNotFindBest,ConvertTo-ServiceTypeDiff

ScriptStackTrace:
at ConvertTo-ServiceTypeDiff, <No file>: line 198
at Get-ServiceDiff, <No file>: line 240
at <ScriptBlock>, <No file>: line 885

System.Management.Automation.MethodException: Cannot find an overload for "ToString" and the argument count: "0".
   at System.Management.Automation.ExceptionHandlingOps.CheckActionPreference(FunctionContext funcContext, Exception exception)
   at System.Management.Automation.Interpreter.ActionCallInstruction`2.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.Interpreter.Run(InterpretedFrame frame)
   at System.Management.Automation.Interpreter.LightLambda.RunVoid1[T0](T0 arg0)
   at System.Management.Automation.PSScriptCmdlet.RunClause(Action`1 clause, Object dollarUnderbar, Object inputToProcess)
   at System.Management.Automation.CommandProcessorBase.Complete()
fatal: [some.windows.server.com]: FAILED! => {
    "changed": false,
    "msg": "Unhandled exception while executing module: Cannot find an overload for \"ToString\" and the argument count: \"0\"."
}
@cruscio
Copy link
Contributor Author

cruscio commented Nov 7, 2020

Spent some time looking at this and I'm not sure, but I think the ToString() doesn't belong there. The whole point of the switch seems to be to convert the enum value back to a string. I'm not comfortable yet saying this will work for all supported versions, but it seems to be working for me. If I can find time to test it a bit more, and can meet the contributor guidelines, I'll submit a pull request

Current code:

Function ConvertTo-ServiceTypeDiff {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [Ansible.Windows.SCManager.ServiceType]
        $ServiceType
    )

    # Converts the enum ServiceType to the valud for a diff.
    $ServiceType = [uint32]$ServiceType -band -bnot [uint32][Ansible.Windows.SCManager.ServiceType]::InteractiveProcess
    $ServiceType = $ServiceType -band -bnot [uint32][Ansible.Windows.SCManager.ServiceType]::UserServiceInstance
    switch (([Ansible.Windows.SCManager.ServiceType]$ServiceType).ToString()) {
        KernelDriver { 'kernel_driver' }
        FileSystemDriver { 'file_system_driver' }
        Adapter { 'adapter' }
        RecognizerDriver { 'recognizer_driver' }
        Win32OwnProcess { 'win32_own_process' }
        Win32ShareProcess { 'win32_share_process' }
        UserOwnprocess { 'user_own_process' }
        UserShareProcess { 'user_share_process' }
        PkgService { 'pkg_service' }
    }
}

Modified (potential fix):

Function ConvertTo-ServiceTypeDiff {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory=$true)]
        [Ansible.Windows.SCManager.ServiceType]
        $ServiceType
    )

    # Converts the enum ServiceType to the valud for a diff.
    $ServiceType = [uint32]$ServiceType -band -bnot [uint32][Ansible.Windows.SCManager.ServiceType]::InteractiveProcess
    $ServiceType = $ServiceType -band -bnot [uint32][Ansible.Windows.SCManager.ServiceType]::UserServiceInstance
    switch ([Ansible.Windows.SCManager.ServiceType]$ServiceType) {
        [Ansible.Windows.SCManager.ServiceType]::KernelDriver { 'kernel_driver' }
        [Ansible.Windows.SCManager.ServiceType]::FileSystemDriver { 'file_system_driver' }
        [Ansible.Windows.SCManager.ServiceType]::Adapter { 'adapter' }
        [Ansible.Windows.SCManager.ServiceType]::RecognizerDriver { 'recognizer_driver' }
        [Ansible.Windows.SCManager.ServiceType]::Win32OwnProcess { 'win32_own_process' }
        [Ansible.Windows.SCManager.ServiceType]::Win32ShareProcess { 'win32_share_process' }
        [Ansible.Windows.SCManager.ServiceType]::UserOwnprocess { 'user_own_process' }
        [Ansible.Windows.SCManager.ServiceType]::UserShareProcess { 'user_share_process' }
        [Ansible.Windows.SCManager.ServiceType]::PkgService { 'pkg_service' }
    }
}

@briantist
Copy link
Contributor

@cruscio I'm not the most familiar with this code but the fix looks sound. Why not put in a PR? Even if you can't run the tests locally, they will be run via the PR so that should help. I'd recommend trying to add a test to catch this before committing the fix, to see if you can get a test executing that properly catches the condition, then hopefully you'll see that test pass after adding the fix to the PR

@jborean93
Copy link
Collaborator

I can't remember why I had it converting to a string, maybe it was just the line length. But your changes seem sound so happy to accept a PR with them and get them merged in.

@jborean93
Copy link
Collaborator

I was only able to replicate this issue when running against WMF 5.0 and seems like a bonafide bug with PowerShell itself at that version. A quick reproducer of this bug is the following

[IO.FileAttributes]$a = 'Archive'
([IO.FileAttributes]$a).ToString()

There seems to be a problem trying to group a cast to an enum type then call .ToString() on that groups output. I have no idea why but it's no longer a problem on 5.1+ (or even on 4.0 and earlier). I went a slightly different way to the switch as you've proposed just to keep the code mostly the same but when testing against a 5.0 instance it works just fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants