GitHub Actions Runner

This commit is contained in:
Tingluo Huang
2019-10-10 00:52:42 -04:00
commit c8afc84840
1255 changed files with 198670 additions and 0 deletions

View File

@@ -0,0 +1,79 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class AgentJobRequestMessage : JobRequestMessage
{
[JsonConstructor]
internal AgentJobRequestMessage() : base(JobRequestMessageTypes.AgentJobRequest)
{
}
public AgentJobRequestMessage(
TaskOrchestrationPlanReference plan,
TimelineReference timeline,
Guid jobId,
String jobName,
String jobRefName,
JobEnvironment environment,
IEnumerable<TaskInstance> tasks)
: base(JobRequestMessageTypes.AgentJobRequest, plan, timeline, jobId, jobName, jobRefName, environment)
{
m_tasks = new List<TaskInstance>(tasks);
}
[DataMember]
public Int64 RequestId
{
get;
internal set;
}
[DataMember]
public Guid LockToken
{
get;
internal set;
}
[DataMember]
public DateTime LockedUntil
{
get;
internal set;
}
public ReadOnlyCollection<TaskInstance> Tasks
{
get
{
if (m_tasks == null)
{
m_tasks = new List<TaskInstance>();
}
return m_tasks.AsReadOnly();
}
}
public TaskAgentMessage GetAgentMessage()
{
var body = JsonUtility.ToString(this);
return new TaskAgentMessage
{
Body = body,
MessageType = JobRequestMessageTypes.AgentJobRequest
};
}
[DataMember(Name = "Tasks", EmitDefaultValue = false)]
private List<TaskInstance> m_tasks;
}
}

View File

@@ -0,0 +1,49 @@
using Newtonsoft.Json;
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class AgentRefreshMessage
{
public static readonly String MessageType = "AgentRefresh";
[JsonConstructor]
internal AgentRefreshMessage()
{
}
public AgentRefreshMessage(
Int32 agentId,
String targetVersion,
TimeSpan? timeout = null)
{
this.AgentId = agentId;
this.Timeout = timeout ?? TimeSpan.FromMinutes(60);
this.TargetVersion = targetVersion;
}
[DataMember]
public Int32 AgentId
{
get;
private set;
}
[DataMember]
public TimeSpan Timeout
{
get;
private set;
}
[DataMember]
public String TargetVersion
{
get;
private set;
}
}
}

View File

@@ -0,0 +1,19 @@
namespace GitHub.DistributedTask.WebApi
{
using System.Runtime.Serialization;
public enum AuditAction
{
[EnumMember]
Add = 1,
[EnumMember]
Update = 2,
[EnumMember]
Delete = 3,
[EnumMember]
Undelete = 4
}
}

View File

@@ -0,0 +1,30 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureKeyVaultVariableGroupProviderData : VariableGroupProviderData
{
[DataMember(EmitDefaultValue = true)]
public Guid ServiceEndpointId
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public String Vault
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public DateTime LastRefreshedOn
{
get;
set;
}
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureKeyVaultVariableValue: VariableValue
{
public AzureKeyVaultVariableValue()
{
}
public AzureKeyVaultVariableValue(AzureKeyVaultVariableValue value)
: this(value.Value, value.IsSecret, value.Enabled, value.ContentType, value.Expires)
{
}
public AzureKeyVaultVariableValue(String value, Boolean isSecret, Boolean enabled, String contentType, DateTime? expires)
:base(value, isSecret)
{
Enabled = enabled;
ContentType = contentType;
Expires = expires;
}
[DataMember(EmitDefaultValue = true)]
public Boolean Enabled
{
get;
set;
}
[DataMember(EmitDefaultValue = true)]
public String ContentType
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public DateTime? Expires
{
get;
set;
}
}
}

View File

