зеркало из https://github.com/microsoft/Atlas.git
Uploading binary downloads to cdn (#8)
* Adding example to create cdn and storage account * Copying examples folder to artifacts drop location * Adding support for binary data and files * Each cdn rule may have only one condition * Protecting against OS newline differences * Updating install description and status badges
This commit is contained in:
Родитель
374d805c05
Коммит
8d258a6a2c
31
README.md
31
README.md
|
@ -2,7 +2,10 @@
|
|||
|
||||
# Atlas
|
||||
|
||||
[![Build Status]][Build Latest]
|
||||
[![Build Status]][Build Latest]
|
||||
[![Zip Status]][Zip Latest]
|
||||
[![Tarball Status]][Tarball Latest]
|
||||
[![Choco Status]][Choco Latest]
|
||||
|
||||
![Atlas Logo]
|
||||
|
||||
|
@ -17,6 +20,20 @@ With Atlas you can make the configuration of everything from CI/CD to production
|
|||
|
||||
----
|
||||
|
||||
## Install
|
||||
|
||||
Daily builds of the Atlas CLI are available as self-contained downloads.
|
||||
|
||||
| Platform | [Master branch (0.1)][Master Branch] | [Latest build][Latest Json] |
|
||||
|:------:|:------:|:------:|
|
||||
| **Windows x64** | [Download latest zip][Zip Latest] | [![Zip Status]][Zip Latest] |
|
||||
| **Linux x64** | [Download latest tar.gz][Zip Latest] | [![Tarball Status]][Tarball Latest] |
|
||||
|
||||
If you want to use a package manager:
|
||||
|
||||
#### Chocolatey
|
||||
* [Chocolatey](https://chocolatey.org/) users can use `choco install atlas-cli -s https://www.myget.org/F/atlas-ci`
|
||||
|
||||
## Features
|
||||
|
||||
* [YAML] or [JSON] syntax to define workflows and input parameters
|
||||
|
@ -88,8 +105,16 @@ the [Security TechCenter](https://technet.microsoft.com/en-us/security/default).
|
|||
[YAML]: http://yaml.org/
|
||||
[JSON]: http://json.org/
|
||||
[JMESPath]: http://jmespath.org/
|
||||
[Build Status]: https://msasg.visualstudio.com/Falcon/_apis/build/status/Atlas-CI?branch=master
|
||||
[Build Latest]: https://msasg.visualstudio.com/Falcon/_build/latest?definitionId=6598&branch=master
|
||||
[Azure RM REST API]: https://docs.microsoft.com/en-us/rest/api/azure/
|
||||
[Azure AD REST API]: https://docs.microsoft.com/en-us/rest/api/graphrbac/
|
||||
[VSTS REST API]: https://docs.microsoft.com/en-us/rest/api/vsts/?view=vsts-rest-5.0
|
||||
[Build Status]: https://msasg.visualstudio.com/Falcon/_apis/build/status/Atlas-CI?branch=master
|
||||
[Build Latest]: https://msasg.visualstudio.com/Falcon/_build/latest?definitionId=6598&branch=master
|
||||
[Choco Status]: https://img.shields.io/myget/atlas-ci/vpre/atlas-cli.svg?label=choco
|
||||
[Choco Latest]: #chocolatey
|
||||
[Zip Status]: https://img.shields.io/badge/dynamic/json.svg?label=win-x64&url=https%3A%2F%2Fepjdcwdl4ufyw54.azureedge.net%2Fdownloads%2Flatest.json&query=%24[%27win10-x64%27].version
|
||||
[Zip Latest]: https://epjdcwdl4ufyw54.azureedge.net/downloads/atlas-latest-win10-x64.zip
|
||||
[Tarball Status]: https://img.shields.io/badge/dynamic/json.svg?label=linux-x64&url=https%3A%2F%2Fepjdcwdl4ufyw54.azureedge.net%2Fdownloads%2Flatest.json&query=%24[%27linux-x64%27].version
|
||||
[Tarball Latest]: https://epjdcwdl4ufyw54.azureedge.net/downloads/atlas-latest-linux-x64.tar.gz
|
||||
[Master Branch]: https://github.com/microsoft/atlas/tree/master
|
||||
[Latest Json]: https://epjdcwdl4ufyw54.azureedge.net/downloads/latest.json
|
||||
|
|
|
@ -71,6 +71,12 @@ steps:
|
|||
configuration: Release
|
||||
packDirectory: '$(Build.ArtifactStagingDirectory)/chocolatey'
|
||||
|
||||
- task: CopyFiles@2
|
||||
displayName: 'copy examples to $(Build.ArtifactStagingDirectory)'
|
||||
inputs:
|
||||
SourceFolder: examples
|
||||
TargetFolder: '$(Build.ArtifactStagingDirectory)/examples'
|
||||
|
||||
- script: |
|
||||
npm install -g typescript
|
||||
npm install -g tfx-cli
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/resources/deployments/createorupdate
|
||||
|
||||
method: PUT
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourcegroups/{{azure.resourceGroupName}}/providers/Microsoft.Resources/deployments/{{deployment.name}}?api-version=2018-02-01
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
||||
body:
|
||||
properties: {{{json deployment.properties}}}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/resources/deployments/get
|
||||
|
||||
method: GET
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourcegroups/{{azure.resourceGroupName}}/providers/Microsoft.Resources/deployments/{{deployment.name}}?api-version=2018-02-01
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/resources/deployments/validate
|
||||
|
||||
method: POST
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourcegroups/{{azure.resourceGroupName}}/providers/Microsoft.Resources/deployments/{{deployment.name}}/validate?api-version=2018-02-01
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
||||
body:
|
||||
properties: {{{json deployment.properties}}}
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/createorupdate
|
||||
|
||||
method: PUT
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourcegroups/{{azure.resourceGroupName}}?api-version=2018-02-01
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
||||
body:
|
||||
location: {{azure.location}}
|
|
@ -0,0 +1,9 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/resources/resourcegroups/get
|
||||
|
||||
method: GET
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourcegroups/{{azure.resourceGroupName}}?api-version=2018-02-01
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
|
@ -0,0 +1,13 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
|
||||
|
||||
method: PUT
|
||||
url: https://{{storage.account}}.blob.core.windows.net/{{storage.container}}/{{blob.path}}
|
||||
headers:
|
||||
x-ms-date: {{ datetime add="PT0S" format="r" }}
|
||||
x-ms-version: "2018-03-28"
|
||||
x-ms-blob-type: BlockBlob
|
||||
Authorization: "SharedKey {{storage.account}}:{{storage.key}}"
|
||||
Content-Type: {{ blob.contentType }}
|
||||
|
||||
body: {{ binary file=blob.file }}
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
|
||||
|
||||
method: PUT
|
||||
url: https://{{storage.account}}.blob.core.windows.net/{{storage.container}}/{{blob.path}}
|
||||
headers:
|
||||
x-ms-date: {{ datetime add="PT0S" format="r" }}
|
||||
x-ms-version: "2018-03-28"
|
||||
x-ms-blob-type: BlockBlob
|
||||
Authorization: "SharedKey {{storage.account}}:{{storage.key}}"
|
||||
|
||||
body: "{{blob.body}}"
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/storageservices/put-blob
|
||||
|
||||
method: PUT
|
||||
url: https://{{storage.account}}.blob.core.windows.net/{{storage.container}}?restype=container
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://storage.azure.com/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
||||
headers:
|
||||
x-ms-date: {{ datetime add="PT0S" }}
|
||||
x-ms-version: "2018-03-28"
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
# https://docs.microsoft.com/en-us/rest/api/storagerp/srp_json_get_storage_account_keys
|
||||
|
||||
method: POST
|
||||
url: https://management.azure.com/subscriptions/{{azure.subscription}}/resourceGroups/{{azure.resourceGroupName}}/providers/Microsoft.Storage/storageAccounts/{{storage.account}}/listKeys?api-version=2018-03-01-preview
|
||||
auth:
|
||||
tenant: {{azure.tenant}}
|
||||
resource: https://management.core.windows.net/
|
||||
client: 04b07795-8ddb-461a-bbee-02f9e1bf7b46 # Azure CLI
|
||||
secret: keys[*].value
|
|
@ -0,0 +1,182 @@
|
|||
{
|
||||
"$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {
|
||||
"location": {
|
||||
"type": "string",
|
||||
"defaultValue": "[resourceGroup().location]",
|
||||
"metadata": {
|
||||
"description": "Location for all resources."
|
||||
}
|
||||
}
|
||||
},
|
||||
"variables": {
|
||||
"storageAccountName": "[concat('sa', uniqueString(resourceGroup().id))]",
|
||||
"endpointName": "[concat('ep', uniqueString(resourceGroup().id))]",
|
||||
"profileName": "CdnProfile1"
|
||||
},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.Storage/storageAccounts",
|
||||
"name": "[variables('storageAccountName')]",
|
||||
"apiVersion": "2016-01-01",
|
||||
"location": "[parameters('location')]",
|
||||
"tags": {
|
||||
"displayName": "[variables('storageAccountName')]"
|
||||
},
|
||||
"kind": "Storage",
|
||||
"sku": {
|
||||
"name": "{{ storage.sku }}"
|
||||
},
|
||||
"properties": {}
|
||||
},
|
||||
{
|
||||
"type": "Microsoft.Storage/storageAccounts/blobServices/containers",
|
||||
"name": "[concat(variables('storageAccountName'), '/default/', '{{ storage.container }}')]",
|
||||
"dependsOn": [
|
||||
"[variables('storageAccountName')]"
|
||||
],
|
||||
"apiVersion": "2018-03-01-preview",
|
||||
"properties": {
|
||||
"publicAccess": "Container"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "[variables('profileName')]",
|
||||
"type": "Microsoft.Cdn/profiles",
|
||||
"location": "[parameters('location')]",
|
||||
"apiVersion": "2017-10-12",
|
||||
"tags": {
|
||||
"displayName": "[variables('profileName')]"
|
||||
},
|
||||
"sku": {
|
||||
"name": "Standard_Akamai"
|
||||
},
|
||||
"properties": {},
|
||||
"resources": [
|
||||
{
|
||||
"apiVersion": "2017-10-12",
|
||||
"name": "[variables('endpointName')]",
|
||||
"type": "endpoints",
|
||||
"dependsOn": [
|
||||
"[variables('profileName')]",
|
||||
"[variables('storageAccountName')]"
|
||||
],
|
||||
"location": "[parameters('location')]",
|
||||
"tags": {
|
||||
"displayName": "[variables('endpointName')]"
|
||||
},
|
||||
"properties": {
|
||||
"originHostHeader": "[replace(replace(reference(variables('storageAccountName')).primaryEndpoints.blob,'https://',''),'/','')]",
|
||||
"isHttpAllowed": false,
|
||||
"isHttpsAllowed": true,
|
||||
"queryStringCachingBehavior": "IgnoreQueryString",
|
||||
"contentTypesToCompress": [
|
||||
"text/plain",
|
||||
"text/html",
|
||||
"text/css",
|
||||
"application/x-javascript",
|
||||
"text/javascript"
|
||||
],
|
||||
"isCompressionEnabled": true,
|
||||
"origins": [
|
||||
{
|
||||
"name": "origin1",
|
||||
"properties": {
|
||||
"hostName": "[replace(replace(reference(variables('storageAccountName')).primaryEndpoints.blob,'https://',''),'/','')]"
|
||||
}
|
||||
}
|
||||
],
|
||||
"deliveryPolicy":{
|
||||
"rules": [
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"name": "UrlPath",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleUrlPathConditionParameters",
|
||||
"matchType": "Literal",
|
||||
"path": "/downloads/latest.json"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "CacheExpiration",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleCacheExpirationActionParameters",
|
||||
"cacheBehavior": "BypassCache",
|
||||
"cacheType": "All"
|
||||
}
|
||||
}
|
||||
],
|
||||
"order": 1
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"name": "UrlPath",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleUrlPathConditionParameters",
|
||||
"matchType": "Literal",
|
||||
"path": "/downloads/atlas-latest-win10-x64.zip"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "CacheExpiration",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleCacheExpirationActionParameters",
|
||||
"cacheBehavior": "BypassCache",
|
||||
"cacheType": "All"
|
||||
}
|
||||
}
|
||||
],
|
||||
"order": 2
|
||||
},
|
||||
{
|
||||
"conditions": [
|
||||
{
|
||||
"name": "UrlPath",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleUrlPathConditionParameters",
|
||||
"matchType": "Literal",
|
||||
"path": "/downloads/atlas-latest-linux-x64.tar.gz"
|
||||
}
|
||||
}
|
||||
],
|
||||
"actions": [
|
||||
{
|
||||
"name": "CacheExpiration",
|
||||
"parameters": {
|
||||
"@odata.type": "Microsoft.Azure.Cdn.Models.DeliveryRuleCacheExpirationActionParameters",
|
||||
"cacheBehavior": "BypassCache",
|
||||
"cacheType": "All"
|
||||
}
|
||||
}
|
||||
],
|
||||
"order": 3
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"outputs": {
|
||||
"storageAccountName": {
|
||||
"type": "string",
|
||||
"value": "[variables('storageAccountName')]"
|
||||
},
|
||||
"hostName": {
|
||||
"type": "string",
|
||||
"value": "[reference(variables('endpointName')).hostName]"
|
||||
},
|
||||
"originHostHeader": {
|
||||
"type": "string",
|
||||
"value": "[reference(variables('endpointName')).originHostHeader]"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"win10-x64": {
|
||||
"version": "{{ latest.version }}",
|
||||
"path": "atlas-{{ latest.version }}-win10-x64.zip"
|
||||
},
|
||||
"linux-x64": {
|
||||
"version": "{{ latest.version }}",
|
||||
"path": "atlas-{{ latest.version }}-linux-x64.tar.gz"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
azure:
|
||||
# Your Azure Active Directory ID from https://ms.portal.azure.com/#blade/Microsoft_AAD_IAM/ActiveDirectoryMenuBlade/Properties
|
||||
# tenant: TENANT_ID
|
||||
# Your Azure Subscription ID from https://ms.portal.azure.com/#blade/Microsoft_Azure_Billing/SubscriptionsBlade
|
||||
# subscription: SUBSCRIPTION_ID
|
||||
resourceGroupName: atlas-examples-402
|
||||
location: eastus2
|
||||
|
||||
storage:
|
||||
sku: Standard_LRS
|
||||
container: downloads
|
|
@ -0,0 +1,109 @@
|
|||
|
||||
values: {{{ json }}}
|
||||
|
||||
# Declaring secret {{ secret vsts.token }}
|
||||
|
||||
operations:
|
||||
- message: Validating inputs
|
||||
- {condition: (!azure.tenant), output: { missing: {azure: {tenant: or --set azure.tenant=AAD_TENANT_ID }}}}
|
||||
- {condition: (!azure.subscription), output: { missing: {azure: {subscription: or --set azure.subscription=AZURE_SUBSCRIPTION_ID }}}}
|
||||
|
||||
- message: Input validation failed
|
||||
condition: (missing != null)
|
||||
throw:
|
||||
message: >
|
||||
This workflow is missing information which is
|
||||
needed to run.
|
||||
|
||||
Please add them to a values.yaml file in the
|
||||
current directory, or provide the missing values
|
||||
as command line options.
|
||||
details: (missing)
|
||||
|
||||
- message: Preparing resource group
|
||||
request: apis/azure/resourcegroups/apply.yaml
|
||||
|
||||
- message: Deploying cdn and storage account
|
||||
values:
|
||||
deployment:
|
||||
name: cdn-and-storage-{{ guid (datetime add="PT0S") }}
|
||||
properties:
|
||||
mode: Incremental
|
||||
template: {{> azuredeploy.json }}
|
||||
parameters:
|
||||
location:
|
||||
value: {{ azure.location }}
|
||||
operations:
|
||||
- message: Creating deployment
|
||||
request: apis/azure/deployments/apply.yaml
|
||||
|
||||
- message: Waiting for deployment to complete...
|
||||
request: apis/azure/deployments/get.yaml
|
||||
output:
|
||||
deploymentStatus: (@)
|
||||
repeat:
|
||||
condition: deploymentStatus.properties.provisioningState == 'Accepted' || deploymentStatus.properties.provisioningState == 'Running'
|
||||
delay: PT5S
|
||||
timeout: PT4M
|
||||
|
||||
- message: Deployment failed
|
||||
condition: deploymentStatus.properties.provisioningState != 'Succeeded'
|
||||
throw:
|
||||
message: (['Deployment provisioning state is "', deploymentStatus.properties.provisioningState, '". ', deploymentStatus.properties.error.message])
|
||||
details: (deploymentStatus.properties.error)
|
||||
|
||||
output:
|
||||
deployment: (deploymentStatus.properties.{state:provisioningState, error:error, outputs:outputs})
|
||||
storage:
|
||||
account: (deploymentStatus.properties.outputs.storageAccountName.value)
|
||||
|
||||
- message: Uploading files to storage
|
||||
operations:
|
||||
- message: Getting storage keys
|
||||
request: apis/azure/storage/listkeys.yaml
|
||||
output:
|
||||
storage:
|
||||
key: (keys[0].value)
|
||||
|
||||
- message: Sending latest.json
|
||||
values:
|
||||
blob:
|
||||
path: latest.json
|
||||
body: |
|
||||
{{# indent 10 }}
|
||||
{{> latest.json }}
|
||||
{{/ indent }}
|
||||
contentType: application/json
|
||||
request: apis/azure/storage/blob-put.yaml
|
||||
|
||||
- message: Sending atlas-{{ latest.version }}-win10-x64.zip
|
||||
values:
|
||||
blob:
|
||||
path: atlas-{{ latest.version }}-win10-x64.zip
|
||||
file: {{ latest.downloads }}/atlas-{{ latest.version }}-win10-x64.zip
|
||||
contentType: application/zip
|
||||
request: apis/azure/storage/blob-put-binary.yaml
|
||||
|
||||
- message: Sending atlas-{{ latest.version }}-linux-x64.tar.gz
|
||||
values:
|
||||
blob:
|
||||
path: atlas-{{ latest.version }}-linux-x64.tar.gz
|
||||
file: {{ latest.downloads }}/atlas-{{ latest.version }}-linux-x64.tar.gz
|
||||
contentType: application/x-gtar
|
||||
request: apis/azure/storage/blob-put-binary.yaml
|
||||
|
||||
- message: Sending atlas-latest-win10-x64.zip
|
||||
values:
|
||||
blob:
|
||||
path: atlas-latest-win10-x64.zip
|
||||
file: {{ latest.downloads }}/atlas-{{ latest.version }}-win10-x64.zip
|
||||
contentType: application/zip
|
||||
request: apis/azure/storage/blob-put-binary.yaml
|
||||
|
||||
- message: Sending atlas-latest-linux-x64.tar.gz
|
||||
values:
|
||||
blob:
|
||||
path: atlas-latest-linux-x64.tar.gz
|
||||
file: {{ latest.downloads }}/atlas-{{ latest.version }}-linux-x64.tar.gz
|
||||
contentType: application/x-gtar
|
||||
request: apis/azure/storage/blob-put-binary.yaml
|
|
@ -47,6 +47,10 @@ namespace Microsoft.Atlas.CommandLine.JsonClient
|
|||
{
|
||||
request.Content = new StringContent((string)jsonRequest.body);
|
||||
}
|
||||
else if (jsonRequest.body is byte[])
|
||||
{
|
||||
request.Content = new ByteArrayContent((byte[])jsonRequest.body);
|
||||
}
|
||||
else
|
||||
{
|
||||
var memoryStream = new MemoryStream();
|
||||
|
|
|
@ -85,6 +85,7 @@ namespace Microsoft.Atlas.CommandLine
|
|||
.AddSingleton<ITemplateEngineFactory, TemplateEngineFactory>()
|
||||
.AddSingleton<TemplateEngineServices>()
|
||||
.AddTransient<ITemplateHelperProvider, SshHelpers>()
|
||||
.AddTransient<ITemplateHelperProvider, BinaryHelpers>()
|
||||
|
||||
.AddSingleton<CommandLineApplicationServices>()
|
||||
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Serialization;
|
||||
|
||||
namespace Microsoft.Atlas.CommandLine.Serialization
|
||||
{
|
||||
public class ByteArrayConverter : IYamlTypeConverter
|
||||
{
|
||||
public bool Accepts(Type type)
|
||||
{
|
||||
return type == typeof(byte[]);
|
||||
}
|
||||
|
||||
public object ReadYaml(IParser parser, Type type)
|
||||
{
|
||||
var scalar = (YamlDotNet.Core.Events.Scalar)parser.Current;
|
||||
var bytes = Convert.FromBase64String(scalar.Value);
|
||||
parser.MoveNext();
|
||||
return bytes;
|
||||
}
|
||||
|
||||
public void WriteYaml(IEmitter emitter, object value, Type type)
|
||||
{
|
||||
var bytes = (byte[])value;
|
||||
emitter.Emit(new YamlDotNet.Core.Events.Scalar(
|
||||
null,
|
||||
"tag:yaml.org,2002:binary",
|
||||
Convert.ToBase64String(bytes),
|
||||
ScalarStyle.Plain,
|
||||
false,
|
||||
false));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -12,10 +12,30 @@ namespace Microsoft.Atlas.CommandLine.Serialization
|
|||
{
|
||||
public YamlSerializers()
|
||||
{
|
||||
YamlDeserializer = new DeserializerBuilder().WithNodeTypeResolver(new NonStringScalarTypeResolver()).Build();
|
||||
YamlSerializer = new SerializerBuilder().DisableAliases().WithEventEmitter(DoubleQuoteAmbiguousStringScalarEmitter.Factory).Build();
|
||||
JsonSerializer = new SerializerBuilder().DisableAliases().JsonCompatible().Build();
|
||||
ValueSerialier = new SerializerBuilder().DisableAliases().JsonCompatible().BuildValueSerializer();
|
||||
YamlDeserializer = new DeserializerBuilder()
|
||||
.WithNodeTypeResolver(new NonStringScalarTypeResolver())
|
||||
.WithTagMapping("tag:yaml.org,2002:binary", typeof(byte[]))
|
||||
.WithTypeConverter(new ByteArrayConverter())
|
||||
.Build();
|
||||
|
||||
YamlSerializer = new SerializerBuilder()
|
||||
.DisableAliases()
|
||||
.WithEventEmitter(DoubleQuoteAmbiguousStringScalarEmitter.Factory)
|
||||
.WithTypeConverter(new ByteArrayConverter())
|
||||
.Build();
|
||||
|
||||
JsonSerializer = new SerializerBuilder()
|
||||
.DisableAliases()
|
||||
.JsonCompatible()
|
||||
.WithTypeConverter(new ByteArrayConverter())
|
||||
.Build();
|
||||
|
||||
ValueSerialier = new SerializerBuilder()
|
||||
.DisableAliases()
|
||||
.JsonCompatible()
|
||||
.WithTypeConverter(new ByteArrayConverter())
|
||||
.BuildValueSerializer();
|
||||
|
||||
JTokenTranserializer = JTokenTranserializerImpl;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT license.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using HandlebarsDotNet;
|
||||
using Microsoft.Atlas.CommandLine.Secrets;
|
||||
using Org.BouncyCastle.Crypto;
|
||||
using Org.BouncyCastle.Crypto.Generators;
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Prng;
|
||||
using Org.BouncyCastle.OpenSsl;
|
||||
using Org.BouncyCastle.Security;
|
||||
|
||||
namespace Microsoft.Atlas.CommandLine.Templates.Helpers
|
||||
{
|
||||
public class BinaryHelpers : TemplateHelperProvider
|
||||
{
|
||||
private readonly ISecretTracker _secretTracker;
|
||||
|
||||
public BinaryHelpers(ISecretTracker secretTracker)
|
||||
{
|
||||
_secretTracker = secretTracker;
|
||||
}
|
||||
|
||||
[Description("binary")]
|
||||
public void SshKeyGen(TextWriter output, dynamic context, params object[] arguments)
|
||||
{
|
||||
var options = arguments.Last() as IDictionary<string, object>;
|
||||
if (options != null)
|
||||
{
|
||||
if (options.TryGetValue("file", out var file))
|
||||
{
|
||||
// TODO: file reading service, and restricted source locations
|
||||
var bytes = File.ReadAllBytes(file.ToString());
|
||||
output.Write($"!!binary {Convert.ToBase64String(bytes)}");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("'binary' helper requires a file='path' option");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -142,7 +142,8 @@ namespace Microsoft.Atlas.CommandLine.Templates
|
|||
var options = arguments.Last() as IDictionary<string, object>;
|
||||
if (options != null)
|
||||
{
|
||||
if (options.TryGetValue("provider", out var provider) && string.Equals(provider?.ToString(), "RNGCryptoServiceProvider", StringComparison.OrdinalIgnoreCase))
|
||||
if (options.TryGetValue("provider", out var provider) &&
|
||||
string.Equals(provider?.ToString(), "RNGCryptoServiceProvider", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
using (var rng = new RNGCryptoServiceProvider())
|
||||
{
|
||||
|
|
|
@ -196,6 +196,27 @@ eta:
|
|||
Assert.AreEqual(expected, actual);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BinaryCanBeSerialized()
|
||||
{
|
||||
var services = Program.AddServices(new ServiceCollection()).BuildServiceProvider();
|
||||
|
||||
var serializers = services.GetRequiredService<IYamlSerializers>();
|
||||
|
||||
var data = new Dictionary<object, object>
|
||||
{
|
||||
{ "data", new byte[] { 0, 1, 2, 3, 254, 255 } },
|
||||
};
|
||||
|
||||
var yaml = serializers.YamlSerializer.Serialize(data);
|
||||
|
||||
var json = serializers.JsonSerializer.Serialize(data);
|
||||
|
||||
Assert.AreEqual("data: !!binary AAECA/7/", yaml.Replace("\r", string.Empty).Replace("\n", string.Empty));
|
||||
|
||||
Assert.AreEqual(@"{""data"": !!binary AAECA/7/}", json.Replace("\r", string.Empty).Replace("\n", string.Empty));
|
||||
}
|
||||
|
||||
private void AssertAreEqual(object expected, object actual)
|
||||
{
|
||||
Assert.AreSame(expected?.GetType(), actual?.GetType());
|
||||
|
|
Загрузка…
Ссылка в новой задаче