# 声明式管理 API7 企业版

API7 声明式 CLI (ADC) 提供了声明式地配置 API7 企业版的工具，而无需使用 Admin API 或控制台。

ADC 使用 YAML 文件（`adc.yaml`）作为配置 API7 企业版的唯一事实来源。

DevOps 团队可以非常轻松地将其与现有的版本控制系统和 CI/CD 流水线集成。

本文档将指导你设置 ADC 并使用它来管理 API7 企业版。你将学习如何：

1. 配置 ADC 并将其连接到 API7 企业版实例
2. 将配置同步到连接的实例
3. 修改配置、查看修改并同步修改

备注

1. `adc convert` 支持将 OpenAPI 3.0 定义文件转换为 ADC 配置文件（`adc.yaml`）。但是，这种转换可能不完整，你可能需要修改转换后的配置文件以包含授权策略、绑定到服务 ID 等。API7.ai 计划在未来对此进行改进。
2. 无论你的版本控制系统或防火墙策略如何，只要 ADC 能够访问 Admin API，它就可以工作。本文档中的示例在本地计算机上安装了 ADC。

## 先决条件[​](#先决条件 "先决条件的直接链接")

1. [安装 API7 企业版](https://docs.apiseven.com/api7-gateway/3.9.x/getting-started/install-api7-ee.md)。

## 安装 ADC[​](#安装-adc "安装 ADC的直接链接")

ADC 二进制文件适用于 macOS、Linux 和 Windows。通过运行以下命令下载并安装适当的二进制文件：

```
export ADC_VERSION="0.8.0"
export ADC_OS="darwin" # 或 linux, windows
export ADC_ARC="arm64" # 或 amd64

wget "https://run.api7.ai/adc/release/adc_${ADC_VERSION}_${ADC_OS}_${ADC_ARC}.tar.gz"
tar -zxvf "adc_${ADC_VERSION}_${ADC_OS}_${ADC_ARC}.tar.gz"
mv adc /usr/local/bin/adc
```

要确保 ADC 已正确安装，请运行：

```
adc help
```

你将收到如下响应：

```
Usage: adc [options] [command]

Options:
  -V, --version   output the version number
  -h, --help      display help for command

Commands:
  ping [options]  Verify connectivity with the backend
  dump [options]  Dump configurations from the backend
  diff [options]  Show the difference between local and backend configurations
  sync [options]  Sync local configurations to the backend
  convert         Convert other API specs to ADC configurations
  lint [options]  Check provided configuration files, local execution only, ensuring inputs meet ADC requirements
  help [command]  display help for command
```

## 生成 API 令牌[​](#生成-api-令牌 "生成 API 令牌的直接链接")

在开始使用 ADC 之前，你首先需要一个 API 令牌（token）来访问 Admin API。你可以：

1. 从控制台生成令牌：登录 -> 个人资料 (Profile) -> 令牌 (Token) -> 生成新令牌 (Generate New Token)
2. [通过 Admin API](https://docs.api7.ai/api7-gateway/reference/admin-api#tag/Tokens) 生成令牌

## 配置 ADC[​](#配置-adc "配置 ADC的直接链接")

可以通过标志（命令式）或环境变量（声明式）来配置 ADC。

此示例配置控制面地址和令牌，以便 ADC 可以连接到 API7 企业版实例。

创建一个包含以下内容的 `.env` 文件：

```
ADC_BACKEND=api7ee

# 替换为你控制面地址
ADC_SERVER=https://152.42.234.39:7443

# 替换为你 ADC 令牌
ADC_TOKEN=a7ee-6baF8488i8wJ5aj7mEo3BT705573eC8GH905qGrdn889zUWcR37df66a34e9954b61918c5dfd13abce3e
```

ADC 还支持 `ADC_CA_CERT_FILE`、`ADC_TLS_CLIENT_CERT_FILE`、`ADC_TLS_CLIENT_KEY_FILE` 和 `ADC_TLS_SKIP_VERIFY` 环境变量，用于 TLS 配置。

要验证此配置，请运行：

```
adc ping
```

你应该收到如下响应：

```
Connected to the backend successfully!
```

提示

运行 `adc ping -h` 以获取可用标志的列表。你可以如上所示通过环境变量或通过等效标志来配置 ADC。

## 同步配置[​](#同步配置 "同步配置的直接链接")

API7 企业版配置在 YAML 文件（`adc.yaml`）中定义，并由 ADC 进行同步。

以下示例定义了三个服务：

adc.yaml

```
services:
  - name: SOAP Service
    description: "This Service is for SOAP requests"
    upstream:
      name: default
      scheme: https
      type: roundrobin
      hash_on: vars
      nodes:
        - host: apps.learnwebservices.com
          port: 443
          weight: 1
          priority: 0
      retry_timeout: 0
      pass_host: pass
    routes:
      - uris:
          - /services/hello
        name: SOAP proxy
        methods:
          - POST
      - uris:
          - /SayHello
        name: REST to SOAP
        methods:
          - POST
        plugins:
          soap:
            wsdl_url: https://apps.learnwebservices.com/services/hello?wsdl
  - name: httpbin Service
    description: "This is the httpbin Service proxy service"
    labels:
      app: httpbin
      custom_key: custom_value
    routes:
      - name: Generate UUID
        methods:
          - GET
        uris:
          - /uuid
      - name: Anything
        methods:
          - GET
        uris:
          - /anything
        plugins:
          key-auth:
            _meta:
              disable: false
      - name: Rate Limited IP
        methods:
          - GET
        uris:
          - /ip
        plugins:
          limit-count:
            _meta:
              disable: false
            count: 2
            time_window: 10
            rejected_code: 429
            policy: local
    upstream:
      name: default
      scheme: http
      type: roundrobin
      hash_on: vars
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1
          priority: 0
      retry_timeout: 0
      pass_host: pass
  - name: SSE Service
    labels:
      service: sse
    upstream:
      scheme: https
      nodes:
        - host: www.esegece.com
          port: 2053
          weight: 1
          priority: 0
      type: roundrobin
      pass_host: node
    plugins:
      proxy-buffering:
        disable_proxy_buffering: true
    routes:
      - name: SSE API
        uris:
          - /sse
        methods:
          - GET
  consumers:
  - username: tom
    plugins:
      key-auth:
        key: tomskey
  ssls: []
  global_rules: {}
```

要将此配置同步到连接的实例，请运行：

```
adc sync -f adc.yaml
```

同步成功将产生以下响应：

```
✔ Load local configuration
✔ Load remote configuration
✔ Diff configuration
✔ Sync configuration
```

通过向路由发送请求来测试已创建的 "httpbin Service"：

```
curl "152.42.234.39:9080/uuid" -v
```

```
*   Trying 152.42.234.39:9080...
* Connected to 152.42.234.39 (152.42.234.39) port 9080
> GET /uuid HTTP/1.1
> Host: 152.42.234.39:9080
> User-Agent: curl/8.4.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 53
< Connection: keep-alive
< Date: Wed, 17 Apr 2024 09:56:22 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Server: API7/3.2.8
<

{
  "uuid": "22b888f4-9e96-4d09-93a2-408b14e772fe"
}

* Connection #0 to host 152.42.234.39 left intact
```

`/anything` 路由启用了 `key-auth` 插件。在没有密钥的情况下向路由发送请求：

```
curl "152.42.234.39:9080/anything"
```

你将无法完成请求并收到以下消息：

```
{ "message": "Missing API key found in request" }
```

现在，将密钥添加到请求头：

```
curl "152.42.234.39:9080/anything" -H "apikey: tomskey"
```

现在请求已正确验证，你将收到所需的响应：

```
{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Apikey": "tomskey",
    "Host": "152.42.234.39",
    "User-Agent": "curl/8.4.0",
    "X-Amzn-Trace-Id": "Root=1-661f9d57-42c4a66b07b361713713da44",
    "X-Forwarded-Host": "152.42.234.39"
  },
  "json": null,
  "method": "GET",
  "origin": "182.255.32.50, 152.42.234.39",
  "url": "http://152.42.234.39/anything"
}
```

## 修改配置[​](#修改配置 "修改配置的直接链接")

要修改配置，只需更新 `adc.yaml` 文件。由于它是唯一的事实来源，你所做的任何修改都将被同步并应用到连接的实例。

以下示例向 "httpbin Service" 添加了一个新的 `/headers` 路由：

```
services:
  - name: SOAP Service
    description: ""
    upstream:
      name: default
      scheme: https
      type: roundrobin
      hash_on: vars
      nodes:
        - host: apps.learnwebservices.com
          port: 443
          weight: 1
          priority: 0
      retry_timeout: 0
      pass_host: pass
    routes:
      - uris:
          - /services/hello
        name: SOAP proxy
        methods:
          - POST
      - uris:
          - /SayHello
        name: REST to SOAP
        methods:
          - POST
        plugins:
          soap:
            wsdl_url: https://apps.learnwebservices.com/services/hello?wsdl
  - name: httpbin Service
    description: ""
    labels:
      app: httpbin
      custom_key: custom_value
    routes:
      - name: Get Headers
        methods:
          - GET
        uris:
          - /headers
      - name: Generate UUID
        methods:
          - GET
        uris:
          - /uuid
      - name: Anything
        methods:
          - GET
        uris:
          - /anything
        plugins:
          key-auth:
            _meta:
              disable: false
      - name: Rate Limited IP
        methods:
          - GET
        uris:
          - /ip
        plugins:
          limit-count:
            _meta:
              disable: false
            count: 2
            time_window: 10
            rejected_code: 429
            policy: local
    upstream:
      name: default
      scheme: http
      type: roundrobin
      hash_on: vars
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1
          priority: 0
      retry_timeout: 0
      pass_host: pass
  - name: SSE Service
    labels:
      service: sse
    upstream:
      scheme: https
      nodes:
        - host: www.esegece.com
          port: 2053
          weight: 1
          priority: 0
      type: roundrobin
      pass_host: node
    plugins:
      proxy-buffering:
        disable_proxy_buffering: true
    routes:
      - name: SSE API
        uris:
          - /sse
        methods:
          - GET
  consumers:
  - username: tom
    plugins:
      key-auth:
        key: tomskey
  ssls: []
  global_rules: {}
```

在同步此修改后的配置之前，你可以使用 `diff` 子命令检查将要进行的修改：

```
adc diff -f ./adc.yaml
```

输出将指出使用此修改后配置所做的确切更改：

```
✔ Load local configuration
✔ Load remote configuration
✔ Diff configuration
  › update consumer: "tom"
    update route: "REST to SOAP"
    update route: "SOAP proxy"
    update route: "Rate Limited IP"
    update route: "Anything"
    update route: "Generate UUID"
    create route: "Get Headers"
    update service: "SSE Service"
    update route: "SSE API"
    Summary: 1 will be created, 8 will be updated, 0 will be deleted
✔ Write detailed diff results to file
```

如输出所述，`diff` 子命令还会生成一个 `diff.yaml` 文件，详细显示了更改内容：

diff.yaml

```
- resourceType: consumer
  type: update
  resourceId: tom
  resourceName: tom
  oldValue:
    username: tom
    description: ""
    plugins:
      key-auth:
        key: tomskey
  newValue:
    username: tom
    plugins:
      key-auth:
        key: tomskey
  diff:
    added: {}
    deleted: {}
    updated: {}
- resourceType: route
  type: update
  resourceId: bef0a3351a392e74c960f9a58c1d025d803f2aef
  resourceName: REST to SOAP
  oldValue:
    uris:
      - /SayHello
    name: REST to SOAP
    methods:
      - POST
    enable_websocket: false
    plugins:
      soap:
        wsdl_url: https://apps.learnwebservices.com/services/hello?wsdl
  newValue:
    uris:
      - /SayHello
    name: REST to SOAP
    methods:
      - POST
    plugins:
      soap:
        wsdl_url: https://apps.learnwebservices.com/services/hello?wsdl
  diff:
    added: {}
    deleted: {}
    updated: {}
  parentId: 602dfcf4c39218f87d40c5d1df8b531b49ca88e8
- resourceType: route
  type: update
  resourceId: da37e65d428446d156279156ac3248c00d0a1533
  resourceName: SOAP proxy
  oldValue:
    uris:
      - /services/hello
    name: SOAP proxy
    methods:
      - POST
    enable_websocket: false
  newValue:
    uris:
      - /services/hello
    name: SOAP proxy
    methods:
      - POST
  diff:
    added: {}
    deleted: {}
    updated: {}
  parentId: 602dfcf4c39218f87d40c5d1df8b531b49ca88e8
- resourceType: route
  type: update
  resourceId: b586591b59c13461ed8932228cb23e53040c09d4
  resourceName: Rate Limited IP
  oldValue:
    uris:
      - /ip
    name: Rate Limited IP
    methods:
      - GET
    enable_websocket: false
    plugins:
      limit-count:
        _meta:
          disable: false
        count: 2
        policy: local
        rejected_code: 429
        time_window: 10
  newValue:
    name: Rate Limited IP
    methods:
      - GET
    uris:
      - /ip
    plugins:
      limit-count:
        _meta:
          disable: false
        count: 2
        time_window: 10
        rejected_code: 429
        policy: local
  diff:
    added: {}
    deleted: {}
    updated: {}
  parentId: 5ce4033cfe1015450e0b81186f7d54b9327cc302
- resourceType: route
  type: update
  resourceId: 5f2de5df1a292b4c8a73f0ec23271233d75707c6
  resourceName: Anything
  oldValue:
    uris:
      - /anything
    name: Anything
    methods:
      - GET
    enable_websocket: false
    plugins:
      key-auth:
        _meta:
          disable: false
  newValue:
    name: Anything
    methods:
      - GET
    uris:
      - /anything
    plugins:
      key-auth:
        _meta:
          disable: false
  diff:
    added: {}
    deleted: {}
    updated: {}
  parentId: 5ce4033cfe1015450e0b81186f7d54b9327cc302
- resourceType: route
  type: update
  resourceId: ed048a2f75fe33eab67319810fbb94bb778d7d97
  resourceName: Generate UUID
  oldValue:
    uris:
      - /uuid
    name: Generate UUID
    methods:
      - GET
    enable_websocket: false
  newValue:
    name: Generate UUID
    methods:
      - GET
    uris:
      - /uuid
  diff:
    added: {}
    deleted: {}
    updated: {}
  parentId: 5ce4033cfe1015450e0b81186f7d54b9327cc302
- resourceType: route
  resourceId: 6b124aff482499cbf7bdad5a56b13205b24ba58e
  resourceName: Get Headers
  type: create
  newValue:
    name: Get Headers
    methods:
      - GET
    uris:
      - /headers
  parentId: 5ce4033cfe1015450e0b81186f7d54b9327cc302
- resourceType: service
  type: update
  resourceId: 54154d3cdf6379ab8686890d27fabb6bf8fa3ace
  resourceName: SSE Service
  oldValue:
    name: SSE Service
    description: ""
    labels:
      service: sse
    upstream:
      name: default
      scheme: https
      type: roundrobin
      hash_on: vars
      nodes:
        - host: www.esegece.com
          port: 2053
          weight: 1
          priority: 0
      retry_timeout: 0
      pass_host: node
    plugins:
      proxy-buffering:
        disable_proxy_buffering: true
  newValue:
    name: SSE Service
    labels:
      service: sse
    upstream:
      scheme: https
      nodes:
        - host: www.esegece.com
          port: 2053
          weight: 1
          priority: 0
      type: roundrobin
      pass_host: node
    plugins:
      proxy-buffering:
        disable_proxy_buffering: true
  diff:
    added: {}
    deleted:
      upstream: {}
    updated: {}
  subEvents:
    - &a1
      resourceType: route
      type: update
      resourceId: 6b808fa543c7c3391321b813d0dc2d658ab02c10
      resourceName: SSE API
      oldValue:
        uris:
          - /sse
        name: SSE API
        methods:
          - GET
        enable_websocket: false
      newValue:
        name: SSE API
        uris:
          - /sse
        methods:
          - GET
      diff:
        added: {}
        deleted: {}
        updated: {}
      parentId: 54154d3cdf6379ab8686890d27fabb6bf8fa3ace
- *a1
```

如果更改看起来没问题，请运行 `sync` 子命令以将修改后的配置同步到连接的实例：

```
adc sync -f ./adc.yaml
```

发送请求以测试这个新创建的路由：

```
curl "152.42.234.39:9080/headers"
```

你将收到类似以下的上游响应：

```
{
  "headers": {
    "Accept": "*/*",
    "Host": "152.42.234.39",
    "User-Agent": "curl/8.4.0",
    "X-Amzn-Trace-Id": "Root=1-661f9edd-188a0adf5d3bf0a509f5b034",
    "X-Forwarded-Host": "152.42.234.39"
  }
}
```

## 后续步骤[​](#后续步骤 "后续步骤的直接链接")

ADC 仍在开发中，并将不断改进。有关可用子命令的完整列表，请参见 ADC 参考文档。