@@ -0,0 +1,103 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Text.RegularExpressions;
using GitHub.Services.Common;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
[JsonConverter(typeof(DemandJsonConverter))]
public abstract class Demand
{
protected Demand(
String name,
String value)
{
ArgumentUtility.CheckStringForNullOrEmpty(name, "name");
this.Name = name;
this.Value = value;
}
[DataMember]
public String Name
{
get;
private set;
}
[DataMember(EmitDefaultValue = false)]
public String Value
{
get;
private set;
}
public override sealed Boolean Equals(Object obj)
{
Demand demand = obj as Demand;
return demand != null && demand.ToString().Equals(this.ToString(), StringComparison.OrdinalIgnoreCase);
}
public override sealed Int32 GetHashCode()
{
return this.ToString().ToUpperInvariant().GetHashCode();
}
public override sealed String ToString()
{
return GetExpression();
}
public abstract Demand Clone();
protected abstract String GetExpression();
public abstract Boolean IsSatisfied(IDictionary<String, String> capabilities);
public static Boolean TryParse(
String input,
out Demand demand)
{
demand = null;
Match match = s_demandRegex.Match(input);
if (!match.Success)
{
return false;
}
String name = match.Groups["name"].Value;
String opcode = match.Groups["opcode"].Value;
String value = match.Groups["value"].Value;
if (String.IsNullOrEmpty(opcode))
{
demand = new DemandExists(name);
}
else
{
switch (opcode)
{
case "equals":
demand = new DemandEquals(name, value);
break;
case "gtVersion":
demand = new DemandMinimumVersion(name, value);
break;
}
}
return demand != null;
}
public void Update(String value)
{
ArgumentUtility.CheckStringForNullOrEmpty(value, "value");
this.Value = value;
}
private static readonly Regex s_demandRegex = new Regex(@"^(?<name>\S+)(\s+\-(?<opcode>\S+)\s+(?<value>.*))?$", RegexOptions.Compiled);
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Runtime.Serialization;
using GitHub.Services.Common;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class DemandEquals : Demand
{
public DemandEquals(
String name,
String value)
: base(name, value)
{
ArgumentUtility.CheckStringForNullOrEmpty(value, "value");
}
public override Demand Clone()
{
return new DemandEquals(this.Name, this.Value);
}
protected override String GetExpression()
{
return String.Format(CultureInfo.InvariantCulture, "{0} -equals {1}", this.Name, this.Value);
}
public override Boolean IsSatisfied(IDictionary<String, String> capabilities)
{
String value;
return capabilities.TryGetValue(this.Name, out value) && this.Value.Equals(value, StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class DemandExists : Demand
{
public DemandExists(String name)
: base(name, null)
{
}
public override Demand Clone()
{
return new DemandExists(this.Name);
}
protected override String GetExpression()
{
return this.Name;
}
public override Boolean IsSatisfied(IDictionary<String, String> capabilities)
{
return capabilities.ContainsKey(this.Name);
}
public new void Update(String value)
{
// Exists can not override value
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,45 @@
using GitHub.Services.WebApi;
using Newtonsoft.Json;
using System;
using System.Reflection;
namespace GitHub.DistributedTask.WebApi
{
internal sealed class DemandJsonConverter : VssSecureJsonConverter
{
public override Boolean CanConvert(Type objectType)
{
return typeof(Demand).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
if (existingValue == null && reader.TokenType == JsonToken.String)
{
Demand demand;
if (Demand.TryParse((String)reader.Value, out demand))
{
existingValue = demand;
}
}
return existingValue;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
base.WriteJson(writer, value, serializer);
if (value != null)
{
writer.WriteValue(value.ToString());
}
}
}
}

View File

@@ -0,0 +1,127 @@
using GitHub.DistributedTask.Pipelines;
using GitHub.Services.Common;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class DemandMinimumVersion : Demand
{
public DemandMinimumVersion(
String name,
String value)
: base(name, value)
{
ArgumentUtility.CheckStringForNullOrEmpty(value, "value");
}
public override Demand Clone()
{
return new DemandMinimumVersion(this.Name, this.Value);
}
protected override String GetExpression()
{
return String.Format(CultureInfo.InvariantCulture, "{0} -gtVersion {1}", this.Name, this.Value);
}
public override Boolean IsSatisfied(IDictionary<String, String> capabilities)
{
String value;
if (capabilities.TryGetValue(this.Name, out value))
{
// return true if our version is less than or equal to the capability version from the agent
return CompareVersion(this.Value, value) <= 0;
}
// same as capabilityVersion == null
return false;
}
public static Int32 CompareVersion(String semanticVersion1, String semanticVersion2)
{
// compare == first - second (-1 means second is greater, 1 means first is greater, 0 means they are equal)
Version version1 = ParseVersion(semanticVersion1);
Version version2 = ParseVersion(semanticVersion2);
if (version1 == null && version2 == null)
{
// they are both null, so they are equal
return 0;
}
else if (version1 == null)
{
// version2 is greater
return -1;
}
else if (version2 == null)
{
// version1 is greater
return 1;
}
return version1.CompareTo(version2);
}
/// <summary>
/// Gets the minimum agent version demand from the specified set of demands. Agent version demands are removed
/// from the input set.
/// </summary>
/// <param name="demands">The demands</param>
/// <returns>The highest minimum version required based in the input set</returns>
public static DemandMinimumVersion MaxAndRemove(ISet<Demand> demands)
{
DemandMinimumVersion minAgentVersion = null;
var demandsCopy = demands.Where(x => x.Name.Equals(PipelineConstants.AgentVersionDemandName, StringComparison.OrdinalIgnoreCase)).OfType<DemandMinimumVersion>().ToList();
foreach (var demand in demandsCopy)
{
if (minAgentVersion == null || CompareVersion(demand.Value, minAgentVersion.Value) > 0)
{
minAgentVersion = demand;
}
demands.Remove(demand);
}
return minAgentVersion;
}
public static DemandMinimumVersion Max(IEnumerable<Demand> demands)
{
DemandMinimumVersion minAgentVersion = null;
foreach (var demand in demands.Where(x => x.Name.Equals(PipelineConstants.AgentVersionDemandName, StringComparison.OrdinalIgnoreCase)).OfType<DemandMinimumVersion>())
{
if (minAgentVersion == null || CompareVersion(demand.Value, minAgentVersion.Value) > 0)
{
minAgentVersion = demand;
}
}
return minAgentVersion;
}
public static Version ParseVersion(String versionString)
{
Version version = null;
if (!String.IsNullOrEmpty(versionString))
{
int index = versionString.IndexOf('-');
if (index > 0)
{
versionString = versionString.Substring(0, index);
}
if (!Version.TryParse(versionString, out version))
{
// If we couldn't parse it, set it back to null
version = null;
}
}
return version;
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment group.
/// </summary>
[DataContract]
public class DeploymentGroup : DeploymentGroupReference
{
/// <summary>
/// Number of deployment targets in the deployment group.
/// </summary>
[DataMember]
public Int32 MachineCount
{
get;
internal set;
}
/// <summary>
/// List of deployment targets in the deployment group.
/// </summary>
public IList<DeploymentMachine> Machines
{
get
{
if (m_machines == null)
{
m_machines = new List<DeploymentMachine>();
}
return m_machines;
}
internal set
{
m_machines = value;
}
}
/// <summary>
/// Description of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
/// <summary>
/// List of unique tags across all deployment targets in the deployment group.
/// </summary>
public IList<String> MachineTags
{
get
{
if (m_tags == null)
{
m_tags = new List<String>();
}
return m_tags;
}
internal set
{
m_tags = value;
}
}
/// <summary>
/// List of deployment targets in the deployment group.
/// </summary>
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Machines")]
private IList<DeploymentMachine> m_machines;
/// <summary>
/// List of unique tags across all deployment targets in the deployment group.
/// </summary>
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "MachineTags")]
private IList<String> m_tags;
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// This is useful in getting a list of deployment groups, filtered for which caller has permissions to take a particular action.
/// </summary>
[Flags]
[DataContract]
public enum DeploymentGroupActionFilter
{
/// <summary>
/// All deployment groups.
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Only deployment groups for which caller has **manage** permission.
/// </summary>
[EnumMember]
Manage = 2,
/// <summary>
/// Only deployment groups for which caller has **use** permission.
/// </summary>
[EnumMember]
Use = 16,
}
}

View File

@@ -0,0 +1,72 @@
using GitHub.Services.WebApi;
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to create Deployment group.
/// </summary>
[DataContract]
public class DeploymentGroupCreateParameter
{
/// <summary>
/// Name of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Description of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
/// <summary>
/// Identifier of the deployment pool in which deployment agents are registered.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 PoolId
{
get;
set;
}
/// <summary>
/// Deployment pool in which deployment agents are registered.
/// This is obsolete. Kept for compatibility. Will be marked obsolete explicitly by M132.
/// </summary>
[DataMember(EmitDefaultValue = false)]
[ClientInternalUseOnly(OmitFromTypeScriptDeclareFile = false)]
public DeploymentGroupCreateParameterPoolProperty Pool
{
get;
set;
}
}
/// <summary>
/// Properties of Deployment pool to create Deployment group.
/// </summary>
[DataContract]
public class DeploymentGroupCreateParameterPoolProperty
{
/// <summary>
/// Deployment pool identifier.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 Id
{
get;
set;
}
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to be included or expanded in deployment group objects. This is useful when getting a single or list of deployment grouops.
/// </summary>
[Flags]
[DataContract]
public enum DeploymentGroupExpands
{
/// <summary>
/// No additional properties.
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Deprecated: Include all the deployment targets.
/// </summary>
[EnumMember]
Machines = 2,
/// <summary>
/// Include unique list of tags across all deployment targets.
/// </summary>
[EnumMember]
Tags = 4
}
}

View File

@@ -0,0 +1,62 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment group metrics.
/// </summary>
[DataContract]
public sealed class DeploymentGroupMetrics
{
/// <summary>
/// Deployment group.
/// </summary>
[DataMember]
public DeploymentGroupReference DeploymentGroup
{
get;
internal set;
}
/// <summary>
/// List of deployment group properties. And types of metrics provided for those properties.
/// </summary>
[DataMember]
public MetricsColumnsHeader ColumnsHeader
{
get;
internal set;
}
/// <summary>
/// Values of properties and the metrics.
/// E.g. 1: total count of deployment targets for which 'TargetState' is 'offline'.
/// E.g. 2: Average time of deployment to the deployment targets for which 'LastJobStatus' is 'passed' and 'TargetState' is 'online'.
/// </summary>
public IList<MetricsRow> Rows
{
get
{
if (m_rows == null)
{
m_rows = new List<MetricsRow>();
}
return m_rows;
}
internal set
{
m_rows = value;
}
}
/// <summary>
/// Values of properties and the metrics.
/// E.g. 1: total count of deployment targets for which 'TargetState' is 'offline'.
/// E.g. 2: Average time of deployment to the deployment targets for which 'LastJobStatus' is 'passed' and 'TargetState' is 'online'.
/// </summary>
[DataMember(Name = "Rows")]
private IList<MetricsRow> m_rows;
}
}

View File

@@ -0,0 +1,90 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment group reference. This is useful for referring a deployment group in another object.
/// </summary>
[DataContract]
public class DeploymentGroupReference
{
[JsonConstructor]
public DeploymentGroupReference()
{
}
private DeploymentGroupReference(DeploymentGroupReference referenceToClone)
{
this.Id = referenceToClone.Id;
this.Name = referenceToClone.Name;
if (referenceToClone.Project != null)
{
this.Project = new ProjectReference
{
Id = referenceToClone.Project.Id,
Name = referenceToClone.Project.Name,
};
}
if (referenceToClone.Pool != null)
{
this.Pool = new TaskAgentPoolReference
{
Id = referenceToClone.Pool.Id,
IsHosted = referenceToClone.Pool.IsHosted,
Name = referenceToClone.Pool.Name,
PoolType = referenceToClone.Pool.PoolType,
Scope = referenceToClone.Pool.Scope,
};
}
}
/// <summary>
/// Deployment group identifier.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 Id
{
get;
internal set;
}
/// <summary>
/// Project to which the deployment group belongs.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public ProjectReference Project
{
get;
internal set;
}
/// <summary>
/// Name of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Deployment pool in which deployment agents are registered.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentPoolReference Pool
{
get;
set;
}
public virtual DeploymentGroupReference Clone()
{
return new DeploymentGroupReference(this);
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment group update parameter.
/// </summary>
[DataContract]
public class DeploymentGroupUpdateParameter
{
/// <summary>
/// Name of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Description of the deployment group.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
}
}

View File

@@ -0,0 +1,99 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment target.
/// </summary>
[DataContract]
public class DeploymentMachine : ICloneable
{
public DeploymentMachine()
{
}
private DeploymentMachine(DeploymentMachine machineToBeCloned)
{
this.Id = machineToBeCloned.Id;
this.Tags = (Tags == null) ? null : new List<String>(machineToBeCloned.Tags);
this.Agent = machineToBeCloned.Agent?.Clone();
}
/// <summary>
/// Deployment target Identifier.
/// </summary>
[DataMember]
public Int32 Id
{
get;
set;
}
/// <summary>
/// Tags of the deployment target.
/// </summary>
public IList<String> Tags
{
get
{
return m_tags;
}
set
{
m_tags = value;
}
}
/// <summary>
/// Deployment agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgent Agent
{
get;
set;
}
public PropertiesCollection Properties
{
get
{
if (m_properties == null)
{
m_properties = new PropertiesCollection();
}
return m_properties;
}
internal set
{
m_properties = value;
}
}
object ICloneable.Clone()
{
return this.Clone();
}
public DeploymentMachine Clone()
{
return new DeploymentMachine(this);
}
/// <summary>
/// Tags of the deployment target.
/// </summary>
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Tags")]
private IList<String> m_tags;
/// <summary>
/// Properties of the deployment target.
/// </summary>
[DataMember(EmitDefaultValue = false, Name = "Properties")]
private PropertiesCollection m_properties;
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[Flags]
[DataContract]
public enum DeploymentMachineExpands
{
[EnumMember]
None = 0,
[EnumMember]
Capabilities = 2,
[EnumMember]
AssignedRequest = 4
}
}

View File

@@ -0,0 +1,38 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class DeploymentMachineGroup : DeploymentMachineGroupReference
{
[DataMember]
public Int32 Size
{
get;
internal set;
}
public IList<DeploymentMachine> Machines
{
get
{
if (m_machines == null)
{
m_machines = new List<DeploymentMachine>();
}
return m_machines;
}
internal set
{
m_machines = value;
}
}
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Machines")]
private IList<DeploymentMachine> m_machines;
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class DeploymentMachineGroupReference
{
[DataMember(EmitDefaultValue = false)]
public Int32 Id
{
get;
internal set;
}
[DataMember(EmitDefaultValue = false)]
public ProjectReference Project
{
get;
internal set;
}
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public TaskAgentPoolReference Pool
{
get;
set;
}
}
}

View File

@@ -0,0 +1,78 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment pool summary.
/// </summary>
[DataContract]
public sealed class DeploymentPoolSummary
{
/// <summary>
/// Deployment pool.
/// </summary>
[DataMember]
public TaskAgentPoolReference Pool
{
get;
internal set;
}
/// <summary>
/// Number of deployment agents that are online.
/// </summary>
[DataMember]
public Int32 OnlineAgentsCount
{
get;
internal set;
}
/// <summary>
/// Number of deployment agents that are offline.
/// </summary>
[DataMember]
public Int32 OfflineAgentsCount
{
get;
internal set;
}
/// <summary>
/// Virtual machine Resource referring in pool.
/// </summary>
[DataMember]
public EnvironmentResourceReference Resource
{
get;
internal set;
}
/// <summary>
/// List of deployment groups referring to the deployment pool.
/// </summary>
public IList<DeploymentGroupReference> DeploymentGroups
{
get
{
if (m_deploymentGroups == null)
{
m_deploymentGroups = new List<DeploymentGroupReference>();
}
return m_deploymentGroups;
}
internal set
{
m_deploymentGroups = value;
}
}
/// <summary>
/// List of deployment groups referring to the deployment pool.
/// </summary>
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "DeploymentGroups")]
private IList<DeploymentGroupReference> m_deploymentGroups;
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to be included or expanded in deployment pool summary objects. This is useful when getting a single or list of deployment pool summaries.
/// </summary>
[Flags]
[DataContract]
public enum DeploymentPoolSummaryExpands
{
/// <summary>
/// No additional properties
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Include deployment groups referring to the deployment pool.
/// </summary>
[EnumMember]
DeploymentGroups = 2,
/// <summary>
/// Include Resource referring to the deployment pool.
/// </summary>
[EnumMember]
Resource = 4
}
}

View File

@@ -0,0 +1,37 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to be included or expanded in deployment target objects. This is useful when getting a single or list of deployment targets.
/// </summary>
[Flags]
[DataContract]
public enum DeploymentTargetExpands
{
/// <summary>
/// No additional properties.
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Include capabilities of the deployment agent.
/// </summary>
[EnumMember]
Capabilities = 2,
/// <summary>
/// Include the job request assigned to the deployment agent.
/// </summary>
[EnumMember]
AssignedRequest = 4,
/// <summary>
/// Include the last completed job request of the deployment agent.
/// </summary>
[EnumMember]
LastCompletedRequest = 8
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Deployment target update parameter.
/// </summary>
[DataContract]
public class DeploymentTargetUpdateParameter
{
/// <summary>
/// Identifier of the deployment target.
/// </summary>
[DataMember]
public Int32 Id
{
get;
set;
}
/// <summary>
/// Tags of the deployment target..
/// </summary>
public IList<String> Tags
{
get
{
return m_tags;
}
set
{
m_tags = value;
}
}
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Tags")]
private IList<String> m_tags;
}
}

View File

@@ -0,0 +1,36 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class DiagnosticLogMetadata
{
public DiagnosticLogMetadata(string agentName, int agentId, int poolId, string phaseName, string fileName, string phaseResult)
{
AgentName = agentName;
AgentId = agentId;
PoolId = poolId;
PhaseName = phaseName;
FileName = fileName;
PhaseResult = phaseResult;
}
[DataMember]
public string AgentName { get; set; }
[DataMember]
public int AgentId { get; set; }
[DataMember]
public int PoolId { get; set; }
[DataMember]
public string PhaseName { get; set; }
[DataMember]
public string FileName { get; set; }
[DataMember]
public string PhaseResult { get; set; }
}
}

View File

@@ -0,0 +1,10 @@
namespace GitHub.DistributedTask.WebApi
{
public enum EnableAccessTokenType
{
None,
Variable,
True = Variable,
SecretVariable,
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to create Environment.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentCreateParameter
{
/// <summary>
/// Name of the environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Description of the environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
}
}

View File

@@ -0,0 +1,192 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// EnvironmentDeploymentExecutionRecord.
/// </summary>
[DataContract]
public class EnvironmentDeploymentExecutionRecord
{
/// <summary>
/// Id of the Environment deployment execution history record
/// </summary>
[DataMember]
public Int64 Id
{
get;
set;
}
/// <summary>
/// Request identifier of the Environment deployment execution history record
/// </summary>
[DataMember]
public String RequestIdentifier
{
get;
set;
}
/// <summary>
/// Id of the Environment
/// </summary>
[DataMember]
public Int32 EnvironmentId
{
get;
set;
}
/// <summary>
/// Service owner Id
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Guid ServiceOwner
{
get;
set;
}
/// <summary>
/// Project Id
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Guid ScopeId
{
get;
set;
}
/// <summary>
/// Resource Id
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32? ResourceId
{
get;
set;
}
/// <summary>
/// Plan type of the environment deployment execution record
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String PlanType
{
get;
set;
}
/// <summary>
/// Plan Id
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Guid PlanId
{
get;
set;
}
/// <summary>
/// Stage name
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String StageName
{
get;
set;
}
/// <summary>
/// Job name
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String JobName
{
get;
set;
}
/// <summary>
/// Stage Attempt
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 StageAttempt
{
get;
set;
}
/// <summary>
/// Job Attempt
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 JobAttempt
{
get;
set;
}
/// <summary>
/// Definition of the environment deployment execution owner
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskOrchestrationOwner Definition
{
get;
set;
}
/// <summary>
/// Owner of the environment deployment execution record
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskOrchestrationOwner Owner
{
get;
set;
}
/// <summary>
/// Result of the environment deployment execution
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskResult? Result
{
get;
set;
}
/// <summary>
/// Queue time of the environment deployment execution
/// </summary>
[DataMember(EmitDefaultValue = false)]
public DateTime QueueTime
{
get;
set;
}
/// <summary>
/// Start time of the environment deployment execution
/// </summary>
[DataMember(EmitDefaultValue = false)]
public DateTime? StartTime
{
get;
set;
}
/// <summary>
/// Finish time of the environment deployment execution
/// </summary>
[DataMember(EmitDefaultValue = false)]
public DateTime? FinishTime
{
get;
set;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to be included or expanded in environment objects. This is useful when getting a single environment.
/// </summary>
[Flags]
[DataContract]
public enum EnvironmentExpands
{
/// <summary>
/// No additional properties
/// </summary>
[EnumMember]
None = 0,
/// <summary>
/// Include resource references referring to the environment.
/// </summary>
[EnumMember]
ResourceReferences = 1
}
}

View File

@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Environment.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentInstance
{
/// <summary>
/// Id of the Environment
/// </summary>
[DataMember]
public Int32 Id
{
get;
set;
}
/// <summary>
/// Name of the Environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Description of the Environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
/// <summary>
/// Identity reference of the user who created the Environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public IdentityRef CreatedBy
{
get;
set;
}
/// <summary>
/// Creation time of the Environment
/// </summary>
[DataMember]
public DateTime CreatedOn
{
get;
set;
}
/// <summary>
/// Identity reference of the user who last modified the Environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public IdentityRef LastModifiedBy
{
get;
set;
}
/// <summary>
/// Last modified time of the Environment
/// </summary>
[DataMember]
public DateTime LastModifiedOn
{
get;
set;
}
/// <summary>
/// List of resources
/// </summary>
public IList<EnvironmentResourceReference> Resources
{
get
{
if (this.resources == null)
{
this.resources = new List<EnvironmentResourceReference>();
}
return this.resources;
}
}
/// <summary>
/// Resources that defined or used for this environment.
/// We use this for deployment job's resource authorization.
/// </summary>
public Pipelines.PipelineResources ReferencedResources
{
get;
set;
}
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Resources")]
private IList<EnvironmentResourceReference> resources;
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// EnvironmentLinkedResourceReference.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentLinkedResourceReference
{
/// <summary>
/// Id of the resource.
/// </summary>
[DataMember]
public String Id
{
get;
set;
}
/// <summary>
/// Type of resource.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String TypeName
{
get;
set;
}
}
}

View File

@@ -0,0 +1,18 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentReference
{
[DataMember]
public Int32 Id { get; set; }
[DataMember]
public String Name { get; set; }
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public abstract class EnvironmentResource
{
[DataMember]
public Int32 Id { get; set; }
[DataMember]
public String Name { get; set; }
/// <summary>
/// Environment resource type
/// </summary>
[DataMember]
public EnvironmentResourceType Type { get; set; }
[DataMember]
public IdentityRef CreatedBy { get; set; }
[DataMember]
public DateTime CreatedOn { get; set; }
[DataMember]
public IdentityRef LastModifiedBy { get; set; }
[DataMember]
public DateTime LastModifiedOn { get; set; }
[DataMember]
public EnvironmentReference EnvironmentReference { get; set; }
protected EnvironmentResource()
{
Name = string.Empty;
CreatedBy = new IdentityRef();
LastModifiedBy = new IdentityRef();
this.EnvironmentReference = new EnvironmentReference();
}
}
}

View File

@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// EnvironmentResourceReference.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentResourceReference
{
/// <summary>
/// Id of the resource.
/// </summary>
[DataMember]
public Int32 Id
{
get;
set;
}
/// <summary>
/// Name of the resource.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Type of the resource.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public EnvironmentResourceType Type
{
get;
set;
}
/// <summary>
/// List of linked resources
/// </summary>
public IList<EnvironmentLinkedResourceReference> LinkedResources
{
get
{
if (m_linkedResources == null)
{
m_linkedResources = new List<EnvironmentLinkedResourceReference>();
}
return m_linkedResources;
}
}
private IList<EnvironmentLinkedResourceReference> m_linkedResources;
}
}

View File

@@ -0,0 +1,31 @@
using System;
using System.ComponentModel;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// EnvironmentResourceType.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[Flags]
public enum EnvironmentResourceType
{
Undefined = 0,
/// <summary>
/// Unknown resource type
/// </summary>
Generic = 1,
/// <summary>
/// Virtual machine resource type
/// </summary>
VirtualMachine = 2,
/// <summary>
/// Kubernetes resource type
/// </summary>
Kubernetes = 4
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Properties to update Environment.
/// </summary>
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class EnvironmentUpdateParameter
{
/// <summary>
/// Name of the environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Description of the environment.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Description
{
get;
set;
}
}
}

View File

@@ -0,0 +1,20 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class KubernetesResource : EnvironmentResource
{
[DataMember]
public String Namespace { get; set; }
[DataMember]
public String ClusterName { get; set; }
[DataMember]
public Guid ServiceEndpointId { get; set; }
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class KubernetesResourceCreateParameters
{
[DataMember]
public String Name { get; set; }
[DataMember]
public String Namespace { get; set; }
[DataMember]
public String ClusterName { get; set; }
[DataMember]
public Guid ServiceEndpointId { get; set; }
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class VirtualMachine
{
[DataMember]
public Int32 Id { get; set; }
[DataMember]
public TaskAgent Agent { get; set; }
/// <summary>
/// List of tags
/// </summary>
public IList<String> Tags
{
get
{
if (this.tags == null)
{
this.tags = new List<String>();
}
return this.tags;
}
set
{
this.tags = value;
}
}
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Tags")]
private IList<String> tags;
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class VirtualMachineGroup : EnvironmentResource
{
[DataMember]
public Int32 PoolId { get; set; }
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class VirtualMachineGroupCreateParameters
{
[DataMember]
public String Name { get; set; }
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class ExpressionValidationItem : ValidationItem
{
public ExpressionValidationItem()
: base(InputValidationTypes.Expression)
{
}
}
}

View File

@@ -0,0 +1,172 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Runtime.Serialization;
using GitHub.DistributedTask.Pipelines;
using GitHub.Services.WebApi;
using GitHub.Services.WebApi.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GitHub.DistributedTask.WebApi
{
[ClientIgnore]
[DataContract]
[EditorBrowsable(EditorBrowsableState.Never)]
public enum OrchestrationProcessType
{
[DataMember]
Container = 1,
[DataMember]
Pipeline = 2,
}
[EditorBrowsable(EditorBrowsableState.Never)]
[JsonConverter(typeof(OrchestrationEnvironmentJsonConverter))]
public interface IOrchestrationEnvironment
{
OrchestrationProcessType ProcessType { get; }
IDictionary<String, VariableValue> Variables { get; }
}
[EditorBrowsable(EditorBrowsableState.Never)]
[JsonConverter(typeof(OrchestrationProcessJsonConverter))]
public interface IOrchestrationProcess
{
OrchestrationProcessType ProcessType { get; }
}
internal sealed class OrchestrationProcessJsonConverter : VssSecureJsonConverter
{
public override Boolean CanWrite
{
get
{
return false;
}
}
public override Boolean CanConvert(Type objectType)
{
return typeof(IOrchestrationProcess).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.StartObject)
{
return null;
}
JObject value = JObject.Load(reader);
IOrchestrationProcess process = null;
if (value.TryGetValue("stages", StringComparison.OrdinalIgnoreCase, out _) ||
value.TryGetValue("phases", StringComparison.OrdinalIgnoreCase, out _))
{
process = new PipelineProcess();
}
else if (value.TryGetValue("children", StringComparison.OrdinalIgnoreCase, out _))
{
process = new TaskOrchestrationContainer();
}
if (process != null)
{
using (var objectReader = value.CreateReader())
{
serializer.Populate(objectReader, process);
}
}
return process;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
internal sealed class OrchestrationEnvironmentJsonConverter : VssSecureJsonConverter
{
public override Boolean CanWrite
{
get
{
return false;
}
}
public override Boolean CanConvert(Type objectType)
{
return typeof(IOrchestrationEnvironment).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.StartObject)
{
return null;
}
JToken propertyValue;
JObject value = JObject.Load(reader);
IOrchestrationEnvironment environment = null;
OrchestrationProcessType processType = OrchestrationProcessType.Container;
if (value.TryGetValue("ProcessType", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
if (propertyValue.Type == JTokenType.Integer)
{
processType = (OrchestrationProcessType)(Int32)propertyValue;
}
else if (propertyValue.Type != JTokenType.String || !Enum.TryParse((String)propertyValue, true, out processType))
{
return null;
}
}
switch (processType)
{
case OrchestrationProcessType.Container:
environment = new PlanEnvironment();
break;
case OrchestrationProcessType.Pipeline:
environment = new PipelineEnvironment();
break;
}
if (environment != null)
{
using (var objectReader = value.CreateReader())
{
serializer.Populate(objectReader, environment);
}
}
return environment;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
public interface ITaskDefinitionReference
{
Guid Id { get; }
String Name { get; }
String Version { get; }
}
}

View File

@@ -0,0 +1,27 @@
using GitHub.Services.WebApi;
namespace GitHub.DistributedTask.WebApi
{
internal static class IdentityRefExtensions
{
public static IdentityRef Clone(this IdentityRef source)
{
if (source == null)
{
return null;
}
return new IdentityRef
{
DisplayName = source.DisplayName,
Id = source.Id,
ImageUrl = source.ImageUrl,
IsAadIdentity = source.IsAadIdentity,
IsContainer = source.IsContainer,
ProfileUrl = source.ProfileUrl,
UniqueName = source.UniqueName,
Url = source.Url,
};
}
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class InputBindingContext
{
/// <summary>
/// Value of the input
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Value
{
get;
set;
}
}
}

View File

@@ -0,0 +1,23 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class InputValidationItem : ValidationItem
{
public InputValidationItem()
: base(InputValidationTypes.Input)
{
}
/// <summary>
/// Provides binding context for the expression to evaluate
/// </summary>
[DataMember(EmitDefaultValue = false)]
public InputBindingContext Context
{
get;
set;
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class Issue
{
public Issue()
{
}
private Issue(Issue issueToBeCloned)
{
this.Type = issueToBeCloned.Type;
this.Category = issueToBeCloned.Category;
this.Message = issueToBeCloned.Message;
if (issueToBeCloned.m_data != null)
{
foreach (var item in issueToBeCloned.m_data)
{
this.Data.Add(item);
}
}
}
[DataMember(Order = 1)]
public IssueType Type
{
get;
set;
}
[DataMember(Order = 2)]
public String Category
{
get;
set;
}
[DataMember(Order = 3)]
public String Message
{
get;
set;
}
public IDictionary<String, String> Data
{
get
{
if (m_data == null)
{
m_data = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_data;
}
}
public Issue Clone()
{
return new Issue(this);
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
SerializationHelper.Copy(ref m_serializedData, ref m_data, StringComparer.OrdinalIgnoreCase, true);
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
SerializationHelper.Copy(ref m_data, ref m_serializedData, StringComparer.OrdinalIgnoreCase);
}
[OnSerialized]
private void OnSerialized(StreamingContext context)
{
m_serializedData = null;
}
[DataMember(Name = "Data", EmitDefaultValue = false, Order = 4)]
private IDictionary<String, String> m_serializedData;
private IDictionary<String, String> m_data;
}
}

View File

@@ -0,0 +1,14 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public enum IssueType
{
[EnumMember]
Error = 1,
[EnumMember]
Warning = 2
}
}

View File

@@ -0,0 +1,47 @@
using System;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class JobCancelMessage
{
public static readonly String MessageType = "JobCancellation";
[JsonConstructor]
internal JobCancelMessage()
{
}
public JobCancelMessage(Guid jobId, TimeSpan timeout)
{
this.JobId = jobId;
this.Timeout = timeout;
}
[DataMember]
public Guid JobId
{
get;
private set;
}
[DataMember]
public TimeSpan Timeout
{
get;
private set;
}
public TaskAgentMessage GetAgentMessage()
{
return new TaskAgentMessage
{
Body = JsonUtility.ToString(this),
MessageType = JobCancelMessage.MessageType,
};
}
}
}

View File

@@ -0,0 +1,294 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using GitHub.DistributedTask.Pipelines;
using GitHub.Services.Common;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Represents the context of variables and vectors for a job request.
/// </summary>
[DataContract]
public sealed class JobEnvironment : ICloneable
{
/// <summary>
/// Initializes a new <c>JobEnvironment</c> with empty collections of repositories, vectors,
/// and variables.
/// </summary>
public JobEnvironment()
{
}
public JobEnvironment(
IDictionary<String, VariableValue> variables,
List<MaskHint> maskhints,
JobResources resources)
{
if (resources!= null)
{
this.Endpoints.AddRange(resources.Endpoints.Where(x => !String.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase)));
this.SystemConnection = resources.Endpoints.FirstOrDefault(x => String.Equals(x.Name, WellKnownServiceEndpointNames.SystemVssConnection, StringComparison.OrdinalIgnoreCase));
this.SecureFiles.AddRange(resources.SecureFiles);
}
if (maskhints != null)
{
this.MaskHints.AddRange(maskhints);
}
if (variables != null)
{
foreach (var variable in variables)
{
this.Variables[variable.Key] = variable.Value?.Value;
if (variable.Value?.IsSecret == true)
{
// Make sure we propagate secret variables into the mask hints
this.MaskHints.Add(new MaskHint { Type = MaskType.Variable, Value = variable.Key });
}
}
}
}
public void Extract(
Dictionary<String, VariableValue> variables,
HashSet<MaskHint> maskhints,
JobResources jobResources)
{
// construct variables
HashSet<String> secretVariables = new HashSet<string>(this.MaskHints.Where(t => t.Type == MaskType.Variable).Select(v => v.Value), StringComparer.OrdinalIgnoreCase);
foreach (var variable in this.Variables)
{
variables[variable.Key] = new VariableValue(variable.Value, secretVariables.Contains(variable.Key));
}
// construct maskhints
maskhints.AddRange(this.MaskHints.Where(x => !(x.Type == MaskType.Variable && secretVariables.Contains(x.Value))).Select(x => x.Clone()));
// constuct job resources (endpoints, securefiles and systemconnection)
jobResources.SecureFiles.AddRange(this.SecureFiles.Select(x => x.Clone()));
jobResources.Endpoints.AddRange(this.Endpoints.Select(x => x.Clone()));
if (this.SystemConnection != null)
{
jobResources.Endpoints.Add(this.SystemConnection.Clone());
}
}
public JobEnvironment(PlanEnvironment environment)
{
ArgumentUtility.CheckForNull(environment, nameof(environment));
if (environment.MaskHints.Count > 0)
{
m_maskHints = new List<MaskHint>(environment.MaskHints.Select(x => x.Clone()));
}
if (environment.Options.Count > 0)
{
m_options = environment.Options.ToDictionary(x => x.Key, x => x.Value.Clone());
}
if (environment.Variables.Count > 0)
{
m_variables = new Dictionary<String, String>(environment.Variables, StringComparer.OrdinalIgnoreCase);
}
}
private JobEnvironment(JobEnvironment environmentToClone)
{
if (environmentToClone.SystemConnection != null)
{
this.SystemConnection = environmentToClone.SystemConnection.Clone();
}
if (environmentToClone.m_maskHints != null)
{
m_maskHints = environmentToClone.m_maskHints.Select(x => x.Clone()).ToList();
}
if (environmentToClone.m_endpoints != null)
{
m_endpoints = environmentToClone.m_endpoints.Select(x => x.Clone()).ToList();
}
if (environmentToClone.m_secureFiles != null)
{
m_secureFiles = environmentToClone.m_secureFiles.Select(x => x.Clone()).ToList();
}
if (environmentToClone.m_options != null)
{
m_options = environmentToClone.m_options.ToDictionary(x => x.Key, x => x.Value.Clone());
}
if (environmentToClone.m_variables != null)
{
m_variables = new Dictionary<String, String>(environmentToClone.m_variables, StringComparer.OrdinalIgnoreCase);
}
}
/// <summary>
/// Gets or sets the endpoint used for communicating back to the calling service.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public ServiceEndpoint SystemConnection
{
get;
set;
}
/// <summary>
/// Gets the collection of mask hints
/// </summary>
public List<MaskHint> MaskHints
{
get
{
if (m_maskHints == null)
{
m_maskHints = new List<MaskHint>();
}
return m_maskHints;
}
}
/// <summary>
/// Gets the collection of endpoints associated with the current context.
/// </summary>
public List<ServiceEndpoint> Endpoints
{
get
{
if (m_endpoints == null)
{
m_endpoints = new List<ServiceEndpoint>();
}
return m_endpoints;
}
}
/// <summary>
/// Gets the collection of secure files associated with the current context
/// </summary>
public List<SecureFile> SecureFiles
{
get
{
if (m_secureFiles == null)
{
m_secureFiles = new List<SecureFile>();
}
return m_secureFiles;
}
}
/// <summary>
/// Gets the collection of options associated with the current context. (Deprecated, use by 1.x agent)
/// </summary>
public IDictionary<Guid, JobOption> Options
{
get
{
if (m_options == null)
{
m_options = new Dictionary<Guid, JobOption>();
}
return m_options;
}
}
/// <summary>
/// Gets the collection of variables associated with the current context.
/// </summary>
public IDictionary<String, String> Variables
{
get
{
if (m_variables == null)
{
m_variables = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_variables;
}
}
Object ICloneable.Clone()
{
return this.Clone();
}
/// <summary>
/// Creates a deep copy of the job environment.
/// </summary>
/// <returns>A deep copy of the job environment</returns>
public JobEnvironment Clone()
{
return new JobEnvironment(this);
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (m_serializedMaskHints != null && m_serializedMaskHints.Count > 0)
{
m_maskHints = new List<MaskHint>(m_serializedMaskHints.Distinct());
}
m_serializedMaskHints = null;
SerializationHelper.Copy(ref m_serializedVariables, ref m_variables, true);
SerializationHelper.Copy(ref m_serializedEndpoints, ref m_endpoints, true);
SerializationHelper.Copy(ref m_serializedSecureFiles, ref m_secureFiles, true);
SerializationHelper.Copy(ref m_serializedOptions, ref m_options, true);
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
if (this.m_maskHints != null && this.m_maskHints.Count > 0)
{
m_serializedMaskHints = new List<MaskHint>(this.m_maskHints.Distinct());
}
SerializationHelper.Copy(ref m_variables, ref m_serializedVariables);
SerializationHelper.Copy(ref m_endpoints, ref m_serializedEndpoints);
SerializationHelper.Copy(ref m_secureFiles, ref m_serializedSecureFiles);
SerializationHelper.Copy(ref m_options, ref m_serializedOptions);
}
[OnSerialized]
private void OnSerialized(StreamingContext context)
{
m_serializedMaskHints = null;
m_serializedVariables = null;
m_serializedEndpoints = null;
m_serializedSecureFiles = null;
m_serializedOptions = null;
}
private List<MaskHint> m_maskHints;
private List<ServiceEndpoint> m_endpoints;
private List<SecureFile> m_secureFiles;
private IDictionary<Guid, JobOption> m_options;
private IDictionary<String, String> m_variables;
[DataMember(Name = "Endpoints", EmitDefaultValue = false)]
private List<ServiceEndpoint> m_serializedEndpoints;
[DataMember(Name = "SecureFiles", EmitDefaultValue = false)]
private List<SecureFile> m_serializedSecureFiles;
[DataMember(Name = "Options", EmitDefaultValue = false)]
private IDictionary<Guid, JobOption> m_serializedOptions;
[DataMember(Name = "Mask", EmitDefaultValue = false)]
private List<MaskHint> m_serializedMaskHints;
[DataMember(Name = "Variables", EmitDefaultValue = false)]
private IDictionary<String, String> m_serializedVariables;
}
}

View File

@@ -0,0 +1,355 @@
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using GitHub.Services.WebApi.Internal;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GitHub.DistributedTask.WebApi
{
public static class JobEventTypes
{
public const String JobAssigned = "JobAssigned";
public const String JobCompleted = "JobCompleted";
public const String JobStarted = "JobStarted";
public const String TaskAssigned = "TaskAssigned";
public const String TaskStarted = "TaskStarted";
public const String TaskCompleted = "TaskCompleted";
}
[DataContract]
[KnownType(typeof(JobAssignedEvent))]
[KnownType(typeof(JobCompletedEvent))]
[KnownType(typeof(JobStartedEvent))]
[KnownType(typeof(TaskAssignedEvent))]
[KnownType(typeof(TaskStartedEvent))]
[KnownType(typeof(TaskCompletedEvent))]
[KnownType(typeof(TaskLocalExecutionCompletedEvent))]
[JsonConverter(typeof(JobEventJsonConverter))]
public abstract class JobEvent
{
protected JobEvent(String name)
{
this.Name = name;
}
protected JobEvent(
String name,
Guid jobId)
{
this.Name = name;
this.JobId = jobId;
}
[DataMember]
public String Name
{
get;
private set;
}
[DataMember(EmitDefaultValue = false)]
public Guid JobId
{
get;
set;
}
}
[DataContract]
public sealed class JobAssignedEvent : JobEvent
{
internal JobAssignedEvent()
: base(JobEventTypes.JobAssigned)
{
}
public JobAssignedEvent(Guid jobId)
: base(JobEventTypes.JobAssigned, jobId)
{
}
public JobAssignedEvent(
Guid jobId,
TaskAgentJobRequest request)
: base(JobEventTypes.JobAssigned, jobId)
{
this.Request = request;
}
[DataMember]
public TaskAgentJobRequest Request
{
get;
set;
}
}
[DataContract]
public sealed class JobStartedEvent : JobEvent
{
internal JobStartedEvent()
: base(JobEventTypes.JobStarted)
{
}
public JobStartedEvent(Guid jobId)
: base(JobEventTypes.JobStarted, jobId)
{
}
}
[DataContract]
public sealed class JobCompletedEvent : JobEvent
{
internal JobCompletedEvent()
: base(JobEventTypes.JobCompleted)
{
}
public JobCompletedEvent(
Guid jobId,
TaskResult result)
: this(0, jobId, result)
{
}
public JobCompletedEvent(
Int64 requestId,
Guid jobId,
TaskResult result)
: this(requestId, jobId, result, null)
{
}
public JobCompletedEvent(
Int64 requestId,
Guid jobId,
TaskResult result,
IDictionary<String, VariableValue> outputVariables)
: base(JobEventTypes.JobCompleted, jobId)
{
this.RequestId = requestId;
this.Result = result;
}
[DataMember(EmitDefaultValue = false)]
public Int64 RequestId
{
get;
set;
}
[DataMember]
public TaskResult Result
{
get;
set;
}
}
[DataContract]
public abstract class TaskEvent : JobEvent
{
protected TaskEvent(string name) : base(name)
{
}
protected TaskEvent(
string name,
Guid jobId,
Guid taskId)
: base(name, jobId)
{
TaskId = taskId;
}
[DataMember(EmitDefaultValue = false)]
public Guid TaskId
{
get;
set;
}
}
[DataContract]
public sealed class TaskAssignedEvent : TaskEvent
{
public TaskAssignedEvent()
: base(JobEventTypes.TaskAssigned)
{
}
public TaskAssignedEvent(
Guid jobId,
Guid taskId)
: base(JobEventTypes.TaskAssigned, jobId, taskId)
{
}
}
[DataContract]
public sealed class TaskStartedEvent : TaskEvent
{
public TaskStartedEvent()
: base(JobEventTypes.TaskStarted)
{
}
public TaskStartedEvent(
Guid jobId,
Guid taskId)
: base(JobEventTypes.TaskStarted, jobId, taskId)
{
}
}
[DataContract]
public sealed class TaskCompletedEvent : TaskEvent
{
public TaskCompletedEvent()
: base(JobEventTypes.TaskCompleted)
{
}
public TaskCompletedEvent(
Guid jobId,
Guid taskId,
TaskResult taskResult)
: base(JobEventTypes.TaskCompleted, jobId, taskId)
{
Result = taskResult;
}
[DataMember]
public TaskResult Result
{
get;
set;
}
}
[DataContract]
[ClientIgnore]
internal sealed class TaskLocalExecutionCompletedEvent : TaskEvent
{
public TaskLocalExecutionCompletedEvent()
: base(JobEventTypes.TaskCompleted)
{
}
public TaskLocalExecutionCompletedEvent(
Guid jobId,
Guid taskId,
ServerTaskSectionExecutionOutput data)
: base(JobEventTypes.TaskCompleted, jobId, taskId)
{
EventData = data;
}
[DataMember]
public ServerTaskSectionExecutionOutput EventData
{
get;
set;
}
}
internal sealed class JobEventJsonConverter : VssSecureJsonConverter
{
public override Boolean CanWrite
{
get
{
return false;
}
}
public override Boolean CanConvert(Type objectType)
{
return typeof(JobEvent).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
var eventObject = JObject.Load(reader);
JToken propertyValue;
JobEvent jobEvent = null;
if (eventObject.TryGetValue("Name", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
if (propertyValue.Type == JTokenType.String)
{
String nameValue = (String)propertyValue;
if (String.Equals(nameValue, JobEventTypes.JobAssigned, StringComparison.Ordinal))
{
jobEvent = new JobAssignedEvent();
}
else if (String.Equals(nameValue, JobEventTypes.JobCompleted, StringComparison.Ordinal))
{
jobEvent = new JobCompletedEvent();
}
else if (String.Equals(nameValue, JobEventTypes.JobStarted, StringComparison.Ordinal))
{
jobEvent = new JobStartedEvent();
}
else if (String.Equals(nameValue, JobEventTypes.TaskAssigned, StringComparison.Ordinal))
{
jobEvent = new TaskAssignedEvent();
}
else if (String.Equals(nameValue, JobEventTypes.TaskStarted, StringComparison.Ordinal))
{
jobEvent = new TaskStartedEvent();
}
else if (String.Equals(nameValue, JobEventTypes.TaskCompleted, StringComparison.Ordinal))
{
jobEvent = new TaskCompletedEvent();
}
}
}
if (jobEvent == null)
{
if (eventObject.TryGetValue("Request", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
jobEvent = new JobAssignedEvent();
}
else if (eventObject.TryGetValue("Result", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
jobEvent = new JobCompletedEvent();
}
}
if (jobEvent == null)
{
return existingValue;
}
using (var objectReader = eventObject.CreateReader())
{
serializer.Populate(objectReader, jobEvent);
}
return jobEvent;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
namespace GitHub.DistributedTask.WebApi
{
public class JobExecutionModeTypes
{
public const string Server = "Server";
public const string Agent = "Agent";
}
}

View File

@@ -0,0 +1,87 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Represents an option that may affect the way an agent runs the job.
/// </summary>
[DataContract]
public class JobOption : ICloneable
{
/// <summary>
/// Initializes a new <c>JobOption</c> with an empty collection of data.
/// </summary>
public JobOption()
{
}
private JobOption(JobOption optionToClone)
{
this.Id = optionToClone.Id;
if (optionToClone.m_data != null)
{
m_data = new Dictionary<String, String>(optionToClone.m_data, StringComparer.OrdinalIgnoreCase);
}
}
/// <summary>
/// Gets the id of the option.
/// </summary>
[DataMember]
public Guid Id { get; set; }
/// <summary>
/// Gets the data associated with the option.
/// </summary>
public IDictionary<String, String> Data
{
get
{
if (m_data == null)
{
m_data = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_data;
}
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
if (m_serializedData != null && m_serializedData.Count > 0)
{
m_data = new Dictionary<String, String>(m_serializedData, StringComparer.OrdinalIgnoreCase);
}
m_serializedData = null;
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
m_serializedData = this.Data.Count > 0 ? this.Data : null;
}
Object ICloneable.Clone()
{
return this.Clone();
}
/// <summary>
/// Creates a deep copy of the job option.
/// </summary>
/// <returns>A deep copy of the job option</returns>
public JobOption Clone()
{
return new JobOption(this);
}
private Dictionary<String, String> m_data;
[DataMember(Name = "Data", EmitDefaultValue = false)]
private IDictionary<String, String> m_serializedData;
}
}

View File

@@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
[JsonConverter(typeof(JobRequestMessageJsonConverter))]
public abstract class JobRequestMessage
{
protected JobRequestMessage(string messageType)
{
this.MessageType = messageType;
}
protected JobRequestMessage(
string messageType,
TaskOrchestrationPlanReference plan,
TimelineReference timeline,
Guid jobId,
String jobName,
String jobRefName,
JobEnvironment environment)
{
this.MessageType = messageType;
this.Plan = plan;
this.JobId = jobId;
this.JobName = jobName;
this.JobRefName = jobRefName;
this.Timeline = timeline;
this.Environment = environment;
}
[DataMember]
public String MessageType
{
get;
private set;
}
[DataMember]
public TaskOrchestrationPlanReference Plan
{
get;
private set;
}
[DataMember]
public TimelineReference Timeline
{
get;
private set;
}
[DataMember]
public Guid JobId
{
get;
private set;
}
[DataMember]
public String JobName
{
get;
private set;
}
[DataMember]
public String JobRefName
{
get;
private set;
}
[DataMember]
public JobEnvironment Environment
{
get;
private set;
}
}
}

View File

@@ -0,0 +1,89 @@
using System;
using System.Reflection;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace GitHub.DistributedTask.WebApi
{
internal sealed class JobRequestMessageJsonConverter : VssSecureJsonConverter
{
public override Boolean CanConvert(Type objectType)
{
return typeof(JobRequestMessage).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Boolean CanWrite
{
get
{
return false;
}
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
if (reader.TokenType != JsonToken.StartObject)
{
return null;
}
Object newValue = null;
JToken propertyValue;
JObject value = JObject.Load(reader);
if (value.TryGetValue("MessageType", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
if (propertyValue.Type == JTokenType.String)
{
var messageType = (String)propertyValue;
switch (messageType)
{
case JobRequestMessageTypes.AgentJobRequest:
newValue = new AgentJobRequestMessage();
break;
case JobRequestMessageTypes.ServerTaskRequest:
case JobRequestMessageTypes.ServerJobRequest:
newValue = new ServerTaskRequestMessage();
break;
}
}
}
if (newValue == null)
{
if (value.TryGetValue("RequestId", StringComparison.OrdinalIgnoreCase, out propertyValue))
{
newValue = new AgentJobRequestMessage();
}
}
if (newValue == null)
{
return existingValue;
}
using (JsonReader objectReader = value.CreateReader())
{
serializer.Populate(objectReader, newValue);
}
return newValue;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
// The virtual method returns false for CanWrite so this should never be invoked
throw new NotSupportedException();
}
}
}

View File

@@ -0,0 +1,15 @@
using System;
namespace GitHub.DistributedTask.WebApi
{
public static class JobRequestMessageTypes
{
public const String AgentJobRequest = "JobRequest";
public const String ServerJobRequest = "ServerJobRequest";
public const String ServerTaskRequest = "ServerTaskRequest";
public const String PipelineAgentJobRequest = "PipelineAgentJobRequest";
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[Flags]
[DataContract]
public enum MachineGroupActionFilter
{
[EnumMember]
None = 0,
[EnumMember]
Manage = 2,
[EnumMember]
Use = 16,
}
}

View File

@@ -0,0 +1,35 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Represents a purchase of resource units in a secondary marketplace.
/// </summary>
/// <remarks>
/// The type of resource purchased (pipelines, minutes) is not represented here.
/// </remarks>
[DataContract]
public sealed class MarketplacePurchasedLicense
{
/// <summary>
/// The Marketplace display name.
/// </summary>
/// <example>"GitHub"</example>
[DataMember(EmitDefaultValue = false)]
public String MarketplaceName { get; set; }
/// <summary>
/// The name of the identity making the purchase as seen by the marketplace
/// </summary>
/// <example>"AppPreview, Microsoft, etc."</example>
[DataMember(EmitDefaultValue = false)]
public String PurchaserName { get; set; }
/// <summary>
/// The quantity purchased.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Int32 PurchaseUnitCount { get; set; }
}
}

View File

@@ -0,0 +1,54 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class MaskHint
{
public MaskHint()
{
}
private MaskHint(MaskHint maskHintToBeCloned)
{
this.Type = maskHintToBeCloned.Type;
this.Value = maskHintToBeCloned.Value;
}
public MaskHint Clone()
{
return new MaskHint(this);
}
[DataMember]
public MaskType Type
{
get;
set;
}
[DataMember]
public String Value
{
get;
set;
}
public override Boolean Equals(Object obj)
{
var otherHint = obj as MaskHint;
if (otherHint != null)
{
return this.Type == otherHint.Type && String.Equals(this.Value ?? String.Empty, otherHint.Value ?? String.Empty, StringComparison.Ordinal);
}
return false;
}
public override Int32 GetHashCode()
{
return this.Type.GetHashCode() ^ (this.Value ?? String.Empty).GetHashCode();
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public enum MaskType
{
[EnumMember]
Variable = 1,
[EnumMember]
Regex = 2
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Metrics columns header
/// </summary>
[DataContract]
public sealed class MetricsColumnsHeader
{
/// <summary>
/// Properties of deployment group for which metrics are provided.
/// E.g. 1: LastJobStatus
/// E.g. 2: TargetState
/// </summary>
public IList<MetricsColumnMetaData> Dimensions
{
get
{
if (m_dimensions == null)
{
m_dimensions = new List<MetricsColumnMetaData>();
}
return m_dimensions;
}
internal set
{
m_dimensions = value;
}
}
/// <summary>
/// The types of metrics.
/// E.g. 1: total count of deployment targets.
/// E.g. 2: Average time of deployment to the deployment targets.
/// </summary>
public IList<MetricsColumnMetaData> Metrics
{
get
{
if (m_metrics == null)
{
m_metrics = new List<MetricsColumnMetaData>();
}
return m_metrics;
}
internal set
{
m_metrics = value;
}
}
/// <summary>
/// Properties of deployment group for which metrics are provided.
/// E.g. 1: LastJobStatus
/// E.g. 2: TargetState
/// </summary>
[DataMember(Name = "Dimensions")]
private IList<MetricsColumnMetaData> m_dimensions;
/// <summary>
/// The types of metrics.
/// E.g. 1: total count of deployment targets.
/// E.g. 2: Average time of deployment to the deployment targets.
/// </summary>
[DataMember(Name = "Metrics")]
private IList<MetricsColumnMetaData> m_metrics;
}
/// <summary>
/// Meta data for a metrics column.
/// </summary>
[DataContract]
public sealed class MetricsColumnMetaData
{
/// <summary>
/// Name.
/// </summary>
[DataMember]
public String ColumnName
{
get;
internal set;
}
/// <summary>
/// Data type.
/// </summary>
[DataMember]
public String ColumnValueType
{
get;
internal set;
}
}
}

View File

@@ -0,0 +1,71 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Metrics row.
/// </summary>
[DataContract]
public sealed class MetricsRow
{
/// <summary>
/// The values of the properties mentioned as 'Dimensions' in column header.
/// E.g. 1: For a property 'LastJobStatus' - metrics will be provided for 'passed', 'failed', etc.
/// E.g. 2: For a property 'TargetState' - metrics will be provided for 'online', 'offline' targets.
/// </summary>
public IList<String> Dimensions
{
get
{
if (m_dimensions == null)
{
m_dimensions = new List<String>();
}
return m_dimensions;
}
internal set
{
m_dimensions = value;
}
}
/// <summary>
/// Metrics in serialized format.
/// Should be deserialized based on the data type provided in header.
/// </summary>
public IList<String> Metrics
{
get
{
if (m_metrics == null)
{
m_metrics = new List<String>();
}
return m_metrics;
}
internal set
{
m_metrics = value;
}
}
/// <summary>
/// The values of the properties mentioned as 'Dimensions' in column header.
/// E.g. 1: For a property 'LastJobStatus' - metrics will be provided for 'passed', 'failed', etc.
/// E.g. 2: For a property 'TargetState' - metrics will be provided for 'online', 'offline' targets.
/// </summary>
[DataMember(Name = "Dimensions")]
private IList<String> m_dimensions;
/// <summary>
/// Metrics in serialized format.
/// Should be deserialized based on the data type provided in header.
/// </summary>
[DataMember(Name = "Metrics")]
private IList<String> m_metrics;
}
}

View File

@@ -0,0 +1,92 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Represents a downloadable package.
/// </summary>
[DataContract]
public class PackageMetadata
{
/// <summary>
/// The type of package (e.g. "agent")
/// </summary>
[DataMember]
public String Type
{
get;
set;
}
/// <summary>
/// The platform (win7, linux, etc.)
/// </summary>
[DataMember]
public String Platform
{
get;
set;
}
/// <summary>
/// The date the package was created
/// </summary>
[DataMember(EmitDefaultValue = false)]
public DateTime CreatedOn
{
get;
set;
}
/// <summary>
/// The package version.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public PackageVersion Version
{
get;
set;
}
/// <summary>
/// A direct link to download the package.
/// </summary>
[DataMember]
public String DownloadUrl
{
get;
set;
}
/// <summary>
/// MD5 hash as a base64 string
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String HashValue
{
get;
set;
}
/// <summary>
/// A link to documentation
/// </summary>
[DataMember]
public String InfoUrl
{
get;
set;
}
/// <summary>
/// The UI uses this to display instructions, i.e. "unzip MyAgent.zip"
/// </summary>
[DataMember]
public String Filename
{
get;
set;
}
}
}

View File

@@ -0,0 +1,108 @@
using System;
using System.Globalization;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class PackageVersion : IComparable<PackageVersion>, IEquatable<PackageVersion>
{
public PackageVersion()
{
}
public PackageVersion(String version)
{
Int32 major, minor, patch;
String semanticVersion;
VersionParser.ParseVersion(version, out major, out minor, out patch, out semanticVersion);
Major = major;
Minor = minor;
Patch = patch;
}
public static Boolean TryParse(String versionStr, out PackageVersion version)
{
version = null;
try
{
version = new PackageVersion(versionStr);
return true;
}
catch
{
return false;
}
}
private PackageVersion(PackageVersion versionToClone)
{
this.Major = versionToClone.Major;
this.Minor = versionToClone.Minor;
this.Patch = versionToClone.Patch;
}
[DataMember]
public Int32 Major
{
get;
set;
}
[DataMember]
public Int32 Minor
{
get;
set;
}
[DataMember]
public Int32 Patch
{
get;
set;
}
public PackageVersion Clone()
{
return new PackageVersion(this);
}
public static implicit operator String(PackageVersion version)
{
return version.ToString();
}
public override String ToString()
{
return String.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}", Major, Minor, Patch);
}
public override int GetHashCode()
{
return this.ToString().GetHashCode();
}
public Int32 CompareTo(PackageVersion other)
{
Int32 rc = Major.CompareTo(other.Major);
if (rc == 0)
{
rc = Minor.CompareTo(other.Minor);
if (rc == 0)
{
rc = Patch.CompareTo(other.Patch);
}
}
return rc;
}
public Boolean Equals(PackageVersion other)
{
return this.CompareTo(other) == 0;
}
}
}

View File

@@ -0,0 +1,156 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using GitHub.DistributedTask.Pipelines;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class PlanEnvironment : IOrchestrationEnvironment
{
public PlanEnvironment()
{
}
private PlanEnvironment(PlanEnvironment environmentToClone)
{
if (environmentToClone.m_options != null)
{
m_options = m_options.ToDictionary(x => x.Key, x => x.Value.Clone());
}
if (environmentToClone.m_maskHints != null)
{
m_maskHints = environmentToClone.m_maskHints.Select(x => x.Clone()).ToList();
}
if (environmentToClone.m_variables != null)
{
m_variables = new VariablesDictionary(environmentToClone.m_variables);
}
}
/// <summary>
/// Gets the collection of mask hints
/// </summary>
public List<MaskHint> MaskHints
{
get
{
if (m_maskHints == null)
{
m_maskHints = new List<MaskHint>();
}
return m_maskHints;
}
}
/// <summary>
/// Gets the collection of options associated with the current context.
/// </summary>
/// <remarks>This is being deprecated and should not be used</remarks>
public IDictionary<Guid, JobOption> Options
{
get
{
if (m_options == null)
{
m_options = new Dictionary<Guid, JobOption>();
}
return m_options;
}
}
/// <summary>
/// Gets the collection of variables associated with the current context.
/// </summary>
public IDictionary<String, String> Variables
{
get
{
if (m_variables == null)
{
m_variables = new VariablesDictionary();
}
return m_variables;
}
}
OrchestrationProcessType IOrchestrationEnvironment.ProcessType
{
get
{
return OrchestrationProcessType.Container;
}
}
IDictionary<String, VariableValue> IOrchestrationEnvironment.Variables
{
get
{
if (m_variables == null)
{
m_variables = new VariablesDictionary();
}
return m_variables;
}
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
SerializationHelper.Copy(ref m_serializedOptions, ref m_options, true);
SerializationHelper.Copy(ref m_serializedMaskHints, ref m_maskHints, true);
var secretNames = new HashSet<String>(m_maskHints?.Where(x => x.Type == MaskType.Variable).Select(x => x.Value) ?? new String[0], StringComparer.OrdinalIgnoreCase);
if (m_serializedVariables != null && m_serializedVariables.Count > 0)
{
m_variables = new VariablesDictionary();
foreach (var variable in m_serializedVariables)
{
m_variables[variable.Key] = new VariableValue(variable.Value, secretNames.Contains(variable.Key));
}
}
m_serializedVariables = null;
}
[OnSerialized]
private void OnSerialized(StreamingContext context)
{
m_serializedOptions = null;
m_serializedMaskHints = null;
m_serializedVariables = null;
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
SerializationHelper.Copy(ref m_options, ref m_serializedOptions);
SerializationHelper.Copy(ref m_maskHints, ref m_serializedMaskHints);
if (m_variables != null && m_variables.Count > 0)
{
m_serializedVariables = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
foreach (var variable in m_variables)
{
m_serializedVariables[variable.Key] = variable.Value?.Value;
}
}
}
private List<MaskHint> m_maskHints;
private Dictionary<Guid, JobOption> m_options;
private VariablesDictionary m_variables;
[DataMember(Name = "Mask", EmitDefaultValue = false)]
private List<MaskHint> m_serializedMaskHints;
[DataMember(Name = "Options", EmitDefaultValue = false)]
private Dictionary<Guid, JobOption> m_serializedOptions;
[DataMember(Name = "Variables", EmitDefaultValue = false)]
private IDictionary<String, String> m_serializedVariables;
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[Flags]
[DataContract]
public enum PlanGroupStatus
{
[EnumMember]
Running = 1,
[EnumMember]
Queued = 2,
[EnumMember]
All = Running | Queued
}
}

View File

@@ -0,0 +1,19 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
public enum PlanTemplateType
{
[DataMember]
None = 0,
[DataMember]
Designer = 1,
[DataMember]
System = 2,
[DataMember]
Yaml = 3,
}
}

View File

@@ -0,0 +1,21 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ProjectReference.cs" company="Microsoft Corporation">
// 2012-2023, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class ProjectReference
{
[DataMember]
public Guid Id { get; set; }
[DataMember]
public string Name { get; set; }
}
}

View File

@@ -0,0 +1,20 @@
// --------------------------------------------------------------------------------------------------------------------
// <copyright file="PublishTaskGroupMetadata.cs" company="Microsoft Corporation">
// 2012-2023, All rights reserved.
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
using System;
namespace GitHub.DistributedTask.WebApi
{
public class PublishTaskGroupMetadata
{
public Guid TaskGroupId { get; set; }
// This is revision of task group that is getting published
public int TaskGroupRevision { get; set; }
public int ParentDefinitionRevision { get; set; }
public Boolean Preview { get; set; }
public String Comment { get; set; }
}
}

View File

@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class ResourceLimit
{
internal ResourceLimit(
Guid hostId,
String parallelismTag,
Boolean isHosted)
{
HostId = hostId;
ParallelismTag = parallelismTag;
IsHosted = isHosted;
}
[DataMember]
public Guid HostId
{
get;
set;
}
[DataMember]
public String ParallelismTag
{
get;
set;
}
[DataMember]
public Boolean IsHosted
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Int32? TotalCount
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Int32? TotalMinutes
{
get;
set;
}
[DataMember]
public Boolean IsPremium
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Boolean FailedToReachAllProviders
{
get;
set;
}
public IDictionary<String, String> Data
{
get
{
if (m_resourceLimitsData == null)
{
m_resourceLimitsData = new Dictionary<String, String>();
}
return m_resourceLimitsData;
}
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
if (m_resourceLimitsData?.Count == 0)
{
m_resourceLimitsData = null;
}
}
[DataMember(Name = "ResourceLimitsData", EmitDefaultValue = false)]
private IDictionary<String, String> m_resourceLimitsData;
}
}

View File

@@ -0,0 +1,58 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[EditorBrowsable(EditorBrowsableState.Never)]
[DataContract]
public class ResourceUsage
{
[DataMember]
public ResourceLimit ResourceLimit
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Int32? UsedCount
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Int32? UsedMinutes
{
get;
set;
}
public IList<TaskAgentJobRequest> RunningRequests
{
get
{
if (m_runningRequests == null)
{
m_runningRequests = new List<TaskAgentJobRequest>();
}
return m_runningRequests;
}
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
if (m_runningRequests?.Count == 0)
{
m_runningRequests = null;
}
}
[DataMember(Name = "RunningRequests", EmitDefaultValue = false)]
private IList<TaskAgentJobRequest> m_runningRequests;
}
}

View File

@@ -0,0 +1,109 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class SecureFile
{
public SecureFile()
{
}
private SecureFile(SecureFile secureFile, Boolean shallow = false)
{
this.Id = secureFile.Id;
this.Name = secureFile.Name;
this.Ticket = secureFile.Ticket;
if (!shallow)
{
this.Properties = secureFile.Properties;
this.CreatedBy = secureFile.CreatedBy;
this.CreatedOn = secureFile.CreatedOn;
this.ModifiedBy = secureFile.ModifiedBy;
this.ModifiedOn = secureFile.ModifiedOn;
}
}
[DataMember(EmitDefaultValue = false)]
public Guid Id
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
public IDictionary<String, String> Properties
{
get
{
if (m_properties == null)
{
m_properties = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
return m_properties;
}
set
{
m_properties = value;
}
}
[DataMember(EmitDefaultValue = false)]
public IdentityRef CreatedBy
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public DateTime CreatedOn
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public IdentityRef ModifiedBy
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public DateTime ModifiedOn
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public String Ticket
{
get;
set;
}
public SecureFile Clone()
{
return new SecureFile(this);
}
public SecureFile CloneShallow()
{
return new SecureFile(this, true);
}
[DataMember(EmitDefaultValue = false, Name = "Properties")]
private IDictionary<String, String> m_properties;
}
}

View File

@@ -0,0 +1,19 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[Flags]
[DataContract]
public enum SecureFileActionFilter
{
[EnumMember]
None = 0,
[EnumMember]
Manage = 2,
[EnumMember]
Use = 16,
}
}

View File

@@ -0,0 +1,43 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class ServerTaskRequestMessage : JobRequestMessage
{
internal ServerTaskRequestMessage()
: base(JobRequestMessageTypes.ServerTaskRequest)
{
}
public ServerTaskRequestMessage(
TaskOrchestrationPlanReference plan,
TimelineReference timeline,
Guid jobId,
String jobName,
String jobRefName,
JobEnvironment environment,
TaskInstance taskInstance,
TaskDefinition taskDefinition)
: base(JobRequestMessageTypes.ServerJobRequest, plan, timeline, jobId, jobName, jobRefName, environment)
{
TaskDefinition = taskDefinition;
TaskInstance = taskInstance;
}
[DataMember]
public TaskDefinition TaskDefinition
{
get;
private set;
}
[DataMember]
public TaskInstance TaskInstance
{
get;
private set;
}
}
}

View File

@@ -0,0 +1,14 @@
using System;
using System.Runtime.Serialization;
using GitHub.Services.WebApi.Internal;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
[ClientIgnore]
public class ServerTaskSectionExecutionOutput
{
[DataMember]
public Boolean? IsCompleted { get; set; }
}
}

View File

@@ -0,0 +1,46 @@
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public enum AadLoginPromptOption
{
/// <summary>
/// Do not provide a prompt option
/// </summary>
[EnumMember]
NoOption = 0,
/// <summary>
/// Force the user to login again.
/// </summary>
[EnumMember]
Login = 1,
/// <summary>
/// Force the user to select which account they are logging in with instead of
/// automatically picking the user up from the session state.
/// NOTE: This does not work for switching bewtween the variants of a dual-homed user.
/// </summary>
[EnumMember]
SelectAccount = 2,
/// <summary>
/// Force the user to login again.
/// <remarks>
/// Ignore current authentication state and force the user to authenticate again. This option should be used instead of Login.
/// </remarks>
/// </summary>
[EnumMember]
FreshLogin = 3,
/// <summary>
/// Force the user to login again with mfa.
/// <remarks>
/// Ignore current authentication state and force the user to authenticate again. This option should be used instead of Login, if MFA is required.
/// </remarks>
/// </summary>
[EnumMember]
FreshLoginWithMfa = 4
}
}

View File

@@ -0,0 +1,21 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class AadOauthTokenRequest
{
[DataMember]
public String Token { get; set; }
[DataMember]
public String Resource { get; set; }
[DataMember]
public String TenantId { get; set; }
[DataMember]
public Boolean Refresh { get; set; }
}
}

View File

@@ -0,0 +1,15 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public sealed class AadOauthTokenResult
{
[DataMember]
public String AccessToken { get; set; }
[DataMember]
public String RefreshTokenCache { get; set; }
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureKeyVaultPermission : AzureResourcePermission
{
[DataMember]
public String Vault { get; set; }
public AzureKeyVaultPermission() : base(AzurePermissionResourceProviders.AzureKeyVaultPermission)
{
}
}
}

View File

@@ -0,0 +1,40 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Azure Management Group
/// </summary>
[DataContract]
public class AzureManagementGroup
{
/// <summary>
/// Azure management group name
/// </summary>
[DataMember]
[JsonProperty(PropertyName = "Name")]
public String Name { get; set; }
/// <summary>
/// Id of azure management group
/// </summary>
[DataMember]
[JsonProperty(PropertyName = "Id")]
public String Id { get; set; }
/// <summary>
/// Display name of azure management group
/// </summary>
[DataMember]
[JsonProperty(PropertyName = "displayName")]
public String DisplayName { get; set; }
/// <summary>
/// Id of tenant from which azure management group belogs
/// </summary>
[DataMember]
public String TenantId { get; set; }
}
}

View File

@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Azure management group query result
/// </summary>
[DataContract]
public class AzureManagementGroupQueryResult
{
/// <summary>
/// List of azure management groups
/// </summary>
[DataMember]
[JsonProperty("value")]
public List<AzureManagementGroup> Value;
/// <summary>
/// Error message in case of an exception
/// </summary>
[DataMember]
public string ErrorMessage;
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Reflection;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[JsonConverter(typeof(AzurePermissionJsonConverter))]
[KnownType(typeof(AzureKeyVaultPermission))]
[DataContract]
public abstract class AzurePermission
{
[DataMember]
public String ResourceProvider { get; set; }
[DataMember(EmitDefaultValue = true)]
public Boolean Provisioned { get; set; }
internal AzurePermission(String resourceProvider)
{
this.ResourceProvider = resourceProvider;
}
}
internal sealed class AzurePermissionJsonConverter : VssSecureJsonConverter
{
public override Boolean CanRead
{
get
{
return true;
}
}
public override Boolean CanWrite
{
get
{
return false;
}
}
public override Boolean CanConvert(Type objectType)
{
return typeof(AzurePermission).GetTypeInfo().IsAssignableFrom(objectType.GetTypeInfo());
}
public override Object ReadJson(
JsonReader reader,
Type objectType,
Object existingValue,
JsonSerializer serializer)
{
if (reader == null)
{
throw new ArgumentNullException("reader");
}
if (serializer == null)
{
throw new ArgumentNullException("serializer");
}
if (reader.TokenType != JsonToken.StartObject)
{
return existingValue;
}
var contract = serializer.ContractResolver.ResolveContract(objectType) as JsonObjectContract;
if (contract == null)
{
return existingValue;
}
JsonProperty resourceProviderProperty = contract.Properties.GetClosestMatchProperty("ResourceProvider");
if (resourceProviderProperty == null)
{
return existingValue;
}
JToken itemTypeValue;
JObject value = JObject.Load(reader);
if (!value.TryGetValue(resourceProviderProperty.PropertyName, StringComparison.OrdinalIgnoreCase, out itemTypeValue))
{
return existingValue;
}
if (itemTypeValue.Type != JTokenType.String)
{
throw new NotSupportedException("ResourceProvider property is mandatory for azure permission");
}
string resourceProvider = (string)itemTypeValue;
AzurePermission returnValue = null;
switch (resourceProvider)
{
case AzurePermissionResourceProviders.AzureRoleAssignmentPermission:
returnValue = new AzureRoleAssignmentPermission();
break;
case AzurePermissionResourceProviders.AzureKeyVaultPermission:
returnValue = new AzureKeyVaultPermission();
break;
default:
throw new NotSupportedException($"{resourceProvider} is not a supported resource provider for azure permission");
}
if (returnValue != null)
{
using (JsonReader objectReader = value.CreateReader())
{
serializer.Populate(objectReader, returnValue);
}
}
return returnValue;
}
public override void WriteJson(
JsonWriter writer,
Object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
}

View File

@@ -0,0 +1,12 @@
using System;
using GitHub.Services.Common;
namespace GitHub.DistributedTask.WebApi
{
[GenerateAllConstants]
public static class AzurePermissionResourceProviders
{
public const String AzureRoleAssignmentPermission = "Microsoft.RoleAssignment";
public const String AzureKeyVaultPermission = "Microsoft.KeyVault";
}
}

View File

@@ -0,0 +1,16 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public abstract class AzureResourcePermission : AzurePermission
{
[DataMember]
public String ResourceGroup { get; set; }
protected AzureResourcePermission(String resourceProvider) : base(resourceProvider)
{
}
}
}

View File

@@ -0,0 +1,17 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureRoleAssignmentPermission : AzurePermission
{
[DataMember]
public Guid RoleAssignmentId { get; set; }
public AzureRoleAssignmentPermission() : base(AzurePermissionResourceProviders.AzureRoleAssignmentPermission)
{
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureSubscription
{
[DataMember]
[JsonProperty(PropertyName = "displayName")]
public String DisplayName { get; set; }
[DataMember]
[JsonProperty(PropertyName = "subscriptionId")]
public String SubscriptionId { get; set; }
[DataMember]
public String SubscriptionTenantId { get; set; }
[DataMember]
public String SubscriptionTenantName { get; set; }
}
}

View File

@@ -0,0 +1,17 @@
using System.Collections.Generic;
using System.Runtime.Serialization;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class AzureSubscriptionQueryResult
{
[DataMember]
[JsonProperty("value")]
public List<AzureSubscription> Value;
[DataMember]
public string ErrorMessage;
}
}

View File

@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CommonContracts = GitHub.DistributedTask.Common.Contracts;
namespace GitHub.DistributedTask.WebApi
{
public class DataSourceBinding : CommonContracts.DataSourceBindingBase
{
public DataSourceBinding()
: base()
{
}
private DataSourceBinding(DataSourceBinding inputDefinitionToClone)
: base(inputDefinitionToClone)
{
}
public DataSourceBinding Clone()
{
return new DataSourceBinding(this);
}
}
}

View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
public sealed class EndpointAuthorizationSchemes
{
public const String AzureStorage = "AzureStorage";
public const String OAuth = "OAuth";
public const String OAuth2 = "OAuth2";
public const String OAuthWrap = "OAuthWrap";
public const String Certificate = "Certificate";
public const String UsernamePassword = "UsernamePassword";
public const String Token = "Token";
public const String PersonalAccessToken = "PersonalAccessToken";
public const String ServicePrincipal = "ServicePrincipal";
public const String None = "None";
public const String Jwt = "JWT";
public const String InstallationToken = "InstallationToken";
}
public sealed class EndpointAuthorizationParameters
{
public const String Username = "Username";
public const String Password = "Password";
public const String Certificate = "Certificate";
public const String AccessToken = "AccessToken";
public const String ApiToken = "ApiToken";
public const String RefreshToken = "RefreshToken";
public const String ServicePrincipalId = "ServicePrincipalId";
public const String ServicePrincipalKey = "ServicePrincipalKey";
public const String TenantId = "TenantId";
public const String RealmName = "RealmName";
public const String IdToken = "IdToken";
public const String Nonce = "nonce";
public const String Scope = "Scope";
public const String Role = "Role";
public const String ServerCertThumbprint = "ServerCertThumbprint";
public const String CompleteCallbackPayload = "CompleteCallbackPayload";
public const String ClientMail = "ClientMail";
public const String PrivateKey = "PrivateKey";
public const String Issuer = "Issuer";
public const String Audience = "Audience";
public const String StorageAccountName = "StorageAccountName";
public const String StorageAccessKey = "StorageAccessKey";
public const String AccessTokenType = "AccessTokenType";
public const String Signature = "Signature";
}
[DataContract]
public sealed class EndpointAuthorization
{
public EndpointAuthorization()
{
}
private EndpointAuthorization(EndpointAuthorization authorizationToClone)
{
this.Scheme = authorizationToClone.Scheme;
if (authorizationToClone.m_parameters != null && authorizationToClone.m_parameters.Count > 0)
{
m_parameters = new Dictionary<String, String>(authorizationToClone.m_parameters, StringComparer.OrdinalIgnoreCase);
}
}
/// <summary>
/// Gets or sets the scheme used for service endpoint authentication.
/// </summary>
[DataMember]
public String Scheme
{
get;
set;
}
public IDictionary<String, String> Parameters
{
get
{
if (m_parameters == null)
{
m_parameters = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_parameters;
}
}
public EndpointAuthorization Clone()
{
return new EndpointAuthorization(this);
}
[OnDeserialized]
private void OnDeserialized(StreamingContext context)
{
SerializationHelper.Copy(ref m_serializedParameters, ref m_parameters, StringComparer.OrdinalIgnoreCase, true);
}
[OnSerializing]
private void OnSerializing(StreamingContext context)
{
SerializationHelper.Copy(ref m_parameters, ref m_serializedParameters, StringComparer.OrdinalIgnoreCase);
}
[OnSerialized]
private void OnSerialized(StreamingContext context)
{
m_serializedParameters = null;
}
private IDictionary<String, String> m_parameters;
/// <summary>
/// Gets or sets the parameters for the selected authorization scheme.
/// </summary>
[DataMember(Name = "Parameters", EmitDefaultValue = false)]
private IDictionary<String, String> m_serializedParameters;
}
}

View File

@@ -0,0 +1,107 @@
using System;
using System.Collections.Generic;
namespace GitHub.DistributedTask.WebApi
{
public static class SerializationHelper
{
public static void Copy<T>(
ref List<T> source,
ref List<T> target,
Boolean clearSource = false)
{
if (source != null && source.Count > 0)
{
target = new List<T>(source);
}
if (clearSource)
{
source = null;
}
}
public static void Copy<T>(
ref IList<T> source,
ref ISet<T> target,
IEqualityComparer<T> comparer,
Boolean clearSource = false)
{
if (source != null && source.Count > 0)
{
target = new HashSet<T>(source, comparer);
}
if (clearSource)
{
source = null;
}
}
public static void Copy<T>(
ref ISet<T> source,
ref IList<T> target,
Boolean clearSource = false)
{
if (source != null && source.Count > 0)
{
target = new List<T>(source);
}
if (clearSource)
{
source = null;
}
}
public static void Copy<TKey, TValue>(
ref Dictionary<TKey, TValue> source,
ref Dictionary<TKey, TValue> target,
Boolean clearSource = false)
{
Copy(ref source, ref target, EqualityComparer<TKey>.Default, clearSource);
}
public static void Copy<TKey, TValue>(
ref IDictionary<TKey, TValue> source,
ref IDictionary<TKey, TValue> target,
Boolean clearSource = false)
{
Copy(ref source, ref target, EqualityComparer<TKey>.Default, clearSource);
}
public static void Copy<TKey, TValue>(
ref Dictionary<TKey, TValue> source,
ref Dictionary<TKey, TValue> target,
IEqualityComparer<TKey> comparer,
Boolean clearSource = false)
{
if (source != null && source.Count > 0)
{
target = new Dictionary<TKey, TValue>(source, comparer);
}
if (clearSource)
{
source = null;
}
}
public static void Copy<TKey, TValue>(
ref IDictionary<TKey, TValue> source,
ref IDictionary<TKey, TValue> target,
IEqualityComparer<TKey> comparer,
Boolean clearSource = false)
{
if (source != null && source.Count > 0)
{
target = new Dictionary<TKey, TValue>(source, comparer);
}
if (clearSource)
{
source = null;
}
}
}
}

View File

@@ -0,0 +1,296 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using GitHub.Services.WebApi;
using GitHub.Services.Common.Internal;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Represents an endpoint which may be used by an orchestration job.
/// </summary>
[DataContract]
public class ServiceEndpoint
{
/// <summary>
/// Constructs an <c>ServiceEndpoint</c> instance with empty values.
/// </summary>
public ServiceEndpoint()
{
m_data = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
IsReady = true;
}
private ServiceEndpoint(ServiceEndpoint endpointToClone)
{
Id = endpointToClone.Id;
Name = endpointToClone.Name;
Type = endpointToClone.Type;
Url = endpointToClone.Url;
Description = endpointToClone.Description;
GroupScopeId = endpointToClone.GroupScopeId;
AdministratorsGroup = endpointToClone.AdministratorsGroup;
ReadersGroup = endpointToClone.ReadersGroup;
if (endpointToClone.Authorization != null)
{
Authorization = endpointToClone.Authorization.Clone();
}
if (endpointToClone.m_data != null)
{
m_data = new Dictionary<String, String>(endpointToClone.m_data, StringComparer.OrdinalIgnoreCase);
}
}
public static bool ValidateServiceEndpoint(ServiceEndpoint endpoint, ref string message)
{
if (endpoint == null)
{
message = "endpoint: null";
return false;
}
if (endpoint.Id == Guid.Empty)
{
message = CommonResources.EmptyGuidNotAllowed("endpoint.Id");
return false;
}
if (string.IsNullOrEmpty(endpoint.Name))
{
message = string.Format("{0}:{1}", CommonResources.EmptyStringNotAllowed(), "endpoint.Name");
return false;
}
if (endpoint.Url == null)
{
message = "endpoint.Url: null";
return false;
}
if (string.IsNullOrEmpty(endpoint.Type))
{
message = string.Format("{0}:{1}", CommonResources.EmptyStringNotAllowed(), "endpoint.Type");
return false;
}
if (endpoint.Authorization == null)
{
message = "endpoint.Authorization: null";
return false;
}
return true;
}
/// <summary>
/// Gets or sets the identifier of this endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Guid Id
{
get;
set;
}
/// <summary>
/// Gets or sets the friendly name of the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Name
{
get;
set;
}
/// <summary>
/// Gets or sets the type of the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Type
{
get;
set;
}
/// <summary>
/// Gets or sets the owner of the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Owner
{
get;
set;
}
/// <summary>
/// Gets or sets the url of the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Uri Url
{
get;
set;
}
/// <summary>
/// Gets or sets the identity reference for the user who created the Service endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public IdentityRef CreatedBy
{
get;
set;
}
/// <summary>
/// Gets or sets the description of endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public string Description
{
get;
set;
}
/// <summary>
/// Gets or sets the authorization data for talking to the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public EndpointAuthorization Authorization
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public Guid GroupScopeId
{
get;
internal set;
}
/// <summary>
/// Gets or sets the identity reference for the administrators group of the service endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public IdentityRef AdministratorsGroup
{
get;
internal set;
}
/// <summary>
/// Gets or sets the identity reference for the readers group of the service endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public IdentityRef ReadersGroup
{
get;
internal set;
}
/// <summary>
/// Gets the custom data associated with this endpoint.
/// </summary>
public IDictionary<String, String> Data
{
get
{
return m_data;
}
set
{
if (value != null)
{
m_data = new Dictionary<String, String>(value, StringComparer.OrdinalIgnoreCase);
}
}
}
/// <summary>
/// Indicates whether service endpoint is shared with other projects or not.
/// </summary>
[DataMember(EmitDefaultValue = true)]
public Boolean IsShared
{
get;
set;
}
/// <summary>
/// EndPoint state indictor
/// </summary>
[DataMember(EmitDefaultValue = true)]
[JsonConverter(typeof(EndpointIsReadyConverter<bool>))]
public bool IsReady
{
get;
set;
}
/// <summary>
/// Error message during creation/deletion of endpoint
/// </summary>
[DataMember(EmitDefaultValue = false)]
public JObject OperationStatus
{
get;
set;
}
/// <summary>
/// Performs a deep clone of the <c>ServiceEndpoint</c> instance.
/// </summary>
/// <returns>A new <c>ServiceEndpoint</c> instance identical to the current instance</returns>
public ServiceEndpoint Clone()
{
return new ServiceEndpoint(this);
}
[DataMember(EmitDefaultValue = false, Name = "Data")]
private Dictionary<String, String> m_data;
}
internal class EndpointIsReadyConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
// we are converting every non-assignable thing to true
return true;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Boolean || reader.TokenType == JsonToken.Integer)
{
return serializer.Deserialize<T>(reader);
}
else if (reader.TokenType == JsonToken.String)
{
var s = (string)reader.Value;
if (s.Equals("false", StringComparison.OrdinalIgnoreCase) || s.Equals("0", StringComparison.OrdinalIgnoreCase))
{
return false;
}
return true;
}
else
{
return true;
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue((bool)value ? true : false);
}
}
}

View File

@@ -0,0 +1,91 @@
using System;
namespace GitHub.DistributedTask.WebApi
{
public static class ServiceEndpointTypes
{
/// <summary>
/// Azure endpoint
/// </summary>
public const String Azure = "Azure";
/// <summary>
/// Chef endpoint
/// </summary>
public const String Chef = "Chef";
/// Chef endpoint
/// </summary>
public const String ExternalTfs = "ExternalTfs";
/// <summary>
/// Generic endpoint
/// </summary>
public const String Generic = "Generic";
/// <summary>
/// GitHub endpoint
/// </summary>
public const String GitHub = "GitHub";
/// <summary>
/// GitHub Enterprise endpoint
/// </summary>
public const String GitHubEnterprise = "GitHubEnterprise";
/// <summary>
/// Bitbucket endpoint
/// </summary>
public const String Bitbucket = "Bitbucket";
/// <summary>
/// SSH endpoint
/// </summary>
public const String SSH = "SSH";
/// <summary>
/// Subversion endpoint
/// </summary>
public const String Subversion = "Subversion";
/// <summary>
///Gcp endpoint
/// </summary>
public const String Gcp = "google-cloud";
/// <summary>
/// Subversion endpoint
/// </summary>
public const String Jenkins = "Jenkins";
/// <summary>
/// External Git repository
/// </summary>
public const String ExternalGit = "Git";
/// <summary>
/// Azure RM endpoint
/// </summary>
public const String AzureRM = "AzureRM";
/// <summary>
/// Azure Deployment Manager
/// </summary>
public const String AzureDeploymentManager = "AzureDeploymentManager";
/// <summary>
/// Azure Service Fabric
/// </summary>
public const String AzureServiceFabric = "ServiceFabric";
/// <summary>
/// Azure Service Fabric
/// </summary>
public const String Docker = "dockerregistry";
/// <summary>
/// Jira
/// </summary>
public const String Jira = "Jira";
}
}

View File

@@ -0,0 +1,223 @@
using GitHub.Services.WebApi;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
public static class AgentConstants
{
// 1.x agent has been deprecated.
public static readonly String Version = "0.0.0";
}
/// <summary>
/// A task agent.
/// </summary>
[DataContract]
public class TaskAgent : TaskAgentReference, ICloneable
{
internal TaskAgent()
{
this.ProvisioningState = TaskAgentProvisioningStateConstants.Provisioned;
}
public TaskAgent(String name)
{
this.Name = name;
this.ProvisioningState = TaskAgentProvisioningStateConstants.Provisioned;
}
internal TaskAgent(TaskAgentReference reference)
: base(reference)
{
}
private TaskAgent(TaskAgent agentToBeCloned)
: base(agentToBeCloned)
{
this.CreatedOn = agentToBeCloned.CreatedOn;
this.MaxParallelism = agentToBeCloned.MaxParallelism;
this.StatusChangedOn = agentToBeCloned.StatusChangedOn;
if (agentToBeCloned.AssignedRequest != null)
{
this.AssignedRequest = agentToBeCloned.AssignedRequest.Clone();
}
if (agentToBeCloned.Authorization != null)
{
this.Authorization = agentToBeCloned.Authorization.Clone();
}
if (agentToBeCloned.m_properties != null && agentToBeCloned.m_properties.Count > 0)
{
m_properties = new PropertiesCollection(agentToBeCloned.m_properties);
}
if (agentToBeCloned.m_systemCapabilities != null && agentToBeCloned.m_systemCapabilities.Count > 0)
{
m_systemCapabilities = new Dictionary<String, String>(agentToBeCloned.m_systemCapabilities, StringComparer.OrdinalIgnoreCase);
}
if (agentToBeCloned.m_userCapabilities != null && agentToBeCloned.m_userCapabilities.Count > 0)
{
m_userCapabilities = new Dictionary<String, String>(agentToBeCloned.m_userCapabilities, StringComparer.OrdinalIgnoreCase);
}
if (agentToBeCloned.PendingUpdate != null)
{
this.PendingUpdate = agentToBeCloned.PendingUpdate.Clone();
}
}
/// <summary>
/// Maximum job parallelism allowed for this agent.
/// </summary>
[DataMember]
public Int32? MaxParallelism
{
get;
set;
}
/// <summary>
/// Date on which this agent was created.
/// </summary>
[DataMember]
public DateTime CreatedOn
{
get;
internal set;
}
/// <summary>
/// Date on which the last connectivity status change occurred.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public DateTime? StatusChangedOn
{
get;
internal set;
}
/// <summary>
/// The request which is currently assigned to this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentJobRequest AssignedRequest
{
get;
internal set;
}
/// <summary>
/// The last request which was completed by this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentJobRequest LastCompletedRequest
{
get;
internal set;
}
/// <summary>
/// Authorization information for this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentAuthorization Authorization
{
get;
set;
}
/// <summary>
/// Pending update for this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentUpdate PendingUpdate
{
get;
internal set;
}
/// <summary>
/// The agent cloud request that's currently associated with this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentCloudRequest AssignedAgentCloudRequest
{
get;
internal set;
}
/// <summary>
/// System-defined capabilities supported by this agent's host.
/// </summary>
public IDictionary<String, String> SystemCapabilities
{
get
{
if (m_systemCapabilities == null)
{
m_systemCapabilities = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_systemCapabilities;
}
}
/// <summary>
/// User-defined capabilities supported by this agent's host.
/// </summary>
public IDictionary<String, String> UserCapabilities
{
get
{
if (m_userCapabilities == null)
{
m_userCapabilities = new Dictionary<String, String>(StringComparer.OrdinalIgnoreCase);
}
return m_userCapabilities;
}
}
/// <summary>
/// Properties which may be used to extend the storage fields available
/// for a given machine instance.
/// </summary>
public PropertiesCollection Properties
{
get
{
if (m_properties == null)
{
m_properties = new PropertiesCollection();
}
return m_properties;
}
internal set
{
m_properties = value;
}
}
Object ICloneable.Clone()
{
return this.Clone();
}
public new TaskAgent Clone()
{
return new TaskAgent(this);
}
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "Properties")]
private PropertiesCollection m_properties;
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "SystemCapabilities")]
private Dictionary<String, String> m_systemCapabilities;
[DataMember(IsRequired = false, EmitDefaultValue = false, Name = "UserCapabilities")]
private Dictionary<String, String> m_userCapabilities;
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
/// <summary>
/// Provides data necessary for authorizing the agent using OAuth 2.0 authentication flows.
/// </summary>
[DataContract]
public sealed class TaskAgentAuthorization
{
/// <summary>
/// Initializes a new <c>TaskAgentAuthorization</c> instance with default values.
/// </summary>
public TaskAgentAuthorization()
{
}
private TaskAgentAuthorization(TaskAgentAuthorization objectToBeCloned)
{
this.AuthorizationUrl = objectToBeCloned.AuthorizationUrl;
this.ClientId = objectToBeCloned.ClientId;
if (objectToBeCloned.PublicKey != null)
{
this.PublicKey = objectToBeCloned.PublicKey.Clone();
}
}
/// <summary>
/// Endpoint used to obtain access tokens from the configured token service.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Uri AuthorizationUrl
{
get;
set;
}
/// <summary>
/// Client identifier for this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Guid ClientId
{
get;
set;
}
/// <summary>
/// Public key used to verify the identity of this agent.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public TaskAgentPublicKey PublicKey
{
get;
set;
}
/// <summary>
/// Creates a deep copy of the authorization data.
/// </summary>
/// <returns>A new <c>TaskAgentAuthorization</c> instance copied from the current instance</returns>
public TaskAgentAuthorization Clone()
{
return new TaskAgentAuthorization(this);
}
}
}

View File

@@ -0,0 +1,156 @@
using System;
using System.Runtime.Serialization;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class TaskAgentCloud
{
private TaskAgentCloud(TaskAgentCloud cloudToBeCloned)
{
this.Id = cloudToBeCloned.Id;
this.AgentCloudId = cloudToBeCloned.AgentCloudId;
this.Name = cloudToBeCloned.Name;
this.AcquireAgentEndpoint = cloudToBeCloned.AcquireAgentEndpoint;
this.ReleaseAgentEndpoint = cloudToBeCloned.ReleaseAgentEndpoint;
this.SharedSecret = cloudToBeCloned.SharedSecret;
this.Internal = cloudToBeCloned.Internal;
if (cloudToBeCloned.GetAgentDefinitionEndpoint != null)
{
this.GetAgentDefinitionEndpoint = cloudToBeCloned.GetAgentDefinitionEndpoint;
}
if (cloudToBeCloned.GetAgentRequestStatusEndpoint != null)
{
this.GetAgentRequestStatusEndpoint = cloudToBeCloned.GetAgentRequestStatusEndpoint;
}
if (cloudToBeCloned.AcquisitionTimeout != null)
{
this.AcquisitionTimeout = cloudToBeCloned.AcquisitionTimeout;
}
if (cloudToBeCloned.GetAccountParallelismEndpoint != null)
{
this.GetAccountParallelismEndpoint = cloudToBeCloned.GetAccountParallelismEndpoint;
}
if (cloudToBeCloned.MaxParallelism != null)
{
this.MaxParallelism = cloudToBeCloned.MaxParallelism;
}
}
public TaskAgentCloud()
{
}
//Id is used for interacting with pool providers, AgentCloudId is internal Id
[DataMember]
public Guid Id
{
get;
set;
}
[DataMember]
public Int32 AgentCloudId
{
get;
set;
}
[DataMember]
public String Name
{
get;
set;
}
/// <summary>
/// Gets or sets the type of the endpoint.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String Type
{
get;
set;
}
/// <summary>
/// Signifies that this Agent Cloud is internal and should not be user-manageable
/// </summary>
[DataMember(EmitDefaultValue = false)]
public Boolean Internal
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public String SharedSecret
{
get;
set;
}
/// <summary>
/// Gets or sets a AcquireAgentEndpoint using which a request can be made to acquire new agent
/// </summary>
[DataMember]
public String AcquireAgentEndpoint
{
get;
set;
}
[DataMember]
public String ReleaseAgentEndpoint
{
get;
set;
}
[DataMember(EmitDefaultValue = false, IsRequired = false)]
public String GetAgentDefinitionEndpoint
{
get;
set;
}
[DataMember(EmitDefaultValue = false, IsRequired = false)]
public String GetAgentRequestStatusEndpoint
{
get;
set;
}
[DataMember(EmitDefaultValue = false, IsRequired = false)]
public Int32? AcquisitionTimeout
{
get;
set;
}
[DataMember(EmitDefaultValue = false, IsRequired = false)]
public String GetAccountParallelismEndpoint
{
get;
set;
}
[DataMember(EmitDefaultValue = false, IsRequired = false)]
public Int32? MaxParallelism
{
get;
set;
}
public TaskAgentCloud Clone()
{
return new TaskAgentCloud(this);
}
}
}

