样书配置

表达式

样书最强大的功能之一是使用表达式。可以在各种方案中使用样书表达式来计算动态值。以下示例是将参数值与文字字符串连接的表达式。

示例

$parameters.appname + "-mon"

此表达式检索名为 appname 的参数,并将其与字符串连接 -mon

注意

在样书定义中定义参数和表达式时,StyleBook 支持使用保留关键字。保留的关键字是 - andfalseinnottrueor

支持以下类型的表达式:

算术表达式

  • 添加 (+)
  • Subtraction (-)
  • 乘法 (*)
  • 分隔 (/)
  • 模数 (%)

示例

  • 添加两个数字:$parameters.a + $parameters.b
  • 乘以两个数字:$parameters.a * 10
  • 在一个数字除以另一个数字后查找剩余数字:

15%10 5 中的结果

字符串表达

  • 连接两个字符串 (+)

示例

连接两个字符串:str(“app-“) + $parameters.appname

列出表达式

合并两个列表 (+)

示例

  • 连接两个列表:$parameters.external-servers + $parameters.internal-servers

  • 如果 $parameters.ports-1 是 [80, 81] 并且 $parameters.port-2 是 [81, 82],则 $parameters.ports-1 + $parameters.ports-2 显示为列表 [80、81、81、82]。

关系表达式

  • == :测试两个操作数是否相等,如果两个操作数相等则返回 true,否则返回 false。

  • !=:测试两个操作数是否不同,如果两个操作数不同,则返回 true,否则返回 false。

  • > :如果第一个操作数大于第二个操作数,则返回 true,否则返回 false。

  • >= :如果第一个操作数大于或等于第二个操作数,则返回 true,否则返回 false。

  • < :如果第一个操作数小于第二个操作数,则返回 true,否则返回 false。

  • <= :如果第一个操作数小于或等于第二个操作数,则返回 true,否则返回 false。

示例

  • 使用平等运算符: $parameters.name = = "abcd"
  • 不等式运算符的使用: $parameters.name != "default"
  • 其他关系运算符示例

    • 10 > 9
    • 10 >= 10
    • 0 < 9
    • 10 <= 9
    • 10 == 10
    • 10 != 1

逻辑表达式-布尔值

  • :逻辑的 ‘和’ 运算符。如果两个操作数为 true,则结果为 true,否则为 false。

  • 或者:逻辑的 ‘或’ 运算符。如果其中一个操作数为 true,则结果为 true,否则为 false。

  • :一元运算符。如果操作数为 true,则结果为 false,而相反。

  • : 测试第一个参数是否为第二个参数的子字符串

  • :测试项目是否为列表的一部分

注意

您可以键入转换表达式,其中字符串被转换为数字(使用 int() 内置函数),并将数字转换为字符串(使用 str() 内置函数)。同样,您可以转换 tcp-port 为数字(使用 int() 内置函数),并可以将 IP 地址转换为字符串(使用 str () 内置函数)。

