
# 创建私有provider
#### 功能介绍
创建私有provider（CreatePrivateProvider）
创建一个私有的空provider。如果用户给予了provider_version和function_graph_urn，则在创建私有provider的同时，还会在私有provider下创建一个私有provider版本。
- 私有provider允许用户将自定义的provider注册到RFS中，并仅提供给当前用户使用。
  
- 如果同名私有provider在当前账户中已经存在，则会返回409。
  
- 版本号遵循语义化版本（Semantic Versioning）规范，支持用户自定义。其各层级（Major.Minor.Patch）均采用无符号 64 位整型（uint64）。
  
- 在本API中，provider_version和function_graph_urn需要搭配使用，如果只指定其中一个参数，则会返回400。
  
- 资源编排服务只会对function_graph_urn进行浅校验，如是否符合正则，是否仅指定为当前region等。并不会深度校验，即用户是否存在权限调用，是否真实存在等。
  
- 该API会返回provider_source字段，该字段按照"huawei.com/private-provider/{provider_name}"的形式拼接。关于provider_name和provider_source字段在模板中的使用细节，详见下方描述中。
  
- 如果用户期望使用名称中不含有大写英文的provider，可以按照如下展示将provider_source字段指定为模板中定义的required_providers中的source参数。
  
- 如果用户期望使用名称含有大写英文的provider，需要将provider_name完全转化为小写英文创建。同时用户既可以在模板中使用API返回的provider_source参数，也可以在模板中以 "huawei.com/private-provider"为固定前缀，按照原含大写英文的provider_name，拼写provider_source参数。
  
- 用户在使用该私有provider时，如果期望RFS使用委托调用FG以及OBS，可在创建私有provider时提供委托信息，该委托对私有provider下所有版本生效。provider_agency_name或provider_agency_urn二者最多只能提供一个，推荐用户在使用信任委托时给予provider_agency_urn，provider_agency_name只支持接收普通委托名称，如果给予了信任委托名称，则会在使用私有provider部署资源栈时失败。
  