View File

@@ -0,0 +1,116 @@
using System;
using System.Runtime.Serialization;
using Newtonsoft.Json.Linq;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class TaskAgentCloudRequest
{
private TaskAgentCloudRequest(TaskAgentCloudRequest requestToBeCloned)
{
this.AgentCloudId = requestToBeCloned.AgentCloudId;
this.RequestId = requestToBeCloned.RequestId;
this.AgentSpecification = requestToBeCloned.AgentSpecification;
this.ProvisionRequestTime = requestToBeCloned.ProvisionRequestTime;
this.ProvisionedTime = requestToBeCloned.ProvisionedTime;
this.AgentConnectedTime = requestToBeCloned.AgentConnectedTime;
this.ReleaseRequestTime = requestToBeCloned.ReleaseRequestTime;
if (requestToBeCloned.AgentData != null)
{
this.AgentData = new JObject(requestToBeCloned.AgentData);
}
if (requestToBeCloned.Pool != null)
{
this.Pool = requestToBeCloned.Pool.Clone();
}
if(requestToBeCloned.Agent != null)
{
this.Agent = requestToBeCloned.Agent.Clone();
}
}
public TaskAgentCloudRequest()
{
}
[DataMember]
public Int32 AgentCloudId
{
get;
set;
}
[DataMember]
public Guid RequestId
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public TaskAgentPoolReference Pool
{
get;
set;
}
[DataMember(EmitDefaultValue = false)]
public TaskAgentReference Agent
{
get;
set;
}
[DataMember]
public JObject AgentSpecification
{
get;
set;
}
[DataMember]
public JObject AgentData
{
get;
set;
}
[DataMember]
public DateTime? ProvisionRequestTime
{
get;
set;
}
[DataMember]
public DateTime? ProvisionedTime
{
get;
set;
}
[DataMember]
public DateTime? AgentConnectedTime
{
get;
set;
}
[DataMember]
public DateTime? ReleaseRequestTime
{
get;
set;
}
public TaskAgentCloudRequest Clone()
{
return new TaskAgentCloudRequest(this);
}
}
}

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using GitHub.Services.FormInput;
namespace GitHub.DistributedTask.WebApi
{
[DataContract]
public class TaskAgentCloudType
{
public TaskAgentCloudType()
{
}
/// <summary>
/// Gets or sets the name of agent cloud type.
/// </summary>
[DataMember]
public String Name
{
get;
set;
}
/// <summary>
/// Gets or sets the display name of agnet cloud type.
/// </summary>
[DataMember(EmitDefaultValue = false)]
public String DisplayName { get; set; }
public List<InputDescriptor> InputDescriptors
{
get
{
return m_inputDescriptors ?? (m_inputDescriptors = new List<InputDescriptor>());
}
set
{
m_inputDescriptors = value;
}
}
/// <summary>
/// Gets or sets the input descriptors
/// </summary>
[DataMember(EmitDefaultValue = false, Name = "InputDescriptors")]
private List<InputDescriptor> m_inputDescriptors;
}
}

Some files were not shown because too many files have changed in this diff Show More