Sintaxe de Rules de modelo do CloudFormation
A seção Rules
é uma parte opcional de um modelo do CloudFormation que permite uma lógica de validação personalizada. Quando incluída, esta seção contém funções de regras que validam os valores dos parâmetros antes que o CloudFormation crie ou atualize quaisquer recursos.
As regras são úteis quando as restrições de parâmetros padrão são insuficientes. Por exemplo, se o SSL estiver habilitado, um certificado e um nome de domínio deverão ser fornecidos.
Sintaxe
A seção Rules
usa a seguinte sintaxe:
JSON
A seção Rules
de um modelo consiste no nome da chave Rules
, seguido por dois-pontos. Você deve usar chaves para delimitar todas as declarações de regras. Se você declarar várias regras, elas serão separadas por vírgulas. Para cada regra, você declara um nome lógico entre aspas seguido por uma vírgula e chaves que incluem a condição da regra e as declarações.
{
"Rules": {
"LogicalRuleName1
": {
"RuleCondition": {
"rule-specific intrinsic function
": "Value
"
},
"Assertions": [
{
"Assert": {
"rule-specific intrinsic function
": "Value
"
},
"AssertDescription": "Information about this assert
"
},
{
"Assert": {
"rule-specific intrinsic function
": "Value
"
},
"AssertDescription": "Information about this assert
"
}
]
},
"LogicalRuleName2
": {
"Assertions": [
{
"Assert": {
"rule-specific intrinsic function
": "Value
"
},
"AssertDescription": "Information about this assert
"
}
]
}
}
}
YAML
Rules:
LogicalRuleName1
:
RuleCondition:
rule-specific intrinsic function
: Value
Assertions:
- Assert:
rule-specific intrinsic function
: Value
AssertDescription: Information about this assert
- Assert:
rule-specific intrinsic function
: Value
AssertDescription: Information about this assert
LogicalRuleName2
:
Assertions:
- Assert:
rule-specific intrinsic function
: Value
AssertDescription: Information about this assert
Campos de regras
A seção Rules
pode incluir os seguintes campos.
- ID lógico (também chamado de nome lógico)
-
Um identificador exclusivo para cada regra.
RuleCondition
(opcional)-
Uma propriedade que determina quando uma regra entra em vigor. Se você não definir uma condição de regra, as declarações da regra sempre entram em vigor. Para cada regra, você pode definir apenas uma condição de regra.
Assertions
(obrigatório)-
Uma ou mais declarações que especificam os valores aceitáveis para um determinado parâmetro.
Assert
-
Uma condição que deve ser avaliada como
true
. AssertDescription
-
Uma mensagem exibida quando uma asserção falha.
Funções intrínsecas específicas de regras
Para definir suas regras, é necessário usar funções específicas à regra, que são funções que podem ser usadas apenas na seção Rules
de um modelo. Embora essas funções possam ser aninhadas, o resultado final de uma condição de regra ou asserção deve ser true
ou false
.
As seguintes funções de regras estão disponíveis:
Essas funções são usadas na condição ou nas asserções de uma regra. A propriedade da condição determina se o CloudFormation se aplica a asserções. Se a condição for avaliada como true
, o CloudFormation avaliará as asserções para verificar se um valor de parâmetro é válido quando um produto provisionado for criado ou atualizado. Se o valor de um parâmetro for inválido, o CloudFormation não criará nem atualizará a pilha. Se a condição for avaliada como false
, o CloudFormation não verificará o valor do parâmetro e prosseguirá com a operação de pilha.
Exemplos
Verificar condicionalmente um valor de parâmetro
No exemplo a seguir, as duas regras verificam o valor do parâmetro InstanceType
. Dependendo do valor do parâmetro de ambiente (test
ou prod
), o usuário deve especificar a1.medium
ou a1.large
para o parâmetro InstanceType
. Os parâmetros InstanceType
e Environment
já devem estar declarados na seção Parameters
do mesmo modelo.
JSON
{ "Rules": { "testInstanceType": { "RuleCondition": { "Fn::Equals": [ {"Ref": "Environment"}, "test" ] }, "Assertions": [ { "Assert": { "Fn::Contains": [ ["a1.medium"], {"Ref": "InstanceType"} ] }, "AssertDescription": "For a test environment, the instance type must be a1.medium" } ] }, "prodInstanceType": { "RuleCondition": { "Fn::Equals": [ {"Ref": "Environment"}, "prod" ] }, "Assertions": [ { "Assert": { "Fn::Contains": [ ["a1.large"], {"Ref": "InstanceType"} ] }, "AssertDescription": "For a production environment, the instance type must be a1.large" } ] } } }
YAML
Rules: testInstanceType: RuleCondition: !Equals - !Ref Environment - test Assertions: - Assert: 'Fn::Contains': - - a1.medium - !Ref InstanceType AssertDescription: 'For a test environment, the instance type must be a1.medium' prodInstanceType: RuleCondition: !Equals - !Ref Environment - prod Assertions: - Assert: 'Fn::Contains': - - a1.large - !Ref InstanceType AssertDescription: 'For a production environment, the instance type must be a1.large'
Validação de parâmetros cruzados
Os modelos de exemplo a seguir demonstram o uso de regras para validações entre parâmetros. Eles criam um site de exemplo executado em um grupo do Auto Scaling atrás de um balanceador de carga. O site está disponível na porta 80 ou 443, dependendo dos parâmetros de entrada. As instâncias no grupo do Auto Scaling podem ser configuradas para escutar em qualquer porta (com 8888 como padrão).
As regras neste modelo validam os parâmetros de entrada antes da criação da pilha. Elas verificam se todas as sub-redes pertencem à VPC especificada e garantem que, quando o parâmetro UseSSL
for definido como Yes
, um ARN de certificado SSL e um nome de zona hospedada sejam fornecidos.
nota
Você será cobrado pelos recursos da AWS usados se criar uma pilha com base nesse modelo.
JSON
{ "AWSTemplateFormatVersion": "2010-09-09", "Parameters": { "VpcId": { "Type": "AWS::EC2::VPC::Id", "Description": "VpcId of your existing Virtual Private Cloud (VPC)", "ConstraintDescription": "must be the VPC Id of an existing Virtual Private Cloud." }, "Subnets": { "Type": "List<AWS::EC2::Subnet::Id>", "Description": "The list of SubnetIds in your Virtual Private Cloud (VPC)", "ConstraintDescription": "must be a list of at least two existing subnets associated with at least two different availability zones." }, "InstanceType": { "Description": "WebServer EC2 instance type", "Type": "String", "Default": "t2.micro", "AllowedValues": ["t2.micro", "t3.micro"], "ConstraintDescription": "must be a valid EC2 instance type." }, "KeyName": { "Description": "Name of an existing EC2 KeyPair to enable SSH access to the instances", "Type": "AWS::EC2::KeyPair::KeyName", "ConstraintDescription": "must be the name of an existing EC2 KeyPair." }, "SSHLocation": { "Description": "The IP address range that can be used to SSH to the EC2 instances", "Type": "String", "MinLength": "9", "MaxLength": "18", "Default": "0.0.0.0/0", "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})", "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x." }, "UseSSL": { "AllowedValues": ["Yes", "No"], "Default": "No", "Description": "Select \"Yes\" to implement SSL, \"No\" to skip (default).", "Type": "String" }, "ALBSSLCertificateARN": { "Default": "", "Description": "[Optional] The ARN of the SSL certificate to be used for the Application Load Balancer", "Type": "String" }, "HostedZoneName": { "AllowedPattern": "^$|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$", "Default": "", "Description": "[Optional] The domain name of a valid Hosted Zone on AWS.", "Type": "String" } }, "Conditions": { "UseALBSSL": {"Fn::Equals": [{"Ref": "UseSSL"}, "Yes"]} }, "Rules": { "SubnetsInVPC": { "Assertions": [ { "Assert": {"Fn::EachMemberEquals": [{"Fn::ValueOf": ["Subnets", "VpcId"]}, {"Ref": "VpcId"}]}, "AssertDescription": "All subnets must be in the VPC" } ] }, "ValidateHostedZone": { "RuleCondition": {"Fn::Equals": [{"Ref": "UseSSL"}, "Yes"]}, "Assertions": [ { "Assert": {"Fn::Not": [{"Fn::Equals": [{"Ref": "ALBSSLCertificateARN"}, ""]}]}, "AssertDescription": "ACM Certificate value cannot be empty if SSL is required" }, { "Assert": {"Fn::Not": [{"Fn::Equals": [{"Ref": "HostedZoneName"}, ""]}]}, "AssertDescription": "Route53 Hosted Zone Name is mandatory when SSL is required" } ] } }, "Mappings": { "AWSAMIRegionMap": { "us-east-1": {"AMZNLINUXHVM": "ami-0ff8a91507f77f867"}, "us-west-1": {"AMZNLINUXHVM": "ami-0bdb828fd58c52235"}, "eu-west-1": {"AMZNLINUXHVM": "ami-047bb4163c506cd98"}, "ap-southeast-1": {"AMZNLINUXHVM": "ami-08569b978cc4dfa10"} } }, "Resources": { "WebServerGroup": { "Type": "AWS::AutoScaling::AutoScalingGroup", "Properties": { "VPCZoneIdentifier": {"Ref": "Subnets"}, "LaunchConfigurationName": {"Ref": "LaunchConfig"}, "MinSize": "2", "MaxSize": "2", "TargetGroupARNs": [{"Ref": "ALBTargetGroup"}] }, "CreationPolicy": { "ResourceSignal": {"Timeout": "PT15M"} }, "UpdatePolicy": { "AutoScalingRollingUpdate": { "MinInstancesInService": "1", "MaxBatchSize": "1", "PauseTime": "PT15M", "WaitOnResourceSignals": true } } }, "LaunchConfig": { "Type": "AWS::AutoScaling::LaunchConfiguration", "Metadata": { "Comment": "Install a simple application", "AWS::CloudFormation::Init": { "config": { "packages": {"yum": {"httpd": []}}, "files": { "/var/www/html/index.html": { "content": {"Fn::Join": ["\n", ["<h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>"]]}, "mode": "000644", "owner": "root", "group": "root" }, "/etc/cfn/cfn-hup.conf": { "content": {"Fn::Join": ["", [ "[main]\n", "stack=", {"Ref": "AWS::StackId"}, "\n", "region=", {"Ref": "AWS::Region"}, "\n" ]]}, "mode": "000400", "owner": "root", "group": "root" }, "/etc/cfn/hooks.d/cfn-auto-reloader.conf": { "content": {"Fn::Join": ["", [ "[cfn-auto-reloader-hook]\n", "triggers=post.update\n", "path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init\n", "action=/opt/aws/bin/cfn-init -v ", " --stack ", {"Ref": "AWS::StackName"}, " --resource LaunchConfig ", " --region ", {"Ref": "AWS::Region"}, "\n", "runas=root\n" ]]}, "mode": "000400", "owner": "root", "group": "root" } }, "services": { "sysvinit": { "httpd": { "enabled": "true", "ensureRunning": "true" }, "cfn-hup": { "enabled": "true", "ensureRunning": "true", "files": [ "/etc/cfn/cfn-hup.conf", "/etc/cfn/hooks.d/cfn-auto-reloader.conf" ] } } } } } }, "Properties": { "ImageId": {"Fn::FindInMap": ["AWSAMIRegionMap", {"Ref": "AWS::Region"}, "AMZNLINUXHVM"]}, "SecurityGroups": [{"Ref": "InstanceSecurityGroup"}], "InstanceType": {"Ref": "InstanceType"}, "KeyName": {"Ref": "KeyName"}, "UserData": { "Fn::Base64": {"Fn::Join": ["", [ "#!/bin/bash -xe\n", "yum update -y aws-cfn-bootstrap\n", "/opt/aws/bin/cfn-init -v ", " --stack ", {"Ref": "AWS::StackName"}, " --resource LaunchConfig ", " --region ", {"Ref": "AWS::Region"}, "\n", "/opt/aws/bin/cfn-signal -e $? ", " --stack ", {"Ref": "AWS::StackName"}, " --resource WebServerGroup ", " --region ", {"Ref": "AWS::Region"}, "\n" ]]} } } }, "ELBSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Allow access to the ELB", "VpcId": {"Ref": "VpcId"}, "SecurityGroupIngress": [{ "Fn::If": [ "UseALBSSL", { "IpProtocol": "tcp", "FromPort": 443, "ToPort": 443, "CidrIp": "0.0.0.0/0" }, { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "CidrIp": "0.0.0.0/0" } ] }] } }, "ApplicationLoadBalancer": { "Type": "AWS::ElasticLoadBalancingV2::LoadBalancer", "Properties": { "Subnets": {"Ref": "Subnets"}, "SecurityGroups": [{"Ref": "ELBSecurityGroup"}] } }, "ALBListener": { "Type": "AWS::ElasticLoadBalancingV2::Listener", "Properties": { "DefaultActions": [{ "Type": "forward", "TargetGroupArn": {"Ref": "ALBTargetGroup"} }], "LoadBalancerArn": {"Ref": "ApplicationLoadBalancer"}, "Port": {"Fn::If": ["UseALBSSL", 443, 80]}, "Protocol": {"Fn::If": ["UseALBSSL", "HTTPS", "HTTP"]}, "Certificates": [{ "Fn::If": [ "UseALBSSL", {"CertificateArn": {"Ref": "ALBSSLCertificateARN"}}, {"Ref": "AWS::NoValue"} ] }] } }, "ALBTargetGroup": { "Type": "AWS::ElasticLoadBalancingV2::TargetGroup", "Properties": { "HealthCheckIntervalSeconds": 30, "HealthCheckTimeoutSeconds": 5, "HealthyThresholdCount": 3, "Port": 80, "Protocol": "HTTP", "UnhealthyThresholdCount": 5, "VpcId": {"Ref": "VpcId"} } }, "InstanceSecurityGroup": { "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "Enable SSH access and HTTP access on the inbound port", "SecurityGroupIngress": [ { "IpProtocol": "tcp", "FromPort": 80, "ToPort": 80, "SourceSecurityGroupId": {"Fn::Select": [0, {"Fn::GetAtt": ["ApplicationLoadBalancer", "SecurityGroups"]}]} }, { "IpProtocol": "tcp", "FromPort": 22, "ToPort": 22, "CidrIp": {"Ref": "SSHLocation"} } ], "VpcId": {"Ref": "VpcId"} } }, "RecordSet": { "Type": "AWS::Route53::RecordSetGroup", "Condition": "UseALBSSL", "Properties": { "HostedZoneName": {"Fn::Join": ["", [{"Ref": "HostedZoneName"}, "."]]}, "RecordSets": [{ "Name": {"Fn::Join": ["", [ {"Fn::Select": ["0", {"Fn::Split": [".", {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}]}]}, ".", {"Ref": "HostedZoneName"}, "." ]]}, "Type": "A", "AliasTarget": { "DNSName": {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}, "EvaluateTargetHealth": true, "HostedZoneId": {"Fn::GetAtt": ["ApplicationLoadBalancer", "CanonicalHostedZoneID"]} } }] } } }, "Outputs": { "URL": { "Description": "URL of the website", "Value": {"Fn::Join": ["", [ {"Fn::If": [ "UseALBSSL", {"Fn::Join": ["", [ "https://", {"Fn::Join": ["", [ {"Fn::Select": ["0", {"Fn::Split": [".", {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]}]}]}, ".", {"Ref": "HostedZoneName"}, "." ]]} ]]}, {"Fn::Join": ["", [ "http://", {"Fn::GetAtt": ["ApplicationLoadBalancer", "DNSName"]} ]]} ]} ]]} } } }
YAML
AWSTemplateFormatVersion: 2010-09-09 Parameters: VpcId: Type: AWS::EC2::VPC::Id Description: VpcId of your existing Virtual Private Cloud (VPC) ConstraintDescription: must be the VPC Id of an existing Virtual Private Cloud. Subnets: Type: List<AWS::EC2::Subnet::Id> Description: The list of SubnetIds in your Virtual Private Cloud (VPC) ConstraintDescription: >- must be a list of at least two existing subnets associated with at least two different availability zones. They should be residing in the selected Virtual Private Cloud. InstanceType: Description: WebServer EC2 instance type Type: String Default: t2.micro AllowedValues: - t2.micro - t3.micro ConstraintDescription: must be a valid EC2 instance type. KeyName: Description: Name of an existing EC2 KeyPair to enable SSH access to the instances Type: AWS::EC2::KeyPair::KeyName ConstraintDescription: must be the name of an existing EC2 KeyPair. SSHLocation: Description: The IP address range that can be used to SSH to the EC2 instances Type: String MinLength: '9' MaxLength: '18' Default: 0.0.0.0/0 AllowedPattern: '(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})/(\d{1,2})' ConstraintDescription: must be a valid IP CIDR range of the form x.x.x.x/x. UseSSL: AllowedValues: - 'Yes' - 'No' ConstraintDescription: Select Yes to create a HTTPS Listener Default: 'No' Description: 'Select "Yes" to implement SSL, "No" to skip (default).' Type: String ALBSSLCertificateARN: Default: '' Description: >- [Optional] The ARN of the SSL certificate to be used for the Application Load Balancer Type: String HostedZoneName: AllowedPattern: >- ^$|(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$ Default: '' Description: '[Optional] The domain name of a valid Hosted Zone on AWS.' Type: String Conditions: UseALBSSL: !Equals - !Ref UseSSL - 'Yes' Rules: SubnetsInVPC: Assertions: - Assert: 'Fn::EachMemberEquals': - 'Fn::ValueOf': - Subnets - VpcId - Ref: VpcId AssertDescription: All subnets must be in the VPC ValidateHostedZone: RuleCondition: !Equals - !Ref UseSSL - 'Yes' Assertions: - Assert: !Not - !Equals - !Ref ALBSSLCertificateARN - '' AssertDescription: ACM Certificate value cannot be empty if SSL is required - Assert: !Not - !Equals - !Ref HostedZoneName - '' AssertDescription: Route53 Hosted Zone Name is mandatory when SSL is required Mappings: AWSAMIRegionMap: us-east-1: AMZNLINUXHVM: ami-0ff8a91507f77f867 us-west-1: AMZNLINUXHVM: ami-0bdb828fd58c52235 eu-west-1: AMZNLINUXHVM: ami-047bb4163c506cd98 ap-southeast-1: AMZNLINUXHVM: ami-08569b978cc4dfa10 Resources: WebServerGroup: Type: AWS::AutoScaling::AutoScalingGroup Properties: VPCZoneIdentifier: !Ref Subnets LaunchConfigurationName: !Ref LaunchConfig MinSize: '2' MaxSize: '2' TargetGroupARNs: - !Ref ALBTargetGroup CreationPolicy: ResourceSignal: Timeout: PT15M UpdatePolicy: AutoScalingRollingUpdate: MinInstancesInService: '1' MaxBatchSize: '1' PauseTime: PT15M WaitOnResourceSignals: 'true' LaunchConfig: Type: AWS::AutoScaling::LaunchConfiguration Metadata: Comment: Install a simple application 'AWS::CloudFormation::Init': config: packages: yum: httpd: [] files: /var/www/html/index.html: content: !Join - |+ - - >- <h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1> mode: '000644' owner: root group: root /etc/cfn/cfn-hup.conf: content: !Sub | [main] stack=${AWS::StackId} region=${AWS::Region} mode: '000400' owner: root group: root /etc/cfn/hooks.d/cfn-auto-reloader.conf: content: !Sub |- [cfn-auto-reloader-hook] triggers=post.update path=Resources.LaunchConfig.Metadata.AWS::CloudFormation::Init action=/opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --region ${AWS::Region} runas=root mode: '000400' owner: root group: root services: sysvinit: httpd: enabled: 'true' ensureRunning: 'true' cfn-hup: enabled: 'true' ensureRunning: 'true' files: - /etc/cfn/cfn-hup.conf - /etc/cfn/hooks.d/cfn-auto-reloader.conf Properties: ImageId: !FindInMap - AWSAMIRegionMap - !Ref 'AWS::Region' - AMZNLINUXHVM SecurityGroups: - !Ref InstanceSecurityGroup InstanceType: !Ref InstanceType KeyName: !Ref KeyName UserData: !Base64 Fn::Sub: |- #!/bin/bash -xe yum update -y aws-cfn-bootstrap /opt/aws/bin/cfn-init -v --stack ${AWS::StackName} --resource LaunchConfig --region ${AWS::Region} /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource WebServerGroup --region ${AWS::Region} ELBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow access to the ELB VpcId: !Ref VpcId SecurityGroupIngress: - !If - UseALBSSL - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 ApplicationLoadBalancer: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Subnets: !Ref Subnets SecurityGroups: - !Ref ELBSecurityGroup ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - Type: forward TargetGroupArn: !Ref ALBTargetGroup LoadBalancerArn: !Ref ApplicationLoadBalancer Port: !If - UseALBSSL - 443 - 80 Protocol: !If - UseALBSSL - HTTPS - HTTP Certificates: - !If - UseALBSSL - CertificateArn: !Ref ALBSSLCertificateARN - !Ref 'AWS::NoValue' ALBTargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: HealthCheckIntervalSeconds: 30 HealthCheckTimeoutSeconds: 5 HealthyThresholdCount: 3 Port: 80 Protocol: HTTP UnhealthyThresholdCount: 5 VpcId: !Ref VpcId InstanceSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Enable SSH access and HTTP access on the inbound port SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !Select - 0 - !GetAtt - ApplicationLoadBalancer - SecurityGroups - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHLocation VpcId: !Ref VpcId RecordSet: Type: AWS::Route53::RecordSetGroup Condition: UseALBSSL Properties: HostedZoneName: !Join - '' - - !Ref HostedZoneName - . RecordSets: - Name: !Join - '' - - !Select - '0' - !Split - . - !GetAtt - ApplicationLoadBalancer - DNSName - . - !Ref HostedZoneName - . Type: A AliasTarget: DNSName: !GetAtt - ApplicationLoadBalancer - DNSName EvaluateTargetHealth: true HostedZoneId: !GetAtt - ApplicationLoadBalancer - CanonicalHostedZoneID Outputs: URL: Description: URL of the website Value: !Join - '' - - !If - UseALBSSL - !Join - '' - - 'https://' - !Join - '' - - !Select - '0' - !Split - . - !GetAtt - ApplicationLoadBalancer - DNSName - . - !Ref HostedZoneName - . - !Join - '' - - 'http://' - !GetAtt - ApplicationLoadBalancer - DNSName