以HCL格式的模板为例，模板中引用私有provider的语法如下：
```
Provider "{provider_name}" {
  source = "{provider_source}"
  version = "{provider_version}"
}
```
以JSON格式的模板为例，模板中引用私有provider的语法如下：
```
{
  "terraform":{
    "required_providers":[
      {
        "{provider_name}":{
          "source":"{provider_source}",
          "version":"{provider_version}"
        }
      }
    ]
  }
}
```
RFS在支持用户使用FunctionGraph(以下简称：FG)的事件函数运行私有Provider时，定义了一套详细的对接规则，以实现RFS与私有Provider之间的成功交互。
其中关于FG的事件函数使用，请参考官网文档： [创建事件函数](https://support.huaweicloud.com/usermanual-functiongraph/functiongraph_01_1441.html)。
用户需要在提供的FG的事件函数方法中，按照如下规则实现一系列对应方法：
1. 用户需要首先在FG中启动一个HTTP Server，用于接受来自RFS的HTTP请求，请求的Path固定为"/provider"，请求方法为"POST"。RFS规定了发送给FG的HTTP请求体，请求体格式如下所示：
   ```
   {
     "method_name": String,
     "request_data": String,
     "context":{
       "session_id": String,
       "config_data": String
     }
   }
   ```
   用户提供的FG的事件函数需要能够接收如上请求。否则会调用私有Provider失败，导致资源编排失败。
   
2. 下面对FG中如何使用请求体中的各个参数，以实现FG与RFS的成功交互做详细解释：
   ```
   tfplugin5.proto：
     "/tfplugin5.Provider/GetSchema"
     "/tfplugin5.Provider/PrepareProviderConfig"
     "/tfplugin5.Provider/ValidateResourceTypeConfig"
     "/tfplugin5.Provider/ValidateDataSourceConfig"
     "/tfplugin5.Provider/UpgradeResourceState"
     "/tfplugin5.Provider/Configure"
     "/tfplugin5.Provider/ReadResource"
     "/tfplugin5.Provider/PlanResourceChange"
     "/tfplugin5.Provider/ApplyResourceChange"
     "/tfplugin5.Provider/ImportResourceState"
     "/tfplugin5.Provider/ReadDataSource"
     "/tfplugin5.Provider/Stop"
   grpc_controller.proto：
     "/plugin.GRPCController/Shutdown"
   ```
   "request_data"：RFS传递给FG的事件函数中每个方法的请求内容。在每个方法的处理逻辑中，需要先将request_data中的数据使用base64解码，然后作为私有provider的gRPC方法的数据传入。
   
3. 在FG的事件函数中实现的请求响应按照固定格式进行返回，响应体的格式如下，成功响应码固定为200，任何其他响应码均视为失败请求，会导致资源编排失败。
   ```
   {
     "response_data": String,
     "error": String
   }
   ```
   "response_data"：调用私有provider的gRPC方法返回的内容。在FG的事件函数中，需要将gRPC方法返回的响应序列化后使用base64编码返回。
   
4. 用户需要对FG事件函数进行异步配置，针对于不涉及资源操作的读相关的gRPC请求，RFS默认通过同步接口调用FG；针对于涉及资源操作的写相关的gRPC请求，RFS默认通过异步接口调用FG。
   ```
   tfplugin5.proto：
     "/tfplugin5.Provider/GetSchema"
     "/tfplugin5.Provider/PrepareProviderConfig"
     "/tfplugin5.Provider/ValidateResourceTypeConfig"
     "/tfplugin5.Provider/ValidateDataSourceConfig"
     "/tfplugin5.Provider/UpgradeResourceState"
     "/tfplugin5.Provider/Configure"
     "/tfplugin5.Provider/ReadResource"
     "/tfplugin5.Provider/ImportResourceState"
     "/tfplugin5.Provider/ReadDataSource"
   ```
   以下gRPC请求默认异步调用：
   ```
   tfplugin5.proto：
     "/tfplugin5.Provider/PlanResourceChange"
     "/tfplugin5.Provider/ApplyResourceChange"
     "/tfplugin5.Provider/Stop"
   grpc_controller.proto：
     "/plugin.GRPCController/Shutdown"
   ```
   目前FG异步配置的成功和失败时通知的目标服务只支持OBS，用户如果开启异步调用状态持久化，RFS会通过轮询FG获取函数异步调用请求列表来获取异步调用的状态，否则会轮询OBS是否存在异步调用结果来判断异步调用状态。
   
"method_name"：RFS期望FG的事件函数中调用的私有provider的gRPC方法名。RFS会在请求体中，根据实际业务场景，每次从如下方法中选择一个进行传递。其中每个方法名需要与provider中原生的gRPC方法一一对应。在收到携带有某个方法名的请求后，FG的事件函数内能够调用对应的私有provider的原生gRPC方法，实现具体资源的处理逻辑。
provider内提供的原生gRPC协议请参考：tfplugin5.proto和grpc_controller.proto。方法名列表如下：
"config_data"：用于自定义provider处理实际请求前的初始化，如果context中config_data非空，FG的事件函数需要先将config_data作为输入调用/tfplugin5.Provider/Configure方法，进行初始化，再根据method_name调用对应的方法获取响应。
"session_id"：表示请求是否来自同一个模板中的同一批编排任务。session_id相同，表示请求来自同一个模板中的同一批编排任务。
注意：用户启动的同一个provider进程不能接受多个来自RFS的请求。RFS推荐用户处理请求时，每次都启动新的进程处理相关请求。
"error"：调用gRPC方法返回的错误信息。
以下gRPC请求默认同步调用：
对于同步调用，RFS阻塞等待FG返回调用结果；对于异步调用，RFS在判断异步调用结束后，获取OBS桶中的异步调用结果。
**约束与限制：**
1. 私有provider为用户自行定义，提供给RFS的provider插件，RFS不负责校验其内部逻辑是否正确。
   
2. RFS不负责维护私有provider的生命周期。用户使用私有provider部署的资源栈，由于私有provider缺失或问题，导致资源栈无法继续部署管理的，RFS不负责提供解决方案。
   
3. RFS不负责保障私有provider的信息安全。用户使用私有provider部署的资源栈，由于模板中存在敏感数据，进而导致敏感信息泄露给第三方相关资源的，RFS不承担其相关责任。
   
4. 当前调用私有provider过程中增加了网络因素，因此使用私有provider部署的失败概率会增加。如果出现因网络原因导致的部署失败，可以增加重试操作。
   
5. 当前RFS默认会同步调用在FG中定义的读相关gRPC请求，单次方法需要确保运行时间不超过30s，否则会极大增加失败概率。
   
6. 当前仅支持在模板中固定私有provider版本，不支持\>,\>=,\<,\<=,\~\>等定义宽松版本的表达式。
   
 
#### 调试
您可以在[API Explorer](https://console.huaweicloud.com/apiexplorer/#/openapi/AOS/doc?api=CreatePrivateProvider)中调试该接口，支持自动认证鉴权。API Explorer可以自动生成SDK代码示例，并提供SDK代码示例调试功能。
#### URI
POST /v1/private-providers
#### 请求参数
表1请求Header参数 
| 参数                | 是否必选 | 参数类型   | 描述                                                                                                                                                                                                                    |
|:---|:---|:---|:---|
| Client-Request-Id | 是    | String | 用户指定的，对于此请求的唯一Id，用于定位某个请求，推荐使用UUID 最小长度：**36** 最大长度：**128** |
   
表2请求Body参数 
| 参数                   | 是否必选 | 参数类型   | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
|:---|:---|:---|:---|
| provider_name        | 是    | String | 私有provider（private-provider）的名称。此名字在domain_id+region下应唯一，可以使用小写英文、数字、中划线。仅支持以小写英文、数字开头结尾。 按照HCL最佳实践，该名称推荐为在模板中定义的provider的本地名称（local_name）。 创建私有Provider（CreatePrivateProvider）API 还会以 "huawei.com/private-provider"为固定前缀，并以"huawei.com/private-provider/{provider_name}"的形式返回provider_source字段。关于provider_name和provider_source字段在模板中的使用细节，详见创建私有Provider的API描述。 最小长度：**1** 最大长度：**64** |
| provider_description | 否    | String | 私有provider（private-provider）的描述。可用于客户识别被管理的私有provider。 最小长度：**0** 最大长度：**1024**                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| provider_version     | 否    | String | provider的版本号。版本号遵循语义化版本（Semantic Versioning）规范，支持用户自定义。其各层级（Major.Minor.Patch）均采用无符号 64 位整型（uint64）。 最小长度：**5** 最大长度：**128**                                                                                                                                                                                                                                                                                                                                                                                                                      |
| version_description  | 否    | String | 私有provider版本（provider version）的描述。可用于客户识别并管理私有provider的版本。注意：provider版本为不可更新（immutable），所以该字段不可更新，如果需要更新，请删除后重建 最小长度：**0** 最大长度：**1024**                                                                                                                                                                                                                                                                                                                                                                                                          |
| function_graph_urn   | 否    | String | FunctionGraph方法的统一资源标识，用于唯一标识的FunctionGraph方法。当前只支持和RFS同region的function_graph_urn，如果给予了关于其他region的，会报错400。 关于该参数的详细解释，请参考官方文档：https://support.huaweicloud.com/api-functiongraph/functiongraph_06_0102.html 最小长度：**32** 最大长度：**256**                                                                                                                                                                                                                                  |
| provider_agency_urn  | 否    | String | 自定义provider所绑定的IAM委托URN，provider_agency_name和provider_agency_urn最多只能提供一个。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| provider_agency_name | 否    | String | 自定义provider所绑定的IAM委托名称，provider_agency_name和provider_agency_urn最多只能提供一个。 最小长度：**0** 最大长度：**64**                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
   
#### 响应参数
**状态码：201**
表3响应Body参数 
| 参数              | 参数类型   | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
|:---|:---|:---|
| provider_id     | String | 私有provider（private-provider）的唯一Id。 此Id由资源编排服务在生成provider的时候生成，为UUID。 由于私有provider名仅仅在同一时间下唯一，即用户允许先生成一个叫HelloWorld的私有provider，删除，再重新创建一个同名私有provider。 对于团队并行开发，用户可能希望确保，当前我操作的私有provider就是我以为的那个，而不是其他队友删除后创建的同名私有provider。因此，使用Id就可以做到强匹配。 资源编排服务保证每次创建的私有provider所对应的Id都不相同，更新不会影响Id。如果给予的provider_id和当前provider的Id不一致，则返回400 最小长度：**36** 最大长度：**36** |
| provider_source | String | 用户使用私有provider，在Terraform模板中定义required_providers信息时，需要指明的source参数。 该参数按照"huawei.com/private-provider/{provider_name}"的形式拼接。关于provider_name和provider_source字段在模板中的使用细节，详见创建私有Provider的API描述。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                              |
   
**状态码：400**
表4响应Body参数 
| 参数                            | 参数类型                                                                                                   | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                 | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                 | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                 | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表5Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
**状态码：401**
表6响应Body参数 
| 参数                            | 参数类型                                                                                                     | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                   | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                   | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                   | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表7Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
**状态码：403**
表8响应Body参数 
| 参数                            | 参数类型                                                                                                     | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                   | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                   | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                   | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表9Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
**状态码：409**
表10响应Body参数 
| 参数                            | 参数类型                                                                                                     | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                   | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                   | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                   | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表11Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
**状态码：429**
表12响应Body参数 
| 参数                            | 参数类型                                                                                                     | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                   | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                   | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                   | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表13Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
**状态码：500**
表14响应Body参数 
| 参数                            | 参数类型                                                                                                     | 描述                                                                                                                                                                                    |
|:---|:---|:---|
| error_code                    | String                                                                                                   | 响应码 最小长度：**11** 最大长度：**11** |
| error_msg                     | String                                                                                                   | 响应消息                                                                                                                                                                                  |
| encoded_authorization_message | String                                                                                                   | 包含有关未经授权请求的信息。                                                                                                                                                                        |
| details                       | Array of [Detail] objects | 权限拒绝时服务返回的详细错误信息。                                                                                                                                                                     |
   
 表15Detail 
| 参数         | 参数类型   | 描述   |
|:---|:---|:---|
| error_code | String | 响应码  |
| error_msg  | String | 响应消息 |
   
#### 请求示例
- 创建一个空的私有provider
  ```
  POST https://{endpoint}/v1/private-providers
  {
    "provider_name" : "my-hello-world-provider-name",
    "provider_description" : "my first private provider"
  }
  ```
  
- 创建一个带有版本的的私有provider
  ```
  POST https://{endpoint}/v1/private-providers
  {
    "provider_name" : "my-hello-world-provider-name",
    "provider_description" : "my first hello world private provider",
    "provider_version" : "0.0.1",
    "function_graph_urn" : "urn:fss:cn-north-7:a61dfe3154de42829367056598d5040f:function:default:test:latest",
    "version_description" : "my first private provider version"
  }
  ```
  
 
#### 响应示例
**状态码：201**
创建成功
```
{
  "provider_id" : "1b15e005-bdbb-4bd7-8f9a-a09b6774b4b3",
  "provider_source" : "huawei.com/private-provider/my-hello-world-provider-name"
}
```
#### 状态码
| 状态码 | 描述                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               |
|:---|:---|
| 201 | 创建成功                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| 400 | 用户请求非法                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 401 | 用户身份认证失败                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| 403 | 1. 用户无权限调用此API   2. 私有provider数量达到上限    |
| 409 | 创建冲突，同名的私有provider已经存在                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 429 | 请求数量过多                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
| 500 | 服务器内部错误                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          |
   
