为什么自动化框架需要每个PowerShell cmdlet的代理功能?

问题描述 投票:1回答:2

在我的新项目团队中,对于每个powershell cmdlet,他们都编写了代理功能。当我问这种做法的原因时,他们说这是编写自动化框架的正常方式。他们还说如果更改了powershell cmdlet,那么我们不需要担心,我们只需更改一个函数即可。

我从未见过powershell cmdlet功能或名称已更改。

例如,在SQL powershell模块中,他们之前使用了snapin,然后他们更改为模块。但仍然是cmdlet相同。 cmdlet签名没有变化。可能会添加额外的参数。

由于这种代理功能,即使是小任务也需要很长时间。他们的恐惧是无根据的还是正确的?是否有任何更改了powershell cmdlet名称或参数的事件?

powershell
2个回答
1
投票

4c74356b41 makes some good points,但我想知道是否有更简单的方法。

在我重申情况的同时忍受我,只是为了确保我理解它。

我对该问题的理解是,某个cmdlet的使用可能会散布在自动化框架的代码库中。

有一天,在PowerShell或该模块的新版本中,实现发生了变化;可能只是内部,可能是参数(签名)甚至更改的cmdlet名称。

那么问题是,您必须在整个代码中更改所有实现。

因此,使用代理功能,您无法阻止此问题;一个重大改变会打破你的框架,但是想法是修复它会更简单,因为你可以在一个地方修复你自己的代理函数实现,然后所有代码都将被修复。

其他选择

由于命令发现在PowerShell中的工作方式,您可以通过定义具有相同名称的函数或别名来覆盖现有命令。

例如,让我们说Get-Service有一个突破性的变化,你全部使用它(没有代理功能)。

您可以定义自己的Get-Service函数,而不是更改所有代码,代码将使用它。它与你现在所做的基本相同,除了你不必实现数百个“空”代理功能。

为了更好地命名,您可以将函数命名为Get-FrameworkService(或其他内容),然后只需为Get-Service定义Get-FrameworkService的别名。测试这种方式要容易一些。

这样做的一个缺点是读取代码可能不清楚,因为当你在某个地方看到Get-Service时,它可能已被覆盖并不是很明显,如果你真的想调用当前的原始版本,这会使它变得不那么简单。

为此,我建议使用-Prefix导入您将使用的所有模块,然后使所有(可能)可覆盖的调用使用前缀,因此有明确的分界。

这甚至适用于许多“内置”命令,因此您可以使用前缀重新导入模块:

Import-Module Microsoft.PowerShell.Utility -Prefix Overridable -Force

TL; DR

简而言之:

  • 避免制作大量的pass-thru代理功能
  • 导入所有带前缀的模块
  • 需要时创建一个新功能来覆盖另一个功能
  • 然后为prefixed_name -> override_function添加别名

Import-Module Microsoft.PowerShell.Utility -Prefix Overridable -Force
Compare-OverridableObject $a $b

这里不需要代理;以后当你想要覆盖它时:

function Compare-CanonicalObject { <# Stuff #> }
New-Alias Compare-OverridableObject Compare-CanonicalObject

在您看到直接调用的代码中的任何位置:

Compare-Object $c $d

然后你知道:要么故意调用该命令的当前实现(在其他地方可以被覆盖),要么永远不要覆盖此命令。

Advantages:

  • 清晰度:查看代码会告诉您是否可以存在覆盖。
  • 可测试性:编写测试对于重写命令更清晰,更容易,因为它们有自己唯一的名称
  • 可发现性:通过搜索具有正确名称模式的别名,即Get-Alias *-Overridable*,可以发现所有被覆盖的命令
  • 更少的代码
  • 所有覆盖及其别名都可以打包到模块中

3
投票

我想他们想要更加安全。 Powershell会在这里和有时会发生重大变化,但我怀疑你的团队正在做什么会受到影响(考虑到这些事件的罕见性)。例如,我几年前的脚本继续正常运行到现在(并且它们主要是针对PS 2-3开发的)。

我会说这是过度工程,但我不能真的责怪他们。

© www.soinside.com 2019 - 2024. All rights reserved.