Looks like I pasted the SecureCredential... file twice (and can't edit/update now). The SecureResource... version is:
SecureResourcePropertiesVariableFunction.cs
using System.Collections;
using System.ComponentModel;
using Inedo.ExecutionEngine.Executer;
using Inedo.Extensibility;
using Inedo.Extensibility.SecureResources;
using Inedo.Extensibility.VariableFunctions;
using Inedo.Serialization;
namespace Inedo.Extensions.VariableFunctions.SecureResources
{
[ScriptAlias("SecureResourceProperties")]
[Description("Gets the properties available to a named Secure Resource. Use `$SecureResourceProperty()` to obtain the value.")]
public sealed class SecureResourcePropertiesVariableFunction : VectorVariableFunction
{
[VariableFunctionParameter(0)]
[ScriptAlias("resource")]
[Description("The name of the Secure Resource for which to fetch property names.")]
public string? ResourceName { get; set; }
[Description("The type of the Secure Resource for which to fetch property names.")]
[ScriptAlias("type")]
[VariableFunctionParameter(1, Optional=true)]
public SecureResourceType? ResourceType { get; set; }
protected override IEnumerable? EvaluateVector(IVariableFunctionContext context)
=> GetPropertyNames(ResourceName, ResourceType, context);
internal static IEnumerable<string> GetPropertyNames(string? resourceName, SecureResourceType? resourceType, IVariableFunctionContext context)
{
var resourceResolutionContext = new ResourceResolutionContext(context.ProjectId);
var secureResource = SecureResource.TryCreate(resourceType.GetValueOrDefault(), resourceName, resourceResolutionContext)
?? throw BadResourceName(resourceName ?? "<null>");
return Persistence.GetPersistentProperties(secureResource.GetType(), true)
.Select(p => p.Name);
}
internal static Exception BadResourceName(string resourceName)
{
return new ExecutionFailureException(string.Concat(
"Could not find a Secure Resource named \"",
resourceName,
"\"; this error may occur if you renamed a resource, " +
"or the application in context does not match any " +
"existing resources. To resolve, edit this item, " +
"property, or operation's configuration, ensure a " +
"valid credential for the application in context is " +
"selected, and then save."));
}
}
[ScriptAlias("SecureResourceHasProperty")]
[Description("Checks if the named property can be read from the named Secure Resource")]
public sealed class SecureResourceHasPropertyVariableFunction : ScalarVariableFunction
{
[VariableFunctionParameter(0)]
[ScriptAlias("resource")]
[Description("The name of the Secure Resource to test.")]
public string? ResourceName { get; set; }
[Description("The name of the property to test.")]
[ScriptAlias("property")]
[VariableFunctionParameter(1)]
public string? PropertyName { get; set; }
[Description("The type of the resource property to test.")]
[ScriptAlias("type")]
[VariableFunctionParameter(2, Optional=true)]
public SecureResourceType? ResourceType { get; set; }
protected override object? EvaluateScalar(IVariableFunctionContext context)
{
if (string.IsNullOrWhiteSpace(PropertyName)) return false;
return SecureResourcePropertiesVariableFunction
.GetPropertyNames(ResourceName, ResourceType, context)
.Contains(PropertyName, StringComparer.InvariantCultureIgnoreCase);
}
}
[ScriptAlias("SecureResourceCredential")]
[Description("Gets the name of the Secure Credential assigned to a Secure Resource")]
public sealed class SecureResourceCredentialVariableFunction : ScalarVariableFunction
{
[VariableFunctionParameter(0)]
[ScriptAlias("resource")]
[Description("Literal text value")]
public string? ResourceName { get; set; }
[Description("The type of the resource property to get.")]
[ScriptAlias("type")]
[VariableFunctionParameter(1, Optional=true)]
public SecureResourceType? ResourceType { get; set; }
protected override object EvaluateScalar(IVariableFunctionContext context)
{
var resourceResolutionContext = new ResourceResolutionContext(context.ProjectId);
var resourceType = ResourceType;
var secureResource = SecureResource.TryCreate(
resourceType.GetValueOrDefault(), ResourceName, resourceResolutionContext)
?? throw SecureResourcePropertiesVariableFunction.BadResourceName(ResourceName ?? "<null>");
return secureResource?.CredentialName
?? string.Empty;
}
}
}

)
(play) button icon against each execution, for which I believe the intention is to re-run any one particular execution with the variable prompts pre-populated with the previously-entered values for that execution.
