diff --git a/Dockerfile b/Dockerfile index b1a26700..f61d95be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.19.3-buster as builder +FROM golang:1.23.1 as builder ENV GOPROXY=https://goproxy.cn,direct ENV GO111MODULE off WORKDIR /go/src/github.com/AliyunContainerService/ack-secret-manager diff --git a/README-zh_CN.md b/README-zh_CN.md index e190b95e..2b36a19b 100644 --- a/README-zh_CN.md +++ b/README-zh_CN.md @@ -1,56 +1,41 @@ - - # ACK Secret Manager -[English](./README.md) | 简体中文 - -[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。 - +[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据或[阿里云OOS加密参数](https://www.alibabacloud.com/help/zh/oos/getting-started/manage-encryption-parameters?spm=a2c63.p38356.0.0.15393f494RyWrR),以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家或加密参数中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。 ## 安装 -1. 请确保组件使用的凭据有足够的权限访问阿里云凭据管家服务,可以使用如下两种配置方式,推荐使用RRSA方式,实现Pod维度的授权。 - - - 在集群对应的 WorkerRole 中添加权限 - - - 登录容器服务控制台 - - - 选择对应集群进入到集群详情页 - - - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面 - - - 点击添加权限按钮,创建自定义权限策略,策略内容如下: - - ```json - { - "Action": [ - "kms:GetSecretValue", - "kms:Decrypt" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ``` - - - 绑定上面创建的自定义策略给集群对应的WorkerRole - - - . 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权 - - * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h) - - * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权 - +1. 请确保组件使用的凭据有足够的权限访问需要同步的阿里云服务,可以使用如下两种配置方式,推荐使用RRSA方式,实现Pod维度的授权 + - 在集群对应的 WorkerRole 中添加权限 + - 登录容器服务控制台 + - 选择对应集群进入到集群详情页 + - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面 + - 点击添加权限按钮,创建自定义权限策略,策略内容如下(仅需授权需要同步的服务权限即可,保证最小权限原则): + ```json + { + "Action": [ + // 阿里云KMS凭据管家所需权限 + "kms:GetSecretValue", + "kms:Decrypt", + + // 阿里云OOS加密参数所需权限 + "oos:GetSecretParameter", + "kms:GetSecretValue" + ], + "Resource": [ + "*" + ], + "Effect": "Allow" + } + ``` + - 绑定上面创建的自定义策略给集群对应的WorkerRole + - 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权 + * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h) + * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权 2. 登录到容器服务控制台 - - * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面; - - * 选择需要安装的目标集群和命名空间、发布名称; - - * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的`rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**; - - * 点击**确定**按钮完成安装。 + * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面; + * 选择需要安装的目标集群和命名空间、发布名称; + * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的 `rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**; + * 点击**确定**按钮完成安装。 ## 升级 @@ -66,250 +51,349 @@ ## 配置说明 -| **参数** | **说明** | **默认值** | -| --------------------------------------------------- | ------------------------------------------------------------ | ---------------------- | -| env.WATCH_NAMESPACE | 指定组件watch的namespace(默认空值代表watch所有命名空间) | | -| envVarsFromSecret.ACCESS_KEY_ID | 可以通过设置ACCESS_KEY_ID变量指定凭证AK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.SECRET_ACCESS_KEY | 可以通过设置SECRET_ACCESS_KEY变量指定凭证SK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_ROLE_ARN | 可以通过设置ALICLOUD_ROLE_ARN变量指定RAM角色ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | 可以通过设置ALICLOUD_ROLE_SESSION_NAME变量指定RAM角色session name用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| **参数** | **说明** | **默认值** | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| env.WATCH_NAMESPACE | 指定组件watch的namespace(默认空值代表watch所有命名空间) | | +| envVarsFromSecret.ACCESS_KEY_ID | 可以通过设置ACCESS_KEY_ID变量指定凭证AK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.SECRET_ACCESS_KEY | 可以通过设置SECRET_ACCESS_KEY变量指定凭证SK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_ROLE_ARN | 可以通过设置ALICLOUD_ROLE_ARN变量指定RAM角色ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | 可以通过设置ALICLOUD_ROLE_SESSION_NAME变量指定RAM角色session name用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | | envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | 可以通过设置ALICLOUD_ROLE_SESSION_EXPIRATION变量指定RAM角色session过期时长用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | 可以通过设置ALICLOUD_OIDC_PROVIDER_ARN变量指定RAM OIDC供应商的ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | 可以通过设置ALICLOUD_OIDC_TOKEN_FILE变量指定pod内oidc token文件路径用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | 可以通过设置 ALICLOUD_REMOTE_ROLE_ARN 变量指定另一个账号的 RAM Role Arn,用于在跨账号拉取凭据数据时进行角色扮演 | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | 可以通过设置 ALICLOUD_REMOTE_ROLE_SESSION_NAME 变量指定 RAM Role Session Name,于在跨账号拉取凭据数据时进行角色扮演 | | -| rrsa.enable | 是否启用RRSA特性,默认为false,启用后需要配置envVarsFromSecret中的ALICLOUD_ROLE_ARN和 ALICLOUD_OIDC_PROVIDER_ARN参数 | false | -| command.backend | 对接的外部密钥管理系统后端,当前仅支持阿里云凭据管家,配置为alicloud-kms | alicloud-kms | -| command.reconcilePeriod | 控制器重新协调externalSecret实例的间隔时间,默认5秒 | 5s | -| command.reconcileCount | 指定并发协调externalSecret实例的worker数量,默认是1 | 1 | -| command.tokenRotationPeriod | 检查KMS client访问STS token是否过期的轮询时间 | 120s | -| command.region | 从指定region拉取secret凭据 | | -| command.disablePolling | 关闭从KMS后端自动同步拉取最新的凭据内容,默认false | false | -| command.pollingInterval | 从KMS后端同步存量secret实例的间隔时间 | 120s | -| image.repository | 指定的ack-secret-manager 镜像仓库名称 | acs/ack-secret-manager | -| image.tag | 指定的ack-secret-manager 镜像tag | v0.5.0 | -| image.pullPolicy | 镜像拉取策略,默认为Always | Always | -| nameOverride | 覆盖应用名称 | nil | -| fullnameOverride | 覆盖应用全名 | nil | -| rbac.create | 是否创建并使用RBAC资源,默认为true | true | -| securityContext.fsGroup | 指定应用的security context配置 | {} | -| serviceAccount.create | 是否创建serviceaccount | true | -| serviceAccount.name | 指定创建serviceaccount的名称 | 自动生成 | -| serviceAccount.annotations | 指定添加serviceaccount annotation标签 | nil | -| podAnnotations | 指定添加到pod中的annotation标签 | {} | -| podLabels | 指定添加到pod中的Label标签 | {} | -| replicaCount | 控制器副本个数 | 1 | -| nodeSelector | 指定的nodeSelector标签 | {} | -| tolerations | 指定的污点容忍配置 | [] | -| affinity | 指定的Pod亲和性配置 | {} | -| resources | 指定的Pod requests和limits配置 | {} | +| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | 可以通过设置ALICLOUD_OIDC_PROVIDER_ARN变量指定RAM OIDC供应商的ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | 可以通过设置ALICLOUD_OIDC_TOKEN_FILE变量指定pod内oidc token文件路径用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | 可以通过设置 ALICLOUD_REMOTE_ROLE_ARN 变量指定另一个账号的 RAM Role Arn,用于在跨账号拉取凭据数据时进行角色扮演 | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | 可以通过设置 ALICLOUD_REMOTE_ROLE_SESSION_NAME 变量指定 RAM Role Session Name,于在跨账号拉取凭据数据时进行角色扮演 | | +| rrsa.enable | 是否启用RRSA特性,默认为false,启用后需要配置envVarsFromSecret中的ALICLOUD_ROLE_ARN和 ALICLOUD_OIDC_PROVIDER_ARN参数 | false | +| command.reconcilePeriod | 控制器重新协调externalSecret实例的间隔时间,默认5秒 | 5s | +| command.reconcileCount | 指定并发协调externalSecret实例的worker数量,默认是1 | 1 | +| command.tokenRotationPeriod | 检查 client访问STS token是否过期的轮询时间 | 120s | +| command.region | 从指定region拉取secret凭据 | | +| command.disablePolling | 关闭从后端自动同步拉取最新的凭据内容,默认false | false | +| command.pollingInterval | 从后端同步存量secret实例的间隔时间 | 120s | +| command.maxConcurrentSecretPulls | 已弃用 | - | +| command.maxConcurrentKmsSecretPulls | kms secret 每秒同步的最大并发数量 | 10 | +| command.maxConcurrentOosSecretPulls | oos secret 每秒同步的最大并发数量 | 10 | +| image.repository | 指定的ack-secret-manager 镜像仓库名称 | acs/ack-secret-manager | +| image.tag | 指定的ack-secret-manager 镜像tag | v0.5.0 | +| image.pullPolicy | 镜像拉取策略,默认为Always | Always | +| nameOverride | 覆盖应用名称 | nil | +| fullnameOverride | 覆盖应用全名 | nil | +| rbac.create | 是否创建并使用RBAC资源,默认为true | true | +| securityContext.fsGroup | 指定应用的security context配置 | {} | +| serviceAccount.create | 是否创建serviceaccount | true | +| serviceAccount.name | 指定创建serviceaccount的名称 | 自动生成 | +| serviceAccount.annotations | 指定添加serviceaccount annotation标签 | nil | +| podAnnotations | 指定添加到pod中的annotation标签 | {} | +| podLabels | 指定添加到pod中的Label标签 | {} | +| replicaCount | 控制器副本个数 | 1 | +| nodeSelector | 指定的nodeSelector标签 | {} | +| tolerations | 指定的污点容忍配置 | [] | +| affinity | 指定的Pod亲和性配置 | {} | +| resources | 指定的Pod requests和limits配置 | {} | + +## 使用说明 +下文会在阿里云 KMS 凭据管家中添加一个测试凭据进行凭据同步,并展示部分扩展功能。 +**Tip: 阿里云其它产品密文同步的方式与 KMS 凭据管家同步类似,仅需参考步骤 1 中对应产品添加密文的方式先添加密文,然后修改下文 SecretStore、ExternalSecret 示例中的关键字及其取值为下面表格中对应的值即可** -## 使用说明 +| 配置字段 & 产品 | 阿里云 KMS 凭据 | 阿里云 OOS 加密参数 | +| -------------------------------------- | ------------------------------ | ---------------------------------- | +| **SecretStore 认证方式关键字** | SecretStore.Spec.KMS.KMSAuth | SecretStore.Spec.OOS.OOSAuth | +| **ExternalSecret.spec.provider** | kms | oos | +| **ExternalSecret.spec.data.key** | (如下文的 test1) | (如下文的 test2) | -ack-secret-manager 包含两种 CRD,其中SecretStore 用于存放访问凭据(例如 RRSA ,ClientKey,AK 配置等),ExternalSecret 用于存放需要同步的凭据基础信息(如凭据名称,版本等)以及指定 SecretStore,保证了权限与数据分离,增强使用灵活性。具体介绍 [CRD参数配置指导](doc/crd.md) +ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据(例如 RRSA ,ClientKey,AK 配置等),ExternalSecret 用于存放需要同步的凭据基础信息(如凭据名称,版本等)以及指定 SecretStore,保证了权限与数据分离,增强使用灵活性。具体介绍见下方 **CRD 配置介绍** -1. 创建凭据 +1. 创建密文 + 当前支持同步 KMS 凭证和 OOS 加密参数,下面分别是两种密文的创建方式参考 - 在KMS凭据管家中添加如下凭证,详细流程请参考[管理通用凭据](https://www.alibabacloud.com/help/zh/doc-detail/152003.html) + - 在KMS凭据管家中添加如下凭证,详细流程请参考[管理通用凭据](https://www.alibabacloud.com/help/zh/doc-detail/152003.html) - ```txt - SecretName: test1 - SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} - VersionId: v1 - ``` + ```txt + SecretName: test1 + SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + VersionId: v1 + ``` + - 在OOS加密参数中添加如下加密参数,详细流程请参考[管理加密参数](https://www.alibabacloud.com/help/zh/oos/developer-reference/api-oos-2019-06-01-createsecretparameter) + ```txt + Name: test2 + Value: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + ``` 2. 创建SecretStore & ExternalSecret 前提:给集群开启 RRSA,并且正确配置相关 RAM Role 权限 - 创建 SecretStore 的测试实例,测试模板如下,需对部分字段进行替换 - + - 创建文件 `hello-service-secret-store.yml`如下并保存为测试模板, 其可以创建名称为 `scdemo` 的 SecretStore 的测试实例, 需对部分字段进行替换 ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: scdemo - spec: - KMS: - KMSAuth: - oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" - ramRoleARN: "acs:ram::{accountID}:role/{roleName}" + apiVersion: 'alibabacloud.com/v1alpha1' + kind: SecretStore + metadata: + name: scdemo + spec: + KMS: # 同步 kms 凭据时,指定为 KMS, 同步 oos 加密参数时,指定为 OOS + KMSAuth: # 同步 kms 凭据时,指定为 KMSAuth, 同步 oos 加密参数时,指定为 OOSAuth + oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" + ramRoleARN: "acs:ram::{accountID}:role/{roleName}" ``` - - 创建名称为`hello-service-external-secret.yml`的ExternalSecret的测试模版文件,测试模板如下: - + - 创建文件 `hello-service-external-secret.yml`如下并保存为测试模板, 其可以创建名称为 `esdemo` 的ExternalSecret的测试实例: ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: esdemo - spec: - data: #无需特殊处理的数据源 - - key: test1 # kms 凭据名称 - name: test1 # 存入 secret 字段 - versionId: v1 #kms 凭据版本 - secretStoreRef: - name: scdemo - namespace: default + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: esdemo + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + data: #无需特殊处理的数据源 + - key: test1 # kms 凭据名称 + name: test1 # 存入 secret 字段 + versionId: v1 #kms 凭据版本, 当 provider 为非 kms 时, 则不需要指定该字段 + secretStoreRef: + name: scdemo + namespace: default ``` - - 执行命令创建externalsecret测试实例: - + - 执行命令创建secretstore测试实例: ```sh - kubectl apply -f hello-service-external-secret.yml + kubectl apply -f hello-service-secret-store.yml ``` - - 查看目标secret是否创建成功: - + - 执行命令创建externalsecret测试实例: + ```sh + kubectl apply -f hello-service-external-secret.yml + ``` + - 查看目标secret是否创建成功: ```sh - kubectl get secret esdemo -oyaml + kubectl get secret esdemo -oyaml ``` + - 如果创建成功,查看secret内容如下: + ```yaml + apiVersion: v1 + data: + test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= + kind: Secret + metadata: + name: esdemo + namespace: default + type: Opaque + ``` + - 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步 +3. JSON凭据解析 - 如果创建成功,查看secret内容如下: + **data** + - 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用 `jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中 ```yaml - apiVersion: v1 - data: - test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= - kind: Secret - metadata: - name: esdemo - namespace: default - type: Opaque + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: es-json-demo + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + data: #无需特殊处理的数据源 + - key: test1 # kms 凭据名称 + name: test1 # 存入 secret 字段 + versionId: v1 #kms 凭据版本, 当 provider 为非 kms 时, 则不需要指定该字段 + secretStoreRef: + name: scdemo + namespace: default + jmesPath: # 解析 json 串中的部分字段 + - path: "name" + objectAlias: "name" + - path: "friends[0].name" + objectAlias: "friendname" + ``` + - 当您使用 `jmesPath`字段时,必需指定下面两个子字段: + - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段 + - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称 + - 部署后检查 secret 是否创建成功 + ```sh + kubectl get secret es-json-demo -oyaml + ``` + - 同步成功即可看到如下结果 + ```yaml + apiVersion: v1 + data: + friendname: bGlsaQ== + name: dG9t + kind: Secret + metadata: + name: es-json-demo + namespace: default + type: Opaque ``` - 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步 - - 另外ack-secret-manager支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore: + **datasource** + - 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: extract-secret + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + dataProcess: + - extract: + key: test1 + name: extract + versionId: v1 #kms 凭据版本, 当 provider 是 oos 时, 则不需要指定该字段 + secretStoreRef: + name: dkms-client + namespace: default + replaceRule: + - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud + target: "alibabacloud" + - source: "^f.*s$" + target: "ack" + ``` + - 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换 ```yaml + apiVersion: v1 + data: + ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0= + age: IjE0Ig== + alibabacloud: InRvbSI= + kind: Secret + metadata: + name: extract-secret + namespace: default + type: Opaque + ``` +4. 当前支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore + + ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: SecretStore metadata: name: scdemo spec: - KMS: - KMSAuth: + KMS: # 同步 kms 凭据时,指定为 KMS, 同步 oos 加密参数时,指定为 OOS + KMSAuth: # 同步 kms 凭据时,指定为 KMSAuth, 同步 oos 加密参数时,指定为 OOSAuth oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" ramRoleARN: "acs:ram::{accountID}:role/{roleName}" remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" remoteRamRoleSessionName: "" - ``` + ``` +## CRD 配置介绍 -3. JSON凭据解析 +### ExternalSecret - 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用`jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中 +**spec** - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: es-json-demo - spec: - data: #无需特殊处理的数据源 - - key: test1 # kms 凭据名称 - name: test1 # 存入 secret 字段 - versionId: v1 #kms 凭据版本 - secretStoreRef: - name: scdemo - namespace: default - jmesPath: # 解析 json 串中的部分字段 - - path: "name" - objectAlias: "name" - - path: "friends[0].name" - objectAlias: "friendname" - ``` +| crd 字段 | 描述 | 是否必选 | +| ----------- | ------------------------------------------ | -------- | +| provider | 获取 secret 的目标云产品(如 KMS 、OOS等) | 否 | +| data | 数据源(目标数据的标识) | 否 | +| dataProcess | 需要进行特殊加工的数据源(目标数据的标识) | 否 | +| type | k8s secret 类型(Opaque等) | 否 | - 当您使用`jmesPath`字段时,必需指定下面两个子字段: +**data(无需经过特殊处理的数据源)** - - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段 +| crd 字段 | 描述 | 是否必选 | +| -------------- | --------------------------------------------------------------------- | -------- | +| key | 目标 secret 的唯一标识(例如 KMS 凭据的 key) | 是 | +| name | 在集群 secret data 中对应的 key | 否 | +| versionStage | 目标 secret 版本状态 | 否 | +| versionId | 目标 secret 版本号, 当 provider 是 oos 时, 则不需要指定该字段 | 否 | +| jmesPath | 如果目标 secret 为 json 类型,可指定获取 json 中特定 key 对应的 value | 否 | +| secretStoreRef | 引用的 SecretStore 信息 | 否 | - - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称 +**dataProcess(需要进行特殊处理的数据源)** +| crd 字段 | 描述 | 是否必选 | +| ----------- | -------------------------------------------------------------------------------- | -------- | +| extract | 针对目标 secret 进行 json 解析,不需要用户指定 json key | 否 | +| replaceRule | 根据特定规则替换经过 json 解析的 secret 的 key,防止非法 key 不能存入 k8s secret | 否 | -部署后检查 secret 是否创建成功 +**replaceRule(用于进行 Secret Key 内容替换)** - ```sh - kubectl get secret es-json-demo -oyaml - ``` +| crd 字段 | 描述 | 是否必选 | +| -------- | ------------------------------------ | -------- | +| target | 用于替换的字符串 | 是 | +| source | 需要被替换的字符串,可以为正则表达式 | 是 | -同步成功即可看到如下结果 +**jmesPath** - ```yaml - apiVersion: v1 - data: - friendname: bGlsaQ== - name: dG9t - kind: Secret - metadata: - creationTimestamp: "2023-10-09T13:11:05Z" - labels: - lastUpdatedAt: 2023-10-09T13.11.05Z - name: es-json-demo - namespace: default - resourceVersion: "7313940" - uid: 18d84558-f526-4ff5-ab9a-720ec1861c30 - type: Opaque - ``` +| crd 字段 | 描述 | 是否必选 | +| ----------- | ------------------------------- | -------- | +| path | jmes 表达式,用户指定 json key | 是 | +| objectAlias | 存入 k8s secret 对应的 data key | 是 | +**secretStoreRef** -​ - -- dataProcess - - 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: extract-secret - spec: - dataProcess: - - extract: - key: test1 - name: extract - versionId: v1 - secretStoreRef: - name: dkms-client - namespace: default - replaceRule: - - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud - target: "alibabacloud" - - source: "^f.*s$" - target: "ack" - ``` - - 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换 - - ```yaml - apiVersion: v1 - data: - ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0= - age: IjE0Ig== - alibabacloud: InRvbSI= - kind: Secret - metadata: - creationTimestamp: "2023-10-09T14:07:35Z" - labels: - lastUpdatedAt: 2023-10-09T14.07.35Z - name: extract-secret - namespace: default - resourceVersion: "7328187" - uid: a3ab5278-02bd-4544-bae7-b502acccfe3c - type: Opaque - ``` +| crd 字段 | 描述 | 是否必选 | +| --------- | ---------------------------- | -------- | +| name | 指定的 SecretStore name | 是 | +| namespace | 指定的 SecretStore namespace | 是 | + +### SecretStore + +**spec** + +| crd 字段 | 描述 | 是否必选 | +| -------- | ------------------- | -------- | +| KMS | 代表目标云产品为KMS | 否 | +| OOS | 代表目标云产品为OOS | 否 | + +**KMS** + +| crd 字段 | 描述 | 是否必选 | +| -------- | ------------------------------- | -------- | +| KMSAuth | 访问 KMS 所需凭证(密钥管理服务) | 否 | + +**OOS** + +| crd 字段 | 描述 | 是否必选 | +| -------- | -------------------------------- | -------- | +| OOSAuth | 访问 OOS 所需凭证(管理加密参数) | 否 | + +**KMSAuth** + +| crd 字段 | 描述 | 是否必选 | +| ------------------------ | ---------------------------- | -------- | +| accessKey | 用户AK | 否 | +| accessKeySecret | 用户SK | 否 | +| ramRoleARN | ram 角色 arn | 否 | +| ramRoleSessionName | 角色会话名 | 否 | +| oidcProviderARN | oidc 提供商 arn | 否 | +| oidcTokenFilePath | 暂时无用 | 否 | +| remoteRamRoleArn | 跨账号 ram 角色 arn | 否 | +| remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 | + +**OOSAuth** + +| crd 字段 | 描述 | 是否必选 | +| ------------------------ | ---------------------------- | -------- | +| accessKey | 用户AK | 否 | +| accessKeySecret | 用户SK | 否 | +| ramRoleARN | ram 角色 arn | 否 | +| ramRoleSessionName | 角色会话名 | 否 | +| oidcProviderARN | oidc 提供商 arn | 否· | +| oidcTokenFilePath | 暂时无用 | 否 | +| remoteRamRoleArn | 跨账号 ram 角色 arn | 否 | +| remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 | + +**SecretRef(敏感访问凭据存放在 K8S secret 中)** + +| crd 字段 | 描述 | 是否必选 | +| --------- | ------------------------ | -------- | +| name | k8s secret 名称 | 是 | +| namespace | k8s secret 所在namaspace | 是 | +| key | k8s secret 数据对应的key | 是 | ## 安全 + 对于发现的安全漏洞,请发送邮件至**kubernetes-security@service.aliyun.com**,您可在[SECURITY.md](./SECURITY.md)文件中找到更多信息。 ## Release Note -| 版本号 | 变更时间 | 变更内容 | -| ------- | -------------- | ------------------------------------------------------------ | -| `0.4.0` | 2022年12月22日 | 支持基于JMES解析提取JSON格式的密文字段 | +| 版本号 | 变更时间 | 变更内容 | +| --------- | -------------- | -------------------------------------------------------------------------------------------------------------------- | +| `0.4.0` | 2022年12月22日 | 支持基于JMES解析提取JSON格式的密文字段 | | `0.5.0` | 2023年10月10日 | 1.支持专属版 KMS 凭据同步
2.多阿里云访问凭据管理
3.凭据自解析与键规则替换
4.共享版 KMS 跨账号凭据同步 | - +| `0.5.1` | 2023年10月18日 | 部分功能与性能优化 | +| `0.5.2` | 2024年8月1日 | 大规模资源同步并发优化 | +| `0.5.3` | 2024年10月10日 | 支持资源同步秒级限流,修复部分软件包cve | +| `0.5.4` | 2024年10月31日 | 支持同步 OOS 加密参数 | +| `0.5.5` | 2024年11月22日 | 支持同步 binary 类型的凭据 | diff --git a/README.md b/README.md index 2c690e4c..2c1ad9a0 100644 --- a/README.md +++ b/README.md @@ -2,57 +2,43 @@ English | [简体中文](./README-zh_CN.md) -[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import ciphertext stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can securely inject the ciphertext, which is stored in the Secrets Manager, into your application by mounting a Secret within the application's Pod. This practice helps to prevent the leakage and proliferation of sensitive data throughout the application supply chain. - - +[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import key credentials stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) or [Alibaba Cloud OOS Secret Parameter ](https://www.alibabacloud.com/help/en/oos/getting-started/manage-encryption-parameters?spm=a2c63.p38356.0.0.40bc27beO4CDFR)into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can introduce the ciphertext stored in the Secrets Manager into the application in the form of mounting Secret in the application Pod to avoid the spread of sensitive data in the application development and construction process and leaks. ## Install -1. Please make sure that the credentials used by the ack-secret-manager have enough permissions to access the Alibaba Cloud KMS Secrets Manager. You can use the following two configuration methods, and we recommend you to use the second **RRSA** method to achieve authorization in the Pod level. - -- Add permissions to the WorkerRole corresponding to the cluster - - - Log in to the Container Service console - - - Select the cluster to enter the cluster details page - - - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role. - - - Add kms RAM policy below into the policy bind to the worker role - - ```json - { - "Action": [ +1. Make sure that the credentials used by the ack-secret-manager has sufficient permissions to access the Alibaba Cloud product service. You can use the following two configuration methods, and we recommend you to use the second **RRSA** method to achieve authorization in the Pod level. + + - Add permissions to the WorkerRole corresponding to the cluster + - Log in to the Container Service console + - Select the cluster to enter the cluster details page + - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role. + - Add kms RAM policy below into the policy bind to the worker role(You only need to authorize the service permissions that need to be synchronized, ensuring the principle of minimum permissions.) + ```json + { + "Action": [ + // Permission required to access Alibaba Cloud KMS Secrets Manager "kms:GetSecretValue", - "kms:Decrypt" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ``` - - -- Implement Pod dimension authorization through [RRSA method](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/use-rrsa-to-authorize-pods-to-access-different-cloud-services) - - * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h) - - * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role - + "kms:Decrypt", + + // Permission required to access Alibaba Cloud OOS Secret Parameters + "oos:GetSecretParameter", + "kms:GetSecretValue" + ], + "Resource": [ + "*" + ], + "Effect": "Allow" + } + ``` + - Implement Pod dimension authorization through [RRSA method](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/use-rrsa-to-authorize-pods-to-access-different-cloud-services) + * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h) + * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role 2. Log in to the Container Service console - * Select **Marketplace** -> **Marketplace** in the left navigation bar, enter **ack-secret-manager** in the search bar, and select to enter the application page; - - - * Select the target cluster, namespace, and release name to be installed; - - - * Configure custom parameters on the parameter configuration page, including `rrsa.enable` in values.yaml and related parameters in `envVarsFromSecret`. For parameter descriptions, see the **configuration instructions** below; - - - * Click the **OK** button to complete the installation. - + * Select **Marketplace** -> **Marketplace** in the left navigation bar, enter **ack-secret-manager** in the search bar, and select to enter the application page; + * Select the target cluster, namespace, and release name to be installed; + * Configure custom parameters on the parameter configuration page, including `rrsa.enable` in values.yaml and related parameters in `envVarsFromSecret`. For parameter descriptions, see the **configuration instructions** below; + * Click the **OK** button to complete the installation. ## Upgrade @@ -68,162 +54,148 @@ English | [简体中文](./README-zh_CN.md) ## Configuration instructions -| **parameter** | **introduction** | **default value** | -| --------------------------------------------------- | ------------------------------------------------------------ | ---------------------- | -| env.WATCH_NAMESPACE | Specify the namespace of the component watch (the default empty value represents all namespaces of watch) | | -| envVarsFromSecret.ACCESS_KEY_ID | You can build the SDK client by specifying the credential AK by setting the ACCESS_KEY_ID variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.SECRET_ACCESS_KEY | You can build the SDK client by specifying the credential SK by setting the SECRET_ACCESS_KEY variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_ARN | You can specify the RAM role ARN used to build the SDK client by setting the ALICLOUD_ROLE_ARN variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | You can specify the RAM role session name by setting the ALICLOUD_ROLE_SESSION_NAME variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | You can specify the RAM role session expiration length by setting the ALICLOUD_ROLE_SESSION_EXPIRATION variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | -| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | You can specify the ARN of the RAM OIDC provider by setting the ALICLOUD_OIDC_PROVIDER_ARN variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | You can specify the oidc token file path in the pod by setting the ALICLOUD_OIDC_TOKEN_FILE variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | You can specify the RAM Role Arn of another account by setting the ALICLOUD_REMOTE_ROLE_ARN variable for role playing when pulling credential data across accounts. | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | You can specify the RAM Role Session Name by setting the ALICLOUD_REMOTE_ROLE_SESSION_NAME variable to perform role play when pulling credential data across accounts. | | -| rrsa.enable | Whether to enable the RRSA feature, the default is false. After enabling, you need to configure the ALICLOUD_ROLE_ARN and ALICLOUD_OIDC_PROVIDER_ARN parameters in envVarsFromSecret. | false | -| command.backend | The docked external key management system backend currently only supports Alibaba Cloud Secrets Manager, configured as alicloud-kms | alicloud-kms | -| command.reconcilePeriod | The interval for the controller to re-coordinate the externalSecret instance, the default is 5 seconds | 5s | -| command.reconcileCount | Specify the number of workers to concurrently coordinate the externalSecret instance. The default is 1 | 1 | -| command.tokenRotationPeriod | Polling time to check whether the KMS client access STS token has expired | 120s | -| command.region | Pull secret credentials from the specified region | | -| command.disablePolling | Turn off automatic synchronization of pulling the latest credential content from the KMS backend, default false | false | -| command.pollingInterval | The interval for synchronizing existing secret instances from the KMS backend | 120s | -| image.repository | Specified ack-secret-manager mirror warehouse name | acs/ack-secret-manager | -| image.tag | Specified ack-secret-manager image tag | v0.5.0 | -| image.pullPolicy | Image pull strategy, default is Always | Always | -| nameOverride | Override app name | nil | -| fullnameOverride | Override application full name | nil | -| rbac.create | Whether to create and use RBAC resources, the default is true | true | -| securityContext.fsGroup | Specify the security context configuration of the application | {} | -| serviceAccount.create | Whether to create serviceaccount | true | -| serviceAccount.name | Specify the name of the created serviceaccount | Automatic generated | -| serviceAccount.annotations | Specify adding the serviceaccount annotation tag | nil | -| podAnnotations | Specify the annotation label added to the pod | {} | -| podLabels | Specify the Label added to the pod | {} | -| replicaCount | Number of controller copies | 1 | -| nodeSelector | The specified nodeSelector tag | {} | -| tolerations | Specified taint tolerance configuration | [] | -| affinity | Specified Pod affinity configuration | {} | -| resources | Specified Pod requests and limits configuration | {} | +| **parameter** | **introduction** | **default value** | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| env.WATCH_NAMESPACE | Specify the namespace of the component watch (the default empty value represents all namespaces of watch) | | +| envVarsFromSecret.ACCESS_KEY_ID | You can build the SDK client by specifying the credential AK by setting the ACCESS_KEY_ID variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.SECRET_ACCESS_KEY | You can build the SDK client by specifying the credential SK by setting the SECRET_ACCESS_KEY variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_ARN | You can specify the RAM role ARN used to build the SDK client by setting the ALICLOUD_ROLE_ARN variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | You can specify the RAM role session name by setting the ALICLOUD_ROLE_SESSION_NAME variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | You can specify the RAM role session expiration length by setting the ALICLOUD_ROLE_SESSION_EXPIRATION variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | +| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | You can specify the ARN of the RAM OIDC provider by setting the ALICLOUD_OIDC_PROVIDER_ARN variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | You can specify the oidc token file path in the pod by setting the ALICLOUD_OIDC_TOKEN_FILE variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | You can specify the RAM Role Arn of another account by setting the ALICLOUD_REMOTE_ROLE_ARN variable for role playing when pulling credential data across accounts. | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | You can specify the RAM Role Session Name by setting the ALICLOUD_REMOTE_ROLE_SESSION_NAME variable to perform role play when pulling credential data across accounts. | | +| rrsa.enable | Whether to enable the RRSA feature, the default is false. After enabling, you need to configure the ALICLOUD_ROLE_ARN and ALICLOUD_OIDC_PROVIDER_ARN parameters in envVarsFromSecret. | false | +| command.reconcilePeriod | The interval for the controller to re-coordinate the externalSecret instance, the default is 5 seconds | 5s | +| command.reconcileCount | Specify the number of workers to concurrently coordinate the externalSecret instance. The default is 1 | 1 | +| command.tokenRotationPeriod | Polling time to check whether the client access STS token has expired | 120s | +| command.region | Pull secret credentials from the specified region | | +| command.disablePolling | Turn off automatic synchronization of pulling the latest credential content from the backend, default false | false | +| command.pollingInterval | The interval for synchronizing existing secret instances from the backend | 120s | +| command.maxConcurrentSecretPulls | Deprecated | - | +| command.maxConcurrentKmsSecretPulls | Maximum concurrent synchronization per second of kms secrets | 10 | +| command.maxConcurrentOosSecretPulls | Maximum concurrent synchronization per second of oos secrets | 10 | +| image.repository | Specified ack-secret-manager mirror warehouse name | acs/ack-secret-manager | +| image.tag | Specified ack-secret-manager image tag | v0.5.0 | +| image.pullPolicy | Image pull strategy, default is Always | Always | +| nameOverride | Override app name | nil | +| fullnameOverride | Override application full name | nil | +| rbac.create | Whether to create and use RBAC resources, the default is true | true | +| securityContext.fsGroup | Specify the security context configuration of the application | {} | +| serviceAccount.create | Whether to create serviceaccount | true | +| serviceAccount.name | Specify the name of the created serviceaccount | Automatic generated | +| serviceAccount.annotations | Specify adding the serviceaccount annotation tag | nil | +| podAnnotations | Specify the annotation label added to the pod | {} | +| podLabels | Specify the Label added to the pod | {} | +| replicaCount | Number of controller copies | 1 | +| nodeSelector | The specified nodeSelector tag | {} | +| tolerations | Specified taint tolerance configuration | [] | +| affinity | Specified Pod affinity configuration | {} | +| resources | Specified Pod requests and limits configuration | {} | +## Instructions for use +The following will add a test credential in Alibaba Cloud KMS Secrets Manager for synchronize the credentials, and demonstrate some extended functions. -## Instructions for use +**Tip: The method of cryptotext synchronization for other Alibaba Cloud products is similar to that of KMS credential steward. Just refer to the method of adding cryptotext for corresponding products in step 1 to add cryptotext first, and then modify the keywords in the SecretStore and ExternalSecret examples below and their values to the corresponding values in the table below.** -The following will add a test credential in Alibaba Cloud KMS Secrets Manager, synchronize the credentials through dedicated KMS and shared KMS, and demonstrate some extended functions. +| Configuration Field & Product | Alibaba KMS Credential | Alibaba Cloud OOS Secret Parameter | +| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------- | +| **SecretStore keyword authentication method** | SecretStore.Spec.KMS.KMSAuth | SecretStore.Spec.OOS.OOSAuth | +| **ExternalSecret.spec.provider** | kms | oos | +| **ExternalSecret.spec.data.key** | ``(as follows test1) | ``(as follows test2) | -ack-secret-manager involves two CRDs. SecretStore is used to store access credentials (such as RRSA configuration, ClientKey, AK configuration, etc.), and ExternalSecret is used to store basic credential information that needs to be synchronized (such as credential name, version, etc.) and specify the SecretStore. It helps to enhance the isolation of credentials permission and the usability. Please check the [parameters guide](doc/crd.md) +ack-secret-manager involves two CRDs. SecretStore is used to store access credentials (such as RRSA configuration, ClientKey, AK configuration, etc.), and ExternalSecret is used to store basic credential information that needs to be synchronized (such as credential name, version, etc.) and specify the SecretStore. It ensures the separation of permissions and data and enhances the flexibility of use. See below for details **CRD configuration introduction** 1. Create credentials + Currently supports synchronization of KMS credentials and OOS encryption parameters. The following are references to how to create two ciphertexts. - Add the following credentials in the KMS Secrets Manager. For detailed procedures, please refer to [Manage Common Credentials](https://www.alibabacloud.com/help/en/key-management-service/latest/manage-generic-secrets) + - Add the following credentials in the KMS Secrets Manager. For detailed procedures, please refer to [Manage Common Credentials](https://www.alibabacloud.com/help/en/key-management-service/latest/manage-generic-secrets) - ```txt - SecretName: test1 - SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} - VersionId: v1 - ``` + ```txt + SecretName: test1 + SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + VersionId: v1 + ``` + - Add the following encryption parameters to the OOS Encryption Parameters. Please refer to the detailed process[CreateSecretParameter](https://www.alibabacloud.com/help/en/oos/developer-reference/api-oos-2019-06-01-createsecretparameter) + ```txt + Name: test2 + Value: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + ``` 2. Create SecretStore & ExternalSecret Prerequisite: Enable RRSA for the cluster and correctly configure the relevant RAM Role permissions - Create a test instance of SecretStore. The test template is as follows. Some fields need to be replaced. - + - Create a test instance named scdemo of SecretStore, and saved as a file `hello-service-secret-store.yml`. The test template is as follows. Some fields need to be replaced. ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: SecretStore metadata: name: scdemo spec: - KMS: - KMSAuth: + KMS: # Specify KMS when synchronizing kms credentials, OOS when synchronizing oos encryption parameters + KMSAuth: # Specify KMSAuth when synchronizing kms credentials, OOSAuth when synchronizing oos encryption parameters oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" ramRoleARN: "acs:ram::{accountID}:role/{roleName}" ``` - - Create a test instance of ExternalSecret. The test template is as follows: - + - Create a test instance named `esdemo` of ExternalSecret, and saved as a file `hello-service-external-secret.yml`. The test template is as follows: ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: esdemo spec: + provider: kms # Default is kms, optional when synchronizing kms credentials data: #Data sources that require no special processing - - key: test1 # kms credential name + - key: test1 # kms credential name name: test1 # Fields stored in secret - versionId: v1 # kms credential version + versionId: v1 # kms credential version, when provider is not kms, this field is not required secretStoreRef: name: scdemo namespace: default ``` - - Execute the command to create an externalsecret test instance: - + - Execute the command to create an secretstore test instance: + ```sh + kubectl apply -f hello-service-secret-store.yml + ``` + - Execute the command to create an externalsecret test instance: ```sh kubectl apply -f hello-service-external-secret.yml ``` - - Check whether the target secret is created successfully: - + - Check whether the target secret is created successfully: ```sh kubectl get secret esdemo -oyaml ``` - - If the creation is successful, view the secret content as follows: - + - If the creation is successful, view the secret content as follows: ```yaml apiVersion: v1 data: test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= kind: Secret metadata: - creationTimestamp: "2023-10-09T13:03:09Z" - labels: - lastUpdatedAt: 2023-10-09T13.03.09Z name: esdemo namespace: default - resourceVersion: "7311947" - uid: 163c6a33-0bee-40b6-8ffe-6897277036cd type: Opaque ``` + - Without turning off the automatic synchronization configuration, you can modify the key content in the KMS Secrets Manager and wait for a while to check whether the target secret has been synchronized. +3. JSON-formatted support - Without turning off the automatic synchronization configuration, you can modify the key content in the KMS Secrets Manager and wait for a while to check whether the target secret has been synchronized. - - We supports cross-account synchronization of credentials. Just configure `remoteRamRoleArn` and `remoteRamRoleSessionName` in `SecretStore.Spec.KMS.KMSAuth`. The following is a sample SecretStore - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: scdemo - spec: - KMS: - KMSAuth: - oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" - ramRoleARN: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleSessionName: " - ``` - - -3. JSON-formatted support - -- jmesPath - - If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster + **data** + - If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: es-json-demo spec: + provider: kms # Default is kms, optional when synchronizing kms credentials data: - key: test1 name: test1 - versionId: v1 + versionId: v1 # kms credential version, this field is not required when provider is oos secretStoreRef: name: scdemo namespace: default @@ -233,15 +205,11 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden - path: "friends[0].name" objectAlias: "friendname" ``` - - After deployment, check whether the secret is created successfully - + - After deployment, check whether the secret is created successfully ```sh kubectl get secret es-json-demo -oyaml ``` - - If the synchronization is successful, you will see the following results: - + - If the synchronization is successful, you will see the following results: ```yaml apiVersion: v1 data: @@ -249,39 +217,29 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden name: dG9t kind: Secret metadata: - creationTimestamp: "2023-10-09T13:11:05Z" - labels: - lastUpdatedAt: 2023-10-09T13.11.05Z name: es-json-demo namespace: default - resourceVersion: "7313940" - uid: 18d84558-f526-4ff5-ab9a-720ec1861c30 type: Opaque ``` + - When you use the `jmesPath` field, you must specify the following two subfields: + - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification + - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret - When you use the `jmesPath` field, you must specify the following two subfields: - - - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification - - - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret - - - -- dataProcess - - If you want to parse JSON credentials and store them in a secret but don't know the specific structure of the credentials, you can use the self-extraction feature, which is the `dataProcess.Extract` field. You can also perform rule-based replacements on the parsed field keys using the `dataProcess.replaceRule` field to prevent irregular secret data keys from causing issues when creating a secret. The following is an example of an ExternalSecret: + **dataProcess** + - If you want to parse JSON credentials and store them in a secret but don't know the specific structure of the credentials, you can use the self-extraction feature, which is the `dataProcess.Extract` field. You can also perform rule-based replacements on the parsed field keys using the `dataProcess.replaceRule` field to prevent irregular secret data keys from causing issues when creating a secret. The following is an example of an ExternalSecret: ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: extract-secret spec: + provider: kms # Default is kms, optional when synchronizing kms credentials dataProcess: - extract: key: test1 name: extract - versionId: v1 + versionId: v1 # kms credential version, this field is not required when provider is oos secretStoreRef: name: dkms-client namespace: default @@ -291,9 +249,7 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden - source: "^f.*s$" target: "ack" ``` - - Once the synchronization is successful, you will be able to see the following results. The JSON credentials are parsed into three parts, and their respective keys are replaced according to the replaceRule rules. - + - Once the synchronization is successful, you will be able to see the following results. The JSON credentials are parsed into three parts, and their respective keys are replaced according to the replaceRule rules. ```yaml apiVersion: v1 data: @@ -302,22 +258,145 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden alibabacloud: InRvbSI= kind: Secret metadata: - creationTimestamp: "2023-10-09T14:07:35Z" - labels: - lastUpdatedAt: 2023-10-09T14.07.35Z name: extract-secret namespace: default - resourceVersion: "7328187" - uid: a3ab5278-02bd-4544-bae7-b502acccfe3c type: Opaque ``` +4. Currently supports cross-account synchronization of credentials. Just configure remoteRamRoleArn and remoteRamRoleSessionName in SecretStore.Spec.KMS.KMSAuth. The following is a sample SecretStore + + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: SecretStore + metadata: + name: scdemo + spec: + KMS: # Specify KMS when synchronizing kms credentials, OOS when synchronizing oos encryption parameters + KMSAuth: # Specify KMSAuth when synchronizing kms credentials, OOSAuth when synchronizing oos encryption parameters + oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" + ramRoleARN: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleSessionName: "" + ``` + +## CRD configuration introduction + +### ExternalSecret + +**spec** + +| parameter | description | required | +| ----------- | ------------------------------------------------------------------------- | -------- | +| provider | The target cloud products for syncing credentials, such as KMS, OOS | no | +| data | Data source (identifier for the target data) | no | +| dataProcess | Data source requiring special processing (identifier for the target data) | no | +| type | Kubernetes Secret types (Opaque, etc.) | no | + +**data** + +| parameter | description | required | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- | +| key | The unique identifier for the target credential, such as the key for KMS credentials | yes | +| name | The corresponding key for the credentials in the secret data of the cluster | no | +| versionStage | The version stage of the target credential | no | +| versionId | The version Id of the target credential, this field is not required when provider is oos | no | +| jmesPath | If the target credential is in JSON format, you can specify to retrieve the value corresponding to a specific key in the JSON | no | +| secretStoreRef | Information of the referenced SecretStore | no | + +**dataProcess(Data source requiring special processing.)** + +| parameter | description | required | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | +| extract | Parsing JSON for the target credential without requiring the user to specify the JSON key | no | +| replaceRule | Replacing keys of the parsed secret based on specific rules to prevent illegal keys from being stored in the Kubernetes Secret | no | + +**replaceRule(The content replacement used for the Secret Key.)** + +| parameter | description | required | +| --------- | ----------------------------------------------------------------------- | -------- | +| target | The string used for replacement | yes | +| source | The string that needs to be replaced, which can be a regular expression | yes | + +**jmesPath** + +| parameter | description | required | +| ----------- | --------------------------------------------------------------------------------- | -------- | +| path | JMESPath expression that allows users to specify the JSON key | yes | +| objectAlias | The data key corresponding to the Kubernetes Secret where the data will be stored | yes | + +**secretStoreRef** + +| parameter | description | required | +| --------- | ----------------------------------- | -------- | +| name | The specified SecretStore name | yes | +| namespace | The specified SecretStore namespace | Yes | + +### SecretStore + +**spec** + +| parameter | description | required | +| --------- | ------------------------------------------------------------------------- | -------- | +| KMS | Representing the target cloud product as KMS (Key Management Service) | no | +| OOS | Representing the target cloud product as OOS(Manage Encryption Parameter) | no | + +**KMS** + +| parameter | description | required | +| --------- | ------------------------------------------------------------------------------ | -------- | +| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no | + +**OOS** + +| parameter | description | required | +| --------- | --------------------------------------------------------------- | -------- | +| OOSAuth | Credentials required to access OOS(Manage Encryption Parameter) | no | + +**KMSAuth** + +| parameter | description | required | +| ------------------------ | ----------------------------------- | -------- | +| accessKey | AccessKey | no | +| accessKeySecret | AccessKey Secret | no | +| ramRoleARN | Ram role arn | no | +| ramRoleSessionName | Role session name | no | +| oidcProviderARN | OIDC provider arn | no | +| oidcTokenFilePath | | no | +| remoteRamRoleArn | Cross-account ram role are | no | +| remoteRamRoleSessionName | Cross-account ram role session name | no | + +**OOSAuth** + +| parameter | description | required | +| ------------------------ | ----------------------------------- | -------- | +| accessKey | AccessKey | no | +| accessKeySecret | AccessKey Secret | no | +| ramRoleARN | Ram role arn | no | +| ramRoleSessionName | Role session name | no | +| oidcProviderARN | OIDC provider arn | no | +| oidcTokenFilePath | | no | +| remoteRamRoleArn | Cross-account ram role are | no | +| remoteRamRoleSessionName | Cross-account ram role session name | no | + +**SecretRef(sensitive access credentials are stored in K8S secret)** + +| parameter | description | required | +| --------- | -------------------- | -------- | +| name | k8s secret name | yes | +| namespace | k8s secret namaspace | yes | +| key | k8s secret key | Yes | ## Security + Please report vulnerabilities by email to **kubernetes-security@service.aliyun.com**. Also see our [SECURITY.md](./SECURITY.md) file for details. ## Release Note -| Version | Date | Changes | -| ------- | ---------- | ------------------------------------------------------------ | -| `0.4.0` | 2022/12/22 | Support sync specific key-value pairs extract from a JSON-formatted secret based on JMES path | -| `0.5.0` | 2023/10/10 | 1.dedicated KMS credential synchronization
2.multiple Alibaba Cloud access credentials management,
3.self-resolving credentials and key rule replacement
4.shared KMS cross-account credential synchronization. | \ No newline at end of file +| Version | Date | Changes | +| --------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `0.4.0` | 2022/12/22 | Support sync specific key-value pairs extract from a JSON-formatted secret based on JMES path | +| `0.5.0` | 2023/10/10 | 1.dedicated KMS credential synchronization
2.multiple Alibaba Cloud access credentials management,
3.self-resolving credentials and key rule replacement
4.shared KMS cross-account credential synchronization. | +| `0.5.1` | 2023/10/18 | Function and performance optimization | +| `0.5.2` | 2024/08/01 | Large-scale resource synchronization concurrency optimization | +| `0.5.3` | 2024/10/10 | Supports resource synchronization with second-level rate limiting, fixes for certain software package CVEs | +| `0.5.4` | 2024/10/31 | Supports OOS secret parameter synchronization | +| `0.5.5` | 2024/11/22 | Supports synchronization of binary-type secrets | diff --git a/ack-secret-manager-cli/README-zh_CN.md b/ack-secret-manager-cli/README-zh_CN.md deleted file mode 100644 index 6169e524..00000000 --- a/ack-secret-manager-cli/README-zh_CN.md +++ /dev/null @@ -1,33 +0,0 @@ - - -# ACK Secret Manager Cli - -ACK Secret Manager Cli 帮助您简化 ACK Secret Manager 的配置与使用,并尽可能帮助您减少配置过程中的错误。 - -## 安装 - -```shell -cd cli -go install github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli -``` - -## 使用 - -1. 创建 RRSA 类型的凭据 - - ![](./img/rrsa.gif) - -2. 创建 RAM Role 类型的凭据(需要创建 Secret 额外保存敏感信息) - - ![](./img/ramrole.gif) - -3. 创建跨账号类型的凭据(需要指定一个 SecretStore 添加跨账号配置,跨账号扮演另一个账号的角色) - - ![](./img/cross.gif) - -4. 创建 ExternalSecret - - ![](./img/es.gif) - - - diff --git a/ack-secret-manager-cli/README.md b/ack-secret-manager-cli/README.md deleted file mode 100644 index 48f634db..00000000 --- a/ack-secret-manager-cli/README.md +++ /dev/null @@ -1,35 +0,0 @@ - - -# ACK Secret Manager Cli - -The ACK Secret Manager Cli helps simplify the configuration and usage of ACK Secret Manager, and strives to minimize errors during the configuration process. - - - -## Install - -```shell -cd cli -go install github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli -``` - -## Example - -1. Create RRSA type credentials - - ![](./img/rrsa.gif) - -2. Create RAM Role type credentials (need to create a Secret to save additional sensitive information) - - ![](./img/ramrole.gif) - -3. Create cross-account type credentials (you need to specify a SecretStore to add cross-account configuration, and the cross-account assumes the role of another account) - - ![](./img/cross.gif) - -4. Create ExternalSecret - - ![](./img/es.gif) - - - diff --git a/ack-secret-manager-cli/client/clientset/versioned/clientset.go b/ack-secret-manager-cli/client/clientset/versioned/clientset.go deleted file mode 100644 index a74618e2..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/clientset.go +++ /dev/null @@ -1,104 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package versioned - -import ( - "fmt" - "net/http" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - discovery "k8s.io/client-go/discovery" - rest "k8s.io/client-go/rest" - flowcontrol "k8s.io/client-go/util/flowcontrol" -) - -type Interface interface { - Discovery() discovery.DiscoveryInterface - AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface -} - -// Clientset contains the clients for groups. -type Clientset struct { - *discovery.DiscoveryClient - alibabacloudV1alpha1 *alibabacloudv1alpha1.AlibabacloudV1alpha1Client -} - -// AlibabacloudV1alpha1 retrieves the AlibabacloudV1alpha1Client -func (c *Clientset) AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface { - return c.alibabacloudV1alpha1 -} - -// Discovery retrieves the DiscoveryClient -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - if c == nil { - return nil - } - return c.DiscoveryClient -} - -// NewForConfig creates a new Clientset for the given config. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfig will generate a rate-limiter in configShallowCopy. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*Clientset, error) { - configShallowCopy := *c - - if configShallowCopy.UserAgent == "" { - configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() - } - - // share the transport between all clients - httpClient, err := rest.HTTPClientFor(&configShallowCopy) - if err != nil { - return nil, err - } - - return NewForConfigAndClient(&configShallowCopy, httpClient) -} - -// NewForConfigAndClient creates a new Clientset for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. -func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { - configShallowCopy := *c - if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { - if configShallowCopy.Burst <= 0 { - return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") - } - configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) - } - - var cs Clientset - var err error - cs.alibabacloudV1alpha1, err = alibabacloudv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - - cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - return &cs, nil -} - -// NewForConfigOrDie creates a new Clientset for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *Clientset { - cs, err := NewForConfig(c) - if err != nil { - panic(err) - } - return cs -} - -// New creates a new Clientset for the given RESTClient. -func New(c rest.Interface) *Clientset { - var cs Clientset - cs.alibabacloudV1alpha1 = alibabacloudv1alpha1.New(c) - - cs.DiscoveryClient = discovery.NewDiscoveryClient(c) - return &cs -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/fake/clientset_generated.go b/ack-secret-manager-cli/client/clientset/versioned/fake/clientset_generated.go deleted file mode 100644 index 1718f9bb..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/fake/clientset_generated.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - clientset "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - fakealibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/discovery" - fakediscovery "k8s.io/client-go/discovery/fake" - "k8s.io/client-go/testing" -) - -// NewSimpleClientset returns a clientset that will respond with the provided objects. -// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, -// without applying any validations and/or defaults. It shouldn't be considered a replacement -// for a real clientset and is mostly useful in simple unit tests. -func NewSimpleClientset(objects ...runtime.Object) *Clientset { - o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) - for _, obj := range objects { - if err := o.Add(obj); err != nil { - panic(err) - } - } - - cs := &Clientset{tracker: o} - cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} - cs.AddReactor("*", "*", testing.ObjectReaction(o)) - cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { - gvr := action.GetResource() - ns := action.GetNamespace() - watch, err := o.Watch(gvr, ns) - if err != nil { - return false, nil, err - } - return true, watch, nil - }) - - return cs -} - -// Clientset implements clientset.Interface. Meant to be embedded into a -// struct to get a default implementation. This makes faking out just the method -// you want to test easier. -type Clientset struct { - testing.Fake - discovery *fakediscovery.FakeDiscovery - tracker testing.ObjectTracker -} - -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - return c.discovery -} - -func (c *Clientset) Tracker() testing.ObjectTracker { - return c.tracker -} - -var ( - _ clientset.Interface = &Clientset{} - _ testing.FakeClient = &Clientset{} -) - -// AlibabacloudV1alpha1 retrieves the AlibabacloudV1alpha1Client -func (c *Clientset) AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface { - return &fakealibabacloudv1alpha1.FakeAlibabacloudV1alpha1{Fake: &c.Fake} -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/fake/doc.go b/ack-secret-manager-cli/client/clientset/versioned/fake/doc.go deleted file mode 100644 index 3630ed1c..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/fake/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated fake clientset. -package fake diff --git a/ack-secret-manager-cli/client/clientset/versioned/fake/register.go b/ack-secret-manager-cli/client/clientset/versioned/fake/register.go deleted file mode 100644 index 8d653806..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/fake/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - serializer "k8s.io/apimachinery/pkg/runtime/serializer" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" -) - -var scheme = runtime.NewScheme() -var codecs = serializer.NewCodecFactory(scheme) - -var localSchemeBuilder = runtime.SchemeBuilder{ - alibabacloudv1alpha1.AddToScheme, -} - -// AddToScheme adds all types of this clientset into the given scheme. This allows composition -// of clientsets, like in: -// -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) -// -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) -// -// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types -// correctly. -var AddToScheme = localSchemeBuilder.AddToScheme - -func init() { - v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) - utilruntime.Must(AddToScheme(scheme)) -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/scheme/doc.go b/ack-secret-manager-cli/client/clientset/versioned/scheme/doc.go deleted file mode 100644 index 14db57a5..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/scheme/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package contains the scheme of the automatically generated clientset. -package scheme diff --git a/ack-secret-manager-cli/client/clientset/versioned/scheme/register.go b/ack-secret-manager-cli/client/clientset/versioned/scheme/register.go deleted file mode 100644 index ba987253..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/scheme/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package scheme - -import ( - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - serializer "k8s.io/apimachinery/pkg/runtime/serializer" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" -) - -var Scheme = runtime.NewScheme() -var Codecs = serializer.NewCodecFactory(Scheme) -var ParameterCodec = runtime.NewParameterCodec(Scheme) -var localSchemeBuilder = runtime.SchemeBuilder{ - alibabacloudv1alpha1.AddToScheme, -} - -// AddToScheme adds all types of this clientset into the given scheme. This allows composition -// of clientsets, like in: -// -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) -// -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) -// -// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types -// correctly. -var AddToScheme = localSchemeBuilder.AddToScheme - -func init() { - v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - utilruntime.Must(AddToScheme(Scheme)) -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go deleted file mode 100644 index 54884adb..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go +++ /dev/null @@ -1,96 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "net/http" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - rest "k8s.io/client-go/rest" -) - -type AlibabacloudV1alpha1Interface interface { - RESTClient() rest.Interface - ExternalSecretsGetter - SecretStoresGetter -} - -// AlibabacloudV1alpha1Client is used to interact with features provided by the alibabacloud.com group. -type AlibabacloudV1alpha1Client struct { - restClient rest.Interface -} - -func (c *AlibabacloudV1alpha1Client) ExternalSecrets(namespace string) ExternalSecretInterface { - return newExternalSecrets(c, namespace) -} - -func (c *AlibabacloudV1alpha1Client) SecretStores(namespace string) SecretStoreInterface { - return newSecretStores(c, namespace) -} - -// NewForConfig creates a new AlibabacloudV1alpha1Client for the given config. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*AlibabacloudV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - httpClient, err := rest.HTTPClientFor(&config) - if err != nil { - return nil, err - } - return NewForConfigAndClient(&config, httpClient) -} - -// NewForConfigAndClient creates a new AlibabacloudV1alpha1Client for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AlibabacloudV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - client, err := rest.RESTClientForConfigAndClient(&config, h) - if err != nil { - return nil, err - } - return &AlibabacloudV1alpha1Client{client}, nil -} - -// NewForConfigOrDie creates a new AlibabacloudV1alpha1Client for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *AlibabacloudV1alpha1Client { - client, err := NewForConfig(c) - if err != nil { - panic(err) - } - return client -} - -// New creates a new AlibabacloudV1alpha1Client for the given RESTClient. -func New(c rest.Interface) *AlibabacloudV1alpha1Client { - return &AlibabacloudV1alpha1Client{c} -} - -func setConfigDefaults(config *rest.Config) error { - gv := v1alpha1.SchemeGroupVersion - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() - - if config.UserAgent == "" { - config.UserAgent = rest.DefaultKubernetesUserAgent() - } - - return nil -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *AlibabacloudV1alpha1Client) RESTClient() rest.Interface { - if c == nil { - return nil - } - return c.restClient -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go deleted file mode 100644 index 93a7ca4e..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated typed clients. -package v1alpha1 diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index c220af10..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,179 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - scheme "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ExternalSecretsGetter has a method to return a ExternalSecretInterface. -// A group's client should implement this interface. -type ExternalSecretsGetter interface { - ExternalSecrets(namespace string) ExternalSecretInterface -} - -// ExternalSecretInterface has methods to work with ExternalSecret resources. -type ExternalSecretInterface interface { - Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (*v1alpha1.ExternalSecret, error) - Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) - UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ExternalSecret, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ExternalSecretList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) - ExternalSecretExpansion -} - -// externalSecrets implements ExternalSecretInterface -type externalSecrets struct { - client rest.Interface - ns string -} - -// newExternalSecrets returns a ExternalSecrets -func newExternalSecrets(c *AlibabacloudV1alpha1Client, namespace string) *externalSecrets { - return &externalSecrets{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the externalSecret, and returns the corresponding externalSecret object, and an error if there is any. -func (c *externalSecrets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ExternalSecrets that match those selectors. -func (c *externalSecrets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ExternalSecretList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.ExternalSecretList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested externalSecrets. -func (c *externalSecrets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a externalSecret and creates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *externalSecrets) Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Post(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a externalSecret and updates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *externalSecrets) Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Put(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(externalSecret.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *externalSecrets) UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Put(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(externalSecret.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the externalSecret and deletes it. Returns an error if one occurs. -func (c *externalSecrets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *externalSecrets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched externalSecret. -func (c *externalSecrets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go deleted file mode 100644 index 2b5ba4c8..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// Package fake has the automatically generated clients. -package fake diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go deleted file mode 100644 index bd050e26..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - rest "k8s.io/client-go/rest" - testing "k8s.io/client-go/testing" -) - -type FakeAlibabacloudV1alpha1 struct { - *testing.Fake -} - -func (c *FakeAlibabacloudV1alpha1) ExternalSecrets(namespace string) v1alpha1.ExternalSecretInterface { - return &FakeExternalSecrets{c, namespace} -} - -func (c *FakeAlibabacloudV1alpha1) SecretStores(namespace string) v1alpha1.SecretStoreInterface { - return &FakeSecretStores{c, namespace} -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeAlibabacloudV1alpha1) RESTClient() rest.Interface { - var ret *rest.RESTClient - return ret -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go deleted file mode 100644 index 0b966144..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go +++ /dev/null @@ -1,125 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeExternalSecrets implements ExternalSecretInterface -type FakeExternalSecrets struct { - Fake *FakeAlibabacloudV1alpha1 - ns string -} - -var externalsecretsResource = v1alpha1.SchemeGroupVersion.WithResource("externalsecrets") - -var externalsecretsKind = v1alpha1.SchemeGroupVersion.WithKind("ExternalSecret") - -// Get takes name of the externalSecret, and returns the corresponding externalSecret object, and an error if there is any. -func (c *FakeExternalSecrets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(externalsecretsResource, c.ns, name), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// List takes label and field selectors, and returns the list of ExternalSecrets that match those selectors. -func (c *FakeExternalSecrets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ExternalSecretList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(externalsecretsResource, externalsecretsKind, c.ns, opts), &v1alpha1.ExternalSecretList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.ExternalSecretList{ListMeta: obj.(*v1alpha1.ExternalSecretList).ListMeta} - for _, item := range obj.(*v1alpha1.ExternalSecretList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested externalSecrets. -func (c *FakeExternalSecrets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(externalsecretsResource, c.ns, opts)) - -} - -// Create takes the representation of a externalSecret and creates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *FakeExternalSecrets) Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(externalsecretsResource, c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// Update takes the representation of a externalSecret and updates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *FakeExternalSecrets) Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(externalsecretsResource, c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeExternalSecrets) UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(externalsecretsResource, "status", c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// Delete takes name of the externalSecret and deletes it. Returns an error if one occurs. -func (c *FakeExternalSecrets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(externalsecretsResource, c.ns, name, opts), &v1alpha1.ExternalSecret{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeExternalSecrets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(externalsecretsResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.ExternalSecretList{}) - return err -} - -// Patch applies the patch and returns the patched externalSecret. -func (c *FakeExternalSecrets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(externalsecretsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go deleted file mode 100644 index 27dc41a8..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go +++ /dev/null @@ -1,125 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeSecretStores implements SecretStoreInterface -type FakeSecretStores struct { - Fake *FakeAlibabacloudV1alpha1 - ns string -} - -var secretstoresResource = v1alpha1.SchemeGroupVersion.WithResource("secretstores") - -var secretstoresKind = v1alpha1.SchemeGroupVersion.WithKind("SecretStore") - -// Get takes name of the secretStore, and returns the corresponding secretStore object, and an error if there is any. -func (c *FakeSecretStores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(secretstoresResource, c.ns, name), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// List takes label and field selectors, and returns the list of SecretStores that match those selectors. -func (c *FakeSecretStores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.SecretStoreList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(secretstoresResource, secretstoresKind, c.ns, opts), &v1alpha1.SecretStoreList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.SecretStoreList{ListMeta: obj.(*v1alpha1.SecretStoreList).ListMeta} - for _, item := range obj.(*v1alpha1.SecretStoreList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested secretStores. -func (c *FakeSecretStores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(secretstoresResource, c.ns, opts)) - -} - -// Create takes the representation of a secretStore and creates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *FakeSecretStores) Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(secretstoresResource, c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// Update takes the representation of a secretStore and updates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *FakeSecretStores) Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(secretstoresResource, c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeSecretStores) UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(secretstoresResource, "status", c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// Delete takes name of the secretStore and deletes it. Returns an error if one occurs. -func (c *FakeSecretStores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(secretstoresResource, c.ns, name, opts), &v1alpha1.SecretStore{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeSecretStores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(secretstoresResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.SecretStoreList{}) - return err -} - -// Patch applies the patch and returns the patched secretStore. -func (c *FakeSecretStores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(secretstoresResource, c.ns, name, pt, data, subresources...), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go deleted file mode 100644 index 6104b9ee..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go +++ /dev/null @@ -1,7 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -type ExternalSecretExpansion interface{} - -type SecretStoreExpansion interface{} diff --git a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index c37fdcf1..00000000 --- a/ack-secret-manager-cli/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,179 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - scheme "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// SecretStoresGetter has a method to return a SecretStoreInterface. -// A group's client should implement this interface. -type SecretStoresGetter interface { - SecretStores(namespace string) SecretStoreInterface -} - -// SecretStoreInterface has methods to work with SecretStore resources. -type SecretStoreInterface interface { - Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (*v1alpha1.SecretStore, error) - Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) - UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.SecretStore, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.SecretStoreList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) - SecretStoreExpansion -} - -// secretStores implements SecretStoreInterface -type secretStores struct { - client rest.Interface - ns string -} - -// newSecretStores returns a SecretStores -func newSecretStores(c *AlibabacloudV1alpha1Client, namespace string) *secretStores { - return &secretStores{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the secretStore, and returns the corresponding secretStore object, and an error if there is any. -func (c *secretStores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of SecretStores that match those selectors. -func (c *secretStores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.SecretStoreList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.SecretStoreList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested secretStores. -func (c *secretStores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a secretStore and creates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *secretStores) Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Post(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a secretStore and updates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *secretStores) Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Put(). - Namespace(c.ns). - Resource("secretstores"). - Name(secretStore.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *secretStores) UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Put(). - Namespace(c.ns). - Resource("secretstores"). - Name(secretStore.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the secretStore and deletes it. Returns an error if one occurs. -func (c *secretStores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *secretStores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched secretStore. -func (c *secretStores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/interface.go b/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/interface.go deleted file mode 100644 index 23c8cd1f..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/interface.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package alibabacloud - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" -) - -// Interface provides access to each of this group's versions. -type Interface interface { - // V1alpha1 provides access to shared informers for resources in V1alpha1. - V1alpha1() v1alpha1.Interface -} - -type group struct { - factory internalinterfaces.SharedInformerFactory - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { - return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} -} - -// V1alpha1 returns a new v1alpha1.Interface. -func (g *group) V1alpha1() v1alpha1.Interface { - return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index 76d82bbc..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - time "time" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// ExternalSecretInformer provides access to a shared informer and lister for -// ExternalSecrets. -type ExternalSecretInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.ExternalSecretLister -} - -type externalSecretInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewExternalSecretInformer constructs a new informer for ExternalSecret type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewExternalSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredExternalSecretInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredExternalSecretInformer constructs a new informer for ExternalSecret type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredExternalSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().ExternalSecrets(namespace).List(context.TODO(), options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().ExternalSecrets(namespace).Watch(context.TODO(), options) - }, - }, - &alibabacloudv1alpha1.ExternalSecret{}, - resyncPeriod, - indexers, - ) -} - -func (f *externalSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredExternalSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *externalSecretInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&alibabacloudv1alpha1.ExternalSecret{}, f.defaultInformer) -} - -func (f *externalSecretInformer) Lister() v1alpha1.ExternalSecretLister { - return v1alpha1.NewExternalSecretLister(f.Informer().GetIndexer()) -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/interface.go b/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/interface.go deleted file mode 100644 index b4007ed6..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/interface.go +++ /dev/null @@ -1,36 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" -) - -// Interface provides access to all the informers in this group version. -type Interface interface { - // ExternalSecrets returns a ExternalSecretInformer. - ExternalSecrets() ExternalSecretInformer - // SecretStores returns a SecretStoreInformer. - SecretStores() SecretStoreInformer -} - -type version struct { - factory internalinterfaces.SharedInformerFactory - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { - return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} -} - -// ExternalSecrets returns a ExternalSecretInformer. -func (v *version) ExternalSecrets() ExternalSecretInformer { - return &externalSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} - -// SecretStores returns a SecretStoreInformer. -func (v *version) SecretStores() SecretStoreInformer { - return &secretStoreInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index 59ba83dc..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - time "time" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// SecretStoreInformer provides access to a shared informer and lister for -// SecretStores. -type SecretStoreInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.SecretStoreLister -} - -type secretStoreInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewSecretStoreInformer constructs a new informer for SecretStore type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewSecretStoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredSecretStoreInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredSecretStoreInformer constructs a new informer for SecretStore type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredSecretStoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().SecretStores(namespace).List(context.TODO(), options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().SecretStores(namespace).Watch(context.TODO(), options) - }, - }, - &alibabacloudv1alpha1.SecretStore{}, - resyncPeriod, - indexers, - ) -} - -func (f *secretStoreInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredSecretStoreInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *secretStoreInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&alibabacloudv1alpha1.SecretStore{}, f.defaultInformer) -} - -func (f *secretStoreInformer) Lister() v1alpha1.SecretStoreLister { - return v1alpha1.NewSecretStoreLister(f.Informer().GetIndexer()) -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/factory.go b/ack-secret-manager-cli/client/informers/externalversions/factory.go deleted file mode 100644 index 0ff7e4f2..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/factory.go +++ /dev/null @@ -1,235 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package externalversions - -import ( - reflect "reflect" - sync "sync" - time "time" - - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - alibabacloud "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - cache "k8s.io/client-go/tools/cache" -) - -// SharedInformerOption defines the functional option type for SharedInformerFactory. -type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory - -type sharedInformerFactory struct { - client versioned.Interface - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc - lock sync.Mutex - defaultResync time.Duration - customResync map[reflect.Type]time.Duration - - informers map[reflect.Type]cache.SharedIndexInformer - // startedInformers is used for tracking which informers have been started. - // This allows Start() to be called multiple times safely. - startedInformers map[reflect.Type]bool - // wg tracks how many goroutines were started. - wg sync.WaitGroup - // shuttingDown is true when Shutdown has been called. It may still be running - // because it needs to wait for goroutines. - shuttingDown bool -} - -// WithCustomResyncConfig sets a custom resync period for the specified informer types. -func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - for k, v := range resyncConfig { - factory.customResync[reflect.TypeOf(k)] = v - } - return factory - } -} - -// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. -func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - factory.tweakListOptions = tweakListOptions - return factory - } -} - -// WithNamespace limits the SharedInformerFactory to the specified namespace. -func WithNamespace(namespace string) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - factory.namespace = namespace - return factory - } -} - -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. -func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewSharedInformerFactoryWithOptions(client, defaultResync) -} - -// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. -// Listers obtained via this SharedInformerFactory will be subject to the same filters -// as specified here. -// Deprecated: Please use NewSharedInformerFactoryWithOptions instead -func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) -} - -// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. -func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { - factory := &sharedInformerFactory{ - client: client, - namespace: v1.NamespaceAll, - defaultResync: defaultResync, - informers: make(map[reflect.Type]cache.SharedIndexInformer), - startedInformers: make(map[reflect.Type]bool), - customResync: make(map[reflect.Type]time.Duration), - } - - // Apply all options - for _, opt := range options { - factory = opt(factory) - } - - return factory -} - -func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { - f.lock.Lock() - defer f.lock.Unlock() - - if f.shuttingDown { - return - } - - for informerType, informer := range f.informers { - if !f.startedInformers[informerType] { - f.wg.Add(1) - // We need a new variable in each loop iteration, - // otherwise the goroutine would use the loop variable - // and that keeps changing. - informer := informer - go func() { - defer f.wg.Done() - informer.Run(stopCh) - }() - f.startedInformers[informerType] = true - } - } -} - -func (f *sharedInformerFactory) Shutdown() { - f.lock.Lock() - f.shuttingDown = true - f.lock.Unlock() - - // Will return immediately if there is nothing to wait for. - f.wg.Wait() -} - -func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { - informers := func() map[reflect.Type]cache.SharedIndexInformer { - f.lock.Lock() - defer f.lock.Unlock() - - informers := map[reflect.Type]cache.SharedIndexInformer{} - for informerType, informer := range f.informers { - if f.startedInformers[informerType] { - informers[informerType] = informer - } - } - return informers - }() - - res := map[reflect.Type]bool{} - for informType, informer := range informers { - res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) - } - return res -} - -// InformerFor returns the SharedIndexInformer for obj using an internal -// client. -func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { - f.lock.Lock() - defer f.lock.Unlock() - - informerType := reflect.TypeOf(obj) - informer, exists := f.informers[informerType] - if exists { - return informer - } - - resyncPeriod, exists := f.customResync[informerType] - if !exists { - resyncPeriod = f.defaultResync - } - - informer = newFunc(f.client, resyncPeriod) - f.informers[informerType] = informer - - return informer -} - -// SharedInformerFactory provides shared informers for resources in all known -// API group versions. -// -// It is typically used like this: -// -// ctx, cancel := context.Background() -// defer cancel() -// factory := NewSharedInformerFactory(client, resyncPeriod) -// defer factory.WaitForStop() // Returns immediately if nothing was started. -// genericInformer := factory.ForResource(resource) -// typedInformer := factory.SomeAPIGroup().V1().SomeType() -// factory.Start(ctx.Done()) // Start processing these informers. -// synced := factory.WaitForCacheSync(ctx.Done()) -// for v, ok := range synced { -// if !ok { -// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) -// return -// } -// } -// -// // Creating informers can also be created after Start, but then -// // Start must be called again: -// anotherGenericInformer := factory.ForResource(resource) -// factory.Start(ctx.Done()) -type SharedInformerFactory interface { - internalinterfaces.SharedInformerFactory - - // Start initializes all requested informers. They are handled in goroutines - // which run until the stop channel gets closed. - Start(stopCh <-chan struct{}) - - // Shutdown marks a factory as shutting down. At that point no new - // informers can be started anymore and Start will return without - // doing anything. - // - // In addition, Shutdown blocks until all goroutines have terminated. For that - // to happen, the close channel(s) that they were started with must be closed, - // either before Shutdown gets called or while it is waiting. - // - // Shutdown may be called multiple times, even concurrently. All such calls will - // block until all goroutines have terminated. - Shutdown() - - // WaitForCacheSync blocks until all started informers' caches were synced - // or the stop channel gets closed. - WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - - // ForResource gives generic access to a shared informer of the matching type. - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) - - // InformerFor returns the SharedIndexInformer for obj using an internal - // client. - InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer - - Alibabacloud() alibabacloud.Interface -} - -func (f *sharedInformerFactory) Alibabacloud() alibabacloud.Interface { - return alibabacloud.New(f, f.namespace, f.tweakListOptions) -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/generic.go b/ack-secret-manager-cli/client/informers/externalversions/generic.go deleted file mode 100644 index be067fe2..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/generic.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package externalversions - -import ( - "fmt" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - schema "k8s.io/apimachinery/pkg/runtime/schema" - cache "k8s.io/client-go/tools/cache" -) - -// GenericInformer is type of SharedIndexInformer which will locate and delegate to other -// sharedInformers based on type -type GenericInformer interface { - Informer() cache.SharedIndexInformer - Lister() cache.GenericLister -} - -type genericInformer struct { - informer cache.SharedIndexInformer - resource schema.GroupResource -} - -// Informer returns the SharedIndexInformer. -func (f *genericInformer) Informer() cache.SharedIndexInformer { - return f.informer -} - -// Lister returns the GenericLister. -func (f *genericInformer) Lister() cache.GenericLister { - return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) -} - -// ForResource gives generic access to a shared informer of the matching type -// TODO extend this to unknown resources with a client pool -func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { - switch resource { - // Group=alibabacloud.com, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("externalsecrets"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Alibabacloud().V1alpha1().ExternalSecrets().Informer()}, nil - case v1alpha1.SchemeGroupVersion.WithResource("secretstores"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Alibabacloud().V1alpha1().SecretStores().Informer()}, nil - - } - - return nil, fmt.Errorf("no informer found for %v", resource) -} diff --git a/ack-secret-manager-cli/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/ack-secret-manager-cli/client/informers/externalversions/internalinterfaces/factory_interfaces.go deleted file mode 100644 index b5feba69..00000000 --- a/ack-secret-manager-cli/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ /dev/null @@ -1,24 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package internalinterfaces - -import ( - time "time" - - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - cache "k8s.io/client-go/tools/cache" -) - -// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. -type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer - -// SharedInformerFactory a small interface to allow for adding an informer without an import cycle -type SharedInformerFactory interface { - Start(stopCh <-chan struct{}) - InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer -} - -// TweakListOptionsFunc is a function that transforms a v1.ListOptions. -type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/expansion_generated.go b/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/expansion_generated.go deleted file mode 100644 index fe6487bf..00000000 --- a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/expansion_generated.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -// ExternalSecretListerExpansion allows custom methods to be added to -// ExternalSecretLister. -type ExternalSecretListerExpansion interface{} - -// ExternalSecretNamespaceListerExpansion allows custom methods to be added to -// ExternalSecretNamespaceLister. -type ExternalSecretNamespaceListerExpansion interface{} - -// SecretStoreListerExpansion allows custom methods to be added to -// SecretStoreLister. -type SecretStoreListerExpansion interface{} - -// SecretStoreNamespaceListerExpansion allows custom methods to be added to -// SecretStoreNamespaceLister. -type SecretStoreNamespaceListerExpansion interface{} diff --git a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index 26a23e75..00000000 --- a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ExternalSecretLister helps list ExternalSecrets. -// All objects returned here must be treated as read-only. -type ExternalSecretLister interface { - // List lists all ExternalSecrets in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) - // ExternalSecrets returns an object that can list and get ExternalSecrets. - ExternalSecrets(namespace string) ExternalSecretNamespaceLister - ExternalSecretListerExpansion -} - -// externalSecretLister implements the ExternalSecretLister interface. -type externalSecretLister struct { - indexer cache.Indexer -} - -// NewExternalSecretLister returns a new ExternalSecretLister. -func NewExternalSecretLister(indexer cache.Indexer) ExternalSecretLister { - return &externalSecretLister{indexer: indexer} -} - -// List lists all ExternalSecrets in the indexer. -func (s *externalSecretLister) List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExternalSecret)) - }) - return ret, err -} - -// ExternalSecrets returns an object that can list and get ExternalSecrets. -func (s *externalSecretLister) ExternalSecrets(namespace string) ExternalSecretNamespaceLister { - return externalSecretNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// ExternalSecretNamespaceLister helps list and get ExternalSecrets. -// All objects returned here must be treated as read-only. -type ExternalSecretNamespaceLister interface { - // List lists all ExternalSecrets in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) - // Get retrieves the ExternalSecret from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.ExternalSecret, error) - ExternalSecretNamespaceListerExpansion -} - -// externalSecretNamespaceLister implements the ExternalSecretNamespaceLister -// interface. -type externalSecretNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ExternalSecrets in the indexer for a given namespace. -func (s externalSecretNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExternalSecret)) - }) - return ret, err -} - -// Get retrieves the ExternalSecret from the indexer for a given namespace and name. -func (s externalSecretNamespaceLister) Get(name string) (*v1alpha1.ExternalSecret, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("externalsecret"), name) - } - return obj.(*v1alpha1.ExternalSecret), nil -} diff --git a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index ca43e8bb..00000000 --- a/ack-secret-manager-cli/client/listers/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// SecretStoreLister helps list SecretStores. -// All objects returned here must be treated as read-only. -type SecretStoreLister interface { - // List lists all SecretStores in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) - // SecretStores returns an object that can list and get SecretStores. - SecretStores(namespace string) SecretStoreNamespaceLister - SecretStoreListerExpansion -} - -// secretStoreLister implements the SecretStoreLister interface. -type secretStoreLister struct { - indexer cache.Indexer -} - -// NewSecretStoreLister returns a new SecretStoreLister. -func NewSecretStoreLister(indexer cache.Indexer) SecretStoreLister { - return &secretStoreLister{indexer: indexer} -} - -// List lists all SecretStores in the indexer. -func (s *secretStoreLister) List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.SecretStore)) - }) - return ret, err -} - -// SecretStores returns an object that can list and get SecretStores. -func (s *secretStoreLister) SecretStores(namespace string) SecretStoreNamespaceLister { - return secretStoreNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// SecretStoreNamespaceLister helps list and get SecretStores. -// All objects returned here must be treated as read-only. -type SecretStoreNamespaceLister interface { - // List lists all SecretStores in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) - // Get retrieves the SecretStore from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.SecretStore, error) - SecretStoreNamespaceListerExpansion -} - -// secretStoreNamespaceLister implements the SecretStoreNamespaceLister -// interface. -type secretStoreNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all SecretStores in the indexer for a given namespace. -func (s secretStoreNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.SecretStore)) - }) - return ret, err -} - -// Get retrieves the SecretStore from the indexer for a given namespace and name. -func (s secretStoreNamespaceLister) Get(name string) (*v1alpha1.SecretStore, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("secretstore"), name) - } - return obj.(*v1alpha1.SecretStore), nil -} diff --git a/ack-secret-manager-cli/dependencymagnet/doc.go b/ack-secret-manager-cli/dependencymagnet/doc.go deleted file mode 100644 index d85e1479..00000000 --- a/ack-secret-manager-cli/dependencymagnet/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build tools -// +build tools - -// go mod won't pull in code that isn't depended upon, but we have some code we don't depend on from code that must be included -// for our build to work. -package dependencymagnet - -import ( - _ "k8s.io/code-generator" -) diff --git a/ack-secret-manager-cli/go.mod b/ack-secret-manager-cli/go.mod deleted file mode 100644 index dda5f40a..00000000 --- a/ack-secret-manager-cli/go.mod +++ /dev/null @@ -1,80 +0,0 @@ -module github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli - -go 1.19 - -require ( - github.com/charmbracelet/bubbles v0.16.1 - github.com/charmbracelet/bubbletea v0.24.2 - github.com/charmbracelet/lipgloss v0.9.1 - github.com/onsi/ginkgo v1.16.5 - github.com/onsi/gomega v1.28.0 - golang.org/x/net v0.17.0 - k8s.io/api v0.28.2 - k8s.io/apimachinery v0.28.2 - k8s.io/client-go v0.28.2 - k8s.io/code-generator v0.28.2 - sigs.k8s.io/controller-runtime v0.16.2 -) - -require ( - github.com/atotto/clipboard v0.1.4 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful/v3 v3.9.0 // indirect - github.com/evanphx/json-patch v5.6.0+incompatible // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fsnotify/fsnotify v1.6.0 // indirect - github.com/go-logr/logr v1.2.4 // indirect - github.com/go-openapi/jsonpointer v0.19.6 // indirect - github.com/go-openapi/jsonreference v0.20.2 // indirect - github.com/go-openapi/swag v0.22.3 // indirect - github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/protobuf v1.5.3 // indirect - github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect - github.com/google/gofuzz v1.2.0 // indirect - github.com/google/uuid v1.3.0 // indirect - github.com/imdario/mergo v0.3.6 // indirect - github.com/josharian/intern v1.0.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-isatty v0.0.18 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b // indirect - github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.15.2 // indirect - github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect - github.com/nxadm/tail v1.4.8 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.2.0 // indirect - github.com/sahilm/fuzzy v0.1.0 // indirect - github.com/spf13/pflag v1.0.5 // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.13.0 // indirect - golang.org/x/term v0.13.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect - golang.org/x/tools v0.12.0 // indirect - google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/inf.v0 v0.9.1 // indirect - gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect - k8s.io/apiextensions-apiserver v0.28.0 // indirect - k8s.io/gengo v0.0.0-20220902162205-c0856e24416d // indirect - k8s.io/klog/v2 v2.100.1 // indirect - k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect - k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect - sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect - sigs.k8s.io/yaml v1.3.0 // indirect -) diff --git a/ack-secret-manager-cli/go.sum b/ack-secret-manager-cli/go.sum deleted file mode 100644 index f021f4f6..00000000 --- a/ack-secret-manager-cli/go.sum +++ /dev/null @@ -1,277 +0,0 @@ -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= -github.com/charmbracelet/bubbles v0.16.1 h1:6uzpAAaT9ZqKssntbvZMlksWHruQLNxg49H5WdeuYSY= -github.com/charmbracelet/bubbles v0.16.1/go.mod h1:2QCp9LFlEsBQMvIYERr7Ww2H2bA7xen1idUDIzm/+Xc= -github.com/charmbracelet/bubbletea v0.24.2 h1:uaQIKx9Ai6Gdh5zpTbGiWpytMU+CfsPp06RaW2cx/SY= -github.com/charmbracelet/bubbletea v0.24.2/go.mod h1:XdrNrV4J8GiyshTtx3DNuYkR1FDaJmO3l2nejekbsgg= -github.com/charmbracelet/lipgloss v0.9.1 h1:PNyd3jvaJbg4jRHKWXnCj1akQm4rh8dbEzN1p/u1KWg= -github.com/charmbracelet/lipgloss v0.9.1/go.mod h1:1mPmG4cxScwUQALAAnacHaigiiHB9Pmr+v1VEawJl6I= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 h1:q2hJAaP1k2wIvVRd/hEHD7lacgqrCPS+k8g1MndzfWY= -github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/emicklei/go-restful/v3 v3.9.0 h1:XwGDlfxEnQZzuopoqxwSEllNcCOM9DhhFyhFIIGKwxE= -github.com/emicklei/go-restful/v3 v3.9.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= -github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U= -github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= -github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= -github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/zapr v1.2.4 h1:QHVo+6stLbfJmYGkQ7uGHUCu5hnAFAj6mDe6Ea0SeOo= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= -github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= -github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= -github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= -github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= -github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= -github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= -github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= -github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= -github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= -github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28= -github.com/imdario/mergo v0.3.6/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= -github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= -github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98= -github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b h1:1XF24mVaiu7u+CFywTdcDo2ie1pzzhwjt6RHqzpMU34= -github.com/muesli/ansi v0.0.0-20211018074035-2e021307bc4b/go.mod h1:fQuZ0gauxyBcmsdE3ZT4NasjaRdxmbCS0jRHsrWu3Ho= -github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= -github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= -github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= -github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= -github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= -github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= -github.com/onsi/ginkgo/v2 v2.12.0 h1:UIVDowFPwpg6yMUpPjGkYvf06K3RAiJXUhCxEwQVHRI= -github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= -github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.28.0 h1:i2rg/p9n/UqIDAMFUJ6qIUUMcsqOuUHgbpbu235Vr1c= -github.com/onsi/gomega v1.28.0/go.mod h1:A1H2JE76sI14WIP57LMKj7FVfCHx3g3BcZVjJG8bjX8= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/prometheus/client_golang v1.16.0 h1:yk/hx9hDbrGHovbci4BY+pRMfSuuat626eFsHb7tmT8= -github.com/prometheus/client_model v0.4.0 h1:5lQXD3cAg1OXBf4Wq03gTrXHeaV0TQvGfUooCfx1yqY= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/procfs v0.10.1 h1:kYK1Va/YMlutzCGazswoHKo//tZVlFpKYh+PymziUAg= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= -github.com/sahilm/fuzzy v0.1.0 h1:FzWGaw2Opqyu+794ZQ9SYifWv2EIXpwP4q8dY1kDAwI= -github.com/sahilm/fuzzy v0.1.0/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= -github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= -github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= -github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= -golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= -golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= -golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= -golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200505023115-26f46d2f7ef8/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.12.0 h1:YW6HUoUmYBpwSgyaGaZq1fHjrBjX1rlpZ54T6mu2kss= -golang.org/x/tools v0.12.0/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= -google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= -google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= -google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= -google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= -google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= -google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw= -k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg= -k8s.io/apiextensions-apiserver v0.28.0 h1:CszgmBL8CizEnj4sj7/PtLGey6Na3YgWyGCPONv7E9E= -k8s.io/apiextensions-apiserver v0.28.0/go.mod h1:uRdYiwIuu0SyqJKriKmqEN2jThIJPhVmOWETm8ud1VE= -k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ= -k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU= -k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY= -k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY= -k8s.io/code-generator v0.28.2 h1:u47guga1rCWLnEnffF09p+cqj8B20oHOLoQ1lb1HGtQ= -k8s.io/code-generator v0.28.2/go.mod h1:ueeSJZJ61NHBa0ccWLey6mwawum25vX61nRZ6WOzN9A= -k8s.io/component-base v0.28.1 h1:LA4AujMlK2mr0tZbQDZkjWbdhTV5bRyEyAFe0TJxlWg= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d h1:U9tB195lKdzwqicbJvyJeOXV7Klv+wNAWENRnXEGi08= -k8s.io/gengo v0.0.0-20220902162205-c0856e24416d/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= -k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg= -k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 h1:LyMgNKD2P8Wn1iAwQU5OhxCKlKJy0sHc+PcDwFB24dQ= -k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9/go.mod h1:wZK2AVp1uHCp4VamDVgBP2COHZjqD1T68Rf0CM3YjSM= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 h1:qY1Ad8PODbnymg2pRbkyMT/ylpTrCM8P2RJ0yroCyIk= -k8s.io/utils v0.0.0-20230406110748-d93618cff8a2/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/controller-runtime v0.16.2 h1:mwXAVuEk3EQf478PQwQ48zGOXvW27UJc8NHktQVuIPU= -sigs.k8s.io/controller-runtime v0.16.2/go.mod h1:vpMu3LpI5sYWtujJOa2uPK61nB5rbwlN7BAB8aSLvGU= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE= -sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E= -sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= diff --git a/ack-secret-manager-cli/hack/boilerplate.go.txt b/ack-secret-manager-cli/hack/boilerplate.go.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/ack-secret-manager-cli/hack/update-codegen.sh b/ack-secret-manager-cli/hack/update-codegen.sh deleted file mode 100755 index a5ad2553..00000000 --- a/ack-secret-manager-cli/hack/update-codegen.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/bash -e - -set -x - -realpath() { - [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" -} - -# set the passed in directory as a usable GOPATH -# that deepcopy-gen can operate in -ensure-temp-gopath() { - fake_gopath=$1 - - # set up symlink pointing to our repo root - fake_repopath=$fake_gopath/src/github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli - mkdir -p "$(dirname "${fake_repopath}")" - ln -s "$REPO_FULL_PATH" "${fake_repopath}" -} - -SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/.. -REPO_FULL_PATH=$(realpath ${SCRIPT_ROOT}) -cd ${REPO_FULL_PATH} - -CODEGEN_PKG=${CODEGEN_PKG:-$(cd ${SCRIPT_ROOT}; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../../../k8s.io/code-generator)} - -verify="${VERIFY:-}" - -valid_gopath=$(realpath $REPO_FULL_PATH/../../../..) -if [[ "$(realpath ${valid_gopath}/src/github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli)" == "${REPO_FULL_PATH}" ]]; then - temp_gopath=${valid_gopath} -else - TMP_DIR=$(mktemp -d -t ack-secret-manager-codegen.XXXX) - function finish { - chmod -R +w ${TMP_DIR} - # ok b/c we will symlink to the original repo - rm -r ${TMP_DIR} - } - trap finish EXIT - - ensure-temp-gopath ${TMP_DIR} - - temp_gopath=${TMP_DIR} -fi - -GOPATH="${temp_gopath}" GOFLAGS="" bash ${CODEGEN_PKG}/generate-groups.sh "client,informer,lister" \ - github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client \ - github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis \ - "alibabacloud:v1alpha1" \ - --go-header-file ${REPO_FULL_PATH}/hack/boilerplate.go.txt \ - ${verify} diff --git a/ack-secret-manager-cli/img/cross.gif b/ack-secret-manager-cli/img/cross.gif deleted file mode 100644 index e86d682a..00000000 Binary files a/ack-secret-manager-cli/img/cross.gif and /dev/null differ diff --git a/ack-secret-manager-cli/img/es.gif b/ack-secret-manager-cli/img/es.gif deleted file mode 100644 index 0d6946d5..00000000 Binary files a/ack-secret-manager-cli/img/es.gif and /dev/null differ diff --git a/ack-secret-manager-cli/img/ramrole.gif b/ack-secret-manager-cli/img/ramrole.gif deleted file mode 100644 index 704e8f15..00000000 Binary files a/ack-secret-manager-cli/img/ramrole.gif and /dev/null differ diff --git a/ack-secret-manager-cli/img/rrsa.gif b/ack-secret-manager-cli/img/rrsa.gif deleted file mode 100644 index 90750b37..00000000 Binary files a/ack-secret-manager-cli/img/rrsa.gif and /dev/null differ diff --git a/ack-secret-manager-cli/k8s/client.go b/ack-secret-manager-cli/k8s/client.go deleted file mode 100644 index 8eabea96..00000000 --- a/ack-secret-manager-cli/k8s/client.go +++ /dev/null @@ -1,273 +0,0 @@ -package k8s - -import ( - "context" - "fmt" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - aliababaclientset "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" -) - -var ( - k8sClient kubernetes.Interface - crdClient aliababaclientset.Interface -) - -func InitClient(filePath string) error { - config, err := clientcmd.BuildConfigFromFlags("", filePath) - if err != nil { - return err - } - crdClient, err = aliababaclientset.NewForConfig(config) - if err != nil { - return err - } - k8sClient, err = kubernetes.NewForConfig(config) - if err != nil { - return err - } - return nil -} - -func CreateSecretStoreByRRSA(name, namespace, provider, ramRole string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: &v1alpha1.KMSAuth{ - OIDCProviderARN: provider, - RAMRoleARN: ramRole, - }, - }, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateSecretStoreByAKSK(name, namespace, akName, akNamespace, akKey, skName, skNamespace, skKey, ramRoleArn, roleSession string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: &v1alpha1.KMSAuth{ - AccessKey: &v1alpha1.SecretRef{ - Name: akName, - Namespace: akNamespace, - Key: akKey, - }, - AccessKeySecret: &v1alpha1.SecretRef{ - Name: skName, - Namespace: skNamespace, - Key: skKey, - }, - }, - }, - }, - } - if ramRoleArn != "" { - secretStore.Spec.KMS.KMS.RAMRoleARN = ramRoleArn - secretStore.Spec.KMS.KMS.RAMRoleSessionName = roleSession - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CheckSecretKeyExist(name, namespace, key string) (bool, error) { - ctx := context.Background() - secret, err := k8sClient.CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return false, nil - } - return false, err - } - _, ok := secret.Data[key] - if ok { - return true, nil - } - return false, nil -} - -func CreateOrUpdateSecret(name, namespace, key, value string) error { - ctx := context.Background() - secret, err := k8sClient.CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - newSecret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Data: map[string][]byte{ - key: []byte(value), - }, - } - _, err = k8sClient.CoreV1().Secrets(namespace).Create(ctx, newSecret, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil - } - return err - } - secret.Data[key] = []byte(value) - _, err = k8sClient.CoreV1().Secrets(namespace).Update(ctx, secret, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateEmptySecretStore(name, namespace string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: nil, - }, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateDKMSSecretStore(name, namespace, ckName, ckNamespace, ckKey, pwName, pwNamespace, pwKey, cert, endpoint string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - DedicatedKMS: &v1alpha1.DedicatedKMSAuth{ - Protocol: "https", - Endpoint: endpoint, - ClientKeyContent: &v1alpha1.SecretRef{ - Name: ckName, - Namespace: ckNamespace, - Key: ckKey, - }, - Password: &v1alpha1.SecretRef{ - Name: pwName, - Namespace: pwNamespace, - Key: pwKey, - }, - }, - }, - }, - } - if cert == "" { - secretStore.Spec.KMS.DedicatedKMS.IgnoreSSL = true - } else { - secretStore.Spec.KMS.DedicatedKMS.IgnoreSSL = false - secretStore.Spec.KMS.DedicatedKMS.CA = cert - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func ListSecretStore(limit int64, continueToken string) ([]v1alpha1.SecretStore, string, error) { - ctx := context.Background() - listOption := metav1.ListOptions{ - Limit: limit, - Continue: continueToken, - } - secretstores, err := crdClient.AlibabacloudV1alpha1().SecretStores("").List(ctx, listOption) - if err != nil { - return nil, continueToken, err - } - return secretstores.Items, secretstores.Continue, nil -} - -func GetSecretStoreAndUpdate(name, namespace, remoteRoleArn, remoteRoleSession string) error { - ctx := context.Background() - secretstore, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return err - } - if secretstore.Spec.KMS.DedicatedKMS != nil { - return fmt.Errorf("dkms SecretStore %s/%s does not support cross-account", namespace, name) - } - if secretstore.Spec.KMS.KMS == nil { - secretstore.Spec.KMS.KMS = &v1alpha1.KMSAuth{ - RemoteRAMRoleSessionName: remoteRoleSession, - RemoteRAMRoleARN: remoteRoleArn, - } - } else { - secretstore.Spec.KMS.KMS.RemoteRAMRoleARN = remoteRoleArn - secretstore.Spec.KMS.KMS.RemoteRAMRoleSessionName = remoteRoleSession - } - _, err = crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Update(ctx, secretstore, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateExternalSecret(data []v1alpha1.DataSource, dataProcess []v1alpha1.DataProcess, name, namespace, secretType string) error { - ctx := context.Background() - es := &v1alpha1.ExternalSecret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.ExternalSecretSpec{ - Provider: "kms", - Data: data, - Type: secretType, - DataProcess: dataProcess, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().ExternalSecrets(namespace).Create(ctx, es, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} diff --git a/ack-secret-manager-cli/main.go b/ack-secret-manager-cli/main.go deleted file mode 100644 index ccd2b371..00000000 --- a/ack-secret-manager-cli/main.go +++ /dev/null @@ -1,52 +0,0 @@ -package main - -import ( - "flag" - "fmt" - "os" - - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/externalsecret" - _ "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/externalsecret" - _ "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - _ "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/init" - _ "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/secretstore/input" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/secretstore/list" - _ "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/secretstore/list" -) - -var ( - kubeConfigPath string - defaultPath string - helpInfo bool -) - -func main() { - //ctx := context.Background() - homeDir, err := os.UserHomeDir() - if err == nil { - defaultPath = fmt.Sprintf("%s/%s", homeDir, ".kube/config") - } - flag.StringVar(&kubeConfigPath, "kubeconfig", defaultPath, "kubeconfig path") - flag.BoolVar(&helpInfo, "help", false, "help info") - flag.Parse() - if helpInfo { - flag.Usage() - return - } - err = k8s.InitClient(kubeConfigPath) - if err != nil { - panic(err) - } - model.InitModelMap["cross-choose"] = list.InitCrossModel() - model.InitModelMap["secret-store-ref"] = externalsecret.InitSecretStoreRefModel() - m := model.InitModelMap["crd"] - if _, err := tea.NewProgram(m).Run(); err != nil { - fmt.Println("Error running program:", err) - os.Exit(1) - } - return -} diff --git a/ack-secret-manager-cli/model/externalsecret/basic.go b/ack-secret-manager-cli/model/externalsecret/basic.go deleted file mode 100644 index 32397c6c..00000000 --- a/ack-secret-manager-cli/model/externalsecret/basic.go +++ /dev/null @@ -1,200 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - info2 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type BasicESModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - isProcess bool -} - -func init() { - m := initialBasicESModel() - model.InitModelMap["basic"] = m -} - -func initialBasicESModel() *BasicESModel { - m := &BasicESModel{ - inputs: make([]textinput.Model, 4), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "KMS credential Name > " - t.Placeholder = "KMS credential name" - case 1: - t.Prompt = "KMS Secret Key > " - t.Placeholder = "corresponding key of KMS credentials in k8s secret" - case 2: - t.Prompt = "Version Stage > " - t.Placeholder = "Version Stage" - case 3: - t.Prompt = "Version ID > " - t.Placeholder = "Version ID" - } - m.inputs[i] = t - } - - return m -} - -func (m *BasicESModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *BasicESModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *BasicESModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *BasicESModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the basic externalsecret data configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *BasicESModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *BasicESModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info2.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("KMS credential name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.isProcess { - processIndex := len(process) - 1 - if process[processIndex].Extract == nil { - process[processIndex].Extract = &v1alpha1.DataSource{} - } - process[processIndex].Extract.Name = m.inputs[1].Value() - process[processIndex].Extract.Key = m.inputs[0].Value() - process[processIndex].Extract.VersionStage = m.inputs[2].Value() - process[processIndex].Extract.VersionId = m.inputs[3].Value() - next := model.InitModelMap["replace"] - next.SetPreModel(m) - return next, nil - } else { - dataIndex := len(data) - 1 - data[dataIndex].Name = m.inputs[1].Value() - data[dataIndex].Key = m.inputs[0].Value() - data[dataIndex].VersionStage = m.inputs[2].Value() - data[dataIndex].VersionId = m.inputs[3].Value() - next := model.InitModelMap["jmes"] - next.SetPreModel(m) - return next, nil - } - } - return m, nil -} - -func (m *BasicESModel) SetType(isProcess bool) { - m.isProcess = isProcess -} diff --git a/ack-secret-manager-cli/model/externalsecret/continue.go b/ack-secret-manager-cli/model/externalsecret/continue.go deleted file mode 100644 index 48888ac6..00000000 --- a/ack-secret-manager-cli/model/externalsecret/continue.go +++ /dev/null @@ -1,104 +0,0 @@ -package externalsecret - -import ( - "fmt" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ContinueModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func init() { - m := initContinueModel() - model.InitModelMap["continue"] = m -} -func initContinueModel() *ContinueModel { - items := []list.Item{ - item("Yes"), - item("No"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &ContinueModel{ - list: l, - } -} - -func (m *ContinueModel) Init() tea.Cmd { - return nil -} - -func (m *ContinueModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *ContinueModel) View() string { - return "\n" + m.list.View() -} - -func (m *ContinueModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ContinueModel) SetTitle(title string) { - m.list.Title = title -} - -func (m *ContinueModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.choice == "Yes" { - next := model.InitModelMap["data"] - next.SetPreModel(m) - return next, nil - } else { - err := k8s.CreateExternalSecret(data, process, externalSecretName, externalSecretNamespace, secretType) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(nil) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create externalsecret %s/%s success", externalSecretNamespace, externalSecretName)) - eModel.SetPreModel(nil) - return eModel, nil - } -} diff --git a/ack-secret-manager-cli/model/externalsecret/css.go b/ack-secret-manager-cli/model/externalsecret/css.go deleted file mode 100644 index 113d6b10..00000000 --- a/ack-secret-manager-cli/model/externalsecret/css.go +++ /dev/null @@ -1,70 +0,0 @@ -package externalsecret - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) - - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - inputTitleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - focusedContinueButton = focusedStyle.Copy().Render("[ Continue ]") - focusedSkipButton = focusedStyle.Copy().Render("[ Skip ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) - continueButton = fmt.Sprintf("%s", noStyle.Render("[ Continue ]")) - skipButton = fmt.Sprintf("%s", noStyle.Render("[ Skip ]")) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/model/externalsecret/datatype.go b/ack-secret-manager-cli/model/externalsecret/datatype.go deleted file mode 100644 index a9183c74..00000000 --- a/ack-secret-manager-cli/model/externalsecret/datatype.go +++ /dev/null @@ -1,96 +0,0 @@ -package externalsecret - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type DataModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func init() { - m := initDataModel() - model.InitModelMap["data"] = m -} -func initDataModel() *DataModel { - items := []list.Item{ - item("Data"), - item("DataProcess"), - } - items = append(items, item("\n[Previous]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select data source type" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &DataModel{ - list: l, - } -} - -func (m *DataModel) Init() tea.Cmd { - return nil -} - -func (m *DataModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *DataModel) View() string { - return "\n" + m.list.View() -} - -func (m *DataModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *DataModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - return m.preModel, nil - } - next := model.InitModelMap["basic"] - bModel, ok := next.(*BasicESModel) - if !ok { - return m, nil - } - if m.choice == "Data" { - data = append(data, v1alpha1.DataSource{}) - bModel.SetType(false) - } else { - process = append(process, v1alpha1.DataProcess{}) - bModel.SetType(true) - } - bModel.SetPreModel(m) - return bModel, nil -} diff --git a/ack-secret-manager-cli/model/externalsecret/externalsecret.go b/ack-secret-manager-cli/model/externalsecret/externalsecret.go deleted file mode 100644 index a27ba496..00000000 --- a/ack-secret-manager-cli/model/externalsecret/externalsecret.go +++ /dev/null @@ -1,185 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ExternalSecretModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialExternalSecretModel() - model.InitModelMap["external"] = m -} - -func initialExternalSecretModel() *ExternalSecretModel { - m := &ExternalSecretModel{ - inputs: make([]textinput.Model, 3), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "External Secret Name > " - t.Placeholder = "k8s resource name" - case 1: - t.Prompt = "External Secret Namespace > " - t.Placeholder = "k8s resource name" - case 2: - t.Prompt = "Secret Type > " - t.Placeholder = "Opaque" - } - m.inputs[i] = t - } - - return m -} - -func (m *ExternalSecretModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ExternalSecretModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ExternalSecretModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ExternalSecretModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the basic externalsecret data configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *ExternalSecretModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ExternalSecretModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("external secret name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("external secret namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("secret type cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - externalSecretName = m.inputs[0].Value() - externalSecretNamespace = m.inputs[1].Value() - secretType = m.inputs[2].Value() - next := model.InitModelMap["data"] - next.SetPreModel(m) - return next, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/externalsecret/jmes.go b/ack-secret-manager-cli/model/externalsecret/jmes.go deleted file mode 100644 index 294079b1..00000000 --- a/ack-secret-manager-cli/model/externalsecret/jmes.go +++ /dev/null @@ -1,209 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type JMESModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialJMESModelModel() - model.InitModelMap["jmes"] = m -} - -func initialJMESModelModel() *JMESModel { - m := &JMESModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "Path > " - t.Placeholder = "position in json string" - case 1: - t.Prompt = "ObjectAlias > " - t.Placeholder = "the key in k8s secret" - } - m.inputs[i] = t - } - - return m -} - -func (m *JMESModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *JMESModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+2 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 2 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *JMESModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *JMESModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the jmes configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - continueB := &continueButton - if m.focusIndex == len(m.inputs) { - continueB = &focusedContinueButton - } - button := &blurredButton - if m.focusIndex == len(m.inputs)+1 { - button = &focusedButton - } - skip := &skipButton - if m.focusIndex == len(m.inputs)+2 { - skip = &focusedSkipButton - } - fmt.Fprintf(&b, "\n\n%s ", *continueB) - fmt.Fprintf(&b, "%s ", *button) - fmt.Fprintf(&b, "%s\n\n ", *skip) - return b.String() -} - -func (m *JMESModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *JMESModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.focusIndex == len(m.inputs) || m.focusIndex == len(m.inputs)+1 { - if m.inputs[0].Value() == "" { - eModel.SetInfo("json path cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo("json objectAlias cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - dataIndex := len(data) - 1 - if data[dataIndex].JMESPath == nil { - data[dataIndex].JMESPath = make([]v1alpha1.JMESPathObject, 0) - } - data[dataIndex].JMESPath = append(data[dataIndex].JMESPath, v1alpha1.JMESPathObject{ - Path: m.inputs[0].Value(), - ObjectAlias: m.inputs[1].Value(), - }) - if m.focusIndex == len(m.inputs)+1 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(false) - return sModel, nil - } else { - for i, input := range m.inputs { - input.Reset() - m.inputs[i] = input - } - } - } - if m.focusIndex == len(m.inputs)+2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(false) - return sModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/externalsecret/replace.go b/ack-secret-manager-cli/model/externalsecret/replace.go deleted file mode 100644 index c364c3eb..00000000 --- a/ack-secret-manager-cli/model/externalsecret/replace.go +++ /dev/null @@ -1,211 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ReplaceModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialReplaceModelModel() - model.InitModelMap["replace"] = m -} - -func initialReplaceModelModel() *ReplaceModel { - m := &ReplaceModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "Source > " - t.Placeholder = "the string that needs to be replaced (supports regular expressions)" - case 1: - t.Prompt = "Target > " - t.Placeholder = "target string when replacing" - } - m.inputs[i] = t - } - - return m -} - -func (m *ReplaceModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ReplaceModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+2 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 2 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ReplaceModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ReplaceModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the replace configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - continueB := &continueButton - if m.focusIndex == len(m.inputs) { - continueB = &focusedContinueButton - } - button := &blurredButton - if m.focusIndex == len(m.inputs)+1 { - button = &focusedButton - } - skip := &skipButton - if m.focusIndex == len(m.inputs)+2 { - skip = &focusedSkipButton - } - fmt.Fprintf(&b, "\n\n%s ", *continueB) - fmt.Fprintf(&b, "%s ", *button) - fmt.Fprintf(&b, "%s\n\n ", *skip) - - return b.String() -} - -func (m *ReplaceModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ReplaceModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.focusIndex == len(m.inputs) || m.focusIndex == len(m.inputs)+1 { - if m.inputs[0].Value() == "" { - eModel.SetInfo("source string cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo("target string cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - processIndex := len(process) - 1 - if process[processIndex].ReplaceKey == nil { - process[processIndex].ReplaceKey = make([]v1alpha1.ReplaceRule, 0) - } - process[processIndex].ReplaceKey = append(process[processIndex].ReplaceKey, v1alpha1.ReplaceRule{ - Source: m.inputs[0].Value(), - Target: m.inputs[1].Value(), - }) - if m.focusIndex == len(m.inputs)+1 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(true) - return sModel, nil - } else { - for i, input := range m.inputs { - input.Reset() - m.inputs[i] = input - } - } - return m, nil - } - if m.focusIndex == len(m.inputs)+2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(true) - return sModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/externalsecret/secretstoreref.go b/ack-secret-manager-cli/model/externalsecret/secretstoreref.go deleted file mode 100644 index 4e7e79fe..00000000 --- a/ack-secret-manager-cli/model/externalsecret/secretstoreref.go +++ /dev/null @@ -1,150 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type SecretStoreRefModel struct { - list list.Model - choice string - quitting bool - preModel model.Model - continueToken string - isProcess bool -} - -const ( - limit = 5 -) - -func InitSecretStoreRefModel() *SecretStoreRefModel { - secretStores, continueToken, err := k8s.ListSecretStore(limit, "") - if err != nil { - panic(err) - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("[Previous]")) - items = append(items, item("[Skip]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select an existing SecretStore for SecretStoreRef configuration" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &SecretStoreRefModel{ - list: l, - continueToken: continueToken, - } -} - -func (m *SecretStoreRefModel) Init() tea.Cmd { - return nil -} - -func (m *SecretStoreRefModel) SetType(isProcess bool) { - m.isProcess = isProcess -} -func (m *SecretStoreRefModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *SecretStoreRefModel) View() string { - return "\n" + m.list.View() -} - -func (m *SecretStoreRefModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *SecretStoreRefModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - return m.preModel, nil - } - if m.choice == "[Skip]" { - next := model.InitModelMap["continue"] - cModel, ok := next.(*ContinueModel) - if !ok { - return m, nil - } - cModel.SetTitle("Do you want to continue adding data?") - cModel.SetPreModel(m) - return cModel, nil - } - if m.choice == "Next Page" { - secretStores, continueToken, err := k8s.ListSecretStore(limit, m.continueToken) - if err != nil { - return m, nil - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("[Previous]")) - m.list.SetItems(items) - m.continueToken = continueToken - return m, nil - } - names := strings.Split(strings.Split(m.choice, " ")[1], "/") - if m.isProcess { - processIndex := len(process) - 1 - process[processIndex].Extract.SecretStoreRef = &v1alpha1.SecretStoreRef{ - Name: names[1], - Namespace: names[0], - } - } else { - dataIndex := len(data) - 1 - data[dataIndex].SecretStoreRef = &v1alpha1.SecretStoreRef{ - Name: names[1], - Namespace: names[0], - } - } - next := model.InitModelMap["continue"] - cModel, ok := next.(*ContinueModel) - if !ok { - return m, nil - } - cModel.SetTitle("Do you want to continue adding data?") - cModel.SetPreModel(m) - return cModel, nil -} diff --git a/ack-secret-manager-cli/model/externalsecret/sum.go b/ack-secret-manager-cli/model/externalsecret/sum.go deleted file mode 100644 index 50c43146..00000000 --- a/ack-secret-manager-cli/model/externalsecret/sum.go +++ /dev/null @@ -1,11 +0,0 @@ -package externalsecret - -import "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - -var ( - data = make([]v1alpha1.DataSource, 0) - process = make([]v1alpha1.DataProcess, 0) - externalSecretName string - externalSecretNamespace string - secretType string -) diff --git a/ack-secret-manager-cli/model/info/css.go b/ack-secret-manager-cli/model/info/css.go deleted file mode 100644 index d9da8a53..00000000 --- a/ack-secret-manager-cli/model/info/css.go +++ /dev/null @@ -1,20 +0,0 @@ -package info - -import ( - "fmt" - - "github.com/charmbracelet/lipgloss" -) - -var ( - titleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(2) - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) -) diff --git a/ack-secret-manager-cli/model/info/info.go b/ack-secret-manager-cli/model/info/info.go deleted file mode 100644 index 764cb0fc..00000000 --- a/ack-secret-manager-cli/model/info/info.go +++ /dev/null @@ -1,64 +0,0 @@ -package info - -import ( - "strings" - - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type InfoModel struct { - info string - preModel model.Model -} - -func init() { - m := initialModel() - model.InitModelMap["info"] = m -} - -func initialModel() *InfoModel { - m := &InfoModel{} - return m -} - -func (m *InfoModel) SetInfo(info string) { - m.info = info -} - -func (m *InfoModel) Init() tea.Cmd { - return nil -} - -func (m *InfoModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - return m.Next() - } - } - return m, nil -} - -func (m *InfoModel) View() string { - var b strings.Builder - b.WriteString(titleStyle.Render(m.info) + "\n") - b.WriteString(helpStyle.Render("Press \"Enter\" to continue")) - return b.String() -} - -func (m *InfoModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *InfoModel) Next() (model.Model, tea.Cmd) { - if m.preModel == nil { - return m, tea.Quit - } - return m.preModel, nil -} diff --git a/ack-secret-manager-cli/model/info/secret.go b/ack-secret-manager-cli/model/info/secret.go deleted file mode 100644 index beeaa4ff..00000000 --- a/ack-secret-manager-cli/model/info/secret.go +++ /dev/null @@ -1,199 +0,0 @@ -package info - -import ( - "fmt" - "os" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type SecretModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - secretName string - secretNamespace string - secretKey string - needLoad bool -} - -func init() { - m := initialSecretModel() - model.InitModelMap["secret"] = m -} - -func initialSecretModel() *SecretModel { - m := &SecretModel{ - inputs: make([]textinput.Model, 1), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - //t.Prompt = "OIDC Provider Arn > " - //t.Placeholder = OidcProviderARNExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.EchoMode = textinput.EchoPassword - t.EchoCharacter = '•' - } - - m.inputs[i] = t - } - - return m -} - -func (m *SecretModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *SecretModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *SecretModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *SecretModel) View() string { - var b strings.Builder - b.WriteString(titleStyle.Render("The corresponding secret does not exist in the cluster, a new secret will be created, please fill in a new value") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *SecretModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *SecretModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("%v cannot be empty", m.inputs[0].Prompt)) - eModel.SetPreModel(m) - return eModel, nil - } - var value string - value = m.inputs[0].Value() - if m.needLoad { - str, err := os.ReadFile(value) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - value = string(str) - } - err := k8s.CreateOrUpdateSecret(m.secretName, m.secretNamespace, m.secretKey, value) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create secret key %s/%s/%s success", m.secretNamespace, m.secretName, m.secretKey)) - eModel.SetPreModel(m.preModel) - m.inputs[0].Reset() - return eModel, nil - } - return m, nil -} - -func (m *SecretModel) SetInfo(info, name, namespace, key string, load bool) { - m.inputs[0].Prompt = info - m.secretNamespace = namespace - m.secretName = name - m.secretKey = key - m.needLoad = load -} diff --git a/ack-secret-manager-cli/model/init/crd.go b/ack-secret-manager-cli/model/init/crd.go deleted file mode 100644 index df1d92b9..00000000 --- a/ack-secret-manager-cli/model/init/crd.go +++ /dev/null @@ -1,95 +0,0 @@ -package list - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -func init() { - crdModel := InitCRDModel() - model.InitModelMap["crd"] = crdModel -} - -type CrdModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func InitCRDModel() *CrdModel { - items := []list.Item{ - item("SecretStore"), - item("ExternalSecret"), - item("\n[Exit]"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select the CRD you want to create" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &CrdModel{ - list: l, - } -} - -func (m *CrdModel) Init() tea.Cmd { - return nil -} - -func (m *CrdModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *CrdModel) View() string { - return "\n" + m.list.View() -} - -func (m *CrdModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrdModel) Next() (model.Model, tea.Cmd) { - var next model.Model - if m.choice == "SecretStore" { - next = model.InitModelMap["authentication"] - } else if m.choice == "ExternalSecret" { - next = model.InitModelMap["external"] - } else { - return m, tea.Quit - } - next.SetPreModel(m) - return next, nil -} - -//m := InitCRDModel() -// if _, err := tea.NewProgram(m).Run(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } diff --git a/ack-secret-manager-cli/model/init/css.go b/ack-secret-manager-cli/model/init/css.go deleted file mode 100644 index d1eb434f..00000000 --- a/ack-secret-manager-cli/model/init/css.go +++ /dev/null @@ -1,56 +0,0 @@ -package list - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/model/model.go b/ack-secret-manager-cli/model/model.go deleted file mode 100644 index 1dbc6b60..00000000 --- a/ack-secret-manager-cli/model/model.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -import tea "github.com/charmbracelet/bubbletea" - -type Model interface { - // bubbletea - Init() tea.Cmd - Update(msg tea.Msg) (tea.Model, tea.Cmd) - View() string - - Next() (Model, tea.Cmd) - SetPreModel(model Model) -} - -var InitModelMap = make(map[string]Model) diff --git a/ack-secret-manager-cli/model/secretstore/input/ak.go b/ack-secret-manager-cli/model/secretstore/input/ak.go deleted file mode 100644 index 7c1dd9ab..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/ak.go +++ /dev/null @@ -1,263 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type AKModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialAKModel() - model.InitModelMap["ak"] = m -} - -func initialAKModel() *AKModel { - m := &AKModel{ - inputs: make([]textinput.Model, 8), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "AK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key" - case 1: - t.Prompt = "AK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key" - case 2: - t.Prompt = "AK SecretRef key > " - t.Placeholder = "the key of the secret that stores the access key" - case 3: - t.Prompt = "SK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key secret" - case 4: - t.Prompt = "SK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key secret" - case 5: - t.Prompt = "SK SecretRef key > " - t.Placeholder = "the key of the secret that stores the access key secret" - case 6: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 7: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - } - m.inputs[i] = t - } - - return m -} - -func (m *AKModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *AKModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *AKModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *AKModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ak configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *AKModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *AKModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[6].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key > ", m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key Secret > ", m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateSecretStoreByAKSK(m.inputs[6].Value(), m.inputs[7].Value(), m.inputs[0].Value(), - m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), - m.inputs[4].Value(), m.inputs[5].Value(), "", "") - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[7].Value(), m.inputs[6].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/input/cross.go b/ack-secret-manager-cli/model/secretstore/input/cross.go deleted file mode 100644 index c81b2965..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/cross.go +++ /dev/null @@ -1,189 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -type CrossModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - name string - namespace string -} - -func init() { - m := initialCrossModel() - model.InitModelMap["cross"] = m -} - -func initialCrossModel() *CrossModel { - m := &CrossModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Prompt = "Remote RAM Role Arn > " - t.Placeholder = RamRoleArnExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - case 1: - t.Prompt = "Remote Role Session Name > " - t.Placeholder = "role session name" - } - m.inputs[i] = t - } - - return m -} - -func (m *CrossModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *CrossModel) SetInfo(name, namespace string) { - m.name = name - m.namespace = namespace -} -func (m *CrossModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *CrossModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *CrossModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the cross-account configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *CrossModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrossModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - nextModel := model.InitModelMap["info"] - eModel, ok := nextModel.(*info.InfoModel) - if !ok { - return m, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[0].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("remote role session name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.GetSecretStoreAndUpdate(m.name, m.namespace, m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("update SecretStore %s/%s success", m.namespace, m.name)) - eModel.SetPreModel(nil) - return eModel, nil - } - - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/input/css.go b/ack-secret-manager-cli/model/secretstore/input/css.go deleted file mode 100644 index a2c2391d..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/css.go +++ /dev/null @@ -1,19 +0,0 @@ -package input - -import ( - "fmt" - - "github.com/charmbracelet/lipgloss" -) - -var ( - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - titleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) -) diff --git a/ack-secret-manager-cli/model/secretstore/input/dkms.go b/ack-secret-manager-cli/model/secretstore/input/dkms.go deleted file mode 100644 index ad264ba1..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/dkms.go +++ /dev/null @@ -1,275 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type DKMSModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialDKMSModel() - model.InitModelMap["dkms"] = m -} - -func initialDKMSModel() *DKMSModel { - m := &DKMSModel{ - inputs: make([]textinput.Model, 10), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "DKMS InstanceID > " - t.Placeholder = "kst-xxxxxxxxxxxxxxxxxxxxx" - case 1: - t.Prompt = "ClientKey SecretRef Name > " - t.Placeholder = "the name of the secret that stores the client key" - case 2: - t.Prompt = "ClientKey SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the client key" - case 3: - t.Prompt = "ClientKey SecretRef key > " - t.Placeholder = "the key of the secret that stores the client key" - case 4: - t.Prompt = "Password SecretRef Name > " - t.Placeholder = "the name of the secret that stores the password" - case 5: - t.Prompt = "Password SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the password" - case 6: - t.Prompt = "Password SecretRef key > " - t.Placeholder = "the key of the secret that stores the password" - case 7: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 8: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - case 9: - t.Prompt = "CA Cert > " - t.Placeholder = "CA Cert Content(optional, base64 encoding)" - t.CharLimit = 10000 - } - - m.inputs[i] = t - } - return m -} - -func (m *DKMSModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *DKMSModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *DKMSModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *DKMSModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ak configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *DKMSModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *DKMSModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("DKMS InstanceID cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[6].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[8].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Client Key File Path > ", m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), true) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Password > ", m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateDKMSSecretStore(m.inputs[7].Value(), m.inputs[8].Value(), m.inputs[1].Value(), - m.inputs[2].Value(), m.inputs[3].Value(), m.inputs[4].Value(), - m.inputs[5].Value(), m.inputs[6].Value(), m.inputs[9].Value(), m.inputs[0].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[8].Value(), m.inputs[7].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/input/ecs.go b/ack-secret-manager-cli/model/secretstore/input/ecs.go deleted file mode 100644 index ce3f32e2..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/ecs.go +++ /dev/null @@ -1,181 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ECSModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialECSModel() - model.InitModelMap["ecs"] = m -} - -func initialECSModel() *ECSModel { - m := &ECSModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 1: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource namespace" - } - m.inputs[i] = t - } - - return m -} - -func (m *ECSModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ECSModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ECSModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ECSModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ecs ram role configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *ECSModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ECSModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.CreateEmptySecretStore(m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[1].Value(), m.inputs[0].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/input/ramrole.go b/ack-secret-manager-cli/model/secretstore/input/ramrole.go deleted file mode 100644 index f3acd0aa..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/ramrole.go +++ /dev/null @@ -1,281 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - info2 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -type RoleModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialRAMRoleModel() - model.InitModelMap["role"] = m -} - -func initialRAMRoleModel() *RoleModel { - m := &RoleModel{ - inputs: make([]textinput.Model, 10), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "AK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key" - case 1: - t.Prompt = "AK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key" - case 2: - t.Prompt = "AK SecretRef Key > " - t.Placeholder = "the key of the secret key that stores the access key" - case 3: - t.Prompt = "SK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key secret" - case 4: - t.Prompt = "SK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key secret" - case 5: - t.Prompt = "SK SecretRef Key > " - t.Placeholder = "the key of the secret that stores the access key secret" - case 6: - t.Prompt = "RAM Role Arn > " - t.Placeholder = RamRoleArnExample - case 7: - t.Prompt = "Role Session Name > " - t.Placeholder = "role session name" - case 8: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 9: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - } - m.inputs[i] = t - } - - return m -} - -func (m *RoleModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *RoleModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *RoleModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *RoleModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ram role configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *RoleModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *RoleModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info2.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[6].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("role session name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[8].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - - if m.inputs[9].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info2.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key > ", m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info2.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key Secret > ", m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateSecretStoreByAKSK(m.inputs[8].Value(), m.inputs[9].Value(), m.inputs[0].Value(), - m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), - m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value(), m.inputs[7].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[9].Value(), m.inputs[8].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/input/rrsa.go b/ack-secret-manager-cli/model/secretstore/input/rrsa.go deleted file mode 100644 index 51a2716d..00000000 --- a/ack-secret-manager-cli/model/secretstore/input/rrsa.go +++ /dev/null @@ -1,211 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -const ( - OidcProviderARNRegex = "acs:ram::.*:oidc-provider/ack-rrsa-.*" - RamRoleArnRegex = "acs:ram::.*:role/.*" - RamRoleArnExample = "acs:ram::{accountID}:role/{roleName}" - OidcProviderARNExample = "acs:ram::{accountID}:oidc-provider/ack-rrsa-{cluster-id}" -) - -type RRSAModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialRRSAModel() - model.InitModelMap["rrsa"] = m -} - -func initialRRSAModel() *RRSAModel { - m := &RRSAModel{ - inputs: make([]textinput.Model, 4), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Prompt = "OIDC Provider Arn > " - t.Placeholder = OidcProviderARNExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - case 1: - t.Prompt = "RAM Role Arn > " - t.Placeholder = RamRoleArnExample - case 2: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - //t.EchoMode = textinput.EchoPassword - //t.EchoCharacter = '•' - case 3: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - //t.EchoMode = textinput.EchoPassword - //t.EchoCharacter = '•' - } - - m.inputs[i] = t - } - - return m -} - -func (m *RRSAModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *RRSAModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *RRSAModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *RRSAModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the rrsa configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *RRSAModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *RRSAModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - nextModel := model.InitModelMap["info"] - eModel, ok := nextModel.(*info.InfoModel) - if !ok { - return m, nil - } - if !utils.IsMatchRegex(OidcProviderARNRegex, m.inputs[0].Value()) { - eModel.SetInfo(fmt.Sprintf("oidc provider arn fmt error, must be %v", OidcProviderARNExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[1].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.CreateSecretStoreByRRSA(m.inputs[2].Value(), m.inputs[3].Value(), m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[2].Value(), m.inputs[3].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - - return m, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/list/authentication.go b/ack-secret-manager-cli/model/secretstore/list/authentication.go deleted file mode 100644 index eb773871..00000000 --- a/ack-secret-manager-cli/model/secretstore/list/authentication.go +++ /dev/null @@ -1,103 +0,0 @@ -package list - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -func init() { - authenticationModel := InitAuthenticationModel() - model.InitModelMap["authentication"] = authenticationModel -} - -type AuthenticationModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func InitAuthenticationModel() *AuthenticationModel { - items := []list.Item{ - item("RRSA"), - item("RAM Role"), - item("AK"), - item("ClientKey"), - item("ECS RAM Role"), - item("Cross-account synchronization"), - item("\n[ Previous ]"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please choose a KMS (Key Management Service) authentication type" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &AuthenticationModel{ - list: l, - } -} - -func (m *AuthenticationModel) Init() tea.Cmd { - return nil -} - -func (m *AuthenticationModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *AuthenticationModel) View() string { - return "\n" + m.list.View() -} - -func (m *AuthenticationModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *AuthenticationModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - return m.preModel, nil - } - var next model.Model - switch m.choice { - case "RRSA": - next = model.InitModelMap["rrsa"] - case "AK": - next = model.InitModelMap["ak"] - case "RAM Role": - next = model.InitModelMap["role"] - case "ECS RAM Role": - next = model.InitModelMap["ecs"] - case "ClientKey": - next = model.InitModelMap["dkms"] - case "Cross-account synchronization": - next = model.InitModelMap["cross-choose"] - } - next.SetPreModel(m) - return next, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/list/cross.go b/ack-secret-manager-cli/model/secretstore/list/cross.go deleted file mode 100644 index fdb188ae..00000000 --- a/ack-secret-manager-cli/model/secretstore/list/cross.go +++ /dev/null @@ -1,122 +0,0 @@ -package list - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/secretstore/input" -) - -const ( - limit = 5 -) - -type CrossModel struct { - list list.Model - choice string - quitting bool - preModel model.Model - continueToken string -} - -func InitCrossModel() *CrossModel { - secretStores, continueToken, err := k8s.ListSecretStore(limit, "") - if err != nil { - panic(err) - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("\n[Previous]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select an existing SecretStore for cross-account configuration" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &CrossModel{ - list: l, - continueToken: continueToken, - } -} - -func (m *CrossModel) Init() tea.Cmd { - return nil -} - -func (m *CrossModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *CrossModel) View() string { - return "\n" + m.list.View() -} - -func (m *CrossModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrossModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - model.InitModelMap["cross-choose"] = InitCrossModel() - return m.preModel, nil - } - if m.choice == "Next Page" { - secretStores, continueToken, err := k8s.ListSecretStore(limit, m.continueToken) - if err != nil { - return m, nil - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("\n[Previous]")) - m.list.SetItems(items) - m.continueToken = continueToken - return m, nil - } - next := model.InitModelMap["cross"] - crossModel, ok := next.(*input.CrossModel) - if !ok { - return m, nil - } - names := strings.Split(strings.Split(m.choice, " ")[1], "/") - crossModel.SetInfo(names[1], names[0]) - crossModel.SetPreModel(m) - return crossModel, nil -} diff --git a/ack-secret-manager-cli/model/secretstore/list/css.go b/ack-secret-manager-cli/model/secretstore/list/css.go deleted file mode 100644 index d1eb434f..00000000 --- a/ack-secret-manager-cli/model/secretstore/list/css.go +++ /dev/null @@ -1,56 +0,0 @@ -package list - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/doc.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/doc.go deleted file mode 100644 index 95a555a8..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Package v1alpha1 contains API Schema definitions for the alibabacloud v1alpha1 API group -// +k8s:deepcopy-gen=package,register -// +groupName=alibabacloud.com -package v1alpha1 diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types.go deleted file mode 100644 index 547e597e..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types.go +++ /dev/null @@ -1,100 +0,0 @@ -/* - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - -// ExternalSecretSpec defines the desired state of ExternalSecret -// +k8s:openapi-gen=true -type ExternalSecretSpec struct { - Provider string `json:"provider,omitempty"` - Data []DataSource `json:"data,omitempty"` - DataProcess []DataProcess `json:"dataProcess,omitempty"` - Type string `json:"type,omitempty"` -} - -type DataSource struct { - SecretStoreRef *SecretStoreRef `json:"secretStoreRef,omitempty"` - Key string `json:"key"` - Name string `json:"name,omitempty"` - VersionStage string `json:"versionStage,omitempty"` - VersionId string `json:"versionId,omitempty"` - //Optional array to specify what json key value pairs to extract from a secret and mount as individual secrets - JMESPath []JMESPathObject `json:"jmesPath,omitempty"` -} - -type SecretStoreRef struct { - Name string `json:"name"` - Namespace string `json:"namespace"` -} - -type DataProcess struct { - Extract *DataSource `json:"extract,omitempty"` - // +optional - ReplaceKey []ReplaceRule `json:"replaceRule,omitempty"` -} - -type ReplaceRule struct { - Target string `json:"target"` - Source string `json:"source"` -} - -// ExternalSecretStatus defines the observed state of ExternalSecret -type ExternalSecretStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ExternalSecret is the Schema for the externalsecrets API -// +genclient -// +k8s:openapi-gen=true -// +kubebuilder:subresource:status -// +kubebuilder:resource:path=externalsecrets,scope=Namespaced -type ExternalSecret struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec ExternalSecretSpec `json:"spec,omitempty"` - Status ExternalSecretStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// ExternalSecretList contains a list of ExternalSecret -type ExternalSecretList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []ExternalSecret `json:"items"` -} - -// An individual json key value pair to mount -type JMESPathObject struct { - //JMES path to use for retrieval - Path string `json:"path"` - - //File name in which to store the secret in. - ObjectAlias string `json:"objectAlias"` -} - -func init() { - SchemeBuilder.Register(&ExternalSecret{}, &ExternalSecretList{}) -} diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types_test.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types_test.go deleted file mode 100644 index 510fc907..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/externalsecret_types_test.go +++ /dev/null @@ -1,91 +0,0 @@ -package v1alpha1 - -import ( - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - "k8s.io/client-go/kubernetes/scheme" - "k8s.io/client-go/rest" - "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/envtest" - - "golang.org/x/net/context" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" -) - -// These tests are written in BDD-style using Ginkgo framework. Refer to -// http://onsi.github.io/ginkgo to learn more. - -var _ = Describe("ExternalSecret", func() { - var ( - key types.NamespacedName - created, fetched *ExternalSecret - cfg *rest.Config - k8sClient client.Client - testEnv *envtest.Environment - ) - - BeforeEach(func() { - // Add any setup steps that needs to be executed before each test - }) - - AfterEach(func() { - // Add any teardown steps that needs to be executed after each test - }) - - // Add Tests for OpenAPI validation (or additonal CRD features) specified in - // your API definition. - // Avoid adding tests for vanilla CRUD operations because they would - // test Kubernetes API server, which isn't the goal here. - Context("Create API", func() { - - It("should create an object successfully", func() { - - key = types.NamespacedName{ - Name: "foo", - Namespace: "default", - } - created = &ExternalSecret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo", - Namespace: "default", - }, - Spec: ExternalSecretSpec{ - Type: "Opaque", - Data: []DataSource{ - { - Key: "test", - Name: "foo", - VersionStage: "v1test", - }, - { - Key: "test2", - Name: "foo2", - VersionStage: "v2test", - }, - }, - }, - } - var err error - cfg, err = testEnv.Start() - Expect(err).ToNot(HaveOccurred()) - Expect(cfg).ToNot(BeNil()) - - k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) - Expect(err).ToNot(HaveOccurred()) - Expect(k8sClient).ToNot(BeNil()) - - By("creating an API obj") - Expect(k8sClient.Create(context.TODO(), created)).To(Succeed()) - - fetched = &ExternalSecret{} - Expect(k8sClient.Get(context.TODO(), key, fetched)).To(Succeed()) - Expect(fetched).To(Equal(created)) - - By("deleting the created object") - Expect(k8sClient.Delete(context.TODO(), created)).To(Succeed()) - Expect(k8sClient.Get(context.TODO(), key, created)).ToNot(Succeed()) - }) - }) - -}) diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/group.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/group.go deleted file mode 100644 index 14af8382..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/group.go +++ /dev/null @@ -1,29 +0,0 @@ -// Package alibabacloud contains alibabacloud API versions. -// -// This file ensures Go source parsers acknowledge the alibabacloud package -// and any child packages. It can be removed if any other Go source files are -// added to this package. -package v1alpha1 - -import ( - "k8s.io/apimachinery/pkg/runtime/schema" - "sigs.k8s.io/controller-runtime/pkg/scheme" -) - -var ( - // SchemeGroupVersion is group version used to register these objects - SchemeGroupVersion = schema.GroupVersion{Group: "alibabacloud.com", Version: "v1alpha1"} - - // SchemeBuilder is used to add go types to the GroupVersionKind scheme - SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} - - // AddToScheme is required by pkg/client/... - AddToScheme = SchemeBuilder.AddToScheme -) - -func Resource(resource string) schema.GroupResource { - return schema.GroupResource{ - Group: "alibabacloud.com", - Resource: resource, - } -} diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go deleted file mode 100644 index 96b34832..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go +++ /dev/null @@ -1,106 +0,0 @@ -/* -Copyright 2023. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1alpha1 - -import ( - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! -// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. - -// SecretStoreSpec defines the desired state of SecretStore - -// +kubebuilder:validation:MinProperties=1 -// +kubebuilder:validation:MaxProperties=1 -type SecretStoreSpec struct { - // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - // Important: Run "make" to regenerate code after modifying this file - // maybe support more alibabacloud product - KMS *KMSProvider `json:"KMS,omitempty"` -} - -// +kubebuilder:validation:MinProperties=1 -// +kubebuilder:validation:MaxProperties=1 -type KMSProvider struct { - // +optional - KMS *KMSAuth `json:"KMSAuth,omitempty"` - // +optional - DedicatedKMS *DedicatedKMSAuth `json:"dedicatedKMSAuth,omitempty"` -} - -type KMSAuth struct { - AccessKey *SecretRef `json:"accessKey,omitempty"` - AccessKeySecret *SecretRef `json:"accessKeySecret,omitempty"` - RAMRoleARN string `json:"ramRoleARN,omitempty"` - RAMRoleSessionName string `json:"ramRoleSessionName,omitempty"` - OIDCProviderARN string `json:"oidcProviderARN,omitempty"` - OIDCTokenFilePath string `json:"oidcTokenFilePath,omitempty"` - RoleSessionExpiration string `json:"roleSessionExpiration,omitempty"` - RemoteRAMRoleARN string `json:"remoteRamRoleARN,omitempty"` - RemoteRAMRoleSessionName string `json:"remoteRamRoleSessionName,omitempty"` -} - -type DedicatedKMSAuth struct { - Protocol string `json:"protocol"` - Endpoint string `json:"endpoint"` - CA string `json:"ca,omitempty"` - // if ignoreSSL=true custom don't need fill the CA - IgnoreSSL bool `json:"ignoreSSL,omitempty"` - ClientKeyContent *SecretRef `json:"clientKeyContent"` - Password *SecretRef `json:"password"` -} - -type SecretRef struct { - Name string `json:"name"` - Namespace string `json:"namespace"` - Key string `json:"key"` -} - -// SecretStoreStatus defines the observed state of SecretStore -type SecretStoreStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file -} - -// +genclient -//+kubebuilder:object:root=true -//+kubebuilder:subresource:status -//+kubebuilder:resource:path=secretstores -//+kubebuilder:object:generate=true - -// SecretStore is the Schema for the secretstores API -type SecretStore struct { - metav1.TypeMeta `json:",inline"` - metav1.ObjectMeta `json:"metadata,omitempty"` - - Spec SecretStoreSpec `json:"spec,omitempty"` - Status SecretStoreStatus `json:"status,omitempty"` -} - -// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object - -// SecretStoreList contains a list of SecretStore -type SecretStoreList struct { - metav1.TypeMeta `json:",inline"` - metav1.ListMeta `json:"metadata,omitempty"` - Items []SecretStore `json:"items"` -} - -func init() { - SchemeBuilder.Register(&SecretStore{}, &SecretStoreList{}) -} diff --git a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go b/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go deleted file mode 100644 index 94831b41..00000000 --- a/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go +++ /dev/null @@ -1,392 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -// Code generated by controller-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataProcess) DeepCopyInto(out *DataProcess) { - *out = *in - if in.Extract != nil { - in, out := &in.Extract, &out.Extract - *out = new(DataSource) - (*in).DeepCopyInto(*out) - } - if in.ReplaceKey != nil { - in, out := &in.ReplaceKey, &out.ReplaceKey - *out = make([]ReplaceRule, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataProcess. -func (in *DataProcess) DeepCopy() *DataProcess { - if in == nil { - return nil - } - out := new(DataProcess) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DataSource) DeepCopyInto(out *DataSource) { - *out = *in - if in.SecretStoreRef != nil { - in, out := &in.SecretStoreRef, &out.SecretStoreRef - *out = new(SecretStoreRef) - **out = **in - } - if in.JMESPath != nil { - in, out := &in.JMESPath, &out.JMESPath - *out = make([]JMESPathObject, len(*in)) - copy(*out, *in) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DataSource. -func (in *DataSource) DeepCopy() *DataSource { - if in == nil { - return nil - } - out := new(DataSource) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DedicatedKMSAuth) DeepCopyInto(out *DedicatedKMSAuth) { - *out = *in - if in.ClientKeyContent != nil { - in, out := &in.ClientKeyContent, &out.ClientKeyContent - *out = new(SecretRef) - **out = **in - } - if in.Password != nil { - in, out := &in.Password, &out.Password - *out = new(SecretRef) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DedicatedKMSAuth. -func (in *DedicatedKMSAuth) DeepCopy() *DedicatedKMSAuth { - if in == nil { - return nil - } - out := new(DedicatedKMSAuth) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExternalSecret) DeepCopyInto(out *ExternalSecret) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecret. -func (in *ExternalSecret) DeepCopy() *ExternalSecret { - if in == nil { - return nil - } - out := new(ExternalSecret) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExternalSecret) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExternalSecretList) DeepCopyInto(out *ExternalSecretList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]ExternalSecret, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretList. -func (in *ExternalSecretList) DeepCopy() *ExternalSecretList { - if in == nil { - return nil - } - out := new(ExternalSecretList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *ExternalSecretList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExternalSecretSpec) DeepCopyInto(out *ExternalSecretSpec) { - *out = *in - if in.Data != nil { - in, out := &in.Data, &out.Data - *out = make([]DataSource, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - if in.DataProcess != nil { - in, out := &in.DataProcess, &out.DataProcess - *out = make([]DataProcess, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretSpec. -func (in *ExternalSecretSpec) DeepCopy() *ExternalSecretSpec { - if in == nil { - return nil - } - out := new(ExternalSecretSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ExternalSecretStatus) DeepCopyInto(out *ExternalSecretStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExternalSecretStatus. -func (in *ExternalSecretStatus) DeepCopy() *ExternalSecretStatus { - if in == nil { - return nil - } - out := new(ExternalSecretStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *JMESPathObject) DeepCopyInto(out *JMESPathObject) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new JMESPathObject. -func (in *JMESPathObject) DeepCopy() *JMESPathObject { - if in == nil { - return nil - } - out := new(JMESPathObject) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KMSAuth) DeepCopyInto(out *KMSAuth) { - *out = *in - if in.AccessKey != nil { - in, out := &in.AccessKey, &out.AccessKey - *out = new(SecretRef) - **out = **in - } - if in.AccessKeySecret != nil { - in, out := &in.AccessKeySecret, &out.AccessKeySecret - *out = new(SecretRef) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSAuth. -func (in *KMSAuth) DeepCopy() *KMSAuth { - if in == nil { - return nil - } - out := new(KMSAuth) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *KMSProvider) DeepCopyInto(out *KMSProvider) { - *out = *in - if in.KMS != nil { - in, out := &in.KMS, &out.KMS - *out = new(KMSAuth) - (*in).DeepCopyInto(*out) - } - if in.DedicatedKMS != nil { - in, out := &in.DedicatedKMS, &out.DedicatedKMS - *out = new(DedicatedKMSAuth) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KMSProvider. -func (in *KMSProvider) DeepCopy() *KMSProvider { - if in == nil { - return nil - } - out := new(KMSProvider) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *ReplaceRule) DeepCopyInto(out *ReplaceRule) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReplaceRule. -func (in *ReplaceRule) DeepCopy() *ReplaceRule { - if in == nil { - return nil - } - out := new(ReplaceRule) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretRef) DeepCopyInto(out *SecretRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretRef. -func (in *SecretRef) DeepCopy() *SecretRef { - if in == nil { - return nil - } - out := new(SecretRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretStore) DeepCopyInto(out *SecretStore) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - out.Status = in.Status -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStore. -func (in *SecretStore) DeepCopy() *SecretStore { - if in == nil { - return nil - } - out := new(SecretStore) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SecretStore) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretStoreList) DeepCopyInto(out *SecretStoreList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]SecretStore, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreList. -func (in *SecretStoreList) DeepCopy() *SecretStoreList { - if in == nil { - return nil - } - out := new(SecretStoreList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *SecretStoreList) DeepCopyObject() runtime.Object { - if c := in.DeepCopy(); c != nil { - return c - } - return nil -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretStoreRef) DeepCopyInto(out *SecretStoreRef) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreRef. -func (in *SecretStoreRef) DeepCopy() *SecretStoreRef { - if in == nil { - return nil - } - out := new(SecretStoreRef) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretStoreSpec) DeepCopyInto(out *SecretStoreSpec) { - *out = *in - if in.KMS != nil { - in, out := &in.KMS, &out.KMS - *out = new(KMSProvider) - (*in).DeepCopyInto(*out) - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreSpec. -func (in *SecretStoreSpec) DeepCopy() *SecretStoreSpec { - if in == nil { - return nil - } - out := new(SecretStoreSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *SecretStoreStatus) DeepCopyInto(out *SecretStoreStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreStatus. -func (in *SecretStoreStatus) DeepCopy() *SecretStoreStatus { - if in == nil { - return nil - } - out := new(SecretStoreStatus) - in.DeepCopyInto(out) - return out -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/clientset.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/clientset.go deleted file mode 100644 index a74618e2..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/clientset.go +++ /dev/null @@ -1,104 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package versioned - -import ( - "fmt" - "net/http" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - discovery "k8s.io/client-go/discovery" - rest "k8s.io/client-go/rest" - flowcontrol "k8s.io/client-go/util/flowcontrol" -) - -type Interface interface { - Discovery() discovery.DiscoveryInterface - AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface -} - -// Clientset contains the clients for groups. -type Clientset struct { - *discovery.DiscoveryClient - alibabacloudV1alpha1 *alibabacloudv1alpha1.AlibabacloudV1alpha1Client -} - -// AlibabacloudV1alpha1 retrieves the AlibabacloudV1alpha1Client -func (c *Clientset) AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface { - return c.alibabacloudV1alpha1 -} - -// Discovery retrieves the DiscoveryClient -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - if c == nil { - return nil - } - return c.DiscoveryClient -} - -// NewForConfig creates a new Clientset for the given config. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfig will generate a rate-limiter in configShallowCopy. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*Clientset, error) { - configShallowCopy := *c - - if configShallowCopy.UserAgent == "" { - configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent() - } - - // share the transport between all clients - httpClient, err := rest.HTTPClientFor(&configShallowCopy) - if err != nil { - return nil, err - } - - return NewForConfigAndClient(&configShallowCopy, httpClient) -} - -// NewForConfigAndClient creates a new Clientset for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -// If config's RateLimiter is not set and QPS and Burst are acceptable, -// NewForConfigAndClient will generate a rate-limiter in configShallowCopy. -func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) { - configShallowCopy := *c - if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 { - if configShallowCopy.Burst <= 0 { - return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0") - } - configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst) - } - - var cs Clientset - var err error - cs.alibabacloudV1alpha1, err = alibabacloudv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - - cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } - return &cs, nil -} - -// NewForConfigOrDie creates a new Clientset for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *Clientset { - cs, err := NewForConfig(c) - if err != nil { - panic(err) - } - return cs -} - -// New creates a new Clientset for the given RESTClient. -func New(c rest.Interface) *Clientset { - var cs Clientset - cs.alibabacloudV1alpha1 = alibabacloudv1alpha1.New(c) - - cs.DiscoveryClient = discovery.NewDiscoveryClient(c) - return &cs -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/clientset_generated.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/clientset_generated.go deleted file mode 100644 index 1718f9bb..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/clientset_generated.go +++ /dev/null @@ -1,69 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - clientset "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - fakealibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/watch" - "k8s.io/client-go/discovery" - fakediscovery "k8s.io/client-go/discovery/fake" - "k8s.io/client-go/testing" -) - -// NewSimpleClientset returns a clientset that will respond with the provided objects. -// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, -// without applying any validations and/or defaults. It shouldn't be considered a replacement -// for a real clientset and is mostly useful in simple unit tests. -func NewSimpleClientset(objects ...runtime.Object) *Clientset { - o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) - for _, obj := range objects { - if err := o.Add(obj); err != nil { - panic(err) - } - } - - cs := &Clientset{tracker: o} - cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} - cs.AddReactor("*", "*", testing.ObjectReaction(o)) - cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { - gvr := action.GetResource() - ns := action.GetNamespace() - watch, err := o.Watch(gvr, ns) - if err != nil { - return false, nil, err - } - return true, watch, nil - }) - - return cs -} - -// Clientset implements clientset.Interface. Meant to be embedded into a -// struct to get a default implementation. This makes faking out just the method -// you want to test easier. -type Clientset struct { - testing.Fake - discovery *fakediscovery.FakeDiscovery - tracker testing.ObjectTracker -} - -func (c *Clientset) Discovery() discovery.DiscoveryInterface { - return c.discovery -} - -func (c *Clientset) Tracker() testing.ObjectTracker { - return c.tracker -} - -var ( - _ clientset.Interface = &Clientset{} - _ testing.FakeClient = &Clientset{} -) - -// AlibabacloudV1alpha1 retrieves the AlibabacloudV1alpha1Client -func (c *Clientset) AlibabacloudV1alpha1() alibabacloudv1alpha1.AlibabacloudV1alpha1Interface { - return &fakealibabacloudv1alpha1.FakeAlibabacloudV1alpha1{Fake: &c.Fake} -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/doc.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/doc.go deleted file mode 100644 index 3630ed1c..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated fake clientset. -package fake diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/register.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/register.go deleted file mode 100644 index 8d653806..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/fake/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - serializer "k8s.io/apimachinery/pkg/runtime/serializer" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" -) - -var scheme = runtime.NewScheme() -var codecs = serializer.NewCodecFactory(scheme) - -var localSchemeBuilder = runtime.SchemeBuilder{ - alibabacloudv1alpha1.AddToScheme, -} - -// AddToScheme adds all types of this clientset into the given scheme. This allows composition -// of clientsets, like in: -// -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) -// -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) -// -// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types -// correctly. -var AddToScheme = localSchemeBuilder.AddToScheme - -func init() { - v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) - utilruntime.Must(AddToScheme(scheme)) -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/doc.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/doc.go deleted file mode 100644 index 14db57a5..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package contains the scheme of the automatically generated clientset. -package scheme diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/register.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/register.go deleted file mode 100644 index ba987253..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme/register.go +++ /dev/null @@ -1,40 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package scheme - -import ( - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - serializer "k8s.io/apimachinery/pkg/runtime/serializer" - utilruntime "k8s.io/apimachinery/pkg/util/runtime" -) - -var Scheme = runtime.NewScheme() -var Codecs = serializer.NewCodecFactory(Scheme) -var ParameterCodec = runtime.NewParameterCodec(Scheme) -var localSchemeBuilder = runtime.SchemeBuilder{ - alibabacloudv1alpha1.AddToScheme, -} - -// AddToScheme adds all types of this clientset into the given scheme. This allows composition -// of clientsets, like in: -// -// import ( -// "k8s.io/client-go/kubernetes" -// clientsetscheme "k8s.io/client-go/kubernetes/scheme" -// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" -// ) -// -// kclientset, _ := kubernetes.NewForConfig(c) -// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) -// -// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types -// correctly. -var AddToScheme = localSchemeBuilder.AddToScheme - -func init() { - v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"}) - utilruntime.Must(AddToScheme(Scheme)) -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go deleted file mode 100644 index 54884adb..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/alibabacloud_client.go +++ /dev/null @@ -1,96 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "net/http" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - rest "k8s.io/client-go/rest" -) - -type AlibabacloudV1alpha1Interface interface { - RESTClient() rest.Interface - ExternalSecretsGetter - SecretStoresGetter -} - -// AlibabacloudV1alpha1Client is used to interact with features provided by the alibabacloud.com group. -type AlibabacloudV1alpha1Client struct { - restClient rest.Interface -} - -func (c *AlibabacloudV1alpha1Client) ExternalSecrets(namespace string) ExternalSecretInterface { - return newExternalSecrets(c, namespace) -} - -func (c *AlibabacloudV1alpha1Client) SecretStores(namespace string) SecretStoreInterface { - return newSecretStores(c, namespace) -} - -// NewForConfig creates a new AlibabacloudV1alpha1Client for the given config. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*AlibabacloudV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - httpClient, err := rest.HTTPClientFor(&config) - if err != nil { - return nil, err - } - return NewForConfigAndClient(&config, httpClient) -} - -// NewForConfigAndClient creates a new AlibabacloudV1alpha1Client for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -func NewForConfigAndClient(c *rest.Config, h *http.Client) (*AlibabacloudV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - client, err := rest.RESTClientForConfigAndClient(&config, h) - if err != nil { - return nil, err - } - return &AlibabacloudV1alpha1Client{client}, nil -} - -// NewForConfigOrDie creates a new AlibabacloudV1alpha1Client for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *AlibabacloudV1alpha1Client { - client, err := NewForConfig(c) - if err != nil { - panic(err) - } - return client -} - -// New creates a new AlibabacloudV1alpha1Client for the given RESTClient. -func New(c rest.Interface) *AlibabacloudV1alpha1Client { - return &AlibabacloudV1alpha1Client{c} -} - -func setConfigDefaults(config *rest.Config) error { - gv := v1alpha1.SchemeGroupVersion - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = scheme.Codecs.WithoutConversion() - - if config.UserAgent == "" { - config.UserAgent = rest.DefaultKubernetesUserAgent() - } - - return nil -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *AlibabacloudV1alpha1Client) RESTClient() rest.Interface { - if c == nil { - return nil - } - return c.restClient -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go deleted file mode 100644 index 93a7ca4e..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// This package has the automatically generated typed clients. -package v1alpha1 diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index c220af10..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,179 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - scheme "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// ExternalSecretsGetter has a method to return a ExternalSecretInterface. -// A group's client should implement this interface. -type ExternalSecretsGetter interface { - ExternalSecrets(namespace string) ExternalSecretInterface -} - -// ExternalSecretInterface has methods to work with ExternalSecret resources. -type ExternalSecretInterface interface { - Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (*v1alpha1.ExternalSecret, error) - Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) - UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.ExternalSecret, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.ExternalSecretList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) - ExternalSecretExpansion -} - -// externalSecrets implements ExternalSecretInterface -type externalSecrets struct { - client rest.Interface - ns string -} - -// newExternalSecrets returns a ExternalSecrets -func newExternalSecrets(c *AlibabacloudV1alpha1Client, namespace string) *externalSecrets { - return &externalSecrets{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the externalSecret, and returns the corresponding externalSecret object, and an error if there is any. -func (c *externalSecrets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of ExternalSecrets that match those selectors. -func (c *externalSecrets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ExternalSecretList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.ExternalSecretList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested externalSecrets. -func (c *externalSecrets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a externalSecret and creates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *externalSecrets) Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Post(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a externalSecret and updates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *externalSecrets) Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Put(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(externalSecret.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *externalSecrets) UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Put(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(externalSecret.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(externalSecret). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the externalSecret and deletes it. Returns an error if one occurs. -func (c *externalSecrets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *externalSecrets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("externalsecrets"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched externalSecret. -func (c *externalSecrets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) { - result = &v1alpha1.ExternalSecret{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("externalsecrets"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go deleted file mode 100644 index 2b5ba4c8..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/doc.go +++ /dev/null @@ -1,4 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -// Package fake has the automatically generated clients. -package fake diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go deleted file mode 100644 index bd050e26..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_alibabacloud_client.go +++ /dev/null @@ -1,28 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1" - rest "k8s.io/client-go/rest" - testing "k8s.io/client-go/testing" -) - -type FakeAlibabacloudV1alpha1 struct { - *testing.Fake -} - -func (c *FakeAlibabacloudV1alpha1) ExternalSecrets(namespace string) v1alpha1.ExternalSecretInterface { - return &FakeExternalSecrets{c, namespace} -} - -func (c *FakeAlibabacloudV1alpha1) SecretStores(namespace string) v1alpha1.SecretStoreInterface { - return &FakeSecretStores{c, namespace} -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeAlibabacloudV1alpha1) RESTClient() rest.Interface { - var ret *rest.RESTClient - return ret -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go deleted file mode 100644 index 0b966144..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_externalsecret.go +++ /dev/null @@ -1,125 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeExternalSecrets implements ExternalSecretInterface -type FakeExternalSecrets struct { - Fake *FakeAlibabacloudV1alpha1 - ns string -} - -var externalsecretsResource = v1alpha1.SchemeGroupVersion.WithResource("externalsecrets") - -var externalsecretsKind = v1alpha1.SchemeGroupVersion.WithKind("ExternalSecret") - -// Get takes name of the externalSecret, and returns the corresponding externalSecret object, and an error if there is any. -func (c *FakeExternalSecrets) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(externalsecretsResource, c.ns, name), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// List takes label and field selectors, and returns the list of ExternalSecrets that match those selectors. -func (c *FakeExternalSecrets) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.ExternalSecretList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(externalsecretsResource, externalsecretsKind, c.ns, opts), &v1alpha1.ExternalSecretList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.ExternalSecretList{ListMeta: obj.(*v1alpha1.ExternalSecretList).ListMeta} - for _, item := range obj.(*v1alpha1.ExternalSecretList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested externalSecrets. -func (c *FakeExternalSecrets) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(externalsecretsResource, c.ns, opts)) - -} - -// Create takes the representation of a externalSecret and creates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *FakeExternalSecrets) Create(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.CreateOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(externalsecretsResource, c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// Update takes the representation of a externalSecret and updates it. Returns the server's representation of the externalSecret, and an error, if there is any. -func (c *FakeExternalSecrets) Update(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(externalsecretsResource, c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeExternalSecrets) UpdateStatus(ctx context.Context, externalSecret *v1alpha1.ExternalSecret, opts v1.UpdateOptions) (*v1alpha1.ExternalSecret, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(externalsecretsResource, "status", c.ns, externalSecret), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} - -// Delete takes name of the externalSecret and deletes it. Returns an error if one occurs. -func (c *FakeExternalSecrets) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(externalsecretsResource, c.ns, name, opts), &v1alpha1.ExternalSecret{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeExternalSecrets) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(externalsecretsResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.ExternalSecretList{}) - return err -} - -// Patch applies the patch and returns the patched externalSecret. -func (c *FakeExternalSecrets) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.ExternalSecret, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(externalsecretsResource, c.ns, name, pt, data, subresources...), &v1alpha1.ExternalSecret{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.ExternalSecret), err -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go deleted file mode 100644 index 27dc41a8..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/fake/fake_secretstore.go +++ /dev/null @@ -1,125 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package fake - -import ( - "context" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - labels "k8s.io/apimachinery/pkg/labels" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - testing "k8s.io/client-go/testing" -) - -// FakeSecretStores implements SecretStoreInterface -type FakeSecretStores struct { - Fake *FakeAlibabacloudV1alpha1 - ns string -} - -var secretstoresResource = v1alpha1.SchemeGroupVersion.WithResource("secretstores") - -var secretstoresKind = v1alpha1.SchemeGroupVersion.WithKind("SecretStore") - -// Get takes name of the secretStore, and returns the corresponding secretStore object, and an error if there is any. -func (c *FakeSecretStores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewGetAction(secretstoresResource, c.ns, name), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// List takes label and field selectors, and returns the list of SecretStores that match those selectors. -func (c *FakeSecretStores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.SecretStoreList, err error) { - obj, err := c.Fake. - Invokes(testing.NewListAction(secretstoresResource, secretstoresKind, c.ns, opts), &v1alpha1.SecretStoreList{}) - - if obj == nil { - return nil, err - } - - label, _, _ := testing.ExtractFromListOptions(opts) - if label == nil { - label = labels.Everything() - } - list := &v1alpha1.SecretStoreList{ListMeta: obj.(*v1alpha1.SecretStoreList).ListMeta} - for _, item := range obj.(*v1alpha1.SecretStoreList).Items { - if label.Matches(labels.Set(item.Labels)) { - list.Items = append(list.Items, item) - } - } - return list, err -} - -// Watch returns a watch.Interface that watches the requested secretStores. -func (c *FakeSecretStores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - return c.Fake. - InvokesWatch(testing.NewWatchAction(secretstoresResource, c.ns, opts)) - -} - -// Create takes the representation of a secretStore and creates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *FakeSecretStores) Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewCreateAction(secretstoresResource, c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// Update takes the representation of a secretStore and updates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *FakeSecretStores) Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateAction(secretstoresResource, c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *FakeSecretStores) UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) { - obj, err := c.Fake. - Invokes(testing.NewUpdateSubresourceAction(secretstoresResource, "status", c.ns, secretStore), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} - -// Delete takes name of the secretStore and deletes it. Returns an error if one occurs. -func (c *FakeSecretStores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - _, err := c.Fake. - Invokes(testing.NewDeleteActionWithOptions(secretstoresResource, c.ns, name, opts), &v1alpha1.SecretStore{}) - - return err -} - -// DeleteCollection deletes a collection of objects. -func (c *FakeSecretStores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - action := testing.NewDeleteCollectionAction(secretstoresResource, c.ns, listOpts) - - _, err := c.Fake.Invokes(action, &v1alpha1.SecretStoreList{}) - return err -} - -// Patch applies the patch and returns the patched secretStore. -func (c *FakeSecretStores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) { - obj, err := c.Fake. - Invokes(testing.NewPatchSubresourceAction(secretstoresResource, c.ns, name, pt, data, subresources...), &v1alpha1.SecretStore{}) - - if obj == nil { - return nil, err - } - return obj.(*v1alpha1.SecretStore), err -} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go deleted file mode 100644 index 6104b9ee..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/generated_expansion.go +++ /dev/null @@ -1,7 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -type ExternalSecretExpansion interface{} - -type SecretStoreExpansion interface{} diff --git a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index c37fdcf1..00000000 --- a/ack-secret-manager-cli/pkg/client/clientset/versioned/typed/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,179 +0,0 @@ -// Code generated by client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - "time" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - scheme "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned/scheme" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - types "k8s.io/apimachinery/pkg/types" - watch "k8s.io/apimachinery/pkg/watch" - rest "k8s.io/client-go/rest" -) - -// SecretStoresGetter has a method to return a SecretStoreInterface. -// A group's client should implement this interface. -type SecretStoresGetter interface { - SecretStores(namespace string) SecretStoreInterface -} - -// SecretStoreInterface has methods to work with SecretStore resources. -type SecretStoreInterface interface { - Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (*v1alpha1.SecretStore, error) - Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) - UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (*v1alpha1.SecretStore, error) - Delete(ctx context.Context, name string, opts v1.DeleteOptions) error - DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error - Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.SecretStore, error) - List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.SecretStoreList, error) - Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) - Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) - SecretStoreExpansion -} - -// secretStores implements SecretStoreInterface -type secretStores struct { - client rest.Interface - ns string -} - -// newSecretStores returns a SecretStores -func newSecretStores(c *AlibabacloudV1alpha1Client, namespace string) *secretStores { - return &secretStores{ - client: c.RESTClient(), - ns: namespace, - } -} - -// Get takes name of the secretStore, and returns the corresponding secretStore object, and an error if there is any. -func (c *secretStores) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - VersionedParams(&options, scheme.ParameterCodec). - Do(ctx). - Into(result) - return -} - -// List takes label and field selectors, and returns the list of SecretStores that match those selectors. -func (c *secretStores) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.SecretStoreList, err error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - result = &v1alpha1.SecretStoreList{} - err = c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Do(ctx). - Into(result) - return -} - -// Watch returns a watch.Interface that watches the requested secretStores. -func (c *secretStores) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { - var timeout time.Duration - if opts.TimeoutSeconds != nil { - timeout = time.Duration(*opts.TimeoutSeconds) * time.Second - } - opts.Watch = true - return c.client.Get(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Timeout(timeout). - Watch(ctx) -} - -// Create takes the representation of a secretStore and creates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *secretStores) Create(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.CreateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Post(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// Update takes the representation of a secretStore and updates it. Returns the server's representation of the secretStore, and an error, if there is any. -func (c *secretStores) Update(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Put(). - Namespace(c.ns). - Resource("secretstores"). - Name(secretStore.Name). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// UpdateStatus was generated because the type contains a Status member. -// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). -func (c *secretStores) UpdateStatus(ctx context.Context, secretStore *v1alpha1.SecretStore, opts v1.UpdateOptions) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Put(). - Namespace(c.ns). - Resource("secretstores"). - Name(secretStore.Name). - SubResource("status"). - VersionedParams(&opts, scheme.ParameterCodec). - Body(secretStore). - Do(ctx). - Into(result) - return -} - -// Delete takes name of the secretStore and deletes it. Returns an error if one occurs. -func (c *secretStores) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { - return c.client.Delete(). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - Body(&opts). - Do(ctx). - Error() -} - -// DeleteCollection deletes a collection of objects. -func (c *secretStores) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { - var timeout time.Duration - if listOpts.TimeoutSeconds != nil { - timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second - } - return c.client.Delete(). - Namespace(c.ns). - Resource("secretstores"). - VersionedParams(&listOpts, scheme.ParameterCodec). - Timeout(timeout). - Body(&opts). - Do(ctx). - Error() -} - -// Patch applies the patch and returns the patched secretStore. -func (c *secretStores) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.SecretStore, err error) { - result = &v1alpha1.SecretStore{} - err = c.client.Patch(pt). - Namespace(c.ns). - Resource("secretstores"). - Name(name). - SubResource(subresources...). - VersionedParams(&opts, scheme.ParameterCodec). - Body(data). - Do(ctx). - Into(result) - return -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/interface.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/interface.go deleted file mode 100644 index 23c8cd1f..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/interface.go +++ /dev/null @@ -1,30 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package alibabacloud - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" -) - -// Interface provides access to each of this group's versions. -type Interface interface { - // V1alpha1 provides access to shared informers for resources in V1alpha1. - V1alpha1() v1alpha1.Interface -} - -type group struct { - factory internalinterfaces.SharedInformerFactory - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { - return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} -} - -// V1alpha1 returns a new v1alpha1.Interface. -func (g *group) V1alpha1() v1alpha1.Interface { - return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions) -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index 76d82bbc..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - time "time" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// ExternalSecretInformer provides access to a shared informer and lister for -// ExternalSecrets. -type ExternalSecretInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.ExternalSecretLister -} - -type externalSecretInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewExternalSecretInformer constructs a new informer for ExternalSecret type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewExternalSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredExternalSecretInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredExternalSecretInformer constructs a new informer for ExternalSecret type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredExternalSecretInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().ExternalSecrets(namespace).List(context.TODO(), options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().ExternalSecrets(namespace).Watch(context.TODO(), options) - }, - }, - &alibabacloudv1alpha1.ExternalSecret{}, - resyncPeriod, - indexers, - ) -} - -func (f *externalSecretInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredExternalSecretInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *externalSecretInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&alibabacloudv1alpha1.ExternalSecret{}, f.defaultInformer) -} - -func (f *externalSecretInformer) Lister() v1alpha1.ExternalSecretLister { - return v1alpha1.NewExternalSecretLister(f.Informer().GetIndexer()) -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/interface.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/interface.go deleted file mode 100644 index b4007ed6..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/interface.go +++ /dev/null @@ -1,36 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" -) - -// Interface provides access to all the informers in this group version. -type Interface interface { - // ExternalSecrets returns a ExternalSecretInformer. - ExternalSecrets() ExternalSecretInformer - // SecretStores returns a SecretStoreInformer. - SecretStores() SecretStoreInformer -} - -type version struct { - factory internalinterfaces.SharedInformerFactory - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc -} - -// New returns a new Interface. -func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface { - return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions} -} - -// ExternalSecrets returns a ExternalSecretInformer. -func (v *version) ExternalSecrets() ExternalSecretInformer { - return &externalSecretInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} - -// SecretStores returns a SecretStoreInformer. -func (v *version) SecretStores() SecretStoreInformer { - return &secretStoreInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index 59ba83dc..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,74 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - "context" - time "time" - - alibabacloudv1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - watch "k8s.io/apimachinery/pkg/watch" - cache "k8s.io/client-go/tools/cache" -) - -// SecretStoreInformer provides access to a shared informer and lister for -// SecretStores. -type SecretStoreInformer interface { - Informer() cache.SharedIndexInformer - Lister() v1alpha1.SecretStoreLister -} - -type secretStoreInformer struct { - factory internalinterfaces.SharedInformerFactory - tweakListOptions internalinterfaces.TweakListOptionsFunc - namespace string -} - -// NewSecretStoreInformer constructs a new informer for SecretStore type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewSecretStoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { - return NewFilteredSecretStoreInformer(client, namespace, resyncPeriod, indexers, nil) -} - -// NewFilteredSecretStoreInformer constructs a new informer for SecretStore type. -// Always prefer using an informer factory to get a shared informer instead of getting an independent -// one. This reduces memory footprint and number of connections to the server. -func NewFilteredSecretStoreInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { - return cache.NewSharedIndexInformer( - &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().SecretStores(namespace).List(context.TODO(), options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - if tweakListOptions != nil { - tweakListOptions(&options) - } - return client.AlibabacloudV1alpha1().SecretStores(namespace).Watch(context.TODO(), options) - }, - }, - &alibabacloudv1alpha1.SecretStore{}, - resyncPeriod, - indexers, - ) -} - -func (f *secretStoreInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { - return NewFilteredSecretStoreInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) -} - -func (f *secretStoreInformer) Informer() cache.SharedIndexInformer { - return f.factory.InformerFor(&alibabacloudv1alpha1.SecretStore{}, f.defaultInformer) -} - -func (f *secretStoreInformer) Lister() v1alpha1.SecretStoreLister { - return v1alpha1.NewSecretStoreLister(f.Informer().GetIndexer()) -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/factory.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/factory.go deleted file mode 100644 index 0ff7e4f2..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/factory.go +++ /dev/null @@ -1,235 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package externalversions - -import ( - reflect "reflect" - sync "sync" - time "time" - - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - alibabacloud "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/alibabacloud" - internalinterfaces "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - schema "k8s.io/apimachinery/pkg/runtime/schema" - cache "k8s.io/client-go/tools/cache" -) - -// SharedInformerOption defines the functional option type for SharedInformerFactory. -type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory - -type sharedInformerFactory struct { - client versioned.Interface - namespace string - tweakListOptions internalinterfaces.TweakListOptionsFunc - lock sync.Mutex - defaultResync time.Duration - customResync map[reflect.Type]time.Duration - - informers map[reflect.Type]cache.SharedIndexInformer - // startedInformers is used for tracking which informers have been started. - // This allows Start() to be called multiple times safely. - startedInformers map[reflect.Type]bool - // wg tracks how many goroutines were started. - wg sync.WaitGroup - // shuttingDown is true when Shutdown has been called. It may still be running - // because it needs to wait for goroutines. - shuttingDown bool -} - -// WithCustomResyncConfig sets a custom resync period for the specified informer types. -func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - for k, v := range resyncConfig { - factory.customResync[reflect.TypeOf(k)] = v - } - return factory - } -} - -// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory. -func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - factory.tweakListOptions = tweakListOptions - return factory - } -} - -// WithNamespace limits the SharedInformerFactory to the specified namespace. -func WithNamespace(namespace string) SharedInformerOption { - return func(factory *sharedInformerFactory) *sharedInformerFactory { - factory.namespace = namespace - return factory - } -} - -// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces. -func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory { - return NewSharedInformerFactoryWithOptions(client, defaultResync) -} - -// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory. -// Listers obtained via this SharedInformerFactory will be subject to the same filters -// as specified here. -// Deprecated: Please use NewSharedInformerFactoryWithOptions instead -func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory { - return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions)) -} - -// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options. -func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory { - factory := &sharedInformerFactory{ - client: client, - namespace: v1.NamespaceAll, - defaultResync: defaultResync, - informers: make(map[reflect.Type]cache.SharedIndexInformer), - startedInformers: make(map[reflect.Type]bool), - customResync: make(map[reflect.Type]time.Duration), - } - - // Apply all options - for _, opt := range options { - factory = opt(factory) - } - - return factory -} - -func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) { - f.lock.Lock() - defer f.lock.Unlock() - - if f.shuttingDown { - return - } - - for informerType, informer := range f.informers { - if !f.startedInformers[informerType] { - f.wg.Add(1) - // We need a new variable in each loop iteration, - // otherwise the goroutine would use the loop variable - // and that keeps changing. - informer := informer - go func() { - defer f.wg.Done() - informer.Run(stopCh) - }() - f.startedInformers[informerType] = true - } - } -} - -func (f *sharedInformerFactory) Shutdown() { - f.lock.Lock() - f.shuttingDown = true - f.lock.Unlock() - - // Will return immediately if there is nothing to wait for. - f.wg.Wait() -} - -func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool { - informers := func() map[reflect.Type]cache.SharedIndexInformer { - f.lock.Lock() - defer f.lock.Unlock() - - informers := map[reflect.Type]cache.SharedIndexInformer{} - for informerType, informer := range f.informers { - if f.startedInformers[informerType] { - informers[informerType] = informer - } - } - return informers - }() - - res := map[reflect.Type]bool{} - for informType, informer := range informers { - res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced) - } - return res -} - -// InformerFor returns the SharedIndexInformer for obj using an internal -// client. -func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer { - f.lock.Lock() - defer f.lock.Unlock() - - informerType := reflect.TypeOf(obj) - informer, exists := f.informers[informerType] - if exists { - return informer - } - - resyncPeriod, exists := f.customResync[informerType] - if !exists { - resyncPeriod = f.defaultResync - } - - informer = newFunc(f.client, resyncPeriod) - f.informers[informerType] = informer - - return informer -} - -// SharedInformerFactory provides shared informers for resources in all known -// API group versions. -// -// It is typically used like this: -// -// ctx, cancel := context.Background() -// defer cancel() -// factory := NewSharedInformerFactory(client, resyncPeriod) -// defer factory.WaitForStop() // Returns immediately if nothing was started. -// genericInformer := factory.ForResource(resource) -// typedInformer := factory.SomeAPIGroup().V1().SomeType() -// factory.Start(ctx.Done()) // Start processing these informers. -// synced := factory.WaitForCacheSync(ctx.Done()) -// for v, ok := range synced { -// if !ok { -// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v) -// return -// } -// } -// -// // Creating informers can also be created after Start, but then -// // Start must be called again: -// anotherGenericInformer := factory.ForResource(resource) -// factory.Start(ctx.Done()) -type SharedInformerFactory interface { - internalinterfaces.SharedInformerFactory - - // Start initializes all requested informers. They are handled in goroutines - // which run until the stop channel gets closed. - Start(stopCh <-chan struct{}) - - // Shutdown marks a factory as shutting down. At that point no new - // informers can be started anymore and Start will return without - // doing anything. - // - // In addition, Shutdown blocks until all goroutines have terminated. For that - // to happen, the close channel(s) that they were started with must be closed, - // either before Shutdown gets called or while it is waiting. - // - // Shutdown may be called multiple times, even concurrently. All such calls will - // block until all goroutines have terminated. - Shutdown() - - // WaitForCacheSync blocks until all started informers' caches were synced - // or the stop channel gets closed. - WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool - - // ForResource gives generic access to a shared informer of the matching type. - ForResource(resource schema.GroupVersionResource) (GenericInformer, error) - - // InformerFor returns the SharedIndexInformer for obj using an internal - // client. - InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer - - Alibabacloud() alibabacloud.Interface -} - -func (f *sharedInformerFactory) Alibabacloud() alibabacloud.Interface { - return alibabacloud.New(f, f.namespace, f.tweakListOptions) -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/generic.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/generic.go deleted file mode 100644 index be067fe2..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/generic.go +++ /dev/null @@ -1,48 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package externalversions - -import ( - "fmt" - - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - schema "k8s.io/apimachinery/pkg/runtime/schema" - cache "k8s.io/client-go/tools/cache" -) - -// GenericInformer is type of SharedIndexInformer which will locate and delegate to other -// sharedInformers based on type -type GenericInformer interface { - Informer() cache.SharedIndexInformer - Lister() cache.GenericLister -} - -type genericInformer struct { - informer cache.SharedIndexInformer - resource schema.GroupResource -} - -// Informer returns the SharedIndexInformer. -func (f *genericInformer) Informer() cache.SharedIndexInformer { - return f.informer -} - -// Lister returns the GenericLister. -func (f *genericInformer) Lister() cache.GenericLister { - return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource) -} - -// ForResource gives generic access to a shared informer of the matching type -// TODO extend this to unknown resources with a client pool -func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) { - switch resource { - // Group=alibabacloud.com, Version=v1alpha1 - case v1alpha1.SchemeGroupVersion.WithResource("externalsecrets"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Alibabacloud().V1alpha1().ExternalSecrets().Informer()}, nil - case v1alpha1.SchemeGroupVersion.WithResource("secretstores"): - return &genericInformer{resource: resource.GroupResource(), informer: f.Alibabacloud().V1alpha1().SecretStores().Informer()}, nil - - } - - return nil, fmt.Errorf("no informer found for %v", resource) -} diff --git a/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go b/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go deleted file mode 100644 index b5feba69..00000000 --- a/ack-secret-manager-cli/pkg/client/informers/externalversions/internalinterfaces/factory_interfaces.go +++ /dev/null @@ -1,24 +0,0 @@ -// Code generated by informer-gen. DO NOT EDIT. - -package internalinterfaces - -import ( - time "time" - - versioned "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" - cache "k8s.io/client-go/tools/cache" -) - -// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer. -type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer - -// SharedInformerFactory a small interface to allow for adding an informer without an import cycle -type SharedInformerFactory interface { - Start(stopCh <-chan struct{}) - InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer -} - -// TweakListOptionsFunc is a function that transforms a v1.ListOptions. -type TweakListOptionsFunc func(*v1.ListOptions) diff --git a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/expansion_generated.go b/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/expansion_generated.go deleted file mode 100644 index fe6487bf..00000000 --- a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/expansion_generated.go +++ /dev/null @@ -1,19 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -// ExternalSecretListerExpansion allows custom methods to be added to -// ExternalSecretLister. -type ExternalSecretListerExpansion interface{} - -// ExternalSecretNamespaceListerExpansion allows custom methods to be added to -// ExternalSecretNamespaceLister. -type ExternalSecretNamespaceListerExpansion interface{} - -// SecretStoreListerExpansion allows custom methods to be added to -// SecretStoreLister. -type SecretStoreListerExpansion interface{} - -// SecretStoreNamespaceListerExpansion allows custom methods to be added to -// SecretStoreNamespaceLister. -type SecretStoreNamespaceListerExpansion interface{} diff --git a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/externalsecret.go b/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/externalsecret.go deleted file mode 100644 index 26a23e75..00000000 --- a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/externalsecret.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// ExternalSecretLister helps list ExternalSecrets. -// All objects returned here must be treated as read-only. -type ExternalSecretLister interface { - // List lists all ExternalSecrets in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) - // ExternalSecrets returns an object that can list and get ExternalSecrets. - ExternalSecrets(namespace string) ExternalSecretNamespaceLister - ExternalSecretListerExpansion -} - -// externalSecretLister implements the ExternalSecretLister interface. -type externalSecretLister struct { - indexer cache.Indexer -} - -// NewExternalSecretLister returns a new ExternalSecretLister. -func NewExternalSecretLister(indexer cache.Indexer) ExternalSecretLister { - return &externalSecretLister{indexer: indexer} -} - -// List lists all ExternalSecrets in the indexer. -func (s *externalSecretLister) List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExternalSecret)) - }) - return ret, err -} - -// ExternalSecrets returns an object that can list and get ExternalSecrets. -func (s *externalSecretLister) ExternalSecrets(namespace string) ExternalSecretNamespaceLister { - return externalSecretNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// ExternalSecretNamespaceLister helps list and get ExternalSecrets. -// All objects returned here must be treated as read-only. -type ExternalSecretNamespaceLister interface { - // List lists all ExternalSecrets in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) - // Get retrieves the ExternalSecret from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.ExternalSecret, error) - ExternalSecretNamespaceListerExpansion -} - -// externalSecretNamespaceLister implements the ExternalSecretNamespaceLister -// interface. -type externalSecretNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all ExternalSecrets in the indexer for a given namespace. -func (s externalSecretNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.ExternalSecret, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.ExternalSecret)) - }) - return ret, err -} - -// Get retrieves the ExternalSecret from the indexer for a given namespace and name. -func (s externalSecretNamespaceLister) Get(name string) (*v1alpha1.ExternalSecret, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("externalsecret"), name) - } - return obj.(*v1alpha1.ExternalSecret), nil -} diff --git a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/secretstore.go b/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/secretstore.go deleted file mode 100644 index ca43e8bb..00000000 --- a/ack-secret-manager-cli/pkg/client/listers/alibabacloud/v1alpha1/secretstore.go +++ /dev/null @@ -1,83 +0,0 @@ -// Code generated by lister-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1alpha1 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/labels" - "k8s.io/client-go/tools/cache" -) - -// SecretStoreLister helps list SecretStores. -// All objects returned here must be treated as read-only. -type SecretStoreLister interface { - // List lists all SecretStores in the indexer. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) - // SecretStores returns an object that can list and get SecretStores. - SecretStores(namespace string) SecretStoreNamespaceLister - SecretStoreListerExpansion -} - -// secretStoreLister implements the SecretStoreLister interface. -type secretStoreLister struct { - indexer cache.Indexer -} - -// NewSecretStoreLister returns a new SecretStoreLister. -func NewSecretStoreLister(indexer cache.Indexer) SecretStoreLister { - return &secretStoreLister{indexer: indexer} -} - -// List lists all SecretStores in the indexer. -func (s *secretStoreLister) List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) { - err = cache.ListAll(s.indexer, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.SecretStore)) - }) - return ret, err -} - -// SecretStores returns an object that can list and get SecretStores. -func (s *secretStoreLister) SecretStores(namespace string) SecretStoreNamespaceLister { - return secretStoreNamespaceLister{indexer: s.indexer, namespace: namespace} -} - -// SecretStoreNamespaceLister helps list and get SecretStores. -// All objects returned here must be treated as read-only. -type SecretStoreNamespaceLister interface { - // List lists all SecretStores in the indexer for a given namespace. - // Objects returned here must be treated as read-only. - List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) - // Get retrieves the SecretStore from the indexer for a given namespace and name. - // Objects returned here must be treated as read-only. - Get(name string) (*v1alpha1.SecretStore, error) - SecretStoreNamespaceListerExpansion -} - -// secretStoreNamespaceLister implements the SecretStoreNamespaceLister -// interface. -type secretStoreNamespaceLister struct { - indexer cache.Indexer - namespace string -} - -// List lists all SecretStores in the indexer for a given namespace. -func (s secretStoreNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.SecretStore, err error) { - err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { - ret = append(ret, m.(*v1alpha1.SecretStore)) - }) - return ret, err -} - -// Get retrieves the SecretStore from the indexer for a given namespace and name. -func (s secretStoreNamespaceLister) Get(name string) (*v1alpha1.SecretStore, error) { - obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) - if err != nil { - return nil, err - } - if !exists { - return nil, errors.NewNotFound(v1alpha1.Resource("secretstore"), name) - } - return obj.(*v1alpha1.SecretStore), nil -} diff --git a/ack-secret-manager-cli/pkg/dependencymagnet/doc.go b/ack-secret-manager-cli/pkg/dependencymagnet/doc.go deleted file mode 100644 index d85e1479..00000000 --- a/ack-secret-manager-cli/pkg/dependencymagnet/doc.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build tools -// +build tools - -// go mod won't pull in code that isn't depended upon, but we have some code we don't depend on from code that must be included -// for our build to work. -package dependencymagnet - -import ( - _ "k8s.io/code-generator" -) diff --git a/ack-secret-manager-cli/pkg/k8s/client.go b/ack-secret-manager-cli/pkg/k8s/client.go deleted file mode 100644 index 8eabea96..00000000 --- a/ack-secret-manager-cli/pkg/k8s/client.go +++ /dev/null @@ -1,273 +0,0 @@ -package k8s - -import ( - "context" - "fmt" - - v1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/tools/clientcmd" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - aliababaclientset "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/client/clientset/versioned" -) - -var ( - k8sClient kubernetes.Interface - crdClient aliababaclientset.Interface -) - -func InitClient(filePath string) error { - config, err := clientcmd.BuildConfigFromFlags("", filePath) - if err != nil { - return err - } - crdClient, err = aliababaclientset.NewForConfig(config) - if err != nil { - return err - } - k8sClient, err = kubernetes.NewForConfig(config) - if err != nil { - return err - } - return nil -} - -func CreateSecretStoreByRRSA(name, namespace, provider, ramRole string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: &v1alpha1.KMSAuth{ - OIDCProviderARN: provider, - RAMRoleARN: ramRole, - }, - }, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateSecretStoreByAKSK(name, namespace, akName, akNamespace, akKey, skName, skNamespace, skKey, ramRoleArn, roleSession string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: &v1alpha1.KMSAuth{ - AccessKey: &v1alpha1.SecretRef{ - Name: akName, - Namespace: akNamespace, - Key: akKey, - }, - AccessKeySecret: &v1alpha1.SecretRef{ - Name: skName, - Namespace: skNamespace, - Key: skKey, - }, - }, - }, - }, - } - if ramRoleArn != "" { - secretStore.Spec.KMS.KMS.RAMRoleARN = ramRoleArn - secretStore.Spec.KMS.KMS.RAMRoleSessionName = roleSession - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CheckSecretKeyExist(name, namespace, key string) (bool, error) { - ctx := context.Background() - secret, err := k8sClient.CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - return false, nil - } - return false, err - } - _, ok := secret.Data[key] - if ok { - return true, nil - } - return false, nil -} - -func CreateOrUpdateSecret(name, namespace, key, value string) error { - ctx := context.Background() - secret, err := k8sClient.CoreV1().Secrets(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - if errors.IsNotFound(err) { - newSecret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Data: map[string][]byte{ - key: []byte(value), - }, - } - _, err = k8sClient.CoreV1().Secrets(namespace).Create(ctx, newSecret, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil - } - return err - } - secret.Data[key] = []byte(value) - _, err = k8sClient.CoreV1().Secrets(namespace).Update(ctx, secret, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateEmptySecretStore(name, namespace string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - KMS: nil, - }, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateDKMSSecretStore(name, namespace, ckName, ckNamespace, ckKey, pwName, pwNamespace, pwKey, cert, endpoint string) error { - ctx := context.Background() - secretStore := &v1alpha1.SecretStore{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.SecretStoreSpec{ - KMS: &v1alpha1.KMSProvider{ - DedicatedKMS: &v1alpha1.DedicatedKMSAuth{ - Protocol: "https", - Endpoint: endpoint, - ClientKeyContent: &v1alpha1.SecretRef{ - Name: ckName, - Namespace: ckNamespace, - Key: ckKey, - }, - Password: &v1alpha1.SecretRef{ - Name: pwName, - Namespace: pwNamespace, - Key: pwKey, - }, - }, - }, - }, - } - if cert == "" { - secretStore.Spec.KMS.DedicatedKMS.IgnoreSSL = true - } else { - secretStore.Spec.KMS.DedicatedKMS.IgnoreSSL = false - secretStore.Spec.KMS.DedicatedKMS.CA = cert - } - _, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Create(ctx, secretStore, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} - -func ListSecretStore(limit int64, continueToken string) ([]v1alpha1.SecretStore, string, error) { - ctx := context.Background() - listOption := metav1.ListOptions{ - Limit: limit, - Continue: continueToken, - } - secretstores, err := crdClient.AlibabacloudV1alpha1().SecretStores("").List(ctx, listOption) - if err != nil { - return nil, continueToken, err - } - return secretstores.Items, secretstores.Continue, nil -} - -func GetSecretStoreAndUpdate(name, namespace, remoteRoleArn, remoteRoleSession string) error { - ctx := context.Background() - secretstore, err := crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Get(ctx, name, metav1.GetOptions{}) - if err != nil { - return err - } - if secretstore.Spec.KMS.DedicatedKMS != nil { - return fmt.Errorf("dkms SecretStore %s/%s does not support cross-account", namespace, name) - } - if secretstore.Spec.KMS.KMS == nil { - secretstore.Spec.KMS.KMS = &v1alpha1.KMSAuth{ - RemoteRAMRoleSessionName: remoteRoleSession, - RemoteRAMRoleARN: remoteRoleArn, - } - } else { - secretstore.Spec.KMS.KMS.RemoteRAMRoleARN = remoteRoleArn - secretstore.Spec.KMS.KMS.RemoteRAMRoleSessionName = remoteRoleSession - } - _, err = crdClient.AlibabacloudV1alpha1().SecretStores(namespace).Update(ctx, secretstore, metav1.UpdateOptions{}) - if err != nil { - return err - } - return nil -} - -func CreateExternalSecret(data []v1alpha1.DataSource, dataProcess []v1alpha1.DataProcess, name, namespace, secretType string) error { - ctx := context.Background() - es := &v1alpha1.ExternalSecret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - Labels: map[string]string{ - "creator": "ack-secret-manager-cli", - }, - }, - Spec: v1alpha1.ExternalSecretSpec{ - Provider: "kms", - Data: data, - Type: secretType, - DataProcess: dataProcess, - }, - } - _, err := crdClient.AlibabacloudV1alpha1().ExternalSecrets(namespace).Create(ctx, es, metav1.CreateOptions{}) - if err != nil { - return err - } - return nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/basic.go b/ack-secret-manager-cli/pkg/model/externalsecret/basic.go deleted file mode 100644 index 32397c6c..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/basic.go +++ /dev/null @@ -1,200 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - info2 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type BasicESModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - isProcess bool -} - -func init() { - m := initialBasicESModel() - model.InitModelMap["basic"] = m -} - -func initialBasicESModel() *BasicESModel { - m := &BasicESModel{ - inputs: make([]textinput.Model, 4), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "KMS credential Name > " - t.Placeholder = "KMS credential name" - case 1: - t.Prompt = "KMS Secret Key > " - t.Placeholder = "corresponding key of KMS credentials in k8s secret" - case 2: - t.Prompt = "Version Stage > " - t.Placeholder = "Version Stage" - case 3: - t.Prompt = "Version ID > " - t.Placeholder = "Version ID" - } - m.inputs[i] = t - } - - return m -} - -func (m *BasicESModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *BasicESModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *BasicESModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *BasicESModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the basic externalsecret data configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *BasicESModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *BasicESModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info2.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("KMS credential name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.isProcess { - processIndex := len(process) - 1 - if process[processIndex].Extract == nil { - process[processIndex].Extract = &v1alpha1.DataSource{} - } - process[processIndex].Extract.Name = m.inputs[1].Value() - process[processIndex].Extract.Key = m.inputs[0].Value() - process[processIndex].Extract.VersionStage = m.inputs[2].Value() - process[processIndex].Extract.VersionId = m.inputs[3].Value() - next := model.InitModelMap["replace"] - next.SetPreModel(m) - return next, nil - } else { - dataIndex := len(data) - 1 - data[dataIndex].Name = m.inputs[1].Value() - data[dataIndex].Key = m.inputs[0].Value() - data[dataIndex].VersionStage = m.inputs[2].Value() - data[dataIndex].VersionId = m.inputs[3].Value() - next := model.InitModelMap["jmes"] - next.SetPreModel(m) - return next, nil - } - } - return m, nil -} - -func (m *BasicESModel) SetType(isProcess bool) { - m.isProcess = isProcess -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/continue.go b/ack-secret-manager-cli/pkg/model/externalsecret/continue.go deleted file mode 100644 index 48888ac6..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/continue.go +++ /dev/null @@ -1,104 +0,0 @@ -package externalsecret - -import ( - "fmt" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ContinueModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func init() { - m := initContinueModel() - model.InitModelMap["continue"] = m -} -func initContinueModel() *ContinueModel { - items := []list.Item{ - item("Yes"), - item("No"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &ContinueModel{ - list: l, - } -} - -func (m *ContinueModel) Init() tea.Cmd { - return nil -} - -func (m *ContinueModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *ContinueModel) View() string { - return "\n" + m.list.View() -} - -func (m *ContinueModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ContinueModel) SetTitle(title string) { - m.list.Title = title -} - -func (m *ContinueModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.choice == "Yes" { - next := model.InitModelMap["data"] - next.SetPreModel(m) - return next, nil - } else { - err := k8s.CreateExternalSecret(data, process, externalSecretName, externalSecretNamespace, secretType) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(nil) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create externalsecret %s/%s success", externalSecretNamespace, externalSecretName)) - eModel.SetPreModel(nil) - return eModel, nil - } -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/css.go b/ack-secret-manager-cli/pkg/model/externalsecret/css.go deleted file mode 100644 index 113d6b10..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/css.go +++ /dev/null @@ -1,70 +0,0 @@ -package externalsecret - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) - - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - inputTitleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - focusedContinueButton = focusedStyle.Copy().Render("[ Continue ]") - focusedSkipButton = focusedStyle.Copy().Render("[ Skip ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) - continueButton = fmt.Sprintf("%s", noStyle.Render("[ Continue ]")) - skipButton = fmt.Sprintf("%s", noStyle.Render("[ Skip ]")) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/datatype.go b/ack-secret-manager-cli/pkg/model/externalsecret/datatype.go deleted file mode 100644 index a9183c74..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/datatype.go +++ /dev/null @@ -1,96 +0,0 @@ -package externalsecret - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type DataModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func init() { - m := initDataModel() - model.InitModelMap["data"] = m -} -func initDataModel() *DataModel { - items := []list.Item{ - item("Data"), - item("DataProcess"), - } - items = append(items, item("\n[Previous]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select data source type" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &DataModel{ - list: l, - } -} - -func (m *DataModel) Init() tea.Cmd { - return nil -} - -func (m *DataModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *DataModel) View() string { - return "\n" + m.list.View() -} - -func (m *DataModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *DataModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - return m.preModel, nil - } - next := model.InitModelMap["basic"] - bModel, ok := next.(*BasicESModel) - if !ok { - return m, nil - } - if m.choice == "Data" { - data = append(data, v1alpha1.DataSource{}) - bModel.SetType(false) - } else { - process = append(process, v1alpha1.DataProcess{}) - bModel.SetType(true) - } - bModel.SetPreModel(m) - return bModel, nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/externalsecret.go b/ack-secret-manager-cli/pkg/model/externalsecret/externalsecret.go deleted file mode 100644 index a27ba496..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/externalsecret.go +++ /dev/null @@ -1,185 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ExternalSecretModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialExternalSecretModel() - model.InitModelMap["external"] = m -} - -func initialExternalSecretModel() *ExternalSecretModel { - m := &ExternalSecretModel{ - inputs: make([]textinput.Model, 3), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "External Secret Name > " - t.Placeholder = "k8s resource name" - case 1: - t.Prompt = "External Secret Namespace > " - t.Placeholder = "k8s resource name" - case 2: - t.Prompt = "Secret Type > " - t.Placeholder = "Opaque" - } - m.inputs[i] = t - } - - return m -} - -func (m *ExternalSecretModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ExternalSecretModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ExternalSecretModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ExternalSecretModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the basic externalsecret data configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *ExternalSecretModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ExternalSecretModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("external secret name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("external secret namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("secret type cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - externalSecretName = m.inputs[0].Value() - externalSecretNamespace = m.inputs[1].Value() - secretType = m.inputs[2].Value() - next := model.InitModelMap["data"] - next.SetPreModel(m) - return next, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/jmes.go b/ack-secret-manager-cli/pkg/model/externalsecret/jmes.go deleted file mode 100644 index 294079b1..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/jmes.go +++ /dev/null @@ -1,209 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type JMESModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialJMESModelModel() - model.InitModelMap["jmes"] = m -} - -func initialJMESModelModel() *JMESModel { - m := &JMESModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "Path > " - t.Placeholder = "position in json string" - case 1: - t.Prompt = "ObjectAlias > " - t.Placeholder = "the key in k8s secret" - } - m.inputs[i] = t - } - - return m -} - -func (m *JMESModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *JMESModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+2 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 2 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *JMESModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *JMESModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the jmes configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - continueB := &continueButton - if m.focusIndex == len(m.inputs) { - continueB = &focusedContinueButton - } - button := &blurredButton - if m.focusIndex == len(m.inputs)+1 { - button = &focusedButton - } - skip := &skipButton - if m.focusIndex == len(m.inputs)+2 { - skip = &focusedSkipButton - } - fmt.Fprintf(&b, "\n\n%s ", *continueB) - fmt.Fprintf(&b, "%s ", *button) - fmt.Fprintf(&b, "%s\n\n ", *skip) - return b.String() -} - -func (m *JMESModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *JMESModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.focusIndex == len(m.inputs) || m.focusIndex == len(m.inputs)+1 { - if m.inputs[0].Value() == "" { - eModel.SetInfo("json path cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo("json objectAlias cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - dataIndex := len(data) - 1 - if data[dataIndex].JMESPath == nil { - data[dataIndex].JMESPath = make([]v1alpha1.JMESPathObject, 0) - } - data[dataIndex].JMESPath = append(data[dataIndex].JMESPath, v1alpha1.JMESPathObject{ - Path: m.inputs[0].Value(), - ObjectAlias: m.inputs[1].Value(), - }) - if m.focusIndex == len(m.inputs)+1 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(false) - return sModel, nil - } else { - for i, input := range m.inputs { - input.Reset() - m.inputs[i] = input - } - } - } - if m.focusIndex == len(m.inputs)+2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(false) - return sModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/replace.go b/ack-secret-manager-cli/pkg/model/externalsecret/replace.go deleted file mode 100644 index c364c3eb..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/replace.go +++ /dev/null @@ -1,211 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ReplaceModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialReplaceModelModel() - model.InitModelMap["replace"] = m -} - -func initialReplaceModelModel() *ReplaceModel { - m := &ReplaceModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "Source > " - t.Placeholder = "the string that needs to be replaced (supports regular expressions)" - case 1: - t.Prompt = "Target > " - t.Placeholder = "target string when replacing" - } - m.inputs[i] = t - } - - return m -} - -func (m *ReplaceModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ReplaceModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+2 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 2 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ReplaceModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ReplaceModel) View() string { - var b strings.Builder - - b.WriteString(inputTitleStyle.Render("Please enter the replace configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - continueB := &continueButton - if m.focusIndex == len(m.inputs) { - continueB = &focusedContinueButton - } - button := &blurredButton - if m.focusIndex == len(m.inputs)+1 { - button = &focusedButton - } - skip := &skipButton - if m.focusIndex == len(m.inputs)+2 { - skip = &focusedSkipButton - } - fmt.Fprintf(&b, "\n\n%s ", *continueB) - fmt.Fprintf(&b, "%s ", *button) - fmt.Fprintf(&b, "%s\n\n ", *skip) - - return b.String() -} - -func (m *ReplaceModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ReplaceModel) Next() (model.Model, tea.Cmd) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.focusIndex == len(m.inputs) || m.focusIndex == len(m.inputs)+1 { - if m.inputs[0].Value() == "" { - eModel.SetInfo("source string cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo("target string cannot be empty") - eModel.SetPreModel(m) - return eModel, nil - } - processIndex := len(process) - 1 - if process[processIndex].ReplaceKey == nil { - process[processIndex].ReplaceKey = make([]v1alpha1.ReplaceRule, 0) - } - process[processIndex].ReplaceKey = append(process[processIndex].ReplaceKey, v1alpha1.ReplaceRule{ - Source: m.inputs[0].Value(), - Target: m.inputs[1].Value(), - }) - if m.focusIndex == len(m.inputs)+1 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(true) - return sModel, nil - } else { - for i, input := range m.inputs { - input.Reset() - m.inputs[i] = input - } - } - return m, nil - } - if m.focusIndex == len(m.inputs)+2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - next := model.InitModelMap["secret-store-ref"] - sModel, ok := next.(*SecretStoreRefModel) - if !ok { - return m, nil - } - sModel.SetPreModel(m) - sModel.SetType(true) - return sModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/secretstoreref.go b/ack-secret-manager-cli/pkg/model/externalsecret/secretstoreref.go deleted file mode 100644 index 4e7e79fe..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/secretstoreref.go +++ /dev/null @@ -1,150 +0,0 @@ -package externalsecret - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type SecretStoreRefModel struct { - list list.Model - choice string - quitting bool - preModel model.Model - continueToken string - isProcess bool -} - -const ( - limit = 5 -) - -func InitSecretStoreRefModel() *SecretStoreRefModel { - secretStores, continueToken, err := k8s.ListSecretStore(limit, "") - if err != nil { - panic(err) - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("[Previous]")) - items = append(items, item("[Skip]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select an existing SecretStore for SecretStoreRef configuration" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &SecretStoreRefModel{ - list: l, - continueToken: continueToken, - } -} - -func (m *SecretStoreRefModel) Init() tea.Cmd { - return nil -} - -func (m *SecretStoreRefModel) SetType(isProcess bool) { - m.isProcess = isProcess -} -func (m *SecretStoreRefModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *SecretStoreRefModel) View() string { - return "\n" + m.list.View() -} - -func (m *SecretStoreRefModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *SecretStoreRefModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-2 { - model.InitModelMap["secret-store-ref"] = InitSecretStoreRefModel() - return m.preModel, nil - } - if m.choice == "[Skip]" { - next := model.InitModelMap["continue"] - cModel, ok := next.(*ContinueModel) - if !ok { - return m, nil - } - cModel.SetTitle("Do you want to continue adding data?") - cModel.SetPreModel(m) - return cModel, nil - } - if m.choice == "Next Page" { - secretStores, continueToken, err := k8s.ListSecretStore(limit, m.continueToken) - if err != nil { - return m, nil - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("[Previous]")) - m.list.SetItems(items) - m.continueToken = continueToken - return m, nil - } - names := strings.Split(strings.Split(m.choice, " ")[1], "/") - if m.isProcess { - processIndex := len(process) - 1 - process[processIndex].Extract.SecretStoreRef = &v1alpha1.SecretStoreRef{ - Name: names[1], - Namespace: names[0], - } - } else { - dataIndex := len(data) - 1 - data[dataIndex].SecretStoreRef = &v1alpha1.SecretStoreRef{ - Name: names[1], - Namespace: names[0], - } - } - next := model.InitModelMap["continue"] - cModel, ok := next.(*ContinueModel) - if !ok { - return m, nil - } - cModel.SetTitle("Do you want to continue adding data?") - cModel.SetPreModel(m) - return cModel, nil -} diff --git a/ack-secret-manager-cli/pkg/model/externalsecret/sum.go b/ack-secret-manager-cli/pkg/model/externalsecret/sum.go deleted file mode 100644 index 50c43146..00000000 --- a/ack-secret-manager-cli/pkg/model/externalsecret/sum.go +++ /dev/null @@ -1,11 +0,0 @@ -package externalsecret - -import "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/apis/alibabacloud/v1alpha1" - -var ( - data = make([]v1alpha1.DataSource, 0) - process = make([]v1alpha1.DataProcess, 0) - externalSecretName string - externalSecretNamespace string - secretType string -) diff --git a/ack-secret-manager-cli/pkg/model/info/css.go b/ack-secret-manager-cli/pkg/model/info/css.go deleted file mode 100644 index d9da8a53..00000000 --- a/ack-secret-manager-cli/pkg/model/info/css.go +++ /dev/null @@ -1,20 +0,0 @@ -package info - -import ( - "fmt" - - "github.com/charmbracelet/lipgloss" -) - -var ( - titleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - helpStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("240")).PaddingLeft(2) - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) -) diff --git a/ack-secret-manager-cli/pkg/model/info/info.go b/ack-secret-manager-cli/pkg/model/info/info.go deleted file mode 100644 index 764cb0fc..00000000 --- a/ack-secret-manager-cli/pkg/model/info/info.go +++ /dev/null @@ -1,64 +0,0 @@ -package info - -import ( - "strings" - - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type InfoModel struct { - info string - preModel model.Model -} - -func init() { - m := initialModel() - model.InitModelMap["info"] = m -} - -func initialModel() *InfoModel { - m := &InfoModel{} - return m -} - -func (m *InfoModel) SetInfo(info string) { - m.info = info -} - -func (m *InfoModel) Init() tea.Cmd { - return nil -} - -func (m *InfoModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - return m.Next() - } - } - return m, nil -} - -func (m *InfoModel) View() string { - var b strings.Builder - b.WriteString(titleStyle.Render(m.info) + "\n") - b.WriteString(helpStyle.Render("Press \"Enter\" to continue")) - return b.String() -} - -func (m *InfoModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *InfoModel) Next() (model.Model, tea.Cmd) { - if m.preModel == nil { - return m, tea.Quit - } - return m.preModel, nil -} diff --git a/ack-secret-manager-cli/pkg/model/info/secret.go b/ack-secret-manager-cli/pkg/model/info/secret.go deleted file mode 100644 index beeaa4ff..00000000 --- a/ack-secret-manager-cli/pkg/model/info/secret.go +++ /dev/null @@ -1,199 +0,0 @@ -package info - -import ( - "fmt" - "os" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -type SecretModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - secretName string - secretNamespace string - secretKey string - needLoad bool -} - -func init() { - m := initialSecretModel() - model.InitModelMap["secret"] = m -} - -func initialSecretModel() *SecretModel { - m := &SecretModel{ - inputs: make([]textinput.Model, 1), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - //t.Prompt = "OIDC Provider Arn > " - //t.Placeholder = OidcProviderARNExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.EchoMode = textinput.EchoPassword - t.EchoCharacter = '•' - } - - m.inputs[i] = t - } - - return m -} - -func (m *SecretModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *SecretModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *SecretModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *SecretModel) View() string { - var b strings.Builder - b.WriteString(titleStyle.Render("The corresponding secret does not exist in the cluster, a new secret will be created, please fill in a new value") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *SecretModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *SecretModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("%v cannot be empty", m.inputs[0].Prompt)) - eModel.SetPreModel(m) - return eModel, nil - } - var value string - value = m.inputs[0].Value() - if m.needLoad { - str, err := os.ReadFile(value) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - value = string(str) - } - err := k8s.CreateOrUpdateSecret(m.secretName, m.secretNamespace, m.secretKey, value) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create secret key %s/%s/%s success", m.secretNamespace, m.secretName, m.secretKey)) - eModel.SetPreModel(m.preModel) - m.inputs[0].Reset() - return eModel, nil - } - return m, nil -} - -func (m *SecretModel) SetInfo(info, name, namespace, key string, load bool) { - m.inputs[0].Prompt = info - m.secretNamespace = namespace - m.secretName = name - m.secretKey = key - m.needLoad = load -} diff --git a/ack-secret-manager-cli/pkg/model/init/crd.go b/ack-secret-manager-cli/pkg/model/init/crd.go deleted file mode 100644 index df1d92b9..00000000 --- a/ack-secret-manager-cli/pkg/model/init/crd.go +++ /dev/null @@ -1,95 +0,0 @@ -package list - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -func init() { - crdModel := InitCRDModel() - model.InitModelMap["crd"] = crdModel -} - -type CrdModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func InitCRDModel() *CrdModel { - items := []list.Item{ - item("SecretStore"), - item("ExternalSecret"), - item("\n[Exit]"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select the CRD you want to create" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &CrdModel{ - list: l, - } -} - -func (m *CrdModel) Init() tea.Cmd { - return nil -} - -func (m *CrdModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *CrdModel) View() string { - return "\n" + m.list.View() -} - -func (m *CrdModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrdModel) Next() (model.Model, tea.Cmd) { - var next model.Model - if m.choice == "SecretStore" { - next = model.InitModelMap["authentication"] - } else if m.choice == "ExternalSecret" { - next = model.InitModelMap["external"] - } else { - return m, tea.Quit - } - next.SetPreModel(m) - return next, nil -} - -//m := InitCRDModel() -// if _, err := tea.NewProgram(m).Run(); err != nil { -// fmt.Println("Error running program:", err) -// os.Exit(1) -// } diff --git a/ack-secret-manager-cli/pkg/model/init/css.go b/ack-secret-manager-cli/pkg/model/init/css.go deleted file mode 100644 index d1eb434f..00000000 --- a/ack-secret-manager-cli/pkg/model/init/css.go +++ /dev/null @@ -1,56 +0,0 @@ -package list - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/pkg/model/model.go b/ack-secret-manager-cli/pkg/model/model.go deleted file mode 100644 index 1dbc6b60..00000000 --- a/ack-secret-manager-cli/pkg/model/model.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -import tea "github.com/charmbracelet/bubbletea" - -type Model interface { - // bubbletea - Init() tea.Cmd - Update(msg tea.Msg) (tea.Model, tea.Cmd) - View() string - - Next() (Model, tea.Cmd) - SetPreModel(model Model) -} - -var InitModelMap = make(map[string]Model) diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/ak.go b/ack-secret-manager-cli/pkg/model/secretstore/input/ak.go deleted file mode 100644 index 7c1dd9ab..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/ak.go +++ /dev/null @@ -1,263 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type AKModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialAKModel() - model.InitModelMap["ak"] = m -} - -func initialAKModel() *AKModel { - m := &AKModel{ - inputs: make([]textinput.Model, 8), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "AK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key" - case 1: - t.Prompt = "AK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key" - case 2: - t.Prompt = "AK SecretRef key > " - t.Placeholder = "the key of the secret that stores the access key" - case 3: - t.Prompt = "SK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key secret" - case 4: - t.Prompt = "SK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key secret" - case 5: - t.Prompt = "SK SecretRef key > " - t.Placeholder = "the key of the secret that stores the access key secret" - case 6: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 7: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - } - m.inputs[i] = t - } - - return m -} - -func (m *AKModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *AKModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *AKModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *AKModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ak configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *AKModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *AKModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[6].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key > ", m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key Secret > ", m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateSecretStoreByAKSK(m.inputs[6].Value(), m.inputs[7].Value(), m.inputs[0].Value(), - m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), - m.inputs[4].Value(), m.inputs[5].Value(), "", "") - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[7].Value(), m.inputs[6].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/cross.go b/ack-secret-manager-cli/pkg/model/secretstore/input/cross.go deleted file mode 100644 index c81b2965..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/cross.go +++ /dev/null @@ -1,189 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -type CrossModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model - name string - namespace string -} - -func init() { - m := initialCrossModel() - model.InitModelMap["cross"] = m -} - -func initialCrossModel() *CrossModel { - m := &CrossModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Prompt = "Remote RAM Role Arn > " - t.Placeholder = RamRoleArnExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - case 1: - t.Prompt = "Remote Role Session Name > " - t.Placeholder = "role session name" - } - m.inputs[i] = t - } - - return m -} - -func (m *CrossModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *CrossModel) SetInfo(name, namespace string) { - m.name = name - m.namespace = namespace -} -func (m *CrossModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *CrossModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *CrossModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the cross-account configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *CrossModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrossModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - nextModel := model.InitModelMap["info"] - eModel, ok := nextModel.(*info.InfoModel) - if !ok { - return m, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[0].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("remote role session name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.GetSecretStoreAndUpdate(m.name, m.namespace, m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("update SecretStore %s/%s success", m.namespace, m.name)) - eModel.SetPreModel(nil) - return eModel, nil - } - - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/css.go b/ack-secret-manager-cli/pkg/model/secretstore/input/css.go deleted file mode 100644 index a2c2391d..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/css.go +++ /dev/null @@ -1,19 +0,0 @@ -package input - -import ( - "fmt" - - "github.com/charmbracelet/lipgloss" -) - -var ( - focusedStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("205")).PaddingLeft(4) - cursorStyle = focusedStyle.Copy() - titleStyle = lipgloss.NewStyle().PaddingBottom(1).PaddingTop(1).PaddingLeft(2) - noStyle = lipgloss.NewStyle().PaddingLeft(4) - - focusedButton = focusedStyle.Copy().Render("[ Submit ]") - focusedPreviousButton = focusedStyle.Copy().Render("[ Previous ]") - blurredButton = fmt.Sprintf("%s", noStyle.Render("[ Submit ]")) - previousButton = fmt.Sprintf("%s", noStyle.Render("[ Previous ]")) -) diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/dkms.go b/ack-secret-manager-cli/pkg/model/secretstore/input/dkms.go deleted file mode 100644 index ad264ba1..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/dkms.go +++ /dev/null @@ -1,275 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type DKMSModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialDKMSModel() - model.InitModelMap["dkms"] = m -} - -func initialDKMSModel() *DKMSModel { - m := &DKMSModel{ - inputs: make([]textinput.Model, 10), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "DKMS InstanceID > " - t.Placeholder = "kst-xxxxxxxxxxxxxxxxxxxxx" - case 1: - t.Prompt = "ClientKey SecretRef Name > " - t.Placeholder = "the name of the secret that stores the client key" - case 2: - t.Prompt = "ClientKey SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the client key" - case 3: - t.Prompt = "ClientKey SecretRef key > " - t.Placeholder = "the key of the secret that stores the client key" - case 4: - t.Prompt = "Password SecretRef Name > " - t.Placeholder = "the name of the secret that stores the password" - case 5: - t.Prompt = "Password SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the password" - case 6: - t.Prompt = "Password SecretRef key > " - t.Placeholder = "the key of the secret that stores the password" - case 7: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 8: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - case 9: - t.Prompt = "CA Cert > " - t.Placeholder = "CA Cert Content(optional, base64 encoding)" - t.CharLimit = 10000 - } - - m.inputs[i] = t - } - return m -} - -func (m *DKMSModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *DKMSModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *DKMSModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *DKMSModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ak configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *DKMSModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *DKMSModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("DKMS InstanceID cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("ClientKey SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[6].Value() == "" { - eModel.SetInfo(fmt.Sprintf("Password SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[8].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Client Key File Path > ", m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), true) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Password > ", m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateDKMSSecretStore(m.inputs[7].Value(), m.inputs[8].Value(), m.inputs[1].Value(), - m.inputs[2].Value(), m.inputs[3].Value(), m.inputs[4].Value(), - m.inputs[5].Value(), m.inputs[6].Value(), m.inputs[9].Value(), m.inputs[0].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[8].Value(), m.inputs[7].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/ecs.go b/ack-secret-manager-cli/pkg/model/secretstore/input/ecs.go deleted file mode 100644 index ce3f32e2..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/ecs.go +++ /dev/null @@ -1,181 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" -) - -type ECSModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialECSModel() - model.InitModelMap["ecs"] = m -} - -func initialECSModel() *ECSModel { - m := &ECSModel{ - inputs: make([]textinput.Model, 2), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 1: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource namespace" - } - m.inputs[i] = t - } - - return m -} - -func (m *ECSModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *ECSModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *ECSModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *ECSModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ecs ram role configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *ECSModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *ECSModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.CreateEmptySecretStore(m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[1].Value(), m.inputs[0].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/ramrole.go b/ack-secret-manager-cli/pkg/model/secretstore/input/ramrole.go deleted file mode 100644 index f3acd0aa..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/ramrole.go +++ /dev/null @@ -1,281 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - info2 "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -type RoleModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialRAMRoleModel() - model.InitModelMap["role"] = m -} - -func initialRAMRoleModel() *RoleModel { - m := &RoleModel{ - inputs: make([]textinput.Model, 10), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - t.Prompt = "AK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key" - case 1: - t.Prompt = "AK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key" - case 2: - t.Prompt = "AK SecretRef Key > " - t.Placeholder = "the key of the secret key that stores the access key" - case 3: - t.Prompt = "SK SecretRef Name > " - t.Placeholder = "the name of the secret that stores the access key secret" - case 4: - t.Prompt = "SK SecretRef Namespace > " - t.Placeholder = "the namespace of the secret that stores the access key secret" - case 5: - t.Prompt = "SK SecretRef Key > " - t.Placeholder = "the key of the secret that stores the access key secret" - case 6: - t.Prompt = "RAM Role Arn > " - t.Placeholder = RamRoleArnExample - case 7: - t.Prompt = "Role Session Name > " - t.Placeholder = "role session name" - case 8: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - case 9: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - } - m.inputs[i] = t - } - - return m -} - -func (m *RoleModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *RoleModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *RoleModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *RoleModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the ram role configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *RoleModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *RoleModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - tempModel := model.InitModelMap["info"] - eModel, ok := tempModel.(*info2.InfoModel) - if !ok { - return m, nil - } - if m.inputs[0].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[1].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("AK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[4].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[5].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SK SecretRef key cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[6].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[7].Value() == "" { - eModel.SetInfo(fmt.Sprintf("role session name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[8].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - - if m.inputs[9].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - exist, err := k8s.CheckSecretKeyExist(m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info2.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key > ", m.inputs[0].Value(), m.inputs[1].Value(), m.inputs[2].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - exist, err = k8s.CheckSecretKeyExist(m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - if !exist { - sModel := model.InitModelMap["secret"] - secretModel, ok := sModel.(*info2.SecretModel) - if !ok { - return m, nil - } - secretModel.SetInfo("Access Key Secret > ", m.inputs[3].Value(), m.inputs[4].Value(), m.inputs[5].Value(), false) - secretModel.SetPreModel(m) - return secretModel, nil - } - err = k8s.CreateSecretStoreByAKSK(m.inputs[8].Value(), m.inputs[9].Value(), m.inputs[0].Value(), - m.inputs[1].Value(), m.inputs[2].Value(), m.inputs[3].Value(), - m.inputs[4].Value(), m.inputs[5].Value(), m.inputs[6].Value(), m.inputs[7].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[9].Value(), m.inputs[8].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/input/rrsa.go b/ack-secret-manager-cli/pkg/model/secretstore/input/rrsa.go deleted file mode 100644 index 51a2716d..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/input/rrsa.go +++ /dev/null @@ -1,211 +0,0 @@ -package input - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/cursor" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/info" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/utils" -) - -const ( - OidcProviderARNRegex = "acs:ram::.*:oidc-provider/ack-rrsa-.*" - RamRoleArnRegex = "acs:ram::.*:role/.*" - RamRoleArnExample = "acs:ram::{accountID}:role/{roleName}" - OidcProviderARNExample = "acs:ram::{accountID}:oidc-provider/ack-rrsa-{cluster-id}" -) - -type RRSAModel struct { - focusIndex int - inputs []textinput.Model - cursorMode cursor.Mode - preModel model.Model -} - -func init() { - m := initialRRSAModel() - model.InitModelMap["rrsa"] = m -} - -func initialRRSAModel() *RRSAModel { - m := &RRSAModel{ - inputs: make([]textinput.Model, 4), - } - - var t textinput.Model - for i := range m.inputs { - t = textinput.New() - t.Cursor.Style = cursorStyle - t.CharLimit = 256 - t.PromptStyle = noStyle - switch i { - case 0: - t.Prompt = "OIDC Provider Arn > " - t.Placeholder = OidcProviderARNExample - t.Focus() - t.PromptStyle = focusedStyle - t.TextStyle = focusedStyle - case 1: - t.Prompt = "RAM Role Arn > " - t.Placeholder = RamRoleArnExample - case 2: - t.Prompt = "SecretStore Name > " - t.Placeholder = "k8s resource name" - //t.EchoMode = textinput.EchoPassword - //t.EchoCharacter = '•' - case 3: - t.Prompt = "SecretStore Namespace > " - t.Placeholder = "k8s resource name" - //t.EchoMode = textinput.EchoPassword - //t.EchoCharacter = '•' - } - - m.inputs[i] = t - } - - return m -} - -func (m *RRSAModel) Init() tea.Cmd { - return textinput.Blink -} - -func (m *RRSAModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.KeyMsg: - switch msg.String() { - case "ctrl+c", "esc": - return m, tea.Quit - // Set focus to next input - case "tab", "shift+tab", "enter", "up", "down": - s := msg.String() - if s == "enter" { - return m.Next() - } - // Cycle indexes - if s == "up" || s == "shift+tab" { - m.focusIndex-- - } else { - m.focusIndex++ - } - - if m.focusIndex > len(m.inputs)+1 { - m.focusIndex = 0 - } else if m.focusIndex < 0 { - m.focusIndex = len(m.inputs) + 1 - } - - cmds := make([]tea.Cmd, len(m.inputs)) - for i := 0; i <= len(m.inputs)-1; i++ { - if i == m.focusIndex { - // Set focused state - cmds[i] = m.inputs[i].Focus() - m.inputs[i].PromptStyle = focusedStyle - m.inputs[i].TextStyle = focusedStyle - continue - } - // Remove focused state - m.inputs[i].Blur() - m.inputs[i].PromptStyle = noStyle - m.inputs[i].TextStyle = noStyle - } - - return m, tea.Batch(cmds...) - } - } - - // Handle character input and blinking - cmd := m.updateInputs(msg) - - return m, cmd -} - -func (m *RRSAModel) updateInputs(msg tea.Msg) tea.Cmd { - cmds := make([]tea.Cmd, len(m.inputs)) - - // Only text inputs with Focus() set will respond, so it's safe to simply - // update all of them here without any further logic. - for i := range m.inputs { - m.inputs[i], cmds[i] = m.inputs[i].Update(msg) - } - - return tea.Batch(cmds...) -} - -func (m *RRSAModel) View() string { - var b strings.Builder - - b.WriteString(titleStyle.Render("Please enter the rrsa configuration") + "\n") - for i := range m.inputs { - b.WriteString(m.inputs[i].View()) - if i < len(m.inputs)-1 { - b.WriteRune('\n') - } - } - - button := &blurredButton - if m.focusIndex == len(m.inputs) { - button = &focusedButton - } - previous := &previousButton - if m.focusIndex == len(m.inputs)+1 { - previous = &focusedPreviousButton - } - fmt.Fprintf(&b, "\n\n%s ", *button) - fmt.Fprintf(&b, "%s \n\n", *previous) - return b.String() -} - -func (m *RRSAModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *RRSAModel) Next() (model.Model, tea.Cmd) { - if m.focusIndex == len(m.inputs)+1 { - return m.preModel, nil - } - if m.focusIndex == len(m.inputs) { - nextModel := model.InitModelMap["info"] - eModel, ok := nextModel.(*info.InfoModel) - if !ok { - return m, nil - } - if !utils.IsMatchRegex(OidcProviderARNRegex, m.inputs[0].Value()) { - eModel.SetInfo(fmt.Sprintf("oidc provider arn fmt error, must be %v", OidcProviderARNExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if !utils.IsMatchRegex(RamRoleArnRegex, m.inputs[1].Value()) { - eModel.SetInfo(fmt.Sprintf("ram role arn fmt error, must be %v", RamRoleArnExample)) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[2].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore Name cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - if m.inputs[3].Value() == "" { - eModel.SetInfo(fmt.Sprintf("SecretStore Namespace cannot be empty")) - eModel.SetPreModel(m) - return eModel, nil - } - err := k8s.CreateSecretStoreByRRSA(m.inputs[2].Value(), m.inputs[3].Value(), m.inputs[0].Value(), m.inputs[1].Value()) - if err != nil { - eModel.SetInfo(err.Error()) - eModel.SetPreModel(m) - return eModel, nil - } - eModel.SetInfo(fmt.Sprintf("create SecretStore %s/%s success", m.inputs[2].Value(), m.inputs[3].Value())) - eModel.SetPreModel(nil) - return eModel, nil - } - - return m, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/list/authentication.go b/ack-secret-manager-cli/pkg/model/secretstore/list/authentication.go deleted file mode 100644 index eb773871..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/list/authentication.go +++ /dev/null @@ -1,103 +0,0 @@ -package list - -import ( - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" -) - -func init() { - authenticationModel := InitAuthenticationModel() - model.InitModelMap["authentication"] = authenticationModel -} - -type AuthenticationModel struct { - list list.Model - choice string - quitting bool - preModel model.Model -} - -func InitAuthenticationModel() *AuthenticationModel { - items := []list.Item{ - item("RRSA"), - item("RAM Role"), - item("AK"), - item("ClientKey"), - item("ECS RAM Role"), - item("Cross-account synchronization"), - item("\n[ Previous ]"), - } - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please choose a KMS (Key Management Service) authentication type" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &AuthenticationModel{ - list: l, - } -} - -func (m *AuthenticationModel) Init() tea.Cmd { - return nil -} - -func (m *AuthenticationModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *AuthenticationModel) View() string { - return "\n" + m.list.View() -} - -func (m *AuthenticationModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *AuthenticationModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - return m.preModel, nil - } - var next model.Model - switch m.choice { - case "RRSA": - next = model.InitModelMap["rrsa"] - case "AK": - next = model.InitModelMap["ak"] - case "RAM Role": - next = model.InitModelMap["role"] - case "ECS RAM Role": - next = model.InitModelMap["ecs"] - case "ClientKey": - next = model.InitModelMap["dkms"] - case "Cross-account synchronization": - next = model.InitModelMap["cross-choose"] - } - next.SetPreModel(m) - return next, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/list/cross.go b/ack-secret-manager-cli/pkg/model/secretstore/list/cross.go deleted file mode 100644 index fdb188ae..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/list/cross.go +++ /dev/null @@ -1,122 +0,0 @@ -package list - -import ( - "fmt" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/k8s" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model" - "github.com/AliyunContainerService/ack-secret-manager/ack-secret-manager-cli/pkg/model/secretstore/input" -) - -const ( - limit = 5 -) - -type CrossModel struct { - list list.Model - choice string - quitting bool - preModel model.Model - continueToken string -} - -func InitCrossModel() *CrossModel { - secretStores, continueToken, err := k8s.ListSecretStore(limit, "") - if err != nil { - panic(err) - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("\n[Previous]")) - l := list.New(items, itemDelegate{}, defaultWidth, listHeight) - l.Title = "Please select an existing SecretStore for cross-account configuration" - l.SetShowStatusBar(false) - l.SetFilteringEnabled(false) - l.Styles.Title = titleStyle - l.Styles.PaginationStyle = paginationStyle - l.Styles.HelpStyle = helpStyle - return &CrossModel{ - list: l, - continueToken: continueToken, - } -} - -func (m *CrossModel) Init() tea.Cmd { - return nil -} - -func (m *CrossModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - switch msg := msg.(type) { - case tea.WindowSizeMsg: - m.list.SetWidth(msg.Width) - return m, nil - - case tea.KeyMsg: - switch keypress := msg.String(); keypress { - case "ctrl+c": - m.quitting = true - return m, tea.Quit - - case "enter": - i, ok := m.list.SelectedItem().(item) - if ok { - m.choice = string(i) - } - return m.Next() - } - } - - var cmd tea.Cmd - m.list, cmd = m.list.Update(msg) - return m, cmd -} - -func (m *CrossModel) View() string { - return "\n" + m.list.View() -} - -func (m *CrossModel) SetPreModel(preModel model.Model) { - m.preModel = preModel -} - -func (m *CrossModel) Next() (model.Model, tea.Cmd) { - if m.list.Index() == len(m.list.Items())-1 { - model.InitModelMap["cross-choose"] = InitCrossModel() - return m.preModel, nil - } - if m.choice == "Next Page" { - secretStores, continueToken, err := k8s.ListSecretStore(limit, m.continueToken) - if err != nil { - return m, nil - } - items := make([]list.Item, 0) - for _, secretStore := range secretStores { - items = append(items, item(fmt.Sprintf("* %s/%s", secretStore.Namespace, secretStore.Name))) - } - if len(items) == limit { - items = append(items, item("Next Page")) - } - items = append(items, item("\n[Previous]")) - m.list.SetItems(items) - m.continueToken = continueToken - return m, nil - } - next := model.InitModelMap["cross"] - crossModel, ok := next.(*input.CrossModel) - if !ok { - return m, nil - } - names := strings.Split(strings.Split(m.choice, " ")[1], "/") - crossModel.SetInfo(names[1], names[0]) - crossModel.SetPreModel(m) - return crossModel, nil -} diff --git a/ack-secret-manager-cli/pkg/model/secretstore/list/css.go b/ack-secret-manager-cli/pkg/model/secretstore/list/css.go deleted file mode 100644 index d1eb434f..00000000 --- a/ack-secret-manager-cli/pkg/model/secretstore/list/css.go +++ /dev/null @@ -1,56 +0,0 @@ -package list - -import ( - "fmt" - "io" - "strings" - - "github.com/charmbracelet/bubbles/list" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" -) - -const ( - listHeight = 14 - defaultWidth = 200 -) - -var ( - titleStyle = lipgloss.NewStyle().MarginLeft(0) - itemStyle = lipgloss.NewStyle().PaddingLeft(4) - selectedItemStyle = lipgloss.NewStyle().PaddingLeft(4).Foreground(lipgloss.Color("170")) - paginationStyle = list.DefaultStyles().PaginationStyle.PaddingLeft(4) - helpStyle = list.DefaultStyles().HelpStyle.PaddingLeft(4).PaddingBottom(1) -) - -type item string - -func (i item) FilterValue() string { return "" } - -type itemDelegate struct{} - -func (d itemDelegate) Height() int { return 1 } -func (d itemDelegate) Spacing() int { return 0 } -func (d itemDelegate) Update(_ tea.Msg, _ *list.Model) tea.Cmd { return nil } -func (d itemDelegate) Render(w io.Writer, m list.Model, index int, listItem list.Item) { - i, ok := listItem.(item) - if !ok { - return - } - - str := fmt.Sprintf("%s", i) - - fn := itemStyle.Render - if index == m.Index() { - fn = func(s ...string) string { - if index == len(m.Items())-1 { - if len(s) > 0 { - return selectedItemStyle.Render(strings.Join(s, " ")) - } - } - return selectedItemStyle.Render("> " + strings.Join(s, " ")) - } - } - - fmt.Fprint(w, fn(str)) -} diff --git a/ack-secret-manager-cli/utils/util.go b/ack-secret-manager-cli/utils/util.go deleted file mode 100644 index 99a321c1..00000000 --- a/ack-secret-manager-cli/utils/util.go +++ /dev/null @@ -1,8 +0,0 @@ -package utils - -import "regexp" - -func IsMatchRegex(regex, str string) bool { - reg := regexp.MustCompile(regex) - return reg.MatchString(str) -} diff --git a/charts/ack-secret-manager/Chart.yaml b/charts/ack-secret-manager/Chart.yaml index 23a8a600..00d5ecb7 100644 --- a/charts/ack-secret-manager/Chart.yaml +++ b/charts/ack-secret-manager/Chart.yaml @@ -1,7 +1,7 @@ apiVersion: v1 name: ack-secret-manager -version: 0.5.2 -appVersion: 0.5.2 +version: 0.5.5 +appVersion: 0.5.5 description: Provides external secret definitions for importing secret managed in Alibaba Cloud KMS secret-manager keywords: - secret-manager diff --git a/charts/ack-secret-manager/README.md b/charts/ack-secret-manager/README.md index 9151482a..022f6c89 100644 --- a/charts/ack-secret-manager/README.md +++ b/charts/ack-secret-manager/README.md @@ -1,59 +1,41 @@ - - # ACK Secret Manager -[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。 - - +[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) 可以帮助您将存储在[阿里云KMS凭据管家](https://www.alibabacloud.com/help/zh/doc-detail/152001.html) 中的密钥凭据或[阿里云OOS加密参数](https://www.alibabacloud.com/help/zh/oos/getting-started/manage-encryption-parameters?spm=a2c63.p38356.0.0.15393f494RyWrR),以K8s原生Secret对象的形式导入到集群中并实现密钥数据的自动同步,您可以在应用Pod中以挂载Secret等形式将存储在凭据管家或加密参数中的密文引入到应用程序中使用,避免敏感数据在应用开发构建流程中的传播和泄露。 ## 安装 -确保当前账号有足够的权限访问阿里云凭据管家服务,ack-secret-manager 支持共享网关和专属网关两种方式同步凭据管家的凭据。 - -1. 设置共享网关访问权限,这里有两种方式: - - - 在集群对应的 WorkerRole 中添加权限 - - - 登录容器服务控制台 - - - 选择对应集群进入到集群详情页 - - - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面 - - - 点击添加权限按钮,创建自定义权限策略,策略内容如下: - - ```json - { - "Action": [ - "kms:GetSecretValue", - "kms:Decrypt" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ``` - - - 绑定上面创建的自定义策略给集群对应的WorkerRole - - - 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权 - - * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h) - - * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权 - -2. 设置专属网关访问权限,详情见[通过应用接入点访问KMS实例](https://help.aliyun.com/document_detail/604467.html?spm=a2c4g.2252257.0.0.7f047495H2lmEh) - -3. 登录到容器服务控制台 - - * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面; - - * 选择需要安装的目标集群和命名空间、发布名称; - - * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的`rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**; - - * 点击**确定**按钮完成安装。 +1. 请确保组件使用的凭据有足够的权限访问需要同步的阿里云服务,可以使用如下两种配置方式,推荐使用RRSA方式,实现Pod维度的授权 + - 在集群对应的 WorkerRole 中添加权限 + - 登录容器服务控制台 + - 选择对应集群进入到集群详情页 + - 在集群信息中选择**集群资源**页,点击Worker RAM角色中对应的命名为**KubernetesWorkerRole-xxxxxxxxxxxxxxx** 的角色名称,会自动导航到RAM角色对应的控制台页面 + - 点击添加权限按钮,创建自定义权限策略,策略内容如下(仅需授权需要同步的服务权限即可,保证最小权限原则): + ```json + { + "Action": [ + // 阿里云KMS凭据管家所需权限 + "kms:GetSecretValue", + "kms:Decrypt", + + // 阿里云OOS加密参数所需权限 + "oos:GetSecretParameter", + "kms:GetSecretValue" + ], + "Resource": [ + "*" + ], + "Effect": "Allow" + } + ``` + - 绑定上面创建的自定义策略给集群对应的WorkerRole + - 通过 [RRSA方式](https://help.aliyun.com/document_detail/356611.html) 实现Pod维度的授权 + * [启用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-ywl-59g-j8h) + * [使用RRSA功能](https://help.aliyun.com/document_detail/356611.html#section-rmr-eeh-878) :为指定的 serviceaccount 创建对应的 RAM 角色,为 RAM 角色设置信任策略,并为 RAM 角色授权 +2. 登录到容器服务控制台 + * 在左侧导航栏选择**市场** -> **应用市场**,在搜索栏中输入ack-secret-manager,选择进入到应用页面; + * 选择需要安装的目标集群和命名空间、发布名称; + * 在参数配置页面进行自定义参数配置,包括 values.yaml 中的 `rrsa.enable`以及配置 `envVarsFromSecret` 中的相关参数,参数说明参见下方的**配置说明**; + * 点击**确定**按钮完成安装。 ## 升级 @@ -69,319 +51,229 @@ ## 配置说明 -| **参数** | **说明** | **默认值** | -| --------------------------------------------------- | ------------------------------------------------------------ | ---------------------- | -| env.WATCH_NAMESPACE | 指定组件watch的namespace(默认空值代表watch所有命名空间) | | -| envVarsFromSecret.ACCESS_KEY_ID | 可以通过设置ACCESS_KEY_ID变量指定凭证AK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.SECRET_ACCESS_KEY | 可以通过设置SECRET_ACCESS_KEY变量指定凭证SK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_ROLE_ARN | 可以通过设置ALICLOUD_ROLE_ARN变量指定RAM角色ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | 可以通过设置ALICLOUD_ROLE_SESSION_NAME变量指定RAM角色session name用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| **参数** | **说明** | **默认值** | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------- | +| env.WATCH_NAMESPACE | 指定组件watch的namespace(默认空值代表watch所有命名空间) | | +| envVarsFromSecret.ACCESS_KEY_ID | 可以通过设置ACCESS_KEY_ID变量指定凭证AK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.SECRET_ACCESS_KEY | 可以通过设置SECRET_ACCESS_KEY变量指定凭证SK构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_ROLE_ARN | 可以通过设置ALICLOUD_ROLE_ARN变量指定RAM角色ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | 可以通过设置ALICLOUD_ROLE_SESSION_NAME变量指定RAM角色session name用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | | envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | 可以通过设置ALICLOUD_ROLE_SESSION_EXPIRATION变量指定RAM角色session过期时长用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | 可以通过设置ALICLOUD_OIDC_PROVIDER_ARN变量指定RAM OIDC供应商的ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | 可以通过设置ALICLOUD_OIDC_TOKEN_FILE变量指定pod内oidc token文件路径用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | 可以通过设置 ALICLOUD_REMOTE_ROLE_ARN 变量指定另一个账号的 RAM Role Arn,用于在跨账号拉取凭据数据时进行角色扮演 | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | 可以通过设置 ALICLOUD_REMOTE_ROLE_SESSION_NAME 变量指定 RAM Role Session Name,于在跨账号拉取凭据数据时进行角色扮演 | | -| rrsa.enable | 是否启用RRSA特性,默认为false,启用后需要配置envVarsFromSecret中的ALICLOUD_ROLE_ARN和 ALICLOUD_OIDC_PROVIDER_ARN参数 | false | -| command.backend | 对接的外部密钥管理系统后端,当前仅支持阿里云凭据管家,配置为alicloud-kms | alicloud-kms | -| command.reconcilePeriod | 控制器重新协调externalSecret实例的间隔时间,默认5秒 | 5s | -| command.reconcileCount | 指定并发协调externalSecret实例的worker数量,默认是1 | 1 | -| command.tokenRotationPeriod | 检查KMS client访问STS token是否过期的轮询时间 | 120s | -| command.region | 从指定region拉取secret凭据 | | -| command.disablePolling | 关闭从KMS后端自动同步拉取最新的凭据内容,默认false | false | -| command.pollingInterval | 从KMS后端同步存量secret实例的间隔时间 | 120s | -| command.maxConcurrentSecretPulls | secret 同步的最大并发数量 | 5 | -| image.repository | 指定的ack-secret-manager 镜像仓库名称 | acs/ack-secret-manager | -| image.tag | 指定的ack-secret-manager 镜像tag | v0.5.0 | -| image.pullPolicy | 镜像拉取策略,默认为Always | Always | -| nameOverride | 覆盖应用名称 | nil | -| fullnameOverride | 覆盖应用全名 | nil | -| rbac.create | 是否创建并使用RBAC资源,默认为true | true | -| securityContext.fsGroup | 指定应用的security context配置 | {} | -| serviceAccount.create | 是否创建serviceaccount | true | -| serviceAccount.name | 指定创建serviceaccount的名称 | 自动生成 | -| serviceAccount.annotations | 指定添加serviceaccount annotation标签 | nil | -| podAnnotations | 指定添加到pod中的annotation标签 | {} | -| podLabels | 指定添加到pod中的Label标签 | {} | -| replicaCount | 控制器副本个数 | 1 | -| nodeSelector | 指定的nodeSelector标签 | {} | -| tolerations | 指定的污点容忍配置 | [] | -| affinity | 指定的Pod亲和性配置 | {} | -| resources | 指定的Pod requests和limits配置 | {} | +| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | 可以通过设置ALICLOUD_OIDC_PROVIDER_ARN变量指定RAM OIDC供应商的ARN用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | 可以通过设置ALICLOUD_OIDC_TOKEN_FILE变量指定pod内oidc token文件路径用于构建SDK client,需要定义在名称为alibaba-credentials的secret实例中 | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | 可以通过设置 ALICLOUD_REMOTE_ROLE_ARN 变量指定另一个账号的 RAM Role Arn,用于在跨账号拉取凭据数据时进行角色扮演 | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | 可以通过设置 ALICLOUD_REMOTE_ROLE_SESSION_NAME 变量指定 RAM Role Session Name,于在跨账号拉取凭据数据时进行角色扮演 | | +| rrsa.enable | 是否启用RRSA特性,默认为false,启用后需要配置envVarsFromSecret中的ALICLOUD_ROLE_ARN和 ALICLOUD_OIDC_PROVIDER_ARN参数 | false | +| command.reconcilePeriod | 控制器重新协调externalSecret实例的间隔时间,默认5秒 | 5s | +| command.reconcileCount | 指定并发协调externalSecret实例的worker数量,默认是1 | 1 | +| command.tokenRotationPeriod | 检查 client访问STS token是否过期的轮询时间 | 120s | +| command.region | 从指定region拉取secret凭据 | | +| command.disablePolling | 关闭从后端自动同步拉取最新的凭据内容,默认false | false | +| command.pollingInterval | 从后端同步存量secret实例的间隔时间 | 120s | +| command.maxConcurrentSecretPulls | 已弃用 | - | +| command.maxConcurrentKmsSecretPulls | kms secret 每秒同步的最大并发数量 | 10 | +| command.maxConcurrentOosSecretPulls | oos secret 每秒同步的最大并发数量 | 10 | +| image.repository | 指定的ack-secret-manager 镜像仓库名称 | acs/ack-secret-manager | +| image.tag | 指定的ack-secret-manager 镜像tag | v0.5.0 | +| image.pullPolicy | 镜像拉取策略,默认为Always | Always | +| nameOverride | 覆盖应用名称 | nil | +| fullnameOverride | 覆盖应用全名 | nil | +| rbac.create | 是否创建并使用RBAC资源,默认为true | true | +| securityContext.fsGroup | 指定应用的security context配置 | {} | +| serviceAccount.create | 是否创建serviceaccount | true | +| serviceAccount.name | 指定创建serviceaccount的名称 | 自动生成 | +| serviceAccount.annotations | 指定添加serviceaccount annotation标签 | nil | +| podAnnotations | 指定添加到pod中的annotation标签 | {} | +| podLabels | 指定添加到pod中的Label标签 | {} | +| replicaCount | 控制器副本个数 | 1 | +| nodeSelector | 指定的nodeSelector标签 | {} | +| tolerations | 指定的污点容忍配置 | [] | +| affinity | 指定的Pod亲和性配置 | {} | +| resources | 指定的Pod requests和limits配置 | {} | +## 使用说明 +下文会在阿里云 KMS 凭据管家中添加一个测试凭据进行凭据同步,并展示部分扩展功能。 -## 使用说明 +**Tip: 阿里云其它产品密文同步的方式与 KMS 凭据管家同步类似,仅需参考步骤 1 中对应产品添加密文的方式先添加密文,然后修改下文 SecretStore、ExternalSecret 示例中的关键字及其取值为下面表格中对应的值即可** -下文会在阿里云 KMS 凭据管家中添加一个测试凭据,并分别通过专属网关以及共享网关两种方式进行凭据同步,并展示部分扩展功能 +| 配置字段 & 产品 | 阿里云 KMS 凭据 | 阿里云 OOS 加密参数 | +| -------------------------------------- | ------------------------------ | ---------------------------------- | +| **SecretStore 认证方式关键字** | SecretStore.Spec.KMS.KMSAuth | SecretStore.Spec.OOS.OOSAuth | +| **ExternalSecret.spec.provider** | kms | oos | +| **ExternalSecret.spec.data.key** | (如下文的 test1) | (如下文的 test2) | ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据(例如 RRSA ,ClientKey,AK 配置等),ExternalSecret 用于存放需要同步的凭据基础信息(如凭据名称,版本等)以及指定 SecretStore,保证了权限与数据分离,增强使用灵活性。具体介绍见下方 **CRD 配置介绍** -1. 创建凭据 +1. 创建密文 + 当前支持同步 KMS 凭证和 OOS 加密参数,下面分别是两种密文的创建方式参考 - 在KMS凭据管家中添加如下凭证,详细流程请参考[管理通用凭据](https://www.alibabacloud.com/help/zh/doc-detail/152003.html) + - 在KMS凭据管家中添加如下凭证,详细流程请参考[管理通用凭据](https://www.alibabacloud.com/help/zh/doc-detail/152003.html) - ```txt - SecretName: test1 - SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} - VersionId: v1 - ``` + ```txt + SecretName: test1 + SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + VersionId: v1 + ``` + - 在OOS加密参数中添加如下加密参数,详细流程请参考[管理加密参数](https://www.alibabacloud.com/help/zh/oos/developer-reference/api-oos-2019-06-01-createsecretparameter) -2. 共享网关 + ```txt + Name: test2 + Value: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + ``` +2. 创建SecretStore & ExternalSecret 前提:给集群开启 RRSA,并且正确配置相关 RAM Role 权限 - - 创建 SecretStore 的测试实例,测试模板如下,需对部分字段进行替换 - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: scdemo - spec: - KMS: - KMSAuth: - oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" - ramRoleARN: "acs:ram::{accountID}:role/{roleName}" - ``` - - - 创建ExternalSecret的测试实例,测试模板如下: - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: esdemo - spec: - data: #无需特殊处理的数据源 - - key: test1 # kms 凭据名称 - name: test1 # 存入 secret 字段 - versionId: v1 #kms 凭据版本 - secretStoreRef: - name: scdemo - namespace: default - ``` - - - 执行命令创建externalsecret测试实例: - - ```sh - kubectl apply -f hello-service-external-secret.yml - ``` - - - 查看目标secret是否创建成功: - - ```sh - kubectl get secret esdemo -oyaml - ``` - - - 如果创建成功,查看secret内容如下: - - ```yaml - apiVersion: v1 - data: - test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= - kind: Secret - metadata: - creationTimestamp: "2023-10-09T13:03:09Z" - labels: - lastUpdatedAt: 2023-10-09T13.03.09Z - name: esdemo - namespace: default - resourceVersion: "7311947" - uid: 163c6a33-0bee-40b6-8ffe-6897277036cd - type: Opaque - ``` - - - 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步 - - - 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用`jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中 - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: es-json-demo - spec: - data: #无需特殊处理的数据源 - - key: test1 # kms 凭据名称 - name: test1 # 存入 secret 字段 - versionId: v1 #kms 凭据版本 - secretStoreRef: - name: scdemo - namespace: default - jmesPath: # 解析 json 串中的部分字段 - - path: "name" - objectAlias: "name" - - path: "friends[0].name" - objectAlias: "friendname" - ``` - - - 部署后检查 secret 是否创建成功 - - ```sh - kubectl get secret es-json-demo -oyaml - ``` - - - 同步成功即可看到如下结果 - - ```yaml - apiVersion: v1 - data: - friendname: bGlsaQ== - name: dG9t - kind: Secret - metadata: - creationTimestamp: "2023-10-09T13:11:05Z" - labels: - lastUpdatedAt: 2023-10-09T13.11.05Z - name: es-json-demo - namespace: default - resourceVersion: "7313940" - uid: 18d84558-f526-4ff5-ab9a-720ec1861c30 - type: Opaque - ``` - - - 当您使用`jmesPath`字段时,必需指定下面两个子字段: - - - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段 - - - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称 - - - 共享网关当前支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: scdemo - spec: - KMS: - KMSAuth: - oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" - ramRoleARN: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleSessionName: "" - ``` - - - -3. 专属网关 - - 前提:已在 KMS 控制台创建应用接入点,并在应用接入点中创建 ClientKey,ClientKey 正确配置了关于凭据 test1 的权限 - - - 在集群中创建 ClientKeyContent,Password 等相关字段的 secret - - ```yaml - apiVersion: v1 - data: - clientkey: {{ Client Key File Content }} - password: {{ Password }} - kind: Secret - metadata: - name: clientkey - namespace: kube-system - type: Opaque - ``` - - - 创建 SecretStore 实例 - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: dkms-client - spec: - KMS: - dedicatedKMSAuth: - protocol: "https" - endpoint: {{ kms Instance ID }} - ignoreSSL: true - clientKeyContent: - name: clientkey - namespace: kube-system - key: clientkey - password: - name: clientkey - namespace: kube-system - key: password - ``` - - - 创建 ExternalSecret 实例,SecretStoreRef 选择 default/dkms-client - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: es-dkms-demo - spec: - data: #无需特殊处理的数据源 - - key: test1 # kms 凭据名称 - name: dkms # 存入 secret 字段 - versionId: v1 #kms 凭据版本 - secretStoreRef: - name: dkms-client - namespace: default - ``` - - - 同步成功即可看到如下结果 - - ```yaml - apiVersion: v1 - data: - dkms: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0g - kind: Secret - metadata: - creationTimestamp: "2023-10-09T13:59:24Z" - labels: - lastUpdatedAt: 2023-10-09T13.59.24Z - name: es-dkms-demo - namespace: default - resourceVersion: "7326124" - uid: 4773959c-d90a-44c6-bf88-094855802683 - type: Opaque - ``` - - - 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: extract-secret - spec: - dataProcess: - - extract: - key: test1 - name: extract - versionId: v1 - secretStoreRef: - name: dkms-client - namespace: default - replaceRule: - - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud - target: "alibabacloud" - - source: "^f.*s$" - target: "ack" - ``` - - - 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换 - - ```yaml - apiVersion: v1 - data: - ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0= - age: IjE0Ig== - alibabacloud: InRvbSI= - kind: Secret - metadata: - creationTimestamp: "2023-10-09T14:07:35Z" - labels: - lastUpdatedAt: 2023-10-09T14.07.35Z - name: extract-secret - namespace: default - resourceVersion: "7328187" - uid: a3ab5278-02bd-4544-bae7-b502acccfe3c - type: Opaque - ``` + - 创建文件 `hello-service-secret-store.yml`如下并保存为测试模板, 其可以创建名称为 `scdemo` 的 SecretStore 的测试实例, 需对部分字段进行替换 + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: SecretStore + metadata: + name: scdemo + spec: + KMS: # 同步 kms 凭据时,指定为 KMS, 同步 oos 加密参数时,指定为 OOS + KMSAuth: # 同步 kms 凭据时,指定为 KMSAuth, 同步 oos 加密参数时,指定为 OOSAuth + oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" + ramRoleARN: "acs:ram::{accountID}:role/{roleName}" + ``` + - 创建文件 `hello-service-external-secret.yml`如下并保存为测试模板, 其可以创建名称为 `esdemo` 的ExternalSecret的测试实例: + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: esdemo + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + data: #无需特殊处理的数据源 + - key: test1 # kms 凭据名称 + name: test1 # 存入 secret 字段 + versionId: v1 #kms 凭据版本, 当 provider 为非 kms 时, 则不需要指定该字段 + secretStoreRef: + name: scdemo + namespace: default + ``` + - 执行命令创建secretstore测试实例: + ```sh + kubectl apply -f hello-service-secret-store.yml + ``` + - 执行命令创建externalsecret测试实例: + ```sh + kubectl apply -f hello-service-external-secret.yml + ``` + - 查看目标secret是否创建成功: + ```sh + kubectl get secret esdemo -oyaml + ``` + - 如果创建成功,查看secret内容如下: + ```yaml + apiVersion: v1 + data: + test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= + kind: Secret + metadata: + name: esdemo + namespace: default + type: Opaque + ``` + - 在没有关闭自动同步配置的前提下,可以修改KMS凭据管家中的密钥内容,等待片刻后查看目标secret是否已经完成同步 +3. JSON凭据解析 + + **data** + + - 如果您希望解析一个 JSON 格式的 secret 并将其中指定的 key-value 对同步到 k8s secret 中,可以使用 `jmesPath`字段。以下是一个使用 `jmesPath` 字段的样例,我们将其部署在集群中 + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: es-json-demo + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + data: #无需特殊处理的数据源 + - key: test1 # kms 凭据名称 + name: test1 # 存入 secret 字段 + versionId: v1 #kms 凭据版本, 当 provider 为非 kms 时, 则不需要指定该字段 + secretStoreRef: + name: scdemo + namespace: default + jmesPath: # 解析 json 串中的部分字段 + - path: "name" + objectAlias: "name" + - path: "friends[0].name" + objectAlias: "friendname" + ``` + - 当您使用 `jmesPath`字段时,必需指定下面两个子字段: + - `path`: 必需项,基于 [JMES path](https://jmespath.org/specification.html) 规范解析 json 中的指定字段 + - `objectAlias`: 必需项,用于指定解析出的字段同步到 k8s secret 中的 key 名称 + - 部署后检查 secret 是否创建成功 + ```sh + kubectl get secret es-json-demo -oyaml + ``` + - 同步成功即可看到如下结果 + ```yaml + apiVersion: v1 + data: + friendname: bGlsaQ== + name: dG9t + kind: Secret + metadata: + name: es-json-demo + namespace: default + type: Opaque + ``` + + **datasource** + + - 如果您想将 JSON 凭据解析后再存放入 secret 中,但又不知道凭据的具体结构,可以采用自解析功能,即 dataProcess.Extract 字段。并且可以针对解析后的字段键进行规则替换,即 dataProcss.replaceRule 字段,防止不规则的 secret data key 导致无法创建 secret,以下为样例 ExternalSecret + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: ExternalSecret + metadata: + name: extract-secret + spec: + provider: kms # 默认为 kms, 同步 kms 凭据时可不指定该字段 + dataProcess: + - extract: + key: test1 + name: extract + versionId: v1 #kms 凭据版本, 当 provider 是 oos 时, 则不需要指定该字段 + secretStoreRef: + name: dkms-client + namespace: default + replaceRule: + - source: "^n.*e$" #替换 以n开头以e结尾 的 key 为 alibabacloud + target: "alibabacloud" + - source: "^f.*s$" + target: "ack" + ``` + - 同步成功即可看到如下结果,JSON 凭据被解析为三部分,且各自的键根据 replaceRule 规则进行了替换 + ```yaml + apiVersion: v1 + data: + ack: W3sibmFtZSI6ImxpbGkifSx7Im5hbWUiOiJlZGYifV0= + age: IjE0Ig== + alibabacloud: InRvbSI= + kind: Secret + metadata: + name: extract-secret + namespace: default + type: Opaque + ``` +4. 当前支持跨账号同步凭据,在 `SecretStore.Spec.KMS.KMSAuth` 中配置 `remoteRamRoleArn`,`remoteRamRoleSessionName` 即可,以下为样例 SecretStore + + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: SecretStore + metadata: + name: scdemo + spec: + KMS: # 同步 kms 凭据时,指定为 KMS, 同步 oos 加密参数时,指定为 OOS + KMSAuth: # 同步 kms 凭据时,指定为 KMSAuth, 同步 oos 加密参数时,指定为 OOSAuth + oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" + ramRoleARN: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleSessionName: "" + ``` ## CRD 配置介绍 @@ -391,27 +283,27 @@ ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据( | crd 字段 | 描述 | 是否必选 | | ----------- | ------------------------------------------ | -------- | -| provider | 获取 secret 的目标云产品(如 KMS 等) | 否 | +| provider | 获取 secret 的目标云产品(如 KMS 、OOS等) | 否 | | data | 数据源(目标数据的标识) | 否 | | dataProcess | 需要进行特殊加工的数据源(目标数据的标识) | 否 | | type | k8s secret 类型(Opaque等) | 否 | **data(无需经过特殊处理的数据源)** -| crd 字段 | 描述 | 是否必选 | -| -------------- | ------------------------------------------------------------ | -------- | -| key | 目标 secret 的唯一标识(例如 KMS 凭据的 key) | 是 | -| name | 在集群 secret data 中对应的 key | 否 | -| versionStage | 目标 secret 版本状态 | 否 | -| versionId | 目标 secret 版本号 | 否 | +| crd 字段 | 描述 | 是否必选 | +| -------------- | --------------------------------------------------------------------- | -------- | +| key | 目标 secret 的唯一标识(例如 KMS 凭据的 key) | 是 | +| name | 在集群 secret data 中对应的 key | 否 | +| versionStage | 目标 secret 版本状态 | 否 | +| versionId | 目标 secret 版本号, 当 provider 是 oos 时, 则不需要指定该字段 | 否 | | jmesPath | 如果目标 secret 为 json 类型,可指定获取 json 中特定 key 对应的 value | 否 | -| secretStoreRef | 引用的 SecretStore 信息 | 否 | +| secretStoreRef | 引用的 SecretStore 信息 | 否 | **dataProcess(需要进行特殊处理的数据源)** -| crd 字段 | 描述 | 是否必选 | -| ----------- | ------------------------------------------------------------ | -------- | -| extract | 针对目标 secret 进行 json 解析,不需要用户指定 json key | 否 | +| crd 字段 | 描述 | 是否必选 | +| ----------- | -------------------------------------------------------------------------------- | -------- | +| extract | 针对目标 secret 进行 json 解析,不需要用户指定 json key | 否 | | replaceRule | 根据特定规则替换经过 json 解析的 secret 的 key,防止非法 key 不能存入 k8s secret | 否 | **replaceRule(用于进行 Secret Key 内容替换)** @@ -442,13 +334,19 @@ ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据( | crd 字段 | 描述 | 是否必选 | | -------- | ------------------- | -------- | | KMS | 代表目标云产品为KMS | 否 | +| OOS | 代表目标云产品为OOS | 否 | **KMS** -| crd 字段 | 描述 | 是否必选 | -| ---------------- | --------------------------- | -------- | -| KMSAuth | 共享网关下访问 KMS 所需凭证 | 否 | -| dedicatedKMSAuth | 专属网关下访问 KMS 所需凭证 | 否 | +| crd 字段 | 描述 | 是否必选 | +| -------- | ------------------------------- | -------- | +| KMSAuth | 访问 KMS 所需凭证(密钥管理服务) | 否 | + +**OOS** + +| crd 字段 | 描述 | 是否必选 | +| -------- | -------------------------------- | -------- | +| OOSAuth | 访问 OOS 所需凭证(管理加密参数) | 否 | **KMSAuth** @@ -463,16 +361,18 @@ ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据( | remoteRamRoleArn | 跨账号 ram 角色 arn | 否 | | remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 | -**dedicatedKMSAuth** +**OOSAuth** -| crd 字段 | 描述 | 是否必选 | -| ---------------- | ----------------------------- | -------- | -| protocol | 传输协议(https) | 是 | -| endpoint | kms 实例 ID | 是 | -| ca | 用户根CA,base64编码 | 否 | -| ignoreSSL | 是否忽略 ssl 认证 | 否 | -| clientKeyContent | 专属网关 client key file 内容 | 是 | -| password | client key 加密口令 | 是 | +| crd 字段 | 描述 | 是否必选 | +| ------------------------ | ---------------------------- | -------- | +| accessKey | 用户AK | 否 | +| accessKeySecret | 用户SK | 否 | +| ramRoleARN | ram 角色 arn | 否 | +| ramRoleSessionName | 角色会话名 | 否 | +| oidcProviderARN | oidc 提供商 arn | 否· | +| oidcTokenFilePath | 暂时无用 | 否 | +| remoteRamRoleArn | 跨账号 ram 角色 arn | 否 | +| remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 | **SecretRef(敏感访问凭据存放在 K8S secret 中)** @@ -484,10 +384,12 @@ ack-secret-manager 涉及了两种 CRD,SecretStore 用于存放访问凭据( ## Release Note -| 版本号 | 变更时间 | 变更内容 | -| ------- | -------------- | ------------------------------------------------------------ | -| `0.4.0` | 2022年12月22日 | 支持基于JMES解析提取JSON格式的密文字段 | +| 版本号 | 变更时间 | 变更内容 | +| --------- | -------------- | -------------------------------------------------------------------------------------------------------------------- | +| `0.4.0` | 2022年12月22日 | 支持基于JMES解析提取JSON格式的密文字段 | | `0.5.0` | 2023年10月10日 | 1.支持专属版 KMS 凭据同步
2.多阿里云访问凭据管理
3.凭据自解析与键规则替换
4.共享版 KMS 跨账号凭据同步 | -| `0.5.1` | 2023年10月18日 | 部分功能与性能优化 | -| `0.5.2` | 2024年8月1日 | 大规模资源同步并发优化 | - +| `0.5.1` | 2023年10月18日 | 部分功能与性能优化 | +| `0.5.2` | 2024年8月1日 | 大规模资源同步并发优化 | +| `0.5.3` | 2024年10月10日 | 支持资源同步秒级限流,修复部分软件包cve | +| `0.5.4` | 2024年10月31日 | 支持同步 OOS 加密参数 | +| `0.5.5` | 2024年11月22日 | 支持同步 binary 类型的凭据 | diff --git a/charts/ack-secret-manager/README_EN.md b/charts/ack-secret-manager/README_EN.md index e27aac5f..09f8b7bc 100644 --- a/charts/ack-secret-manager/README_EN.md +++ b/charts/ack-secret-manager/README_EN.md @@ -2,55 +2,42 @@ English | [简体中文](./README-zh_CN.md) -[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import key credentials stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can introduce the ciphertext stored in the Secrets Manager into the application in the form of mounting Secret in the application Pod to avoid the spread of sensitive data in the application development and construction process and leaks. - - +[ack-secret-manager](https://github.com/AliyunContainerService/ack-secret-manager) can help you import key credentials stored in [Alibaba Cloud KMS Secrets Manager](https://www.alibabacloud.com/help/en/key-management-service) or [Alibaba Cloud OOS Secret Parameter ](https://www.alibabacloud.com/help/en/oos/getting-started/manage-encryption-parameters?spm=a2c63.p38356.0.0.40bc27beO4CDFR)into the cluster in the form of Kubernetes native Secret objects and achieve automatic synchronization of key data, you can introduce the ciphertext stored in the Secrets Manager into the application in the form of mounting Secret in the application Pod to avoid the spread of sensitive data in the application development and construction process and leaks. ## Install -Make sure that the current account has sufficient permissions to access the Alibaba Cloud KMS Secrets Manager. ack-secret-manager supports two methods: shared KMS and dedicated KMS to synchronize the Secrets Manager's credentials. - -1. There are two ways to set shared KMS access permissions: +1. Make sure that the credentials used by the ack-secret-manager has sufficient permissions to access the Alibaba Cloud product service. You can use the following two configuration methods, and we recommend you to use the second **RRSA** method to achieve authorization in the Pod level. - Add permissions to the WorkerRole corresponding to the cluster - - - Log in to the Container Service console - - - Select the cluster to enter the cluster details page - - - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role. - - - Add kms RAM policy below into the policy bind to the worker role - - ```json - { - "Action": [ - "kms:GetSecretValue", - "kms:Decrypt" - ], - "Resource": [ - "*" - ], - "Effect": "Allow" - } - ``` - + - Log in to the Container Service console + - Select the cluster to enter the cluster details page + - Navigate to the **Cluster Resources** page in the cluster information. Once there, click on the Worker RAM role with the corresponding name **KubernetesWorkerRole-xxxxxxxxxxxxxxx**. This will automatically take you to the console page associated with the RAM role. + - Add kms RAM policy below into the policy bind to the worker role(You only need to authorize the service permissions that need to be synchronized, ensuring the principle of minimum permissions.) + ```json + { + "Action": [ + // Permission required to access Alibaba Cloud KMS Secrets Manager + "kms:GetSecretValue", + "kms:Decrypt", + + // Permission required to access Alibaba Cloud OOS Secret Parameters + "oos:GetSecretParameter", + "kms:GetSecretValue" + ], + "Resource": [ + "*" + ], + "Effect": "Allow" + } + ``` - Implement Pod dimension authorization through [RRSA method](https://www.alibabacloud.com/help/en/ack/ack-managed-and-ack-dedicated/user-guide/use-rrsa-to-authorize-pods-to-access-different-cloud-services) - - * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h) - - * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role - -2. Set dedicated KMS access permissions. For details, see [Access a KMS instance by using an AAP](https://www.alibabacloud.com/help/en/key-management-service/latest/aap?spm=a2c63.l28256.0.0.2d881b76SOifvo) - -3. Log in to the Container Service console + * [Enable RRSA functionality](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-ywl-59g-j8h) + * [Use RRSA function](https://www.alibabacloud.com/help/en/container-service-for-kubernetes/latest/use-rrsa-to-enforce-access-control#section-rmr-eeh-878): Create the corresponding RAM role for the specified serviceaccount, set the trust policy for the RAM role, and authorize the RAM role +2. Log in to the Container Service console * Select **Marketplace** -> **Marketplace** in the left navigation bar, enter **ack-secret-manager** in the search bar, and select to enter the application page; - * Select the target cluster, namespace, and release name to be installed; - * Configure custom parameters on the parameter configuration page, including `rrsa.enable` in values.yaml and related parameters in `envVarsFromSecret`. For parameter descriptions, see the **configuration instructions** below; - * Click the **OK** button to complete the installation. ## Upgrade @@ -67,142 +54,148 @@ Make sure that the current account has sufficient permissions to access the Alib ## Configuration instructions -| **parameter** | **introduction** | **default value** | -| --------------------------------------------------- | ------------------------------------------------------------ | ---------------------- | -| env.WATCH_NAMESPACE | Specify the namespace of the component watch (the default empty value represents all namespaces of watch) | | -| envVarsFromSecret.ACCESS_KEY_ID | You can build the SDK client by specifying the credential AK by setting the ACCESS_KEY_ID variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.SECRET_ACCESS_KEY | You can build the SDK client by specifying the credential SK by setting the SECRET_ACCESS_KEY variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_ARN | You can specify the RAM role ARN used to build the SDK client by setting the ALICLOUD_ROLE_ARN variable, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | You can specify the RAM role session name by setting the ALICLOUD_ROLE_SESSION_NAME variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | You can specify the RAM role session expiration length by setting the ALICLOUD_ROLE_SESSION_EXPIRATION variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | -| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | You can specify the ARN of the RAM OIDC provider by setting the ALICLOUD_OIDC_PROVIDER_ARN variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | -| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | You can specify the oidc token file path in the pod by setting the ALICLOUD_OIDC_TOKEN_FILE variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | You can specify the RAM Role Arn of another account by setting the ALICLOUD_REMOTE_ROLE_ARN variable for role playing when pulling credential data across accounts. | | -| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | You can specify the RAM Role Session Name by setting the ALICLOUD_REMOTE_ROLE_SESSION_NAME variable to perform role play when pulling credential data across accounts. | | -| rrsa.enable | Whether to enable the RRSA feature, the default is false. After enabling, you need to configure the ALICLOUD_ROLE_ARN and ALICLOUD_OIDC_PROVIDER_ARN parameters in envVarsFromSecret. | false | -| command.backend | The docked external key management system backend currently only supports Alibaba Cloud Secrets Manager, configured as alicloud-kms | alicloud-kms | -| command.reconcilePeriod | The interval for the controller to re-coordinate the externalSecret instance, the default is 5 seconds | 5s | -| command.reconcileCount | Specify the number of workers to concurrently coordinate the externalSecret instance. The default is 1 | 1 | -| command.tokenRotationPeriod | Polling time to check whether the KMS client access STS token has expired | 120s | -| command.region | Pull secret credentials from the specified region | | -| command.disablePolling | Turn off automatic synchronization of pulling the latest credential content from the KMS backend, default false | false | -| command.pollingInterval | The interval for synchronizing existing secret instances from the KMS backend | 120s | -| command.maxConcurrentSecretPulls | Maximum concurrent synchronization of secrets | 5 | -| image.repository | Specified ack-secret-manager mirror warehouse name | acs/ack-secret-manager | -| image.tag | Specified ack-secret-manager image tag | v0.5.0 | -| image.pullPolicy | Image pull strategy, default is Always | Always | -| nameOverride | Override app name | nil | -| fullnameOverride | Override application full name | nil | -| rbac.create | Whether to create and use RBAC resources, the default is true | true | -| securityContext.fsGroup | Specify the security context configuration of the application | {} | -| serviceAccount.create | Whether to create serviceaccount | true | -| serviceAccount.name | Specify the name of the created serviceaccount | Automatic generated | -| serviceAccount.annotations | Specify adding the serviceaccount annotation tag | nil | -| podAnnotations | Specify the annotation label added to the pod | {} | -| podLabels | Specify the Label added to the pod | {} | -| replicaCount | Number of controller copies | 1 | -| nodeSelector | The specified nodeSelector tag | {} | -| tolerations | Specified taint tolerance configuration | [] | -| affinity | Specified Pod affinity configuration | {} | -| resources | Specified Pod requests and limits configuration | {} | +| **parameter** | **introduction** | **default value** | +| --------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | +| env.WATCH_NAMESPACE | Specify the namespace of the component watch (the default empty value represents all namespaces of watch) | | +| envVarsFromSecret.ACCESS_KEY_ID | You can build the SDK client by specifying the credential AK by setting the ACCESS_KEY_ID variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.SECRET_ACCESS_KEY | You can build the SDK client by specifying the credential SK by setting the SECRET_ACCESS_KEY variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_ARN | You can specify the RAM role ARN used to build the SDK client by setting the ALICLOUD_ROLE_ARN variable, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_NAME | You can specify the RAM role session name by setting the ALICLOUD_ROLE_SESSION_NAME variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_ROLE_SESSION_EXPIRATION | You can specify the RAM role session expiration length by setting the ALICLOUD_ROLE_SESSION_EXPIRATION variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | +| envVarsFromSecret. ALICLOUD_OIDC_PROVIDER_ARN | You can specify the ARN of the RAM OIDC provider by setting the ALICLOUD_OIDC_PROVIDER_ARN variable to build the SDK client, which needs to be defined in the secret instance named alibaba-credentials | | +| envVarsFromSecret.ALICLOUD_OIDC_TOKEN_FILE | You can specify the oidc token file path in the pod by setting the ALICLOUD_OIDC_TOKEN_FILE variable to build the SDK client. It needs to be defined in the secret instance named alibaba-credentials. | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_ARN | You can specify the RAM Role Arn of another account by setting the ALICLOUD_REMOTE_ROLE_ARN variable for role playing when pulling credential data across accounts. | | +| envVarsFromSecret.ALICLOUD_REMOTE_ROLE_SESSION_NAME | You can specify the RAM Role Session Name by setting the ALICLOUD_REMOTE_ROLE_SESSION_NAME variable to perform role play when pulling credential data across accounts. | | +| rrsa.enable | Whether to enable the RRSA feature, the default is false. After enabling, you need to configure the ALICLOUD_ROLE_ARN and ALICLOUD_OIDC_PROVIDER_ARN parameters in envVarsFromSecret. | false | +| command.reconcilePeriod | The interval for the controller to re-coordinate the externalSecret instance, the default is 5 seconds | 5s | +| command.reconcileCount | Specify the number of workers to concurrently coordinate the externalSecret instance. The default is 1 | 1 | +| command.tokenRotationPeriod | Polling time to check whether the client access STS token has expired | 120s | +| command.region | Pull secret credentials from the specified region | | +| command.disablePolling | Turn off automatic synchronization of pulling the latest credential content from the backend, default false | false | +| command.pollingInterval | The interval for synchronizing existing secret instances from the backend | 120s | +| command.maxConcurrentSecretPulls | Deprecated | - | +| command.maxConcurrentKmsSecretPulls | Maximum concurrent synchronization per second of kms secrets | 10 | +| command.maxConcurrentOosSecretPulls | Maximum concurrent synchronization per second of oos secrets | 10 | +| image.repository | Specified ack-secret-manager mirror warehouse name | acs/ack-secret-manager | +| image.tag | Specified ack-secret-manager image tag | v0.5.0 | +| image.pullPolicy | Image pull strategy, default is Always | Always | +| nameOverride | Override app name | nil | +| fullnameOverride | Override application full name | nil | +| rbac.create | Whether to create and use RBAC resources, the default is true | true | +| securityContext.fsGroup | Specify the security context configuration of the application | {} | +| serviceAccount.create | Whether to create serviceaccount | true | +| serviceAccount.name | Specify the name of the created serviceaccount | Automatic generated | +| serviceAccount.annotations | Specify adding the serviceaccount annotation tag | nil | +| podAnnotations | Specify the annotation label added to the pod | {} | +| podLabels | Specify the Label added to the pod | {} | +| replicaCount | Number of controller copies | 1 | +| nodeSelector | The specified nodeSelector tag | {} | +| tolerations | Specified taint tolerance configuration | [] | +| affinity | Specified Pod affinity configuration | {} | +| resources | Specified Pod requests and limits configuration | {} | +## Instructions for use +The following will add a test credential in Alibaba Cloud KMS Secrets Manager for synchronize the credentials, and demonstrate some extended functions. -## Instructions for use +**Tip: The method of cryptotext synchronization for other Alibaba Cloud products is similar to that of KMS credential steward. Just refer to the method of adding cryptotext for corresponding products in step 1 to add cryptotext first, and then modify the keywords in the SecretStore and ExternalSecret examples below and their values to the corresponding values in the table below.** -The following will add a test credential in Alibaba Cloud KMS Secrets Manager, synchronize the credentials through dedicated KMS and shared KMS, and demonstrate some extended functions. +| Configuration Field & Product | Alibaba KMS Credential | Alibaba Cloud OOS Secret Parameter | +| --------------------------------------------------- | -------------------------------------------- | ------------------------------------------------- | +| **SecretStore keyword authentication method** | SecretStore.Spec.KMS.KMSAuth | SecretStore.Spec.OOS.OOSAuth | +| **ExternalSecret.spec.provider** | kms | oos | +| **ExternalSecret.spec.data.key** | ``(as follows test1) | ``(as follows test2) | ack-secret-manager involves two CRDs. SecretStore is used to store access credentials (such as RRSA configuration, ClientKey, AK configuration, etc.), and ExternalSecret is used to store basic credential information that needs to be synchronized (such as credential name, version, etc.) and specify the SecretStore. It ensures the separation of permissions and data and enhances the flexibility of use. See below for details **CRD configuration introduction** 1. Create credentials + Currently supports synchronization of KMS credentials and OOS encryption parameters. The following are references to how to create two ciphertexts. - Add the following credentials in the KMS Secrets Manager. For detailed procedures, please refer to [Manage Common Credentials](https://www.alibabacloud.com/help/en/key-management-service/latest/manage-generic-secrets) + - Add the following credentials in the KMS Secrets Manager. For detailed procedures, please refer to [Manage Common Credentials](https://www.alibabacloud.com/help/en/key-management-service/latest/manage-generic-secrets) - ```txt - SecretName: test1 - SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} - VersionId: v1 - ``` + ```txt + SecretName: test1 + SecretData: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + VersionId: v1 + ``` + - Add the following encryption parameters to the OOS Encryption Parameters. Please refer to the detailed process[CreateSecretParameter](https://www.alibabacloud.com/help/en/oos/developer-reference/api-oos-2019-06-01-createsecretparameter) -2. Shared KMS + ```txt + Name: test2 + Value: {"name":"tom","age":"14","friends":[{"name":"lili"},{"name":"edf"}]} + ``` +2. Create SecretStore & ExternalSecret Prerequisite: Enable RRSA for the cluster and correctly configure the relevant RAM Role permissions - - Create a test instance of SecretStore. The test template is as follows. Some fields need to be replaced. - + - Create a test instance named scdemo of SecretStore, and saved as a file `hello-service-secret-store.yml`. The test template is as follows. Some fields need to be replaced. ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: SecretStore metadata: name: scdemo spec: - KMS: - KMSAuth: + KMS: # Specify KMS when synchronizing kms credentials, OOS when synchronizing oos encryption parameters + KMSAuth: # Specify KMSAuth when synchronizing kms credentials, OOSAuth when synchronizing oos encryption parameters oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" ramRoleARN: "acs:ram::{accountID}:role/{roleName}" ``` - - - Create a test instance of ExternalSecret. The test template is as follows: - + - Create a test instance named `esdemo` of ExternalSecret, and saved as a file `hello-service-external-secret.yml`. The test template is as follows: ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: esdemo spec: + provider: kms # Default is kms, optional when synchronizing kms credentials data: #Data sources that require no special processing - - key: test1 # kms credential name + - key: test1 # kms credential name name: test1 # Fields stored in secret - versionId: v1 # kms credential version + versionId: v1 # kms credential version, when provider is not kms, this field is not required secretStoreRef: name: scdemo namespace: default ``` - + - Execute the command to create an secretstore test instance: + ```sh + kubectl apply -f hello-service-secret-store.yml + ``` - Execute the command to create an externalsecret test instance: - ```sh kubectl apply -f hello-service-external-secret.yml ``` - - Check whether the target secret is created successfully: - ```sh kubectl get secret esdemo -oyaml ``` - - If the creation is successful, view the secret content as follows: - ```yaml apiVersion: v1 data: test1: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0= kind: Secret metadata: - creationTimestamp: "2023-10-09T13:03:09Z" - labels: - lastUpdatedAt: 2023-10-09T13.03.09Z name: esdemo namespace: default - resourceVersion: "7311947" - uid: 163c6a33-0bee-40b6-8ffe-6897277036cd type: Opaque ``` - - Without turning off the automatic synchronization configuration, you can modify the key content in the KMS Secrets Manager and wait for a while to check whether the target secret has been synchronized. +3. JSON-formatted support - - If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster + **data** + - If you want to parse a JSON-formatted secret and synchronize the key-value pairs specified in it to the k8s secret, you can use the `jmesPath` field. The following is an example using the `jmesPath` field, which we deploy in the cluster ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: es-json-demo spec: + provider: kms # Default is kms, optional when synchronizing kms credentials data: - - key: test1 + - key: test1 name: test1 - versionId: v1 + versionId: v1 # kms credential version, this field is not required when provider is oos secretStoreRef: name: scdemo namespace: default @@ -212,15 +205,11 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden - path: "friends[0].name" objectAlias: "friendname" ``` - - After deployment, check whether the secret is created successfully - ```sh kubectl get secret es-json-demo -oyaml ``` - - If the synchronization is successful, you will see the following results: - ```yaml apiVersion: v1 data: @@ -228,127 +217,29 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden name: dG9t kind: Secret metadata: - creationTimestamp: "2023-10-09T13:11:05Z" - labels: - lastUpdatedAt: 2023-10-09T13.11.05Z name: es-json-demo namespace: default - resourceVersion: "7313940" - uid: 18d84558-f526-4ff5-ab9a-720ec1861c30 type: Opaque ``` - - When you use the `jmesPath` field, you must specify the following two subfields: + - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification + - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret - - `path`: Required, parses the specified field in json based on the [JMES path](https://jmespath.org/specification.html) specification - - - `objectAlias`: Required, used to specify the parsed field to be synchronized to the key name in the k8s secret - - - The shared KMS currently supports cross-account synchronization of credentials. Just configure `remoteRamRoleArn` and `remoteRamRoleSessionName` in `SecretStore.Spec.KMS.KMSAuth`. The following is a sample SecretStore - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: scdemo - spec: - KMS: - KMSAuth: - oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" - ramRoleARN: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" - remoteRamRoleSessionName: " - ``` - -3. Dedicated KMS - - Prerequisite: An AAP (application access point) has been created in the KMS console, and a ClientKey has been created within the access point, correctly configured with permissions for the credential "test1". - - - Create a secret in the cluster containing the relevant fields such as ClientKeyContent, Password, etc. - - ```yaml - apiVersion: v1 - data: - clientkey: {{ Client Key File Content }} - password: {{ Password }} - kind: Secret - metadata: - name: clientkey - namespace: kube-system - type: Opaque - ``` - - - Create a SecretStore instance - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: SecretStore - metadata: - name: dkms-client - spec: - KMS: - dedicatedKMSAuth: - protocol: "https" - endpoint: {{ kms Instance ID }} - ignoreSSL: true - clientKeyContent: - name: clientkey - namespace: kube-system - key: clientkey - password: - name: clientkey - namespace: kube-system - key: password - ``` - - - Create an ExternalSecret instance and select default/dkms-client as the SecretStoreRef. - - ```yaml - apiVersion: 'alibabacloud.com/v1alpha1' - kind: ExternalSecret - metadata: - name: es-dkms-demo - spec: - data: - - key: test1 - name: dkms - versionId: v1 - secretStoreRef: - name: dkms-client - namespace: default - ``` - - - Once the synchronization is successful, you will be able to see the following results. - - ```yaml - apiVersion: v1 - data: - dkms: eyJuYW1lIjoidG9tIiwiYWdlIjoiMTQiLCJmcmllbmRzIjpbeyJuYW1lIjoibGlsaSJ9LHsibmFtZSI6ImVkZiJ9XX0g - kind: Secret - metadata: - creationTimestamp: "2023-10-09T13:59:24Z" - labels: - lastUpdatedAt: 2023-10-09T13.59.24Z - name: es-dkms-demo - namespace: default - resourceVersion: "7326124" - uid: 4773959c-d90a-44c6-bf88-094855802683 - type: Opaque - ``` + **dataProcess** - If you want to parse JSON credentials and store them in a secret but don't know the specific structure of the credentials, you can use the self-extraction feature, which is the `dataProcess.Extract` field. You can also perform rule-based replacements on the parsed field keys using the `dataProcess.replaceRule` field to prevent irregular secret data keys from causing issues when creating a secret. The following is an example of an ExternalSecret: - ```yaml apiVersion: 'alibabacloud.com/v1alpha1' kind: ExternalSecret metadata: name: extract-secret spec: + provider: kms # Default is kms, optional when synchronizing kms credentials dataProcess: - extract: key: test1 name: extract - versionId: v1 + versionId: v1 # kms credential version, this field is not required when provider is oos secretStoreRef: name: dkms-client namespace: default @@ -358,9 +249,7 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden - source: "^f.*s$" target: "ack" ``` - - Once the synchronization is successful, you will be able to see the following results. The JSON credentials are parsed into three parts, and their respective keys are replaced according to the replaceRule rules. - ```yaml apiVersion: v1 data: @@ -369,15 +258,25 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden alibabacloud: InRvbSI= kind: Secret metadata: - creationTimestamp: "2023-10-09T14:07:35Z" - labels: - lastUpdatedAt: 2023-10-09T14.07.35Z name: extract-secret namespace: default - resourceVersion: "7328187" - uid: a3ab5278-02bd-4544-bae7-b502acccfe3c type: Opaque ``` +4. Currently supports cross-account synchronization of credentials. Just configure remoteRamRoleArn and remoteRamRoleSessionName in SecretStore.Spec.KMS.KMSAuth. The following is a sample SecretStore + + ```yaml + apiVersion: 'alibabacloud.com/v1alpha1' + kind: SecretStore + metadata: + name: scdemo + spec: + KMS: # Specify KMS when synchronizing kms credentials, OOS when synchronizing oos encryption parameters + KMSAuth: # Specify KMSAuth when synchronizing kms credentials, OOSAuth when synchronizing oos encryption parameters + oidcProviderARN: "acs:ram::{accountID}:oidc-provider/ack-rrsa-{clusterID}" + ramRoleARN: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleArn: "acs:ram::{accountID}:role/{roleName}" + remoteRamRoleSessionName: "" + ``` ## CRD configuration introduction @@ -385,43 +284,43 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden **spec** -| parameter | description | required | -| ----------- | ------------------------------------------------------------ | -------- | -| provider | The target cloud products for syncing credentials, such as KMS | no | -| data | Data source (identifier for the target data) | no | +| parameter | description | required | +| ----------- | ------------------------------------------------------------------------- | -------- | +| provider | The target cloud products for syncing credentials, such as KMS, OOS | no | +| data | Data source (identifier for the target data) | no | | dataProcess | Data source requiring special processing (identifier for the target data) | no | -| type | Kubernetes Secret types (Opaque, etc.) | no | +| type | Kubernetes Secret types (Opaque, etc.) | no | **data** -| parameter | description | required | -| -------------- | ------------------------------------------------------------ | -------- | -| key | The unique identifier for the target credential, such as the key for KMS credentials | yes | -| name | The corresponding key for the credentials in the secret data of the cluster | no | -| versionStage | The version stage of the target credential | no | -| versionId | The version Id of the target credential | no | +| parameter | description | required | +| -------------- | ----------------------------------------------------------------------------------------------------------------------------- | -------- | +| key | The unique identifier for the target credential, such as the key for KMS credentials | yes | +| name | The corresponding key for the credentials in the secret data of the cluster | no | +| versionStage | The version stage of the target credential | no | +| versionId | The version Id of the target credential, this field is not required when provider is oos | no | | jmesPath | If the target credential is in JSON format, you can specify to retrieve the value corresponding to a specific key in the JSON | no | -| secretStoreRef | Information of the referenced SecretStore | no | +| secretStoreRef | Information of the referenced SecretStore | no | **dataProcess(Data source requiring special processing.)** -| parameter | description | required | -| ----------- | ------------------------------------------------------------ | -------- | -| extract | Parsing JSON for the target credential without requiring the user to specify the JSON key | no | +| parameter | description | required | +| ----------- | ------------------------------------------------------------------------------------------------------------------------------ | -------- | +| extract | Parsing JSON for the target credential without requiring the user to specify the JSON key | no | | replaceRule | Replacing keys of the parsed secret based on specific rules to prevent illegal keys from being stored in the Kubernetes Secret | no | **replaceRule(The content replacement used for the Secret Key.)** -| parameter | description | required | -| --------- | ------------------------------------------------------------ | -------- | -| target | The string used for replacement | yes | +| parameter | description | required | +| --------- | ----------------------------------------------------------------------- | -------- | +| target | The string used for replacement | yes | | source | The string that needs to be replaced, which can be a regular expression | yes | **jmesPath** -| parameter | description | required | -| ----------- | ------------------------------------------------------------ | -------- | -| path | JMESPath expression that allows users to specify the JSON key | yes | +| parameter | description | required | +| ----------- | --------------------------------------------------------------------------------- | -------- | +| path | JMESPath expression that allows users to specify the JSON key | yes | | objectAlias | The data key corresponding to the Kubernetes Secret where the data will be stored | yes | **secretStoreRef** @@ -435,16 +334,22 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden **spec** -| parameter | description | required | -| --------- | ------------------------------------------------------------ | -------- | -| KMS | Representing the target cloud product as KMS (Key Management Service) | no | +| parameter | description | required | +| --------- | ------------------------------------------------------------------------- | -------- | +| KMS | Representing the target cloud product as KMS (Key Management Service) | no | +| OOS | Representing the target cloud product as OOS(Manage Encryption Parameter) | no | **KMS** -| parameter | description | required | -| ---------------- | ------------------------------------------------------------ | -------- | -| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no | -| dedicatedKMSAuth | Credentials required to access KMS (Key Management Service) under a dedicated KMS | no | +| parameter | description | required | +| --------- | ------------------------------------------------------------------------------ | -------- | +| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no | + +**OOS** + +| parameter | description | required | +| --------- | --------------------------------------------------------------- | -------- | +| OOSAuth | Credentials required to access OOS(Manage Encryption Parameter) | no | **KMSAuth** @@ -459,16 +364,18 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden | remoteRamRoleArn | Cross-account ram role are | no | | remoteRamRoleSessionName | Cross-account ram role session name | no | -**dedicatedKMSAuth** +**OOSAuth** -| parameter | description | required | -| ---------------- | ---------------------------------------- | -------- | -| protocol | https | yes | -| endpoint | Kms instance ID | yes | -| ca | User root CA certificate, base64 encoded | no | -| ignoreSSL | Whether to ignore ssl authentication | no | -| clientKeyContent | dedicated KMS client key file content | yes | -| password | client key password | yes | +| parameter | description | required | +| ------------------------ | ----------------------------------- | -------- | +| accessKey | AccessKey | no | +| accessKeySecret | AccessKey Secret | no | +| ramRoleARN | Ram role arn | no | +| ramRoleSessionName | Role session name | no | +| oidcProviderARN | OIDC provider arn | no | +| oidcTokenFilePath | | no | +| remoteRamRoleArn | Cross-account ram role are | no | +| remoteRamRoleSessionName | Cross-account ram role session name | no | **SecretRef(sensitive access credentials are stored in K8S secret)** @@ -480,9 +387,12 @@ ack-secret-manager involves two CRDs. SecretStore is used to store access creden ## Release Note -| Version | Date | Changes | -| ------- | ---------- | ------------------------------------------------------------ | -| `0.4.0` | 2022/12/22 | Support sync specific key-value pairs extract from a JSON-formatted secret based on JMES path | +| Version | Date | Changes | +| --------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `0.4.0` | 2022/12/22 | Support sync specific key-value pairs extract from a JSON-formatted secret based on JMES path | | `0.5.0` | 2023/10/10 | 1.dedicated KMS credential synchronization
2.multiple Alibaba Cloud access credentials management,
3.self-resolving credentials and key rule replacement
4.shared KMS cross-account credential synchronization. | -| `0.5.1` | 2023/10/18 | Function and performance optimization | -| `0.5.2` | 2024/08/01 | Large-scale resource synchronization concurrency optimization | \ No newline at end of file +| `0.5.1` | 2023/10/18 | Function and performance optimization | +| `0.5.2` | 2024/08/01 | Large-scale resource synchronization concurrency optimization | +| `0.5.3` | 2024/10/10 | Supports resource synchronization with second-level rate limiting, fixes for certain software package CVEs | +| `0.5.4` | 2024/10/31 | Supports OOS secret parameter synchronization | +| `0.5.5` | 2024/11/22 | Supports synchronization of binary-type secrets | diff --git a/charts/ack-secret-manager/templates/deployment.yaml b/charts/ack-secret-manager/templates/deployment.yaml index 43b397ab..fb077a10 100644 --- a/charts/ack-secret-manager/templates/deployment.yaml +++ b/charts/ack-secret-manager/templates/deployment.yaml @@ -32,13 +32,14 @@ spec: - name: {{ .Chart.Name }} command: - ack-secret-manager - - --backend={{ .Values.command.backend }} - --token-rotation-period={{ .Values.command.tokenRotationPeriod }} - --reconcile-period={{ .Values.command.reconcilePeriod }} - --reconcile-count={{ .Values.command.reconcileCount }} - --polling-interval={{ .Values.command.pollingInterval }} - --disable-polling={{ .Values.command.disablePolling }} - --region={{ .Values.command.region }} + - --max-concurrent-kms-secret-pulls={{ .Values.command.maxConcurrentKmsSecretPulls }} + - --max-concurrent-oos-secret-pulls={{ .Values.command.maxConcurrentOosSecretPulls }} image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ .Values.image.pullPolicy }} resources: diff --git a/charts/ack-secret-manager/templates/secret-stores-crd.yaml b/charts/ack-secret-manager/templates/secret-stores-crd.yaml index 26ba3247..663e9aa7 100644 --- a/charts/ack-secret-manager/templates/secret-stores-crd.yaml +++ b/charts/ack-secret-manager/templates/secret-stores-crd.yaml @@ -21,14 +21,16 @@ spec: description: SecretStore is the Schema for the secretstores API properties: apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + description: + "APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" type: string kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + description: + "Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" type: string metadata: type: object @@ -37,9 +39,10 @@ spec: minProperties: 1 properties: KMS: - description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - Important: Run "make" to regenerate code after modifying this file - maybe support more alibabacloud product' + description: + 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file + maybe support more alibabacloud product' maxProperties: 1 properties: KMSAuth: @@ -105,7 +108,8 @@ spec: endpoint: type: string ignoreSSL: - description: if ignoreSSL=true custom don't need fill the + description: + if ignoreSSL=true custom don't need fill the CA type: boolean password: @@ -130,6 +134,52 @@ spec: - protocol type: object type: object + OOS: + properties: + OOSAuth: + properties: + accessKey: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + accessKeySecret: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + oidcProviderARN: + type: string + oidcTokenFilePath: + type: string + ramRoleARN: + type: string + ramRoleSessionName: + type: string + remoteRamRoleARN: + type: string + remoteRamRoleSessionName: + type: string + roleSessionExpiration: + type: string + type: object + type: object type: object status: description: SecretStoreStatus defines the observed state of SecretStore diff --git a/charts/ack-secret-manager/values.yaml b/charts/ack-secret-manager/values.yaml index 907dc14b..a8edda27 100644 --- a/charts/ack-secret-manager/values.yaml +++ b/charts/ack-secret-manager/values.yaml @@ -4,14 +4,14 @@ # Environment variables to set on deployment pod command: - backend: alicloud-kms reconcilePeriod: 5s reconcileCount: 1 tokenRotationPeriod: 120s region: disablePolling: false pollingInterval: 120s - maxConcurrentSecretPulls: 5 + maxConcurrentKmsSecretPulls: 10 + maxConcurrentOosSecretPulls: 10 # watchamespaces: # excludeamespaces: @@ -66,12 +66,12 @@ replicaCount: 2 image: repository: registry-cn-hangzhou.ack.aliyuncs.com/acs/ack-secret-manager - tag: v0.5.2 + tag: v0.5.5 pullPolicy: Always cleanupImage: repository: registry-cn-hangzhou.ack.aliyuncs.com/acs/ack-secret-manager-cleanup - tag: v0.4.0 + tag: v0.4.1 pullPolicy: Always nameOverride: "" diff --git a/cmd/manager/main.go b/cmd/manager/main.go index 982bb971..50174966 100644 --- a/cmd/manager/main.go +++ b/cmd/manager/main.go @@ -19,9 +19,10 @@ import ( "context" "flag" "fmt" - "golang.org/x/sync/semaphore" + "golang.org/x/time/rate" "os" "runtime" + "sigs.k8s.io/controller-runtime/pkg/cache" "strings" "time" @@ -34,7 +35,8 @@ import ( apis "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" - _ "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/kms" + _ "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider/kms" + _ "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider/oos" "github.com/AliyunContainerService/ack-secret-manager/pkg/controller/externalsecret" "github.com/AliyunContainerService/ack-secret-manager/pkg/controller/secretstore" "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" @@ -69,6 +71,8 @@ func main() { var region string var tokenRotationPeriod time.Duration var maxConcurrentSecretPulls int + var maxConcurrentKmsSecretPulls int + var maxConcurrentOosSecretPulls int flag.StringVar(&selectedBackend, "backend", "alicloud-kms", "Selected backend. Only alicloud-kms supported") flag.DurationVar(&rotationInterval, "polling-interval", 120*time.Second, "How often the controller will sync existing secret from kms") @@ -79,10 +83,27 @@ func main() { flag.StringVar(®ion, "region", "", "Region id, change it according to where you want to pull the secret from") flag.StringVar(&watchNamespaces, "watch-namespaces", "", "Comma separated list of namespaces that ack-secret-manager watch. By default all namespaces are watched.") flag.StringVar(&excludeNamespaces, "exclude-namespaces", "", "Comma separated list of namespaces that that ack-secret-manager will not watch. By default all namespaces are watched.") - flag.IntVar(&maxConcurrentSecretPulls, "max-concurrent-secret-pulls", 5, "used to control how many secrets are pulled at the same time.\n\n") + flag.IntVar(&maxConcurrentSecretPulls, "max-concurrent-secret-pulls", 10, "used to control how many kms secrets are pulled at the same time.") + flag.IntVar(&maxConcurrentKmsSecretPulls, "max-concurrent-kms-secret-pulls", 10, "used to control how many kms secrets are pulled at the same time.") + flag.IntVar(&maxConcurrentOosSecretPulls, "max-concurrent-oos-secret-pulls", 10, "used to control how many oos secrets are pulled at the same time.") flag.Parse() + finalMaxConcurrentSecretPulls := maxConcurrentKmsSecretPulls + + flag.Visit(func(f *flag.Flag) { + if f.Name == "max-concurrent-secret-pulls" { + finalMaxConcurrentSecretPulls = maxConcurrentSecretPulls + } + }) + flag.Visit(func(f *flag.Flag) { + if f.Name == "max-concurrent-kms-secret-pulls" { + finalMaxConcurrentSecretPulls = maxConcurrentKmsSecretPulls + } + }) + + maxConcurrentKmsSecretPulls = finalMaxConcurrentSecretPulls + ctrl.SetLogger(zap.New()) printVersion() @@ -105,8 +126,9 @@ func main() { region = instanceRegion } opts := &backend.ProviderOptions{ - Region: region, - MaxConcurrent: maxConcurrentSecretPulls, + Region: region, + KmsMaxConcurrent: maxConcurrentKmsSecretPulls, + OosMaxConcurrent: maxConcurrentOosSecretPulls, } for providerName, f := range backend.SupportProvider { log.Info("new provider ", providerName) @@ -117,9 +139,16 @@ func main() { if err != nil { log.Error(err, "") } + var syncPeriod = 10 * time.Hour + if disablePolling { + syncPeriod = 365 * 24 * time.Hour + } // Create a new Cmd to provide shared dependencies and start components mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ Scheme: scheme, + Cache: cache.Options{ + SyncPeriod: &syncPeriod, + }, }) if err != nil { log.Error(err, "unable to start manager") @@ -150,17 +179,18 @@ func main() { watchNs[ns] = false } } - w := semaphore.NewWeighted(int64(opts.MaxConcurrent)) esReconciler := externalsecret.ExternalSecretReconciler{ - Client: mgr.GetClient(), - APIReader: mgr.GetAPIReader(), - Log: ctrl.Log.WithName("controllers").WithName("ExternalSecret"), - Ctx: ctx, - ReconciliationPeriod: reconcilePeriod, - WatchNamespaces: watchNs, - RotationInterval: rotationInterval, - ConcurrentController: w, - } + Client: mgr.GetClient(), + APIReader: mgr.GetAPIReader(), + Log: ctrl.Log.WithName("controllers").WithName("ExternalSecret"), + Ctx: ctx, + DisablePolling: disablePolling, + ReconciliationPeriod: reconcilePeriod, + WatchNamespaces: watchNs, + RotationInterval: rotationInterval, + } + esReconciler.KmsLimiter.SecretPullLimiter = rate.NewLimiter(rate.Limit(maxConcurrentKmsSecretPulls), 1) + esReconciler.OosLimiter.SecretPullLimiter = rate.NewLimiter(rate.Limit(maxConcurrentOosSecretPulls), 1) err = (&esReconciler).SetupWithManager(mgr, reconcileCount) if err != nil { log.Error(err, "unable to create controller", "controller", "ExternalSecret") @@ -177,15 +207,6 @@ func main() { log.Error(err, "unable to create controller", "controller", "SecretStore") os.Exit(1) } - //not start auto sync job if disable polling - if !disablePolling { - err := esReconciler.InitSecretCache() - if err != nil { - log.Error(err, "failed to init secret cache") - os.Exit(1) - } - go esReconciler.SecretRotationJob() - } log.Info("starting ack-secret-manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { diff --git a/deploy/crds/alibabacloud.com_secretstores.yaml b/deploy/crds/alibabacloud.com_secretstores.yaml index 33d4dc41..663e9aa7 100644 --- a/deploy/crds/alibabacloud.com_secretstores.yaml +++ b/deploy/crds/alibabacloud.com_secretstores.yaml @@ -15,127 +15,177 @@ spec: singular: secretstore scope: Namespaced versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: SecretStore is the Schema for the secretstores API - properties: - apiVersion: - description: 'APIVersion defines the versioned schema of this representation - of an object. Servers should convert recognized schemas to the latest - internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' - type: string - kind: - description: 'Kind is a string value representing the REST resource this - object represents. Servers may infer this from the endpoint the client - submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' - type: string - metadata: - type: object - spec: - maxProperties: 1 - minProperties: 1 - properties: - KMS: - description: 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster - Important: Run "make" to regenerate code after modifying this file - maybe support more alibabacloud product' - maxProperties: 1 - properties: - KMSAuth: - properties: - accessKey: - properties: - key: - type: string - name: - type: string - namespace: - type: string - required: - - key - - name - - namespace - type: object - accessKeySecret: - properties: - key: - type: string - name: - type: string - namespace: - type: string - required: - - key - - name - - namespace - type: object - oidcProviderARN: - type: string - oidcTokenFilePath: - type: string - ramRoleARN: - type: string - ramRoleSessionName: - type: string - remoteRamRoleARN: - type: string - remoteRamRoleSessionName: - type: string - roleSessionExpiration: - type: string - type: object - dedicatedKMSAuth: - properties: - ca: - type: string - clientKeyContent: - properties: - key: - type: string - name: - type: string - namespace: - type: string - required: - - key - - name - - namespace - type: object - endpoint: - type: string - ignoreSSL: - description: if ignoreSSL=true custom don't need fill the - CA - type: boolean - password: - properties: - key: - type: string - name: - type: string - namespace: - type: string - required: - - key - - name - - namespace - type: object - protocol: - type: string - required: - - clientKeyContent - - endpoint - - password - - protocol - type: object - type: object - type: object - status: - description: SecretStoreStatus defines the observed state of SecretStore - type: object - type: object - served: true - storage: true - subresources: - status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: SecretStore is the Schema for the secretstores API + properties: + apiVersion: + description: + "APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources" + type: string + kind: + description: + "Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds" + type: string + metadata: + type: object + spec: + maxProperties: 1 + minProperties: 1 + properties: + KMS: + description: + 'INSERT ADDITIONAL SPEC FIELDS - desired state of cluster + Important: Run "make" to regenerate code after modifying this file + maybe support more alibabacloud product' + maxProperties: 1 + properties: + KMSAuth: + properties: + accessKey: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + accessKeySecret: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + oidcProviderARN: + type: string + oidcTokenFilePath: + type: string + ramRoleARN: + type: string + ramRoleSessionName: + type: string + remoteRamRoleARN: + type: string + remoteRamRoleSessionName: + type: string + roleSessionExpiration: + type: string + type: object + dedicatedKMSAuth: + properties: + ca: + type: string + clientKeyContent: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + endpoint: + type: string + ignoreSSL: + description: + if ignoreSSL=true custom don't need fill the + CA + type: boolean + password: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + protocol: + type: string + required: + - clientKeyContent + - endpoint + - password + - protocol + type: object + type: object + OOS: + properties: + OOSAuth: + properties: + accessKey: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + accessKeySecret: + properties: + key: + type: string + name: + type: string + namespace: + type: string + required: + - key + - name + - namespace + type: object + oidcProviderARN: + type: string + oidcTokenFilePath: + type: string + ramRoleARN: + type: string + ramRoleSessionName: + type: string + remoteRamRoleARN: + type: string + remoteRamRoleSessionName: + type: string + roleSessionExpiration: + type: string + type: object + type: object + type: object + status: + description: SecretStoreStatus defines the observed state of SecretStore + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/doc/crd.md b/doc/crd.md index d3ea6051..618d0bdf 100644 --- a/doc/crd.md +++ b/doc/crd.md @@ -18,7 +18,7 @@ | key | The unique identifier for the target credential, such as the key for KMS credentials | yes | | name | The corresponding key for the credentials in the secret data of the cluster | no | | versionStage | The version stage of the target credential | no | -| versionId | The version Id of the target credential | no | +| versionId | The version Id of the target credential, this field is not required when provider is oos | no | | jmesPath | If the target credential is in JSON format, you can specify to retrieve the value corresponding to a specific key in the JSON | no | | secretStoreRef | Information of the referenced SecretStore | no | @@ -57,14 +57,21 @@ | parameter | description | required | | --------- | ------------------------------------------------------------ | -------- | | KMS | Representing the target cloud product as KMS (Key Management Service) | no | +| OOS | Representing the target cloud product as OOS(Key Management Service) | no | **KMS** -| parameter | description | required | -| ---------------- | ------------------------------------------------------------ | -------- | -| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no | +| parameter | description | required | +| ---------------- | --------------------------------------------------------------------------------- | -------- | +| KMSAuth | Credentials required to access KMS (Key Management Service) under a shared KMS | no | | dedicatedKMSAuth | Credentials required to access KMS (Key Management Service) under a dedicated KMS | no | +**OOS** + +| parameter | description | required | +| --------- | ----------------------------------------------------------------------------- | -------- | +| OOSAuth | Credentials required to access OOS(Key Management Service) under a shared OOS | no | + **KMSAuth** | parameter | description | required | @@ -78,6 +85,19 @@ | remoteRamRoleArn | Cross-account ram role are | no | | remoteRamRoleSessionName | Cross-account ram role session name | no | +**OOSAuth** + +| crd 字段 | 描述 | 是否必选 | +| ------------------------ | ---------------------------- | -------- | +| accessKey | 用户AK | 否 | +| accessKeySecret | 用户SK | 否 | +| ramRoleARN | ram 角色 arn | 否 | +| ramRoleSessionName | 角色会话名 | 否 | +| oidcProviderARN | oidc 提供商 arn | 否 | +| oidcTokenFilePath | 暂时无用 | 否 | +| remoteRamRoleArn | 跨账号 ram 角色 arn | 否 | +| remoteRamRoleSessionName | 跨账号 ram 角色 session name | 否 | + **dedicatedKMSAuth** | parameter | description | required | diff --git a/go.mod b/go.mod index f4ce4475..b748ab7c 100644 --- a/go.mod +++ b/go.mod @@ -1,32 +1,35 @@ module github.com/AliyunContainerService/ack-secret-manager -go 1.18 +go 1.23.1 require ( github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.13.0 github.com/alibabacloud-go/darabonba-openapi v0.1.4 + github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2 github.com/alibabacloud-go/kms-20160120/v2 v2.0.0 + github.com/alibabacloud-go/oos-20190601/v3 v3.0.1 github.com/alibabacloud-go/tea v1.2.1 github.com/aliyun/alibaba-cloud-sdk-go v1.61.127 github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.4.0 github.com/aliyun/credentials-go v1.2.2 - github.com/go-logr/logr v0.3.0 + github.com/go-logr/logr v1.4.2 github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af github.com/onsi/ginkgo v1.14.1 - github.com/onsi/gomega v1.10.2 + github.com/onsi/gomega v1.33.1 github.com/operator-framework/operator-lib v0.4.1 - golang.org/x/net v0.11.0 - k8s.io/api v0.20.2 - k8s.io/apimachinery v0.20.2 - k8s.io/client-go v12.0.0+incompatible - k8s.io/code-generator v0.20.1 + golang.org/x/net v0.26.0 + golang.org/x/time v0.3.0 + k8s.io/api v0.31.1 + k8s.io/apimachinery v0.31.1 + k8s.io/client-go v0.31.1 + k8s.io/code-generator v0.31.1 k8s.io/klog v1.0.0 - sigs.k8s.io/controller-runtime v0.8.3 + k8s.io/klog/v2 v2.130.1 + sigs.k8s.io/controller-runtime v0.19.0 ) require ( - github.com/PuerkitoBio/purell v1.1.1 // indirect - github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect + github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect github.com/alibabacloud-go/darabonba-array v0.1.0 // indirect github.com/alibabacloud-go/darabonba-encode-util v0.0.2 // indirect github.com/alibabacloud-go/darabonba-map v0.0.2 // indirect @@ -35,69 +38,66 @@ require ( github.com/alibabacloud-go/endpoint-util v1.1.0 // indirect github.com/alibabacloud-go/openapi-util v0.1.0 // indirect github.com/alibabacloud-go/tea-utils v1.3.9 // indirect - github.com/alibabacloud-go/tea-utils/v2 v2.0.3 // indirect + github.com/alibabacloud-go/tea-utils/v2 v2.0.4 // indirect + github.com/alibabacloud-go/tea-xml v1.1.2 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/cespare/xxhash/v2 v2.1.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/emicklei/go-restful v2.16.0+incompatible // indirect - github.com/evanphx/json-patch v4.9.0+incompatible // indirect - github.com/fsnotify/fsnotify v1.4.9 // indirect - github.com/go-logr/zapr v0.2.0 // indirect - github.com/go-openapi/jsonpointer v0.19.3 // indirect - github.com/go-openapi/jsonreference v0.19.3 // indirect - github.com/go-openapi/spec v0.19.4 // indirect - github.com/go-openapi/swag v0.19.5 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect + github.com/clbanning/mxj/v2 v2.5.5 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/emicklei/go-restful/v3 v3.11.0 // indirect + github.com/evanphx/json-patch/v5 v5.9.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/fxamacker/cbor/v2 v2.7.0 // indirect + github.com/go-logr/zapr v1.3.0 // indirect + github.com/go-openapi/jsonpointer v0.19.6 // indirect + github.com/go-openapi/jsonreference v0.20.2 // indirect + github.com/go-openapi/swag v0.22.4 // indirect github.com/gogo/protobuf v1.3.2 // indirect - github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect - github.com/golang/protobuf v1.5.0 // indirect - github.com/google/go-cmp v0.5.5 // indirect - github.com/google/gofuzz v1.1.0 // indirect - github.com/google/uuid v1.1.2 // indirect - github.com/googleapis/gnostic v0.5.1 // indirect - github.com/hashicorp/golang-lru v0.5.4 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/protobuf v1.5.4 // indirect + github.com/google/gnostic-models v0.6.8 // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/google/gofuzz v1.2.0 // indirect + github.com/google/uuid v1.6.0 // indirect github.com/imdario/mergo v0.3.10 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/mailru/easyjson v0.7.0 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect + github.com/mailru/easyjson v0.7.7 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nxadm/tail v1.4.4 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.7.1 // indirect - github.com/prometheus/client_model v0.2.0 // indirect - github.com/prometheus/common v0.10.0 // indirect - github.com/prometheus/procfs v0.2.0 // indirect + github.com/prometheus/client_golang v1.19.1 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.55.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/tjfoc/gmsm v1.4.1 // indirect - go.uber.org/atomic v1.6.0 // indirect - go.uber.org/multierr v1.5.0 // indirect - go.uber.org/zap v1.15.0 // indirect - golang.org/x/crypto v0.10.0 // indirect - golang.org/x/mod v0.8.0 // indirect - golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect + github.com/x448/float16 v0.8.4 // indirect + go.uber.org/multierr v1.11.0 // indirect + go.uber.org/zap v1.26.0 // indirect + golang.org/x/crypto v0.24.0 // indirect + golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc // indirect + golang.org/x/mod v0.17.0 // indirect + golang.org/x/oauth2 v0.21.0 // indirect golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.9.0 // indirect - golang.org/x/text v0.10.0 // indirect - golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e // indirect - golang.org/x/tools v0.6.0 // indirect - golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect - gomodules.xyz/jsonpatch/v2 v2.1.0 // indirect - google.golang.org/appengine v1.6.6 // indirect - google.golang.org/protobuf v1.31.0 // indirect + golang.org/x/sys v0.21.0 // indirect + golang.org/x/term v0.21.0 // indirect + golang.org/x/text v0.16.0 // indirect + golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect + gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/ini.v1 v1.56.0 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect - gopkg.in/yaml.v2 v2.3.0 // indirect - gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 // indirect - k8s.io/apiextensions-apiserver v0.20.1 // indirect - k8s.io/component-base v0.20.2 // indirect - k8s.io/gengo v0.0.0-20201113003025-83324d819ded // indirect - k8s.io/klog/v2 v2.4.0 // indirect - k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd // indirect - k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 // indirect - sigs.k8s.io/structured-merge-diff/v4 v4.0.2 // indirect - sigs.k8s.io/yaml v1.2.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/apiextensions-apiserver v0.31.0 // indirect + k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 // indirect + k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect + k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 // indirect + sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect + sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect + sigs.k8s.io/yaml v1.4.0 // indirect ) - -replace k8s.io/client-go => k8s.io/client-go v0.20.2 diff --git a/go.sum b/go.sum index c5b41140..981c7cf4 100644 --- a/go.sum +++ b/go.sum @@ -22,37 +22,41 @@ cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiy cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.12.0 h1:nUTgdlM3aLzOHQhdxrtUdO2T4vqBoW3kn6C9QIeClKk= -github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.12.0/go.mod h1:tlqp9mUGbsP+0z3Q+c0Q5MgSdq/OMwQhm5bffR3Q3ss= github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.13.0 h1:J6JXctkQI6QCdPOKTyERNf2KdgNkBVQfwJUn2qy12TQ= github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider v0.13.0/go.mod h1:tlqp9mUGbsP+0z3Q+c0Q5MgSdq/OMwQhm5bffR3Q3ss= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= -github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= -github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= -github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 h1:iC9YFYKDGEy3n/FtqJnOkZsene9olVspKmkX5A2YBEo= +github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4/go.mod h1:sCavSAvdzOjul4cEqeVtvlSaSScfNsTQ+46HwlTL1hc= github.com/alibabacloud-go/darabonba-array v0.1.0 h1:vR8s7b1fWAQIjEjWnuF0JiKsCvclSRTfDzZHTYqfufY= github.com/alibabacloud-go/darabonba-array v0.1.0/go.mod h1:BLKxr0brnggqOJPqT09DFJ8g3fsDshapUD3C3aOEFaI= github.com/alibabacloud-go/darabonba-encode-util v0.0.2 h1:1uJGrbsGEVqWcWxrS9MyC2NG0Ax+GpOM5gtupki31XE= @@ -61,6 +65,8 @@ github.com/alibabacloud-go/darabonba-map v0.0.2 h1:qvPnGB4+dJbJIxOOfawxzF3hzMnIp github.com/alibabacloud-go/darabonba-map v0.0.2/go.mod h1:28AJaX8FOE/ym8OUFWga+MtEzBunJwQGceGQlvaPGPc= github.com/alibabacloud-go/darabonba-openapi v0.1.4 h1:eV4mB+45/QxWFQqghSUVO5H5Ct4c+tCaCp4c57TCTVY= github.com/alibabacloud-go/darabonba-openapi v0.1.4/go.mod h1:j03z4XUkIC9aBj/w5Bt7H0cygmPNt5sug8NXle68+Og= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2 h1:2kR1YkvQloHUstmPcG0Sjk24zTKbza7izzJfJNwBFSs= +github.com/alibabacloud-go/darabonba-openapi/v2 v2.0.2/go.mod h1:5JHVmnHvGzR2wNdgaW1zDLQG8kOC4Uec8ubkMogW7OQ= github.com/alibabacloud-go/darabonba-string v1.0.0/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= github.com/alibabacloud-go/darabonba-string v1.0.2 h1:E714wms5ibdzCqGeYJ9JCFywE5nDyvIXIIQbZVFkkqo= github.com/alibabacloud-go/darabonba-string v1.0.2/go.mod h1:93cTfV3vuPhhEwGGpKKqhVW4jLe7tDpo3LUM0i0g6mA= @@ -70,7 +76,10 @@ github.com/alibabacloud-go/endpoint-util v1.1.0 h1:r/4D3VSw888XGaeNpP994zDUaxdgT github.com/alibabacloud-go/endpoint-util v1.1.0/go.mod h1:O5FuCALmCKs2Ff7JFJMudHs0I5EBgecXXxZRyswlEjE= github.com/alibabacloud-go/kms-20160120/v2 v2.0.0 h1:WERretZ1mLLchpB+VinDizRZjYDuys6P/jWETSj4ND0= github.com/alibabacloud-go/kms-20160120/v2 v2.0.0/go.mod h1:jYnUb2h6v+wLGwg2CRDks6m9nqQWnAkbN0RFKCewgGY= +github.com/alibabacloud-go/oos-20190601/v3 v3.0.1 h1:yAGX1j/ivv29NxxQTb1ghBL6q4YWS+HVgy+Ce2J4/YI= +github.com/alibabacloud-go/oos-20190601/v3 v3.0.1/go.mod h1:Y8dvw2TqM5Lfvq7FAxfI1h49804i7pb+QD/pbfCCfCA= github.com/alibabacloud-go/openapi-util v0.0.7/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= +github.com/alibabacloud-go/openapi-util v0.0.11/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= github.com/alibabacloud-go/openapi-util v0.1.0 h1:0z75cIULkDrdEhkLWgi9tnLe+KhAFE/r5Pb3312/eAY= github.com/alibabacloud-go/openapi-util v0.1.0/go.mod h1:sQuElr4ywwFRlCCberQwKRFhRzIyG4QTP/P4y1CJ6Ws= github.com/alibabacloud-go/tea v1.1.0/go.mod h1:IkGyUSX4Ba1V+k4pCtJUc6jDpZLFph9QMy2VUPTwukg= @@ -79,13 +88,18 @@ github.com/alibabacloud-go/tea v1.1.8/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeG github.com/alibabacloud-go/tea v1.1.11/go.mod h1:/tmnEaQMyb4Ky1/5D+SE1BAsa5zj/KeGOFfwYm3N/p4= github.com/alibabacloud-go/tea v1.1.15/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= github.com/alibabacloud-go/tea v1.1.17/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= +github.com/alibabacloud-go/tea v1.1.19/go.mod h1:nXxjm6CIFkBhwW4FQkNrolwbfon8Svy6cujmKFUq98A= github.com/alibabacloud-go/tea v1.2.1 h1:rFF1LnrAdhaiPmKwH5xwYOKlMh66CqRwPUTzIK74ask= github.com/alibabacloud-go/tea v1.2.1/go.mod h1:qbzof29bM/IFhLMtJPrgTGK3eauV5J2wSyEUo4OEmnA= github.com/alibabacloud-go/tea-utils v1.3.1/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= github.com/alibabacloud-go/tea-utils v1.3.9 h1:TtbzxS+BXrisA7wzbAMRtlU8A2eWLg0ufm7m/Tl6fc4= github.com/alibabacloud-go/tea-utils v1.3.9/go.mod h1:EI/o33aBfj3hETm4RLiAxF/ThQdSngxrpF8rKUDJjPE= -github.com/alibabacloud-go/tea-utils/v2 v2.0.3 h1:6OM8vm/6pjQg1a7zc3QNMviaoumnhImRi5V84CnuFkc= +github.com/alibabacloud-go/tea-utils/v2 v2.0.0/go.mod h1:U5MTY10WwlquGPS34DOeomUGBB0gXbLueiq5Trwu0C4= github.com/alibabacloud-go/tea-utils/v2 v2.0.3/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ= +github.com/alibabacloud-go/tea-utils/v2 v2.0.4 h1:SoFgjJuO7pze88j9RBJNbKb7AgTS52O+J5ITxc00lCs= +github.com/alibabacloud-go/tea-utils/v2 v2.0.4/go.mod h1:sj1PbjPodAVTqGTA3olprfeeqqmwD0A5OQz94o9EuXQ= +github.com/alibabacloud-go/tea-xml v1.1.2 h1:oLxa7JUXm2EDFzMg+7oRsYc+kutgCVwm+bZlhhmvW5M= +github.com/alibabacloud-go/tea-xml v1.1.2/go.mod h1:Rq08vgCcCAjHyRi/M7xlHKUykZCEtyBy9+DPF6GgEu8= github.com/aliyun/alibaba-cloud-sdk-go v1.61.127 h1:AgCt/3Iwi+cGU9ybyD5GBaP7kS15KS1uoeCnS6s68xY= github.com/aliyun/alibaba-cloud-sdk-go v1.61.127/go.mod h1:pUKYbK5JQ+1Dfxk80P0qxGqe5dkxDoabbZS7zOcouyA= github.com/aliyun/alibabacloud-dkms-gcs-go-sdk v0.4.0 h1:6QWm/jay2+WqE1PihsSQOyeY5DKwr3EWCaSKYX6F9wI= @@ -111,11 +125,14 @@ github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnweb github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= -github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= +github.com/clbanning/mxj/v2 v2.5.5 h1:oT81vUeEiQQ/DcHbzSytRngP6Ky9O+L+0Bw0zSJag9E= +github.com/clbanning/mxj/v2 v2.5.5/go.mod h1:hNiWqW14h+kc+MdF9C6/YoRfjEJoR3ou6tn/Qo+ve2s= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -134,9 +151,11 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= @@ -149,8 +168,8 @@ github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25Kn github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= -github.com/emicklei/go-restful v2.16.0+incompatible h1:rgqiKNjTnFQA6kkhFe16D8epTksy9HQ1MyrbDXSdYhM= -github.com/emicklei/go-restful v2.16.0+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= +github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= +github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -159,12 +178,17 @@ github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLi github.com/evanphx/json-patch v4.5.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible h1:kLcOMZeuLAJvL2BPWLMIj5oaZQobrkAqrL+WFZwQses= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= +github.com/evanphx/json-patch/v5 v5.9.0 h1:kcBlZQbplgElYIlo/n1hJbls2z/1awpXxpRi0/FOJfg= +github.com/evanphx/json-patch/v5 v5.9.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/fxamacker/cbor/v2 v2.7.0 h1:iM5WgngdRBanHcxugY4JySA0nk1wZorNOpTgCMedv5E= +github.com/fxamacker/cbor/v2 v2.7.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= @@ -179,10 +203,12 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v0.3.0 h1:q4c+kbcR0d5rSurhBR8dIgieOaYpXtsdTYfx22Cu6rs= github.com/go-logr/logr v0.3.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/zapr v0.2.0 h1:v6Ji8yBW77pva6NkJKQdHLAJKrIJKRHz0RXwPqCHSR4= +github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= +github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/zapr v0.2.0/go.mod h1:qhKdvif7YF5GI9NWEpyxTSSBdGmzkNguibrdCNVPunU= +github.com/go-logr/zapr v1.3.0 h1:XGdV8XW8zdwFiwOA2Dryh1gj2KRQyOOoNmBy4EplIcQ= +github.com/go-logr/zapr v1.3.0/go.mod h1:YKepepNBd1u/oyhd/yQmtjVXmm9uML4IXUgMOwR8/Gg= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik= @@ -195,14 +221,16 @@ github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+ github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.18.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= -github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= +github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg= github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.18.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= -github.com/go-openapi/jsonreference v0.19.3 h1:5cxNfTy0UVC3X8JL5ymxzyoUZmo8iZb+jeTWn7tUa8o= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= +github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= +github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= github.com/go-openapi/loads v0.17.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU= @@ -216,8 +244,6 @@ github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsd github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI= github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= -github.com/go-openapi/spec v0.19.4 h1:ixzUSnHTd6hCemgtAJgluaTSGYpLNpJY4mA2DIkdOAo= -github.com/go-openapi/spec v0.19.4/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/strfmt v0.17.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.18.0/go.mod h1:P82hnJI0CXkErkXi8IKjPbNBM6lV6+5pLP5l494TcyU= github.com/go-openapi/strfmt v0.19.0/go.mod h1:+uW+93UVvGGq2qGaZxdDeJqSAqBqBdl+ZPMF/cC8nDY= @@ -226,14 +252,18 @@ github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dp github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= -github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= +github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU= +github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4= github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA= github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/gobuffalo/flect v0.2.0/go.mod h1:W3K3X9ksuZfir8f/LrfVtWmCDQFfayuylOJ7sz/Fj80= github.com/goccy/go-yaml v1.8.1/go.mod h1:wS4gNoLalDSJxo/SpngzPQ2BN4uuZVLCmbM4S3vd4+Y= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -247,8 +277,9 @@ github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4er github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= @@ -268,39 +299,48 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= +github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= +github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= +github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af h1:kmjWCqn2qkEml422C2Rrd27c3VGxi6a/6HNq8QmHRKM= +github.com/google/pprof v0.0.0-20240525223248-4bfdf5a9a2af/go.mod h1:K1liHPHnj73Fdn/EKuT8nrFqBihUSKXoLYU0BuatOYo= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= -github.com/googleapis/gnostic v0.5.1 h1:A8Yhf6EtqTv9RMsU6MQTyrtV1TjWlR6xU9BsZIwuTCM= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= +github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00 h1:l5lAOZEym3oK3SQ2HBHWsJUfbNBiTXJDeW2QDxw9AQ0= github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -328,7 +368,6 @@ github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/b github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= @@ -344,6 +383,8 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -365,10 +406,14 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -378,8 +423,9 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= -github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -392,7 +438,6 @@ github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOA github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37/go.mod h1:dYWq+UWoFCDY1TndvFUQuhBbIYmZpjreC8adEAx93zE= @@ -413,10 +458,10 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= -github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= @@ -428,13 +473,16 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.1 h1:jMU0WaQrP0a/YAEq8eJmJKjBoMs+pClEr1vDMlM/Do4= github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/ginkgo/v2 v2.19.0 h1:9Cnnf7UHo57Hy3k6/m5k3dRfGTMXGvxhHFvkDTCTpvA= +github.com/onsi/ginkgo/v2 v2.19.0/go.mod h1:rlwLi9PilAFJ8jCg9UE1QP6VBpd6/xj3SRC0d6TU0To= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= -github.com/onsi/gomega v1.10.2 h1:aY/nuoWlKJud2J6U0E3NWsjlg+0GtwXxgEqthRdzlcs= github.com/onsi/gomega v1.10.2/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= +github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk= +github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0= github.com/operator-framework/api v0.5.2/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= github.com/operator-framework/operator-lib v0.4.1 h1:Eh4JHs+LAWeC85ZMHXJ9RXg7G5grYx8J29TkOw8003s= github.com/operator-framework/operator-lib v0.4.1/go.mod h1:2dszbSeSo/472Ea8zIAcjEJhgzXKxzAGG24MgIP+13c= @@ -446,34 +494,41 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.7.1 h1:NTGy1Ja9pByO+xAeH/qiWnLrKtr3hJPNjaVUwnjpdpA= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= +github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G1dc= +github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.2.0 h1:wH4vA7pcjKuZzjF7lM8awk4fnuJO6idemZXoKnULUx4= github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -511,12 +566,18 @@ github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tjfoc/gmsm v1.3.2/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w= @@ -528,6 +589,8 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= +github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= +github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -548,22 +611,24 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/atomic v1.6.0 h1:Ezj3JGmsOnG1MoRWQkPBsKLe9DwWD9QeXzTRzzldNVk= go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= -go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= -go.uber.org/multierr v1.5.0 h1:KCa4XfM8CWFCpxXRGok+Q0SS/0XBhMDbHHGABQLvD2A= go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= -go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee h1:0mgffUl7nfd+FpvXMVz4IDEaUSmT1ysygQC7qYo7sG4= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= go.uber.org/zap v1.8.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= -go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM= go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= +go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190320223903-b7391e95e576/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -578,8 +643,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM= golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I= +golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI= +golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -590,6 +656,8 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0 golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc h1:mCRnTeVUjcrhlRmO0VK8a6k6Rrf6TF9htwo2pJVSjIU= +golang.org/x/exp v0.0.0-20230515195305-f3d0a9c9a5cc/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -601,7 +669,6 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b h1:Wh+f8QHJXR411sJR8/vRBTZ7YapZaRvUcLFFJhusH0k= golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -612,8 +679,9 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= +golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -655,14 +723,16 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= -golang.org/x/net v0.11.0 h1:Gi2tvZIJyBtO9SDr1q9h5hEQCp/4L2RQ+ar0qjx2oNU= golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ= +golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ= +golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d h1:TzXSXBo42m9gQenoE3b9BGiEpg5IG2JkU5FkPIawgtw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= +golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -684,6 +754,7 @@ golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -728,14 +799,15 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= +golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= -golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28= golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo= +golang.org/x/term v0.21.0 h1:WVXCp+/EBEHOj53Rvu+7KiT/iElMrO8ACK16SMZ3jaA= +golang.org/x/term v0.21.0/go.mod h1:ooXLefLobQVslOqselCNF4SxFAaoS6KujMbsGzSDmX0= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -746,14 +818,16 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.10.0 h1:UpjohKhiEgNc0CSauXmwYftY1+LlaC75SJwh0SgCX58= golang.org/x/text v0.10.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= +golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= +golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -804,15 +878,16 @@ golang.org/x/tools v0.0.0-20200616195046-dc31b401abb5/go.mod h1:EkVYQZoAsY45+roY golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= +golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gomodules.xyz/jsonpatch/v2 v2.1.0 h1:Phva6wqu+xR//Njw6iorylFFgn/z547tw5Ne3HZPQ+k= gomodules.xyz/jsonpatch/v2 v2.1.0/go.mod h1:IhYNNY4jnS53ZnfE4PAmpKtDpTCj1JFXc+3mwe7XcUU= +gomodules.xyz/jsonpatch/v2 v2.4.0 h1:Ci3iUJyx9UeRx7CeFN8ARgGbkESwJK+KB9lLcWxY/Zw= +gomodules.xyz/jsonpatch/v2 v2.4.0/go.mod h1:AH3dM2RI6uoBZxn3LVrfvJ3E0/9dG4cSrbuBJT4moAY= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -828,7 +903,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7 google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6 h1:lMO5rYAqUxkmaj76jAkRUvt5JZgFymx/+Q5Mzfivuhc= google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= @@ -872,16 +946,20 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= -google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSPG+6V4= +gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= gopkg.in/go-playground/validator.v9 v9.30.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= @@ -903,12 +981,14 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20190905181640-827449938966/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776 h1:tQIYjPdBoyREyB9XMu+nnTclpTYkz2zFM+lzLJFO4gQ= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -916,63 +996,77 @@ honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWh honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3 h1:sXmLre5bzIR6ypkjXCDI3jHPssRhc8KD/Ome589sc3U= honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= k8s.io/api v0.18.2/go.mod h1:SJCWI7OLzhZSvbY7U8zwNl9UA4o1fizoug34OV/2r78= k8s.io/api v0.20.1/go.mod h1:KqwcCVogGxQY3nBlRpwt+wpAMF/KjaCc7RpywacvqUo= -k8s.io/api v0.20.2 h1:y/HR22XDZY3pniu9hIFDLpUCPq2w5eQ6aV/VFQ7uJMw= k8s.io/api v0.20.2/go.mod h1:d7n6Ehyzx+S+cE3VhTGfVNNqtGc/oL9DCdYYahlurV8= +k8s.io/api v0.31.1 h1:Xe1hX/fPW3PXYYv8BlozYqw63ytA92snr96zMW9gWTU= +k8s.io/api v0.31.1/go.mod h1:sbN1g6eY6XVLeqNsZGLnI5FwVseTrZX7Fv3O26rhAaI= k8s.io/apiextensions-apiserver v0.18.2/go.mod h1:q3faSnRGmYimiocj6cHQ1I3WpLqmDgJFlKL37fC4ZvY= -k8s.io/apiextensions-apiserver v0.20.1 h1:ZrXQeslal+6zKM/HjDXLzThlz/vPSxrfK3OqL8txgVQ= k8s.io/apiextensions-apiserver v0.20.1/go.mod h1:ntnrZV+6a3dB504qwC5PN/Yg9PBiDNt1EVqbW2kORVk= +k8s.io/apiextensions-apiserver v0.31.0 h1:fZgCVhGwsclj3qCw1buVXCV6khjRzKC5eCFt24kyLSk= +k8s.io/apiextensions-apiserver v0.31.0/go.mod h1:b9aMDEYaEe5sdK+1T0KU78ApR/5ZVp4i56VacZYEHxk= k8s.io/apimachinery v0.18.2/go.mod h1:9SnR/e11v5IbyPCGbvJViimtJ0SwHG4nfZFjU77ftcA= k8s.io/apimachinery v0.20.1/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= -k8s.io/apimachinery v0.20.2 h1:hFx6Sbt1oG0n6DZ+g4bFt5f6BoMkOjKWsQFu077M3Vg= k8s.io/apimachinery v0.20.2/go.mod h1:WlLqWAHZGg07AeltaI0MV5uk1Omp8xaN0JGLY6gkRpU= +k8s.io/apimachinery v0.31.1 h1:mhcUBbj7KUjaVhyXILglcVjuS4nYXiwC+KKFBgIVy7U= +k8s.io/apimachinery v0.31.1/go.mod h1:rsPdaZJfTfLsNJSQzNHQvYoTmxhoOEofxtOsF3rtsMo= k8s.io/apiserver v0.18.2/go.mod h1:Xbh066NqrZO8cbsoenCwyDJ1OSi8Ag8I2lezeHxzwzw= k8s.io/apiserver v0.20.1/go.mod h1:ro5QHeQkgMS7ZGpvf4tSMx6bBOgPfE+f52KwvXfScaU= -k8s.io/client-go v0.20.2 h1:uuf+iIAbfnCSw8IGAv/Rg0giM+2bOzHLOsbbrwrdhNQ= +k8s.io/client-go v0.18.2/go.mod h1:Xcm5wVGXX9HAA2JJ2sSBUn3tCJ+4SVlCbl2MNNv+CIU= +k8s.io/client-go v0.20.1/go.mod h1:/zcHdt1TeWSd5HoUe6elJmHSQ6uLLgp4bIJHVEuy+/Y= k8s.io/client-go v0.20.2/go.mod h1:kH5brqWqp7HDxUFKoEgiI4v8G1xzbe9giaCenUWJzgE= +k8s.io/client-go v0.31.1 h1:f0ugtWSbWpxHR7sjVpQwuvw9a3ZKLXX0u0itkFXufb0= +k8s.io/client-go v0.31.1/go.mod h1:sKI8871MJN2OyeqRlmA4W4KM9KBdBUpDLu/43eGemCg= k8s.io/code-generator v0.18.2/go.mod h1:+UHX5rSbxmR8kzS+FAv7um6dtYrZokQvjHpDSYRVkTc= -k8s.io/code-generator v0.20.1 h1:kre3GNich5gbO3d1FyTT8fHI4ZJezZV217yFdWlQaRQ= k8s.io/code-generator v0.20.1/go.mod h1:UsqdF+VX4PU2g46NC2JRs4gc+IfrctnwHb76RNbWHJg= +k8s.io/code-generator v0.31.1 h1:GvkRZEP2g2UnB2QKT2Dgc/kYxIkDxCHENv2Q1itioVs= +k8s.io/code-generator v0.31.1/go.mod h1:oL2ky46L48osNqqZAeOcWWy0S5BXj50vVdwOtTefqIs= k8s.io/component-base v0.18.2/go.mod h1:kqLlMuhJNHQ9lz8Z7V5bxUUtjFZnrypArGl58gmDfUM= k8s.io/component-base v0.20.1/go.mod h1:guxkoJnNoh8LNrbtiQOlyp2Y2XFCZQmrcg2n/DeYNLk= -k8s.io/component-base v0.20.2 h1:LMmu5I0pLtwjpp5009KLuMGFqSc2S2isGw8t1hpYKLE= k8s.io/component-base v0.20.2/go.mod h1:pzFtCiwe/ASD0iV7ySMu8SYVJjCapNM9bjvk7ptpKh0= k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200114144118-36b2048a9120/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0= -k8s.io/gengo v0.0.0-20201113003025-83324d819ded h1:JApXBKYyB7l9xx+DK7/+mFjC7A9Bt5A93FPvFD0HIFE= k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70 h1:NGrVE502P0s0/1hudf8zjgwki1X/TByhmAoILTarmzo= +k8s.io/gengo/v2 v2.0.0-20240228010128-51d4e06bde70/go.mod h1:VH3AT8AaQOqiGjMF9p0/IM1Dj+82ZwjfxUP1IxaHE+8= k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk= k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8= k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I= k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE= k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= -k8s.io/klog/v2 v2.4.0 h1:7+X0fUguPyrKEC4WjH8iGDg3laWgMo5tMnRTIGTTxGQ= k8s.io/klog/v2 v2.4.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y= +k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk= +k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE= k8s.io/kube-openapi v0.0.0-20200121204235-bf4fb3bd569c/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E= -k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd h1:sOHNzJIkytDF6qadMNKhhDRpc6ODik8lVC6nOur7B2c= k8s.io/kube-openapi v0.0.0-20201113171705-d219536bb9fd/go.mod h1:WOJ3KddDSol4tAGcJo0Tvi+dK12EcqSLqcWsryKMpfM= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag= +k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98= k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew= k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= -k8s.io/utils v0.0.0-20210111153108-fddb29f9d009 h1:0T5IaWHO3sJTEmCP6mUlBvMukxPKUQWqiI/YuiBNMiQ= k8s.io/utils v0.0.0-20210111153108-fddb29f9d009/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8 h1:pUdcCO1Lk/tbT5ztQWOBi5HBgbBP1J8+AsQnQCKsi8A= +k8s.io/utils v0.0.0-20240711033017-18e509b52bc8/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.7/go.mod h1:PHgbrJT7lCHcxMU+mDHEm+nx46H4zuuHZkDP6icnhu0= sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.14/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg= sigs.k8s.io/controller-runtime v0.8.0/go.mod h1:v9Lbj5oX443uR7GXYY46E0EE2o7k2YxQ58GxVNeXSW4= -sigs.k8s.io/controller-runtime v0.8.3 h1:GMHvzjTmaWHQB8HadW+dIvBoJuLvZObYJ5YoZruPRao= sigs.k8s.io/controller-runtime v0.8.3/go.mod h1:U/l+DUopBc1ecfRZ5aviA9JDmGFQKvLf5YkZNx2e0sU= +sigs.k8s.io/controller-runtime v0.19.0 h1:nWVM7aq+Il2ABxwiCizrVDSlmDcshi9llbaFbC0ji/Q= +sigs.k8s.io/controller-runtime v0.19.0/go.mod h1:iRmWllt8IlaLjvTTDLhRBXIEtkCK6hwVBJJsYS9Ajf4= sigs.k8s.io/controller-tools v0.4.1/go.mod h1:G9rHdZMVlBDocIxGkK3jHLWqcTMNvveypYJwrvYKjWU= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= +sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw= -sigs.k8s.io/structured-merge-diff/v4 v4.0.2 h1:YHQV7Dajm86OuqnIR6zAelnDWBRjo+YhYV9PmGrh1s8= sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= +sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= -sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= +sigs.k8s.io/yaml v1.4.0 h1:Mk1wCc2gy/F0THH0TAp1QYyJNzRm2KCLy3o5ASXVI5E= +sigs.k8s.io/yaml v1.4.0/go.mod h1:Ejl7/uTz7PSA4eKMyQCUTnhZYNmLIl+5c2lQPGR2BPY= diff --git a/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go b/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go index 6b687301..c943dee6 100644 --- a/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go +++ b/pkg/apis/alibabacloud/v1alpha1/secretstore_types.go @@ -32,6 +32,7 @@ type SecretStoreSpec struct { // Important: Run "make" to regenerate code after modifying this file // maybe support more alibabacloud product KMS *KMSProvider `json:"KMS,omitempty"` + OOS *OOSProvider `json:"OOS,omitempty"` } // +kubebuilder:validation:MaxProperties=1 @@ -54,6 +55,22 @@ type KMSAuth struct { RemoteRAMRoleSessionName string `json:"remoteRamRoleSessionName,omitempty"` } +type OOSProvider struct { + OOS *OOSAuth `json:"OOSAuth,omitempty"` +} + +type OOSAuth struct { + AccessKey *SecretRef `json:"accessKey,omitempty"` + AccessKeySecret *SecretRef `json:"accessKeySecret,omitempty"` + RAMRoleARN string `json:"ramRoleARN,omitempty"` + RAMRoleSessionName string `json:"ramRoleSessionName,omitempty"` + OIDCProviderARN string `json:"oidcProviderARN,omitempty"` + OIDCTokenFilePath string `json:"oidcTokenFilePath,omitempty"` + RoleSessionExpiration string `json:"roleSessionExpiration,omitempty"` + RemoteRAMRoleARN string `json:"remoteRamRoleARN,omitempty"` + RemoteRAMRoleSessionName string `json:"remoteRamRoleSessionName,omitempty"` +} + type DedicatedKMSAuth struct { Protocol string `json:"protocol"` Endpoint string `json:"endpoint"` diff --git a/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go index 94831b41..b50a277a 100644 --- a/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/apis/alibabacloud/v1alpha1/zz_generated.deepcopy.go @@ -1,5 +1,4 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated // Code generated by controller-gen. DO NOT EDIT. @@ -252,6 +251,51 @@ func (in *KMSProvider) DeepCopy() *KMSProvider { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OOSAuth) DeepCopyInto(out *OOSAuth) { + *out = *in + if in.AccessKey != nil { + in, out := &in.AccessKey, &out.AccessKey + *out = new(SecretRef) + **out = **in + } + if in.AccessKeySecret != nil { + in, out := &in.AccessKeySecret, &out.AccessKeySecret + *out = new(SecretRef) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OOSAuth. +func (in *OOSAuth) DeepCopy() *OOSAuth { + if in == nil { + return nil + } + out := new(OOSAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OOSProvider) DeepCopyInto(out *OOSProvider) { + *out = *in + if in.OOS != nil { + in, out := &in.OOS, &out.OOS + *out = new(OOSAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OOSProvider. +func (in *OOSProvider) DeepCopy() *OOSProvider { + if in == nil { + return nil + } + out := new(OOSProvider) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ReplaceRule) DeepCopyInto(out *ReplaceRule) { *out = *in @@ -364,6 +408,11 @@ func (in *SecretStoreSpec) DeepCopyInto(out *SecretStoreSpec) { *out = new(KMSProvider) (*in).DeepCopyInto(*out) } + if in.OOS != nil { + in, out := &in.OOS, &out.OOS + *out = new(OOSProvider) + (*in).DeepCopyInto(*out) + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretStoreSpec. diff --git a/pkg/backend/auth/auth.go b/pkg/backend/auth/auth.go new file mode 100644 index 00000000..2428c7f3 --- /dev/null +++ b/pkg/backend/auth/auth.go @@ -0,0 +1,101 @@ +package auth + +import ( + "os" + "time" + + "github.com/aliyun/credentials-go/credentials" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" + backendp "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider" + "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" +) + +const ( + RamRoleARNAuthType = "ram_role_arn" + AKAuthType = "access_key" + EcsRamRoleAuthType = "ecs_ram_role" + OidcAuthType = "oidc_role_arn" + oidcRoleSessionName = "ack-secret-manager" + oidcTokenFilePath = "/var/run/secrets/tokens/ack-secret-manager" +) + +type AuthConfig struct { + ClientName string + RoleArn string + OidcArn string + AccessKey string + AccessSecretKey string + RoleSessionName string + RoleSessionExpiration string + RemoteRoleArn string + RemoteRoleSessionName string + RefreshPeriod time.Duration +} + +func (a *AuthConfig) GetAuthCred(region string, maxConcurrentCount int, m *backendp.Manager) (credentials.Credential, error) { + providers := make([]provider.CredentialsProvider, 0) + var semaphoreProvider *provider.SemaphoreProvider + if a.OidcArn != "" && a.RoleArn != "" { + oidcProvider := provider.NewOIDCProvider(provider.OIDCProviderOptions{ + STSEndpoint: provider.GetSTSEndpoint(region, true), + SessionName: oidcRoleSessionName, + OIDCTokenFile: oidcTokenFilePath, + RoleArn: a.RoleArn, + OIDCProviderArn: a.OidcArn, + RefreshPeriod: a.RefreshPeriod, + }) + providers = append(providers, oidcProvider) + } + if a.AccessKey != "" && a.AccessSecretKey != "" && a.RoleSessionName != "" && a.RoleArn != "" { + ramRoleProvider := provider.NewRoleArnProvider(provider.NewAccessKeyProvider(a.AccessKey, a.AccessSecretKey), a.RoleArn, provider.RoleArnProviderOptions{ + STSEndpoint: provider.GetSTSEndpoint(region, true), + SessionName: a.RoleSessionName, + RefreshPeriod: a.RefreshPeriod, + }) + providers = append(providers, ramRoleProvider) + } + if a.AccessKey != "" && a.AccessSecretKey != "" { + akProvider := provider.NewAccessKeyProvider(a.AccessKey, a.AccessSecretKey) + providers = append(providers, akProvider) + } + providers = append(providers, provider.NewECSMetadataProvider(provider.ECSMetadataProviderOptions{ + RefreshPeriod: a.RefreshPeriod, + })) + chainProvider := provider.NewChainProvider(providers...) + var remoteRoleProvider *provider.RoleArnProvider + var cred *provider.CredentialForV2SDK + if a.RemoteRoleArn != "" && a.RemoteRoleSessionName != "" { + remoteRoleProvider = provider.NewRoleArnProvider(chainProvider, a.RemoteRoleArn, provider.RoleArnProviderOptions{ + STSEndpoint: provider.GetSTSEndpoint(region, true), + SessionName: a.RemoteRoleSessionName, + RefreshPeriod: a.RefreshPeriod, + }) + semaphoreProvider = provider.NewSemaphoreProvider(remoteRoleProvider, provider.SemaphoreProviderOptions{ + MaxWeight: int64(maxConcurrentCount), + }) + } else { + semaphoreProvider = provider.NewSemaphoreProvider(chainProvider, provider.SemaphoreProviderOptions{ + MaxWeight: int64(maxConcurrentCount), + }) + } + backendp.RegisterRamProvider(a.ClientName, semaphoreProvider, m) + cred = provider.NewCredentialForV2SDK(semaphoreProvider, provider.CredentialForV2SDKOptions{ + CredentialRetrievalTimeout: 10 * time.Minute, + }) + return cred, nil +} + +func GetCredentialParameterFromEnv() AuthConfig { + return AuthConfig{ + ClientName: backend.EnvClient, + RoleArn: os.Getenv("ALICLOUD_ROLE_ARN"), + OidcArn: os.Getenv("ALICLOUD_OIDC_PROVIDER_ARN"), + AccessKey: os.Getenv("ACCESS_KEY_ID"), + AccessSecretKey: os.Getenv("SECRET_ACCESS_KEY"), + RoleSessionName: os.Getenv("ALICLOUD_ROLE_SESSION_NAME"), + RoleSessionExpiration: os.Getenv("ALICLOUD_ROLE_SESSION_EXPIRATION"), + RemoteRoleSessionName: os.Getenv("ALICLOUD_REMOTE_ROLE_SESSION_NAME"), + RemoteRoleArn: os.Getenv("ALICLOUD_REMOTE_ROLE_ARN"), + RefreshPeriod: time.Second * 10, + } +} \ No newline at end of file diff --git a/pkg/backend/kms/auth.go b/pkg/backend/kms/auth.go deleted file mode 100644 index 11708ffb..00000000 --- a/pkg/backend/kms/auth.go +++ /dev/null @@ -1,84 +0,0 @@ -package kms - -import ( - "time" - - "github.com/aliyun/credentials-go/credentials" - - "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" -) - -const ( - RamRoleARNAuthType = "ram_role_arn" - AKAuthType = "access_key" - EcsRamRoleAuthType = "ecs_ram_role" - OidcAuthType = "oidc_role_arn" - oidcRoleSessionName = "ack-secret-manager" - oidcTokenFilePath = "/var/run/secrets/tokens/ack-secret-manager" -) - -type authConfig struct { - clientName string - roleArn string - oidcArn string - accessKey string - accessSecretKey string - roleSessionName string - roleSessionExpiration string - remoteRoleArn string - remoteRoleSessionName string - refreshPeriod time.Duration -} - -func (a *authConfig) getKMSAuthCred(region string, p *Provider) (credentials.Credential, error) { - providers := make([]provider.CredentialsProvider, 0) - var semaphoreProvider *provider.SemaphoreProvider - if a.oidcArn != "" && a.roleArn != "" { - oidcProvider := provider.NewOIDCProvider(provider.OIDCProviderOptions{ - STSEndpoint: provider.GetSTSEndpoint(region, true), - SessionName: oidcRoleSessionName, - OIDCTokenFile: oidcTokenFilePath, - RoleArn: a.roleArn, - OIDCProviderArn: a.oidcArn, - RefreshPeriod: a.refreshPeriod, - }) - providers = append(providers, oidcProvider) - } - if a.accessKey != "" && a.accessSecretKey != "" && a.roleSessionName != "" && a.roleArn != "" { - ramRoleProvider := provider.NewRoleArnProvider(provider.NewAccessKeyProvider(a.accessKey, a.accessSecretKey), a.roleArn, provider.RoleArnProviderOptions{ - STSEndpoint: provider.GetSTSEndpoint(region, true), - SessionName: a.roleSessionName, - RefreshPeriod: a.refreshPeriod, - }) - providers = append(providers, ramRoleProvider) - } - if a.accessKey != "" && a.accessSecretKey != "" { - akProvider := provider.NewAccessKeyProvider(a.accessKey, a.accessSecretKey) - providers = append(providers, akProvider) - } - providers = append(providers, provider.NewECSMetadataProvider(provider.ECSMetadataProviderOptions{ - RefreshPeriod: a.refreshPeriod, - })) - chainProvider := provider.NewChainProvider(providers...) - var remoteRoleProvider *provider.RoleArnProvider - var cred *provider.CredentialForV2SDK - if a.remoteRoleArn != "" && a.remoteRoleSessionName != "" { - remoteRoleProvider = provider.NewRoleArnProvider(chainProvider, a.remoteRoleArn, provider.RoleArnProviderOptions{ - STSEndpoint: provider.GetSTSEndpoint(region, true), - SessionName: a.remoteRoleSessionName, - RefreshPeriod: a.refreshPeriod, - }) - semaphoreProvider = provider.NewSemaphoreProvider(remoteRoleProvider, provider.SemaphoreProviderOptions{ - MaxWeight: int64(p.maxConcurrentCount), - }) - } else { - semaphoreProvider = provider.NewSemaphoreProvider(chainProvider, provider.SemaphoreProviderOptions{ - MaxWeight: int64(p.maxConcurrentCount), - }) - } - p.RegisterRamProvider(a.clientName, semaphoreProvider) - cred = provider.NewCredentialForV2SDK(semaphoreProvider, provider.CredentialForV2SDKOptions{ - CredentialRetrievalTimeout: 10 * time.Minute, - }) - return cred, nil -} diff --git a/pkg/backend/kms/client_manager.go b/pkg/backend/kms/client_manager.go deleted file mode 100644 index 514b4f92..00000000 --- a/pkg/backend/kms/client_manager.go +++ /dev/null @@ -1,111 +0,0 @@ -package kms - -import ( - "context" - "fmt" - "sync" - "time" - - "k8s.io/klog" - - "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" - backendin "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" -) - -type Manager struct { - region string - // kms multi-account client pool - kmsClientMap sync.Map - // dkms multi-instance client pool - dedicateKmsClientMap sync.Map - // ram lock - ramLock sync.Mutex - // RamProvider pool - ramProvider map[string]provider.Stopper -} - -func NewManager(region string) *Manager { - return &Manager{ - region: region, - ramProvider: make(map[string]provider.Stopper), - } -} - -func (m *Manager) RegisterRamProvider(clientName string, stopper provider.Stopper) { - m.ramLock.Lock() - defer m.ramLock.Unlock() - providerIns, ok := m.ramProvider[clientName] - if ok { - timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - // cancel is earlier than m.ramLock.Unlock - defer cancel() - providerIns.Stop(timeoutCtx) - } - m.ramProvider[clientName] = stopper - klog.Infof("register provider %v success", clientName) -} - -func (m *Manager) StopProvider(clientName string) { - m.ramLock.Lock() - defer m.ramLock.Unlock() - providerIns, ok := m.ramProvider[clientName] - if !ok || providerIns == nil { - return - } - timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) - // cancel is earlier than m.ramLock.Unlock - defer cancel() - providerIns.Stop(timeoutCtx) - delete(m.ramProvider, clientName) - klog.Infof("stop provider %v success", clientName) -} - -func (m *Manager) Register(clientName string, client backendin.SecretClient) { - kmsClient, ok := client.(*KMSClient) - if !ok { - klog.Errorf("client type error") - return - } - if kmsClient.kmsClient != nil { - m.kmsClientMap.Store(clientName, client) - } - if kmsClient.dedicatedClient != nil { - m.dedicateKmsClientMap.Store(clientName, client) - } - klog.Infof("register or update client, clientName %v", clientName) -} - -func (m *Manager) Delete(clientName string) { - // delete the client map, and stop the ram provider refresh go routine - m.kmsClientMap.Delete(clientName) - m.dedicateKmsClientMap.Delete(clientName) - m.StopProvider(clientName) - klog.Infof("delete client, clientName %v", clientName) -} - -func (m *Manager) GetClient(clientName string) (backendin.SecretClient, error) { - client, ok := m.kmsClientMap.Load(clientName) - if ok { - kmsClient, ok := client.(*KMSClient) - if !ok { - return nil, fmt.Errorf("client type error,clientName %v", clientName) - } - return &KMSClient{ - clientName: clientName, - kmsClient: kmsClient.kmsClient, - }, nil - } - klog.Infof("client not register in kms client pool,clientName %v", clientName) - client, ok = m.dedicateKmsClientMap.Load(clientName) - if ok { - dkmsClient, ok := client.(*KMSClient) - if !ok { - return nil, fmt.Errorf("client type error,clientName %v", clientName) - } - return &KMSClient{ - dedicatedClient: dkmsClient.dedicatedClient, - clientName: clientName, - }, nil - } - return nil, fmt.Errorf("client not register,clientName %v", clientName) -} diff --git a/pkg/backend/provider.go b/pkg/backend/provider.go index c5e8afe4..3ef4cb0f 100644 --- a/pkg/backend/provider.go +++ b/pkg/backend/provider.go @@ -12,11 +12,17 @@ import ( const EnvClient = "env.client" +const ( + ProviderKMSName = "kms" + ProviderOOSName = "oos" +) + type CreateProvider func(opt *ProviderOptions) type ProviderOptions struct { - Region string - MaxConcurrent int + Region string + KmsMaxConcurrent int + OosMaxConcurrent int } var ( diff --git a/pkg/backend/provider/kms/client_manager.go b/pkg/backend/provider/kms/client_manager.go new file mode 100644 index 00000000..2d832213 --- /dev/null +++ b/pkg/backend/provider/kms/client_manager.go @@ -0,0 +1,78 @@ +package kms + +import ( + "fmt" + "sync" + "k8s.io/klog" + + "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" + backendp "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider" + backendin "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" +) + +type Manager backendp.Manager + +func NewManager(region string) *Manager { + return &Manager{ + Region: region, + RamLock: &sync.Mutex{}, + RamProvider: make(map[string]provider.Stopper), + } +} + +func (m *Manager) Register(clientName string, client backendin.SecretClient) { + kmsClient, ok := client.(*KMSClient) + if kmsClient ==nil { + klog.Errorf("client is nil") + return + } + if !ok { + klog.Errorf("client type error") + return + } + if kmsClient.kmsClient != nil { + m.KmsClientMap.Store(clientName, client) + } + if kmsClient.dedicatedClient != nil { + m.DedicateKmsClientMap.Store(clientName, client) + } + klog.Infof("register or update client, clientName %v", clientName) +} + +func (m *Manager) Delete(clientName string) { + // delete the client map, and stop the ram provider refresh go routine + m.KmsClientMap.Delete(clientName) + m.DedicateKmsClientMap.Delete(clientName) + backendp.StopProvider(clientName, &backendp.Manager{ + RamLock: m.RamLock, + RamProvider: m.RamProvider, + }) + klog.Infof("delete client, clientName %v", clientName) +} + +func (m *Manager) GetClient(clientName string) (backendin.SecretClient, error) { + client, ok := m.KmsClientMap.Load(clientName) + if ok { + kmsClient, ok := client.(*KMSClient) + if !ok { + return nil, fmt.Errorf("client type error,clientName %v", clientName) + } + return &KMSClient{ + clientName: clientName, + kmsClient: kmsClient.kmsClient, + }, nil + } + klog.Infof("client not register in kms client pool,clientName %v", clientName) + client, ok = m.DedicateKmsClientMap.Load(clientName) + if ok { + dkmsClient, ok := client.(*KMSClient) + if !ok { + return nil, fmt.Errorf("client type error,clientName %v", clientName) + } + return &KMSClient{ + dedicatedClient: dkmsClient.dedicatedClient, + clientName: clientName, + }, nil + } + return nil, fmt.Errorf("client not register,clientName %v", clientName) +} diff --git a/pkg/backend/kms/client_provider.go b/pkg/backend/provider/kms/client_provider.go similarity index 78% rename from pkg/backend/kms/client_provider.go rename to pkg/backend/provider/kms/client_provider.go index 903834f0..05a85899 100644 --- a/pkg/backend/kms/client_provider.go +++ b/pkg/backend/provider/kms/client_provider.go @@ -4,7 +4,6 @@ import ( "context" "encoding/base64" "fmt" - "os" "time" openapi "github.com/alibabacloud-go/darabonba-openapi/client" @@ -16,12 +15,13 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/auth" + backendp "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider" "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" ) const ( - ProviderName = "kms" defaultKmsDomain = "kms-vpc.%s.aliyuncs.com" HTTPS = "https" noCA = "noca" @@ -30,7 +30,7 @@ const ( ) func init() { - backend.SupportProvider[ProviderName] = NewProvider + backend.SupportProvider[backend.ProviderKMSName] = NewProvider } // Provider provides the ability to generate kms clients and manage kms clients @@ -45,10 +45,10 @@ func NewProvider(opts *backend.ProviderOptions) { provider := &Provider{ Manager: NewManager(opts.Region), region: opts.Region, - name: ProviderName, - maxConcurrentCount: 5, + name: backend.ProviderKMSName, + maxConcurrentCount: opts.KmsMaxConcurrent, } - backend.RegisterProvider(ProviderName, provider) + backend.RegisterProvider(backend.ProviderKMSName, provider) } func (p *Provider) GetName() string { @@ -60,6 +60,9 @@ func (p *Provider) GetRegion() string { } func (p *Provider) NewClient(ctx context.Context, store *v1alpha1.SecretStore, kube client.Client) (backend.SecretClient, error) { + if store.Spec.KMS == nil{ + return nil, fmt.Errorf("kms config is empty") + } clientName := fmt.Sprintf("%s/%s", store.Namespace, store.Name) region := p.GetRegion() if store.Spec.KMS.DedicatedKMS != nil { @@ -130,9 +133,9 @@ func NewDedicateKMSClient(ctx context.Context, store *v1alpha1.SecretStore, kube func NewShareKMSClient(ctx context.Context, store *v1alpha1.SecretStore, kube client.Client, region string, p *Provider) (*kms.Client, error) { var ak, sk string kmsConfig := store.Spec.KMS.KMS - auth := authConfig{ - clientName: fmt.Sprintf("%s/%s", store.Namespace, store.Name), - refreshPeriod: time.Minute * 10, + auth := auth.AuthConfig{ + ClientName: fmt.Sprintf("%s/%s", store.Namespace, store.Name), + RefreshPeriod: time.Minute * 10, } if kmsConfig != nil { if kmsConfig.AccessKey != nil { @@ -143,7 +146,7 @@ func NewShareKMSClient(ctx context.Context, store *v1alpha1.SecretStore, kube cl } else { ak = string(accessKey) } - auth.accessKey = ak + auth.AccessKey = ak } if kmsConfig.AccessKeySecret != nil { accessKeySecret, err := utils.GetConfigFromSecret(ctx, kube, kmsConfig.AccessKeySecret) @@ -153,17 +156,20 @@ func NewShareKMSClient(ctx context.Context, store *v1alpha1.SecretStore, kube cl } else { sk = string(accessKeySecret) } - auth.accessSecretKey = sk + auth.AccessSecretKey = sk } - auth.roleArn = kmsConfig.RAMRoleARN - auth.oidcArn = kmsConfig.OIDCProviderARN - auth.roleSessionName = kmsConfig.RAMRoleSessionName - auth.roleSessionExpiration = kmsConfig.RoleSessionExpiration - auth.remoteRoleSessionName = kmsConfig.RemoteRAMRoleSessionName - auth.remoteRoleArn = kmsConfig.RemoteRAMRoleARN + auth.RoleArn = kmsConfig.RAMRoleARN + auth.OidcArn = kmsConfig.OIDCProviderARN + auth.RoleSessionName = kmsConfig.RAMRoleSessionName + auth.RoleSessionExpiration = kmsConfig.RoleSessionExpiration + auth.RemoteRoleSessionName = kmsConfig.RemoteRAMRoleSessionName + auth.RemoteRoleArn = kmsConfig.RemoteRAMRoleARN } //get ram auth credential - cred, err := auth.getKMSAuthCred(region, p) + cred, err := auth.GetAuthCred(region, p.maxConcurrentCount, &backendp.Manager{ + RamLock: p.Manager.RamLock, + RamProvider: p.Manager.RamProvider, + }) if err != nil { return nil, err } @@ -183,20 +189,12 @@ func NewShareKMSClient(ctx context.Context, store *v1alpha1.SecretStore, kube cl } func (p *Provider) NewClientByENV(ctx context.Context, region string) (backend.SecretClient, error) { - authEnvs := authConfig{ - clientName: backend.EnvClient, - roleArn: os.Getenv("ALICLOUD_ROLE_ARN"), - oidcArn: os.Getenv("ALICLOUD_OIDC_PROVIDER_ARN"), - accessKey: os.Getenv("ACCESS_KEY_ID"), - accessSecretKey: os.Getenv("SECRET_ACCESS_KEY"), - roleSessionName: os.Getenv("ALICLOUD_ROLE_SESSION_NAME"), - roleSessionExpiration: os.Getenv("ALICLOUD_ROLE_SESSION_EXPIRATION"), - remoteRoleSessionName: os.Getenv("ALICLOUD_REMOTE_ROLE_SESSION_NAME"), - remoteRoleArn: os.Getenv("ALICLOUD_REMOTE_ROLE_ARN"), - refreshPeriod: time.Second * 10, - } + authEnvs := auth.GetCredentialParameterFromEnv() //get ram auth credential - cred, err := authEnvs.getKMSAuthCred(region, p) + cred, err := authEnvs.GetAuthCred(region, p.maxConcurrentCount, &backendp.Manager{ + RamLock: p.Manager.RamLock, + RamProvider: p.Manager.RamProvider, + }) if err != nil { return nil, err } diff --git a/pkg/backend/kms/kms_service.go b/pkg/backend/provider/kms/kms_service.go similarity index 63% rename from pkg/backend/kms/kms_service.go rename to pkg/backend/provider/kms/kms_service.go index b8684e03..ce308cba 100644 --- a/pkg/backend/kms/kms_service.go +++ b/pkg/backend/provider/kms/kms_service.go @@ -2,16 +2,13 @@ package kms import ( "context" + "encoding/base64" "encoding/json" "fmt" - "github.com/jmespath/go-jmespath" - "math" - "regexp" "time" kms "github.com/alibabacloud-go/kms-20160120/v2/client" "github.com/alibabacloud-go/tea/tea" - sdkErr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" dkmsopenapiutil "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/openapi-util" dkms "github.com/aliyun/alibabacloud-dkms-gcs-go-sdk/sdk" "k8s.io/klog" @@ -21,17 +18,6 @@ import ( "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" ) -const ( - REJECTED_THROTTLING = "Rejected.Throttling" - SERVICE_UNAVAILABLE_TEMPORARY = "ServiceUnavailableTemporary" - INTERNAL_FAILURE = "InternalFailure" -) - -var ( - BACKOFF_DEFAULT_RETRY_INTERVAL = time.Second - BACKOFF_DEFAULT_CAPACITY = time.Duration(10) * time.Second -) - // Client interface represent a backend client interface that should be implemented type KMSClient struct { dedicatedClient *dkms.Client @@ -74,7 +60,7 @@ func (c *KMSClient) GetExternalSecret(ctx context.Context, data *v1alpha1.DataSo // jmes if len(data.JMESPath) > 0 { klog.Infof("parse jmes format, key %v", data.Key) - jsonDataMap, err := getJsonSecrets(data.JMESPath, string(externalData), data.Key) + jsonDataMap, err := utils.GetJsonSecrets(data.JMESPath, string(externalData), data.Key) if err != nil { klog.Errorf("parse jmes format error %v, key %v, jmes %v, data.JMESPath", err, data.Key, data.JMESPath) } else if len(jsonDataMap) > 0 { @@ -108,9 +94,9 @@ func (c *KMSClient) GetExternalSecretWithExtract(ctx context.Context, data *v1al for k, v := range tempKV { kv[k] = utils.JsonStr(v) } - if data.ReplaceKey != nil && len(data.ReplaceKey) != 0 { + if len(data.ReplaceKey) != 0 { for _, rule := range data.ReplaceKey { - kv, err = RewriteRegexp(rule, kv) + kv, err = utils.RewriteRegexp(rule, kv) if err != nil { klog.Errorf("replace data key failed, error %v", err) continue @@ -123,48 +109,6 @@ func (c *KMSClient) GetExternalSecretWithExtract(ctx context.Context, data *v1al return secretDatas, nil } -// RewriteRegexp rewrites a single Regexp Rewrite Operation. -func RewriteRegexp(operation v1alpha1.ReplaceRule, in map[string]string) (map[string]string, error) { - out := make(map[string]string) - re, err := regexp.Compile(operation.Source) - if err != nil { - return nil, err - } - for key, value := range in { - newKey := re.ReplaceAllString(key, operation.Target) - out[newKey] = value - } - return out, nil -} - -func getJsonSecrets(jmesObj []v1alpha1.JMESPathObject, secretValue, key string) (jsonMap map[string]string, err error) { - jsonMap = make(map[string]string, 0) - var data interface{} - err = json.Unmarshal([]byte(secretValue), &data) - if err != nil { - return nil, fmt.Errorf("invalid JSON used with jmesPath in secret key: %s", key) - } - //fetch all specified key value pairs` - for _, jmesPathEntry := range jmesObj { - jsonSecret, err := jmespath.Search(jmesPathEntry.Path, data) - if err != nil { - return nil, fmt.Errorf("Invalid JMES Path: %s.", jmesPathEntry.Path) - } - - if jsonSecret == nil { - return nil, fmt.Errorf("JMES Path - %s for object alias - %s does not point to a valid object.", - jmesPathEntry.Path, jmesPathEntry.ObjectAlias) - } - - jsonSecretAsString, isString := jsonSecret.(string) - if !isString { - return nil, fmt.Errorf("Invalid JMES search result type for path:%s. Only string is allowed.", jmesPathEntry.Path) - } - jsonMap[jmesPathEntry.ObjectAlias] = jsonSecretAsString - } - return jsonMap, nil -} - func (c *KMSClient) getExternalDataFromKMS(data v1alpha1.DataSource) ([]byte, error) { if c.kmsClient == nil { return nil, fmt.Errorf("kms client is nil,kms key %v", data.Key) @@ -180,11 +124,11 @@ func (c *KMSClient) getExternalDataFromKMS(data v1alpha1.DataSource) ([]byte, er } resp, err := c.kmsClient.GetSecretValue(req) if err != nil { - if !judgeNeedRetry(err) { + if !utils.JudgeNeedRetry(err) { klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err) return nil, err } else { - time.Sleep(getWaitTimeExponential(1)) + time.Sleep(utils.GetWaitTimeExponential(1)) resp, err = c.kmsClient.GetSecretValue(req) if err != nil { klog.Errorf("retry to get secret value from kms failed,key %v,error %v", data.Key, err) @@ -192,9 +136,16 @@ func (c *KMSClient) getExternalDataFromKMS(data v1alpha1.DataSource) ([]byte, er } } } - if *resp.Body.SecretDataType == utils.BinaryType { - klog.Errorf("not support binary type yet,key %v", data.Key) - return nil, utils.BackendSecretTypeNotSupportError{ErrType: utils.EmptySecretKeyErrorType, Key: data.Key} + if resp == nil || resp.Body == nil { + return nil, fmt.Errorf("get secret value from kms failed because response is empty, key %v", data.Key) + } + if resp.Body.SecretDataType != nil && *resp.Body.SecretDataType == utils.BinaryType { + klog.Infof("got binary secret data from kms service,key %v", data.Key) + originData, err := base64.StdEncoding.DecodeString(*resp.Body.SecretData) + if err != nil { + return nil, fmt.Errorf("decode binary data error %v,key %v", err, data.Key) + } + return originData, nil } klog.Infof("got secret data from kms service,key %v", data.Key) return []byte(*resp.Body.SecretData), nil @@ -217,11 +168,11 @@ func (c *KMSClient) getExternalDataFromDKMS(data v1alpha1.DataSource) ([]byte, e runtimeOptions := &dkmsopenapiutil.RuntimeOptions{} resp, err := c.dedicatedClient.GetSecretValueWithOptions(req, runtimeOptions) if err != nil { - if !judgeNeedRetry(err) { + if !utils.JudgeNeedRetry(err) { klog.Errorf("failed to get secret value from kms,key %v,error %v", data.Key, err) return nil, err } else { - time.Sleep(getWaitTimeExponential(1)) + time.Sleep(utils.GetWaitTimeExponential(1)) resp, err = c.dedicatedClient.GetSecretValueWithOptions(req, runtimeOptions) if err != nil { klog.Errorf("retry to get secret value from kms failed,key %v,error %v", data.Key, err) @@ -236,20 +187,3 @@ func (c *KMSClient) getExternalDataFromDKMS(data v1alpha1.DataSource) ([]byte, e klog.Infof("got secret data from kms service,key %v", data.Key) return []byte(*resp.SecretData), nil } - -func judgeNeedRetry(err error) bool { - respErr, is := err.(*sdkErr.ClientError) - if is && (respErr.ErrorCode() == REJECTED_THROTTLING || respErr.ErrorCode() == SERVICE_UNAVAILABLE_TEMPORARY || respErr.ErrorCode() == INTERNAL_FAILURE) { - return true - } - return false -} - -func getWaitTimeExponential(retryTimes int) time.Duration { - sleepInterval := time.Duration(math.Pow(2, float64(retryTimes))) * BACKOFF_DEFAULT_RETRY_INTERVAL - if sleepInterval >= BACKOFF_DEFAULT_CAPACITY { - return BACKOFF_DEFAULT_CAPACITY - } else { - return sleepInterval - } -} diff --git a/pkg/backend/provider/oos/client_manager.go b/pkg/backend/provider/oos/client_manager.go new file mode 100644 index 00000000..31225ed1 --- /dev/null +++ b/pkg/backend/provider/oos/client_manager.go @@ -0,0 +1,64 @@ +package oos + +import ( + "fmt" + "sync" + "k8s.io/klog" + + "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" + backendp "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider" + backendin "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" +) + +type Manager backendp.Manager + +func NewManager(region string) *Manager { + return &Manager{ + Region: region, + RamLock: &sync.Mutex{}, + RamProvider: make(map[string]provider.Stopper), + } +} + +func (m *Manager) Register(clientName string, client backendin.SecretClient) { + oosClient, ok := client.(*OOSClient) + if oosClient == nil { + klog.Errorf("client is nil") + return + } + if !ok { + klog.Errorf("client type error") + return + } + if oosClient.oosClient != nil { + m.OosClientMap.Store(clientName, client) + } + klog.Infof("register or update client, clientName %v", clientName) +} + +func (m *Manager) Delete(clientName string) { + // delete the client map, and stop the ram provider refresh go routine + m.OosClientMap.Delete(clientName) + backendp.StopProvider(clientName, &backendp.Manager{ + RamLock: m.RamLock, + RamProvider: m.RamProvider, + }) + klog.Infof("delete client, clientName %v", clientName) +} + +func (m *Manager) GetClient(clientName string) (backendin.SecretClient, error) { + client, ok := m.OosClientMap.Load(clientName) + if ok { + oosClient, ok := client.(*OOSClient) + if !ok { + return nil, fmt.Errorf("client type error,clientName %v", clientName) + } + return &OOSClient{ + clientName: clientName, + oosClient: oosClient.oosClient, + }, nil + } + + klog.Infof("client not register in oos client pool,clientName %v", clientName) + return nil, fmt.Errorf("client not register,clientName %v", clientName) +} diff --git a/pkg/backend/provider/oos/client_provider.go b/pkg/backend/provider/oos/client_provider.go new file mode 100644 index 00000000..8319d099 --- /dev/null +++ b/pkg/backend/provider/oos/client_provider.go @@ -0,0 +1,161 @@ +package oos + +import ( + "context" + "fmt" + "time" + + openapi "github.com/alibabacloud-go/darabonba-openapi/v2/client" + oos "github.com/alibabacloud-go/oos-20190601/v3/client" + "github.com/alibabacloud-go/tea/tea" + "k8s.io/klog" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/auth" + backendp "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" + "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" +) + +const ( + defaultOosDomain = "oos-vpc.%s.aliyuncs.com" +) + +func init() { + backend.SupportProvider[backend.ProviderOOSName] = NewProvider +} + +// Provider provides the ability to generate oos clients and manage oos clients +type Provider struct { + *Manager + region string + name string + maxConcurrentCount int +} + +func NewProvider(opts *backend.ProviderOptions) { + provider := &Provider{ + Manager: NewManager(opts.Region), + region: opts.Region, + name: backend.ProviderOOSName, + maxConcurrentCount: opts.OosMaxConcurrent, + } + backend.RegisterProvider(backend.ProviderOOSName, provider) +} + +func (p *Provider) GetName() string { + return p.name +} + +func (p *Provider) GetRegion() string { + return p.region +} + +func (p *Provider) NewClient(ctx context.Context, store *v1alpha1.SecretStore, kube client.Client) (backend.SecretClient, error) { + clientName := fmt.Sprintf("%s/%s", store.Namespace, store.Name) + region := p.GetRegion() + shareClient, err := NewOOSClient(ctx, store, kube, region, p) + if err != nil { + klog.Errorf("new share oos client error %v", err) + return nil, err + } + cl := &OOSClient{ + oosClient: shareClient, + clientName: clientName, + } + return cl, nil +} + +func NewOOSClient(ctx context.Context, store *v1alpha1.SecretStore, kube client.Client, region string, p *Provider) (*oos.Client, error) { + if store.Spec.OOS == nil { + return nil, fmt.Errorf("oos config is empty") + } + + var ak, sk string + oosConfig := store.Spec.OOS.OOS + auth := auth.AuthConfig{ + ClientName: fmt.Sprintf("%s/%s", store.Namespace, store.Name), + RefreshPeriod: time.Minute * 10, + } + + if oosConfig != nil { + if oosConfig.AccessKey != nil { + accessKey, err := utils.GetConfigFromSecret(ctx, kube, oosConfig.AccessKey) + if err != nil { + klog.Errorf("get ak config from secret error %v", err) + ak = "" + } else { + ak = string(accessKey) + } + auth.AccessKey = ak + } + if oosConfig.AccessKeySecret != nil { + accessKeySecret, err := utils.GetConfigFromSecret(ctx, kube, oosConfig.AccessKeySecret) + if err != nil { + klog.Errorf("get sk config from secret error %v", err) + sk = "" + } else { + sk = string(accessKeySecret) + } + auth.AccessSecretKey = sk + } + auth.RoleArn = oosConfig.RAMRoleARN + auth.OidcArn = oosConfig.OIDCProviderARN + auth.RoleSessionName = oosConfig.RAMRoleSessionName + auth.RoleSessionExpiration = oosConfig.RoleSessionExpiration + auth.RemoteRoleSessionName = oosConfig.RemoteRAMRoleSessionName + auth.RemoteRoleArn = oosConfig.RemoteRAMRoleARN + } + + //get ram auth credential + cred, err := auth.GetAuthCred(region, p.maxConcurrentCount, &backendp.Manager{ + RamLock: p.Manager.RamLock, + RamProvider: p.Manager.RamProvider, + }) + if err != nil { + return nil, err + } + if cred == nil { + return nil, fmt.Errorf("cred is empty") + } + endpoint := fmt.Sprintf(defaultOosDomain, region) + client, err := oos.NewClient(&openapi.Config{ + Endpoint: tea.String(endpoint), + RegionId: tea.String(region), + Credential: cred, + }) + if err != nil { + return nil, err + } + return client, nil +} + +func (p *Provider) NewClientByENV(ctx context.Context, region string) (backend.SecretClient, error) { + authEnvs := auth.GetCredentialParameterFromEnv() + //get ram auth credential + cred, err := authEnvs.GetAuthCred(region, p.maxConcurrentCount, &backendp.Manager{ + RamLock: p.Manager.RamLock, + RamProvider: p.Manager.RamProvider, + }) + if err != nil { + return nil, err + } + if cred == nil { + return nil, fmt.Errorf("cred is empty") + } + endpoint := fmt.Sprintf(defaultOosDomain, region) + client, err := oos.NewClient(&openapi.Config{ + Endpoint: tea.String(endpoint), + RegionId: tea.String(region), + Credential: cred, + }) + if err != nil { + return nil, err + } + cl := &OOSClient{ + oosClient: client, + clientName: backend.EnvClient, + } + return cl, nil +} diff --git a/pkg/backend/provider/oos/oos_service.go b/pkg/backend/provider/oos/oos_service.go new file mode 100644 index 00000000..c325028a --- /dev/null +++ b/pkg/backend/provider/oos/oos_service.go @@ -0,0 +1,124 @@ +package oos + +import ( + "context" + "encoding/json" + "fmt" + "time" + + oos "github.com/alibabacloud-go/oos-20190601/v3/client" + "github.com/alibabacloud-go/tea/tea" + "k8s.io/klog" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" +) + +// Client interface represent a backend client interface that should be implemented +type OOSClient struct { + oosClient *oos.Client + clientName string +} + +func (c *OOSClient) GetName() string { + return c.clientName +} + +func (c *OOSClient) getExternalData(ctx context.Context, data v1alpha1.DataSource) ([]byte, error) { + // oos + oosData, err := c.getExternalDataFromOOS(data) + if err != nil { + klog.Errorf("get external data from oos error %v,key %v", err, data.Key) + return nil, err + } + + return oosData, nil +} + +func (c *OOSClient) GetExternalSecret(ctx context.Context, data *v1alpha1.DataSource, kube client.Client) (map[string][]byte, error) { + secretDatas := make(map[string][]byte) + //getExternalData + externalData, err := c.getExternalData(ctx, *data) + if err != nil { + klog.Errorf("get external data error %v,key %v", err, data.Key) + return nil, err + } + // jmes + if len(data.JMESPath) > 0 { + klog.Infof("parse jmes format, key %v", data.Key) + jsonDataMap, err := utils.GetJsonSecrets(data.JMESPath, string(externalData), data.Key) + if err != nil { + klog.Errorf("parse jmes format error %v, key %v, jmes %v, data.JMESPath", err, data.Key, data.JMESPath) + } else if len(jsonDataMap) > 0 { + //use parsed k-value in target secret + for k, v := range jsonDataMap { + secretDatas[k] = []byte(v) + } + return secretDatas, nil + } + } + secretDatas[data.Name] = externalData + return secretDatas, nil +} + +func (c *OOSClient) GetExternalSecretWithExtract(ctx context.Context, data *v1alpha1.DataProcess, kube client.Client) (map[string][]byte, error) { + secretDatas := make(map[string][]byte) + if data.Extract == nil { + return nil, fmt.Errorf("extract data is empty") + } + externalData, err := c.getExternalData(ctx, *data.Extract) + if err != nil { + return nil, err + } + tempKV := make(map[string]interface{}) + err = json.Unmarshal(externalData, &tempKV) + if err != nil { + klog.Errorf("extract secret error %v key %v", err, data.Extract.Key) + return nil, err + } + kv := make(map[string]string) + for k, v := range tempKV { + kv[k] = utils.JsonStr(v) + } + if len(data.ReplaceKey) != 0 { + for _, rule := range data.ReplaceKey { + kv, err = utils.RewriteRegexp(rule, kv) + if err != nil { + klog.Errorf("replace data key failed, error %v", err) + continue + } + } + } + for k, v := range kv { + secretDatas[k] = []byte(v) + } + return secretDatas, nil +} + +func (c *OOSClient) getExternalDataFromOOS(data v1alpha1.DataSource) ([]byte, error) { + if c.oosClient == nil { + return nil, fmt.Errorf("oos client is nil,oos key %v", data.Key) + } + req := &oos.GetSecretParameterRequest{ + Name: tea.String(data.Key), + WithDecryption: tea.Bool(true), + } + resp, err := c.oosClient.GetSecretParameter(req) + if err != nil { + if !utils.JudgeNeedRetry(err) { + klog.Errorf("failed to get secret value from oos,key %v,error %v", data.Key, err) + return nil, err + } else { + time.Sleep(utils.GetWaitTimeExponential(1)) + resp, err = c.oosClient.GetSecretParameter(req) + if err != nil { + klog.Errorf("retry to get secret value from oos failed,key %v,error %v", data.Key, err) + return nil, err + } + } + } + + klog.Infof("got secret data from oos service,key %v", data.Key) + return []byte(*resp.Body.Parameter.Value), nil +} diff --git a/pkg/backend/provider/provider_manager.go b/pkg/backend/provider/provider_manager.go new file mode 100644 index 00000000..71844b80 --- /dev/null +++ b/pkg/backend/provider/provider_manager.go @@ -0,0 +1,62 @@ +package provider + +import ( + "context" + "sync" + "time" + + "k8s.io/klog/v2" + + "github.com/AliyunContainerService/ack-ram-tool/pkg/credentials/provider" +) + +type Manager struct { + Region string + // kms multi-account client pool + KmsClientMap sync.Map + // dkms multi-instance client pool + DedicateKmsClientMap sync.Map + // oos multi-account client pool + OosClientMap sync.Map + // ram lock + RamLock *sync.Mutex + // RamProvider pool + RamProvider map[string]provider.Stopper +} + +func RegisterRamProvider(clientName string, stopper provider.Stopper, m *Manager) { + if m == nil || m.RamLock == nil { + klog.Errorf("Manager init error") + return + } + m.RamLock.Lock() + defer m.RamLock.Unlock() + providerIns, ok := m.RamProvider[clientName] + if ok { + timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + // cancel is earlier than m.RamLock.Unlock + defer cancel() + providerIns.Stop(timeoutCtx) + } + m.RamProvider[clientName] = stopper + klog.Infof("register provider %v success", clientName) +} + +func StopProvider(clientName string, m *Manager) { + if m == nil || m.RamLock == nil { + klog.Errorf("Manager init error") + return + } + m.RamLock.Lock() + defer m.RamLock.Unlock() + providerIns, ok := m.RamProvider[clientName] + if !ok || providerIns == nil { + return + } + timeoutCtx, cancel := context.WithTimeout(context.Background(), 30*time.Minute) + // cancel is earlier than m.RamLock.Unlock + defer cancel() + providerIns.Stop(timeoutCtx) + delete(m.RamProvider, clientName) + klog.Infof("stop provider %v success", clientName) +} diff --git a/pkg/controller/externalsecret/predicates.go b/pkg/controller/externalsecret/predicates.go index d05801f5..2273605e 100644 --- a/pkg/controller/externalsecret/predicates.go +++ b/pkg/controller/externalsecret/predicates.go @@ -18,29 +18,39 @@ package externalsecret import ( "reflect" - "sigs.k8s.io/controller-runtime/pkg/event" - "sigs.k8s.io/controller-runtime/pkg/predicate" - api "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "sigs.k8s.io/controller-runtime/pkg/event" ) -func getWatchPredicateForExternalSecret() predicate.Funcs { - return predicate.Funcs{ - CreateFunc: func(e event.CreateEvent) bool { - return true - }, - DeleteFunc: func(e event.DeleteEvent) bool { - return true - }, - UpdateFunc: func(e event.UpdateEvent) bool { - old := e.ObjectOld.(*api.ExternalSecret) - new := e.ObjectNew.(*api.ExternalSecret) - if !reflect.DeepEqual(old.Spec, new.Spec) || !reflect.DeepEqual(old.Status, new.Status) || - old.GetDeletionTimestamp() != new.GetDeletionTimestamp() || - old.GetGeneration() != new.GetGeneration() { - return true - } - return false - }, +type ExternalSecretsPredicate[object any] struct{} + +func (p ExternalSecretsPredicate[object]) Create(e event.TypedCreateEvent[object]) bool { + return true +} + +func (p ExternalSecretsPredicate[object]) Delete(e event.TypedDeleteEvent[object]) bool { + return true +} + +func (p ExternalSecretsPredicate[object]) Update(e event.TypedUpdateEvent[object]) bool { + var oldObjInterface interface{} = e.ObjectOld + var newObjInterface interface{} = e.ObjectNew + oldObj, ok := oldObjInterface.(*api.ExternalSecret) + if !ok { + return false + } + newObj, ok := newObjInterface.(*api.ExternalSecret) + if !ok { + return false } + if !reflect.DeepEqual(oldObj.Spec, newObj.Spec) || !reflect.DeepEqual(oldObj.Status, newObj.Status) || + oldObj.GetDeletionTimestamp() != newObj.GetDeletionTimestamp() || + oldObj.GetGeneration() != newObj.GetGeneration() { + return true + } + return false +} + +func (p ExternalSecretsPredicate[object]) Generic(e event.TypedGenericEvent[object]) bool { + return true } diff --git a/pkg/controller/externalsecret/pull_limit.go b/pkg/controller/externalsecret/pull_limit.go new file mode 100644 index 00000000..f7692533 --- /dev/null +++ b/pkg/controller/externalsecret/pull_limit.go @@ -0,0 +1,33 @@ +package externalsecret + +import ( + "context" + "fmt" + "golang.org/x/time/rate" +) + +type PullLimit interface { + Wait(context.Context) error +} + +type KmsLimiter struct { + SecretPullLimiter *rate.Limiter +} + +func (k KmsLimiter) Wait(c context.Context) error { + if k.SecretPullLimiter == nil { + return fmt.Errorf("secret pull limiter is empty") + } + return k.SecretPullLimiter.Wait(c) +} + +type OosLimiter struct { + SecretPullLimiter *rate.Limiter +} + +func (o OosLimiter) Wait(c context.Context) error { + if o.SecretPullLimiter == nil { + return fmt.Errorf("secret pull limiter is empty") + } + return o.SecretPullLimiter.Wait(c) +} diff --git a/pkg/controller/externalsecret/secret_controller.go b/pkg/controller/externalsecret/secret_controller.go index 18b71993..82d75b15 100644 --- a/pkg/controller/externalsecret/secret_controller.go +++ b/pkg/controller/externalsecret/secret_controller.go @@ -17,13 +17,13 @@ package externalsecret import ( "context" - "encoding/json" "fmt" - "golang.org/x/sync/semaphore" "reflect" - "sync" "time" + api "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" + "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" "github.com/go-logr/logr" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -33,12 +33,9 @@ import ( ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - - api "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" - "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" - kmsprovider "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/kms" - "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" + "sigs.k8s.io/controller-runtime/pkg/source" ) const ( @@ -54,11 +51,13 @@ type ExternalSecretReconciler struct { Ctx context.Context WatchNamespaces map[string]bool ReconciliationPeriod time.Duration - RotationInterval time.Duration // Key rotation job running interval. - rotationTicker *time.Ticker - secrets sync.Map // secrets map is the cache for secrets. - closing chan bool // close channel. - ConcurrentController *semaphore.Weighted + + DisablePolling bool + RotationInterval time.Duration // Key rotation job running interval. + rotationTicker *time.Ticker + closing chan bool // close channel. + KmsLimiter KmsLimiter + OosLimiter OosLimiter } var ( @@ -139,11 +138,19 @@ func (r *ExternalSecretReconciler) AddFinalizerIfNotPresent(externalSec *api.Ext return nil } +func (r *ExternalSecretReconciler) Requeue(result ctrl.Result) ctrl.Result { + if r.DisablePolling { + return ctrl.Result{Requeue: false} + } + return result +} + func (r *ExternalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { log := r.Log.WithValues("ExternalSecret", req.NamespacedName) externalSec := &api.ExternalSecret{} + // only do not requeue when getting CR fails. err := r.Get(r.Ctx, req.NamespacedName, externalSec) if err != nil { log.Error(err, fmt.Sprintf("could not get ExternalSecret '%s'", req.NamespacedName)) @@ -170,17 +177,18 @@ func (r *ExternalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Reque err := r.Update(context.TODO(), externalSec) if err != nil { log.Error(err, "failed to update externalSec when clean finalizers") - return reconcile.Result{}, err + return r.Requeue(reconcile.Result{RequeueAfter: r.ReconciliationPeriod}), err } - r.secrets.Delete(secretIndex) } - return reconcile.Result{}, nil + return r.Requeue(reconcile.Result{RequeueAfter: r.RotationInterval}), nil } + klog.Infof("reconcile external secret %v", secretIndex) + // add Finalizer to external secret instance if !utils.Contains(externalSec.GetFinalizers(), secretFinalizer) { if err := r.addFinalizer(log, externalSec); err != nil { - return reconcile.Result{}, err + return r.Requeue(reconcile.Result{RequeueAfter: r.ReconciliationPeriod}), err } } if !r.shouldWatch(secretNamespace) { @@ -189,11 +197,10 @@ func (r *ExternalSecretReconciler) Reconcile(ctx context.Context, req ctrl.Reque } _, syncErr := r.syncIfNeedUpdate(externalSec) if syncErr != nil { - return ctrl.Result{}, syncErr + return r.Requeue(ctrl.Result{RequeueAfter: r.ReconciliationPeriod}), syncErr } - r.secrets.Store(secretIndex, externalSec) log.Info("update secret store", "index", secretIndex) - return ctrl.Result{Requeue: false}, nil + return r.Requeue(ctrl.Result{RequeueAfter: r.RotationInterval}), nil } func (r *ExternalSecretReconciler) finalizeExternalSecret(log logr.Logger, secretNamespace, secretName string) error { @@ -226,66 +233,16 @@ func (r *ExternalSecretReconciler) SetupWithManager(mgr ctrl.Manager, reconcileC MaxConcurrentReconciles: reconcileCount, Reconciler: r, } - return ctrl.NewControllerManagedBy(mgr).WithOptions(options).WithEventFilter(getWatchPredicateForExternalSecret()). - For(&api.ExternalSecret{}). - Complete(r) -} - -// secretRotationJob refresh the secret if updated in kms secret-manager -func (r *ExternalSecretReconciler) SecretRotationJob() { - r.Log.Info("begin polling job", "polling interval", r.RotationInterval) - r.closing = make(chan bool) - r.rotationTicker = time.NewTicker(r.RotationInterval) - for { - select { - case <-r.rotationTicker.C: - r.rotate() - case <-r.closing: - if r.rotationTicker != nil { - r.rotationTicker.Stop() - } - } + externalSecretController, err := controller.New("externalSecret-controller", mgr, options) + if err != nil { + return err } -} - -func (r *ExternalSecretReconciler) rotate() { - r.Log.Info("rotate job running") - - var secretMap sync.Map - wg := sync.WaitGroup{} - r.secrets.Range(func(k interface{}, v interface{}) bool { - es := v.(*api.ExternalSecret) - r.Log.Info("rotate checking secret", "index", k) - // Re-generate secret if update in kms secret-manager. - timeoutContext, cancel := context.WithTimeout(context.Background(), 10*time.Minute) - if err := r.ConcurrentController.Acquire(timeoutContext, 1); err != nil { - cancel() - return true - } - wg.Add(1) - go func() { - defer wg.Done() - defer r.ConcurrentController.Release(1) - defer cancel() - updated, _ := r.syncIfNeedUpdate(es) - if updated { - secretMap.Store(fmt.Sprintf("%s/%s", es.Namespace, es.Name), es) - } - }() - return true - }) - - wg.Wait() - secretMap.Range(func(k interface{}, v interface{}) bool { - secretIndex := k.(string) - r.Log.Info("sync secret store", "index", secretIndex) - es, ok := v.(*api.ExternalSecret) - if !ok { - return true - } - r.secrets.Store(secretIndex, es) - return true - }) + // Watch for Pod create / update / delete events and call Reconcile + err = externalSecretController.Watch(source.Kind(mgr.GetCache(), &api.ExternalSecret{}, &handler.TypedEnqueueRequestForObject[*api.ExternalSecret]{}, ExternalSecretsPredicate[*api.ExternalSecret]{})) + if err != nil { + return err + } + return nil } func (r *ExternalSecretReconciler) getExternalSecret(provider backend.Provider, dataSources []api.DataSource) (map[string][]byte, error) { @@ -368,32 +325,56 @@ func (r *ExternalSecretReconciler) getExternalSecretWithExtract(provider backend } func (r *ExternalSecretReconciler) syncIfNeedUpdate(externalSec *api.ExternalSecret) (bool, error) { - esIndex := fmt.Sprintf("%s/%s", externalSec.Namespace, externalSec.Name) - log := r.Log.WithValues("secret", esIndex) providerName := externalSec.Spec.Provider if providerName == "" { - providerName = kmsprovider.ProviderName + providerName = backend.ProviderKMSName } + waitTimeoutCtx, cancel := context.WithTimeout(r.Ctx, 5*time.Minute) + defer cancel() + + var err error + switch providerName { + case backend.ProviderKMSName: + err = r.KmsLimiter.SecretPullLimiter.Wait(waitTimeoutCtx) + case backend.ProviderOOSName: + err = r.OosLimiter.SecretPullLimiter.Wait(waitTimeoutCtx) + default: + return false, fmt.Errorf("provider %v not found, only support kms or oos", providerName) + } + if err != nil { + return false, err + } + + esIndex := fmt.Sprintf("%s/%s", externalSec.Namespace, externalSec.Name) + log := r.Log.WithValues("secret", esIndex) + provider := backend.GetProviderByName(providerName) + if provider == nil { + return false, fmt.Errorf("provider %v not found, only support kms or oos", providerName) + } + secretMap := make(map[string][]byte) - if externalSec.Spec.Data != nil && len(externalSec.Spec.Data) != 0 { + if len(externalSec.Spec.Data) != 0 { out, err := r.getExternalSecret(provider, externalSec.Spec.Data) if err != nil { klog.Errorf("get external secret error %v", err) } + for k, v := range out { secretMap[k] = v } } - if externalSec.Spec.DataProcess != nil && len(externalSec.Spec.DataProcess) != 0 { + if len(externalSec.Spec.DataProcess) != 0 { out, err := r.getExternalSecretWithExtract(provider, externalSec.Spec.DataProcess) if err != nil { klog.Errorf("get external secret error %v", err) } + for k, v := range out { secretMap[k] = v } } + // Get the actual secret from Kubernetes currentData, err := r.getCurrentData(externalSec.Namespace, externalSec.Name) if err != nil && !errors.IsNotFound(err) { @@ -413,33 +394,6 @@ func (r *ExternalSecretReconciler) syncIfNeedUpdate(externalSec *api.ExternalSec return false, nil } -func (r *ExternalSecretReconciler) InitSecretCache() error { - k8sCli, err := utils.GetKubernetesClients() - if err != nil { - r.Log.Error(err, "failed to get external secret clientset") - } - - esList, err := k8sCli.Resource(externalSecretGRV).Namespace("").List(context.TODO(), metav1.ListOptions{}) - if err != nil { - r.Log.Error(err, "failed to list all external secrets") - return err - } - - //add existing secret into reconciler secret map - for _, esObj := range esList.Items { - esIndex := fmt.Sprintf("%s/%s", esObj.GetNamespace(), esObj.GetName()) - r.Log.Info("init secret store", "key", esIndex) - esBytes, _ := esObj.MarshalJSON() - es := &api.ExternalSecret{} - if err := json.Unmarshal(esBytes, &es); err != nil { - r.Log.Error(err, "failed to unmarshal externalsecret during init secret store") - continue - } - r.secrets.Store(esIndex, es) - } - return nil -} - func (r *ExternalSecretReconciler) getSecretStore(secretStoreRef *api.SecretStoreRef) (*api.SecretStore, error) { if secretStoreRef == nil { return nil, fmt.Errorf("secret store ref is nil") diff --git a/pkg/controller/secretstore/kms.go b/pkg/controller/secretstore/kms.go index edbac049..773ef303 100644 --- a/pkg/controller/secretstore/kms.go +++ b/pkg/controller/secretstore/kms.go @@ -11,23 +11,20 @@ import ( "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" - kmsprovider "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/kms" + kmsprovider "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider/kms" "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" ) -const ( - secretFinalizer = "finalizer.ack.secrets-manager.alibabacloud.com" -) - func (r *SecretStoreReconciler) ReconcileKMS(ctx context.Context, log logr.Logger, secretStore *v1alpha1.SecretStore) (ctrl.Result, error) { - provider := backend.GetProviderByName(kmsprovider.ProviderName) + kmsProvider := backend.GetProviderByName(backend.ProviderKMSName) clientName := fmt.Sprintf("%s/%s", secretStore.Namespace, secretStore.Name) isSecretStoretMarkedToBeDeleted := secretStore.GetDeletionTimestamp() != nil if isSecretStoretMarkedToBeDeleted { + log.Info("SecretStore kms is marked to be deleted") if utils.Contains(secretStore.GetFinalizers(), secretFinalizer) { // exec the clean work in secretFinalizer // do not delete Finalizer if clean failed, the clean work will exec in next reconcile - provider.Delete(clientName) + kmsProvider.Delete(clientName) // remove secretFinalizer log.Info("removing finalizer", "currentFinalizers", secretStore.GetFinalizers()) secretStore.SetFinalizers(utils.Remove(secretStore.GetFinalizers(), secretFinalizer)) @@ -45,9 +42,10 @@ func (r *SecretStoreReconciler) ReconcileKMS(ctx context.Context, log logr.Logge return ctrl.Result{}, err } } - secretClient, err := provider.NewClient(ctx, secretStore, r.Client) + + secretClient, err := kmsProvider.NewClient(ctx, secretStore, r.Client) if err != nil { - log.Error(err, fmt.Sprintf("could not new client %s", clientName)) + log.Error(err, fmt.Sprintf("could not new kms client %s", clientName)) return ctrl.Result{}, err } kmsClient, ok := secretClient.(*kmsprovider.KMSClient) @@ -55,18 +53,6 @@ func (r *SecretStoreReconciler) ReconcileKMS(ctx context.Context, log logr.Logge klog.Errorf("client type error") return ctrl.Result{}, err } - provider.Register(kmsClient.GetName(), kmsClient) + kmsProvider.Register(kmsClient.GetName(), kmsClient) return ctrl.Result{}, nil } - -func (r *SecretStoreReconciler) addFinalizer(logger logr.Logger, ss *v1alpha1.SecretStore) error { - logger.Info("Adding Finalizer for the secretstore", "name", ss.Name, "namespace", ss.Namespace) - ss.SetFinalizers(append(ss.GetFinalizers(), secretFinalizer)) - //update external secret instance - err := r.Client.Update(context.TODO(), ss) - if err != nil { - logger.Error(err, "Failed to update secretstore with finalizer", "name", ss.Name, "namespace", ss.Namespace) - return err - } - return nil -} diff --git a/pkg/controller/secretstore/oos.go b/pkg/controller/secretstore/oos.go new file mode 100644 index 00000000..e9876b05 --- /dev/null +++ b/pkg/controller/secretstore/oos.go @@ -0,0 +1,59 @@ +package secretstore + +import ( + "context" + "fmt" + + "github.com/go-logr/logr" + "k8s.io/klog" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "github.com/AliyunContainerService/ack-secret-manager/pkg/backend" + oosprovider "github.com/AliyunContainerService/ack-secret-manager/pkg/backend/provider/oos" + "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" +) + +func (r *SecretStoreReconciler) ReconcileOOS(ctx context.Context, log logr.Logger, secretStore *v1alpha1.SecretStore) (ctrl.Result, error) { + oosProvider := backend.GetProviderByName(backend.ProviderOOSName) + clientName := fmt.Sprintf("%s/%s", secretStore.Namespace, secretStore.Name) + isSecretStoretMarkedToBeDeleted := secretStore.GetDeletionTimestamp() != nil + if isSecretStoretMarkedToBeDeleted { + log.Info("SecretStore oos is marked to be deleted") + if utils.Contains(secretStore.GetFinalizers(), secretFinalizer) { + // exec the clean work in secretFinalizer + // do not delete Finalizer if clean failed, the clean work will exec in next reconcile + oosProvider.Delete(clientName) + // remove secretFinalizer + log.Info("removing finalizer", "currentFinalizers", secretStore.GetFinalizers()) + secretStore.SetFinalizers(utils.Remove(secretStore.GetFinalizers(), secretFinalizer)) + err := r.Update(context.TODO(), secretStore) + if err != nil { + log.Error(err, "failed to update externalSec when clean finalizers") + return reconcile.Result{}, err + } + } + return reconcile.Result{}, nil + } + + if !utils.Contains(secretStore.GetFinalizers(), secretFinalizer) { + if err := r.addFinalizer(log, secretStore); err != nil { + return ctrl.Result{}, err + } + } + + secretClient, err := oosProvider.NewClient(ctx, secretStore, r.Client) + if err != nil { + log.Error(err, fmt.Sprintf("could not new oos client %s", clientName)) + return ctrl.Result{}, err + } + oosClient, ok := secretClient.(*oosprovider.OOSClient) + if !ok { + klog.Errorf("client type error") + return ctrl.Result{}, err + } + oosProvider.Register(oosClient.GetName(), oosClient) + + return ctrl.Result{}, nil +} diff --git a/pkg/controller/secretstore/predicates.go b/pkg/controller/secretstore/predicates.go new file mode 100644 index 00000000..3b4157f8 --- /dev/null +++ b/pkg/controller/secretstore/predicates.go @@ -0,0 +1,40 @@ +package secretstore + +import ( + api "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" + "reflect" + "sigs.k8s.io/controller-runtime/pkg/event" +) + +type SecretStorePredicate[object any] struct{} + +func (p SecretStorePredicate[object]) Create(e event.TypedCreateEvent[object]) bool { + return true +} + +func (p SecretStorePredicate[object]) Delete(e event.TypedDeleteEvent[object]) bool { + return true +} + +func (p SecretStorePredicate[object]) Update(e event.TypedUpdateEvent[object]) bool { + var oldObjInterface interface{} = e.ObjectOld + var newObjInterface interface{} = e.ObjectNew + oldObj, ok := oldObjInterface.(*api.SecretStore) + if !ok { + return false + } + newObj, ok := newObjInterface.(*api.SecretStore) + if !ok { + return false + } + if !reflect.DeepEqual(oldObj.Spec, newObj.Spec) || !reflect.DeepEqual(oldObj.Status, newObj.Status) || + oldObj.GetDeletionTimestamp() != newObj.GetDeletionTimestamp() || + oldObj.GetGeneration() != newObj.GetGeneration() { + return true + } + return false +} + +func (p SecretStorePredicate[object]) Generic(e event.TypedGenericEvent[object]) bool { + return true +} diff --git a/pkg/controller/secretstore/secretstore_controller.go b/pkg/controller/secretstore/secretstore_controller.go index 6180c665..8cae6a73 100644 --- a/pkg/controller/secretstore/secretstore_controller.go +++ b/pkg/controller/secretstore/secretstore_controller.go @@ -19,6 +19,8 @@ package secretstore import ( "context" "fmt" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/source" "time" "github.com/go-logr/logr" @@ -31,6 +33,10 @@ import ( "github.com/AliyunContainerService/ack-secret-manager/pkg/utils" ) +const ( + secretFinalizer = "finalizer.ack.secrets-manager.alibabacloud.com" +) + // SecretStoreReconciler reconciles a SecretStore object type SecretStoreReconciler struct { client.Client @@ -63,9 +69,14 @@ func (r *SecretStoreReconciler) Reconcile(ctx context.Context, req ctrl.Request) return ctrl.Result{}, utils.IgnoreNotFoundError(err) } r.Log.Info("secret store info", req.NamespacedName) + + // SecretStoreSpec kubebuilder:validation:MaxProperties=1 if secretStore.Spec.KMS != nil { return r.ReconcileKMS(ctx, log, secretStore) } + if secretStore.Spec.OOS != nil { + return r.ReconcileOOS(ctx, log, secretStore) + } return ctrl.Result{}, nil } @@ -75,7 +86,25 @@ func (r *SecretStoreReconciler) SetupWithManager(mgr ctrl.Manager, reconcileCoun MaxConcurrentReconciles: reconcileCount, Reconciler: r, } - return ctrl.NewControllerManagedBy(mgr).WithOptions(options). - For(&v1alpha1.SecretStore{}). - Complete(r) + secretStoreController, err := controller.New("secretStore-controller", mgr, options) + if err != nil { + return err + } + err = secretStoreController.Watch(source.Kind(mgr.GetCache(), &v1alpha1.SecretStore{}, &handler.TypedEnqueueRequestForObject[*v1alpha1.SecretStore]{}, SecretStorePredicate[*v1alpha1.SecretStore]{})) + if err != nil { + return err + } + return nil +} + +func (r *SecretStoreReconciler) addFinalizer(logger logr.Logger, ss *v1alpha1.SecretStore) error { + logger.Info("Adding Finalizer for the secretstore", "name", ss.Name, "namespace", ss.Namespace) + ss.SetFinalizers(append(ss.GetFinalizers(), secretFinalizer)) + //update external secret instance + err := r.Client.Update(context.TODO(), ss) + if err != nil { + logger.Error(err, "Failed to update secretstore with finalizer", "name", ss.Name, "namespace", ss.Namespace) + return err + } + return nil } diff --git a/pkg/utils/util.go b/pkg/utils/util.go index f8746a0c..6cfb816b 100644 --- a/pkg/utils/util.go +++ b/pkg/utils/util.go @@ -20,6 +20,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "math" "net/http" "regexp" "time" @@ -30,6 +31,8 @@ import ( "k8s.io/client-go/rest" "sigs.k8s.io/controller-runtime/pkg/client" + "github.com/jmespath/go-jmespath" + sdkErr "github.com/aliyun/alibaba-cloud-sdk-go/sdk/errors" "github.com/AliyunContainerService/ack-secret-manager/pkg/apis/alibabacloud/v1alpha1" ) @@ -40,6 +43,17 @@ const ( RAM = "ram/" ) +const ( + REJECTED_THROTTLING = "Rejected.Throttling" + SERVICE_UNAVAILABLE_TEMPORARY = "ServiceUnavailableTemporary" + INTERNAL_FAILURE = "InternalFailure" +) + +var ( + BACKOFF_DEFAULT_RETRY_INTERVAL = time.Second + BACKOFF_DEFAULT_CAPACITY = time.Duration(10) * time.Second +) + var clusterIDPattern = regexp.MustCompile(`^c[0-9a-z]{32}$`) func IsClusterNamespace(s string) bool { @@ -177,3 +191,62 @@ func IgnoreNotFoundError(err error) error { } return err } + +func GetJsonSecrets(jmesObj []v1alpha1.JMESPathObject, secretValue, key string) (jsonMap map[string]string, err error) { + jsonMap = make(map[string]string, 0) + var data interface{} + err = json.Unmarshal([]byte(secretValue), &data) + if err != nil { + return nil, fmt.Errorf("invalid JSON used with jmesPath in secret key: %s", key) + } + //fetch all specified key value pairs` + for _, jmesPathEntry := range jmesObj { + jsonSecret, err := jmespath.Search(jmesPathEntry.Path, data) + if err != nil { + return nil, fmt.Errorf("Invalid JMES Path: %s.", jmesPathEntry.Path) + } + + if jsonSecret == nil { + return nil, fmt.Errorf("JMES Path - %s for object alias - %s does not point to a valid object.", + jmesPathEntry.Path, jmesPathEntry.ObjectAlias) + } + + jsonSecretAsString, isString := jsonSecret.(string) + if !isString { + return nil, fmt.Errorf("Invalid JMES search result type for path:%s. Only string is allowed.", jmesPathEntry.Path) + } + jsonMap[jmesPathEntry.ObjectAlias] = jsonSecretAsString + } + return jsonMap, nil +} + +// RewriteRegexp rewrites a single Regexp Rewrite Operation. +func RewriteRegexp(operation v1alpha1.ReplaceRule, in map[string]string) (map[string]string, error) { + out := make(map[string]string) + re, err := regexp.Compile(operation.Source) + if err != nil { + return nil, err + } + for key, value := range in { + newKey := re.ReplaceAllString(key, operation.Target) + out[newKey] = value + } + return out, nil +} + +func JudgeNeedRetry(err error) bool { + respErr, is := err.(*sdkErr.ClientError) + if is && (respErr.ErrorCode() == REJECTED_THROTTLING || respErr.ErrorCode() == SERVICE_UNAVAILABLE_TEMPORARY || respErr.ErrorCode() == INTERNAL_FAILURE) { + return true + } + return false +} + +func GetWaitTimeExponential(retryTimes int) time.Duration { + sleepInterval := time.Duration(math.Pow(2, float64(retryTimes))) * BACKOFF_DEFAULT_RETRY_INTERVAL + if sleepInterval >= BACKOFF_DEFAULT_CAPACITY { + return BACKOFF_DEFAULT_CAPACITY + } else { + return sleepInterval + } +} \ No newline at end of file