在任何运算符之前和之后使用分隔符。可以使用以下分隔符:

  • 在运算符之前:spacetabcomma()[]

  • 在运算符之后:spacetab([

例如:

  • abc + def

  • 100 % 10

  • 10 > 9

  • $item in $parameters.some-list

Splat 表达式

splat 表达式 [*] 提供了一种更简单的方法来从所有迭代的复杂列表中检索某个属性。现在,您可以在样书定义中包含 splat 表达式。

语法:

list[*].attribute
<!--NeedCopy-->

此表达式遍历其左侧指定的列表的所有项目,并返回其右侧指定的属性值。

当您要从列表中检索每个虚拟服务器的 IP 地址或主机名时,可以使用以下 splat 表达式:

示例 1

$parameters.server-members[*].hostname
<!--NeedCopy-->

此表达式返回所有服务器成员的主机名列表。

示例 2

$parameters.server-members[\*].sub-domains[\*].name
<!--NeedCopy-->

此表达式返回每个服务器成员的子域下所有名称的列表。

这些表达式总是返回最右边的元素类型的列表。

逐字字符串表达式

当字符串中的特殊字符必须采用文字形式时,可以使用逐字字符串。这些字符串可以包含转义字符、反斜杠、引号、括号、空格、括号等。在逐字字符串中,特殊角色的通常解释被跳过。字符串中的所有字符都以其文字形式保留。

在样书中,您可以使用逐字字符串将 Citrix ADC 策略表达式包含在其文本形式中。策略表达式通常包含特殊字符。如果没有逐字字符串,您必须通过将字符串分成子字符串来转义特殊字符。

要创建逐字字符串,请将字符串封装在特殊字符之间,如下所示:

~{string}~
<!--NeedCopy-->

您可以在样书表达式中使用逐字字符串。

注意请

勿在输入字符串中使用字符 }~ 的序列,因为此序列表示逐字字符串的结尾。

示例:

 ~{HTTP.REQ.COOKIE.VALUE("jsessionid") ALT HTTP.REQ.URL.BEFORE_STR("=").AFTER_STR(";jsessionid=") ALT HTTP.REQ.URL.AFTER_STR(";jsessionid=")}~
<!--NeedCopy-->

连接多个逐字字符串

您可以将逐字字符串与常规字符串或带插值的字符串连接起来。当您这样做时,样书只会跳过逐字字符串的解释。在字符串之间使用加号 (+) 运算符进行连接。

示例:

value: "~{"id": "}~ + %{$atom.key}% + ~{", "value": "}~ + %{$atom.value}% + ~{"}~"
<!--NeedCopy-->

在此例子中,将解释 %{$atom.key}%%{$atom.value}%。而且,剩下的解释被跳过。

目标表达式

在样书定义中,您可以使用 $current-target 表达式引用当前目标 ADC 实例。要特别引用目标 ADC 实例的 IP 地址,请按如下方式使用此表达式:

$current-target.ip
<!--NeedCopy-->

示例:

components:
 -
  name: lb-comp
  type: ns::lbvserver
  properties:
    name: $current-target.ip + "-lbvserver"
<!--NeedCopy-->

在此示例中,lbvserver 的名称使用目标 ADC 实例的 IP 地址。

表达式类型验证

StyleBook 引擎现在允许在编译时进行更强的类型检查,也就是说,编写样书时使用的表达式是在导入样书本身的过程中验证的,而不是在创建配置包时进行验证。

对参数、替换、组件、组件属性、组件输出、用户定义变量(repeat-item、repeat-index、替代函数的参数)等的所有引用都经过验证,以确定它们的存在和类型。

类型检查示例

在以下示例中, lbvserver StyleBook 的端口属性的预期类型为 tcp-port。在 Citrix ADM 中,类型验证在编译时(导入时)进行。编译器发现该字符串并且 tcp-port 不兼容类型,因此,样书编译器显示错误,导入或迁移样书失败。


components:
  -
    name: lbvserver-comp
    type: ns::lbvserver
    properties:
      name: mylb
      ipv46: 10.102.190.15
      port: str("80")
      servicetype: HTTP
<!--NeedCopy-->

要成功编译此样书,请在编译器中将以下内容声明为数字:

port: 80

标记无效表达式的示例:

将样书导入 Citrix ADM 时,编译器会识别出无效的表达式并对其进行标记。因此,样书无法导入到 Citrix ADM。

在以下示例中,分配给 lb-sg-binding-comp 组件中 name 属性的表达式为: $components.lbvserver-comp.properties.lbvservername。但是,组件 lbvserver-comp 中没有调用 lbvservername 的属性。

Components:
  -
    name: lbvserver-comp
    type: ns::lbvserver
    properties:
      name: mylb
      ipv46: 10.102.190.15
      port: 80
      servicetype: HTTP
  -
    name: sg-comp
    type: ns::servicegroup
    properties:
      servicegroupname: mysg
      servicetype: HTTP
  -
    name: lb-sg-binding-comp
    type: ns::lbvserver_servicegroup_binding
    condition: $parameters.create-binding
    properties:
      name: $components.lbvserver-comp.properties.lbvservername
      servicegroupname: $components.sg-comp.properties.servicegroupname
<!--NeedCopy-->

数据类型的隐式类型转换

当您将样书表达式用于不同的数据类型时,样书引擎现在会隐式地将输出类型转换为适当的数据类型。数据类型的隐式类型转换支持二进制运算和值分配。

二进制运算示例

  • 添加 (+) 两个类型为 stringnumber 的变量,将输出数据类型设置为 string

$parameters.appname + '_' + $parameters.app_instance_num

  • 添加 (+) 两个类型为 stringipaddress 的变量,将输出数据类型设置为 string

$parameters.appname + '_' + $parameters.instance_ip

  • 添加 (+) 两个类型为 ipaddressnumber 的变量,将输出数据类型设置为 ipaddress

$parameters.instance_ip + $parameters.number

  • 减去 (-) 两个类型为 ipaddressnumber 的变量,将输出数据类型设置为 ipaddress

$parameters.instance_ip - $parameters.number

  • 将 (*) 两个类型为 stringnumber 的变量相乘,将输出数据类型设置为 string

$parameters.dummy_str * $parameters.count

值赋值示例

  • 如果将变量定义为 string 数据类型,则分配的值将转换为定义的数据类型。

name: $parameters.port * 3

  • 如果将变量定义为 portnumber 数据类型,则分配的值会转换为 portnumber 数据类型,但有例外。

port: $index + $parameters.lower_limit

为列表建立索引

现在,可以直接为列表中的项目建立索引来访问它们:

   
表达式 说明
$components.test-lbs[0] thetest-lbs 组件中的第一个项目
$components.test-lbs[0].properties.p1 是指测试 lbs 组件中第一个项目的属性 p1
$components.lbcomps[0].outputs.servicegroups[1].properties.servicegroupname servicegroups 组件中第二个项目的属性 servicegroupname,该属性是 lbcomps 组件第一项的输出
表达式