- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
本指南以 Gophercloud 官方 README 为核心,结合本仓库(OpenShift Conformance test suite 的origin镜像)中 vendored 的 Gophercloud 源码,系统讲解如何安装 SDK、准备 OpenStack 凭据、完成 Keystone 认证、创建服务客户端并编排云资源(如创建云服务器)。读完本文,你将掌握gophercloud与gophercloud/utils两种认证路径、ProviderClient与ServiceClient的底层工作方式,以及自动重认证、限流退避等高级行为的实现原理,可直接套用到自己的 Go 项目中。
什么是 Gophercloud
Gophercloud 是一个面向 OpenStack 的 Go SDK(官方定位为 "An OpenStack SDK for Go")。它把 OpenStack 各服务的 REST API 封装成 Go 类型与函数,让开发者可以用类型安全的 Go 代码完成认证、查询服务目录、创建/删除云资源等操作。
在当前仓库中,Gophercloud 以第三方依赖的形式被 vendored 在vendor/github.com/gophercloud/gophercloud/目录下,其顶层包包含认证选项(auth_options.go)、Provider 客户端(provider_client.go)、服务客户端(service_client.go)、端点搜索(endpoint_search.go)、分页(pagination/)等核心模块,openstack/子目录下则提供了各 OpenStack 服务(identity、compute、objectstorage 等)的实现。从 provider_client.go 中的DefaultUserAgent = "gophercloud/v1.14.1"可以看出,本仓库 vendored 的是 v1.14.1 版本。
如何安装
Gophercloud 与大多数 Go 库一样,通过标准 Go module 机制引入。在你的代码中引用任意 Gophercloud 包即可触发依赖解析:
import "github.com/gophercloud/gophercloud"随后更新go.mod并拉取依赖:
go mod tidyGophercloud 的顶层包通常与其他包配合使用,常见组合是同时导入github.com/gophercloud/gophercloud/openstack(提供各服务客户端工厂函数)以及具体的服务资源包(如.../openstack/compute/v2/servers),具体用法见下文。
准备 OpenStack 凭据
因为要调用 OpenStack API,你首先需要获取自己的 OpenStack 凭据。官方推荐将凭据存放到clouds.yaml文件中,而不是写死在 Go 源码里——把凭据信息与源代码解耦后,你可以放心地把代码推送到版本控制系统而无需担心泄露。
需要准备的信息包括:
- 一个有效的 Keystone identity URL(认证服务地址);
- 凭据本身。可以是用户名/密码组合、一组 Application Credentials(应用凭据)、一个预生成的 token,或任何其他受支持的认证机制。
通过 Horizon 快速导出凭据
如果你部署了 OpenStack 仪表盘(Horizon),有一个快捷方式:访问project/api_access路径,点击右上角的 "Download OpenStack RC File" 按钮,即可下载两种格式的凭据文件:
clouds.yaml:结构化的 YAML 配置文件,包含全部访问细节。将其放到~/.config/openstack/clouds.yaml即可被 Gophercloud 生态的配置读取器识别;openrc:一个 bash 脚本,执行source openrc会把所有访问细节导出为环境变量,随后会提示你输入密码。
需要说明的是:Gophercloud 核心库本身不直接解析clouds.yaml,该能力由配套库gophercloud/utils提供(见下文认证一节)。
认证:构建 ProviderClient
有了凭据之后,下一步是认证。Gophercloud 的认证由顶层 "Provider" 结构体——即ProviderClient——承担。ProviderClient是一个"顶级客户端",所有 OpenStack 服务客户端都由它派生而来,它内部保存了访问 API 所需的全部认证细节(如基础 URL 和 token ID)。
从 provider_client.go 的源码可以看到,ProviderClient的核心字段包括:
| 字段 | 作用 |
|---|---|
IdentityBase | 身份服务的基础 URL,用于发起认证请求,应指向身份服务的根资源而非某个特定版本 |
IdentityEndpoint | 身份端点,可能是特定版本的身份服务;若指定了版本,将直接使用该端点而非先查询版本 |
TokenID | 最近一次签发的有效 token 的 ID;应用不应直接读写该字段,而应使用Token()/SetTokenAndAuthResult() |
EndpointLocator | 描述如何从服务目录中为各服务发现端点 |
HTTPClient | 允许用户注入自定义的 http/https 传输行为 |
UserAgent | 请求中的 User-Agent 头(默认gophercloud/v1.14.1,可通过UserAgent.Prepend()追加自定义前缀) |
ReauthFunc | 请求返回 401 时用于重新认证的函数,因为不同版本的身份服务可能有不同的认证函数 |
RetryBackoffFunc/MaxBackoffRetries | 限流(429)时的退避重试函数与最大重试次数(默认 60 次) |
RetryFunc | 通用失败请求处理函数,请求失败后总会调用;置空则遇到错误直接中止 |
方式一:使用 gophercloud/utils(推荐)
github.com/gophercloud/utils 库提供clientconfig包来简化认证,其中包含读取clouds.yaml文件等附加能力。使用clientconfig生成 Provider 客户端:
import ( "github.com/gophercloud/utils/openstack/clientconfig" ) // 也可以跳过配置,改在环境中设置 'OS_CLOUD' opts := new(clientconfig.ClientOpts) opts.Cloud = "devstack-admin" provider, err := clientconfig.AuthenticatedClient(opts)注意:clientconfig属于独立的gophercloud/utils仓库,本仓库 vendored 的gophercloud核心库并未包含该包,使用前需要单独引入。
方式二:不使用 gophercloud/utils
Gophercloud 核心库不提供clouds.yaml文件支持,如果你不想依赖gophercloud/utils,需要自行实现这部分功能。此时有两种方式填充认证选项:
import ( "github.com/gophercloud/gophercloud" "github.com/gophercloud/gophercloud/openstack" ) // 方式 1:手动传入认证信息 opts := gophercloud.AuthOptions{ IdentityEndpoint: "https://openstack.example.com:5000/v2.0", Username: "{username}", Password: "{password}", } // 方式 2:用工具函数从环境变量读取 opts, err := openstack.AuthOptionsFromEnv()拿到opts后,传入openstack.AuthenticatedClient(opts)即可获得一个ProviderClient:
provider, err := openstack.AuthenticatedClient(opts)AuthOptions 字段详解
gophercloud.AuthOptions(定义于 auth_options.go)是所有身份实现与 provider 字段的并集,常用字段如下:
| 字段 | 说明 |
|---|---|
IdentityEndpoint | 身份 API 的 HTTP 端点,即云运营商常说的 "auth_url" /OS_AUTH_URL |
Username/UserID | Identity V2 需要 Username;Identity V3 需要 UserID 或 Username + DomainID/DomainName |
Password | 密码 |
Passcode | TOTP 认证方法使用的动态口令 |
DomainID/DomainName | 使用 Username 配合 Identity V3 时,两者最多提供一个;否则均可选 |
TenantID/TenantName | V2 API 中的租户;在 V3 中对应 project_id / project_name(这里统一叫 Tenant),部分 provider 允许用名称代替 ID |
AllowReauth | 为 true 时允许 Gophercloud 在内存中缓存凭据并在 token 过期时自动重新认证(默认 false)。注意:若不加以限制,重认证可能无限重试,官方建议通过自定义 RoundTripper 记录失败次数来限制 |
TokenID | 允许用既有 token(可能是他人身份)完成认证 |
Scope | 认证请求的作用域(AuthScope含ProjectID、ProjectName、DomainID、DomainName、System) |
ApplicationCredentialID/ApplicationCredentialName/ApplicationCredentialSecret | Application Credentials 认证所需信息 |
从ToTokenV3CreateMap()的实现可以看出,认证时支持password、token、application_credential、totp等 identity method,并对各类组合做了严格校验(如 Username 与 UserID 不能同时提供、使用 Username 时 DomainID/DomainName 必须提供其一、ApplicationCredential 必须提供 Secret 等)。注意CanReauth()对 TOTP 口令返回 false,即 TOTP 认证不支持自动重认证。
从环境变量读取:AuthOptionsFromEnv
openstack/auth_env.go 中的AuthOptionsFromEnv()会读取标准的OS_*环境变量并填充AuthOptions:
- 必填:
OS_AUTH_URL、OS_USERNAME(或OS_USERID)、OS_PASSWORD,缺失会返回对应的ErrMissingEnvironmentVariable; - 可选:
OS_PROJECT_ID、OS_PROJECT_NAME(OS_TENANT_ID、OS_TENANT_NAME是二者的废弃形式)、OS_DOMAIN_ID、OS_DOMAIN_NAME、OS_APPLICATION_CREDENTIAL_ID/NAME/SECRET、OS_PASSCODE、OS_SYSTEM_SCOPE; - 若设置了
OS_PROJECT_NAME,还需要设置OS_PROJECT_ID,以处理不在默认 domain 下的 project; OS_SYSTEM_SCOPE=all时会把 Scope 设为系统级(System: true)。
典型用法是先source openrc导出环境变量,再调用:
opts, err := openstack.AuthOptionsFromEnv() provider, err := openstack.AuthenticatedClient(opts)ProviderClient 的认证流程
调用openstack.AuthenticatedClient(options)时(见 openstack/client.go),实际执行两步:
NewClient(options.IdentityEndpoint):创建未认证的ProviderClient,规范化 URL 并填充IdentityBase/IdentityEndpoint,同时调用UseTokenLock()初始化并发安全的 token 锁;Authenticate(client, options):向端点发起认证请求,根据端点支持的版本自动选择 Keystone v2(优先级 20)或 v3(优先级 30,优先选择 v3),成功后将 token 与 service catalog 写入客户端。
认证成功后,ProviderClient会:
- 记录 token,并通过
AuthenticatedHeaders()在后续请求中自动附带X-Auth-Token头; - 设置
EndpointLocator,后续各服务客户端依据服务目录(catalog)定位端点; - 若设置了
AllowReauth,会构造一个"一次性客户端"(throw-away client,token 与 reauth 函数被清零),注册ReauthFunc——当某个请求收到 401 时,provider_client.go 中的Request()会自动调用Reauthenticate()重新认证并重放请求(同一请求只重认证一次,避免无限循环)。
创建服务客户端
有了基础 Provider 之后,将其作为依赖注入到各个 OpenStack 服务中。例如,要使用 Compute API,需要创建一个 Compute 服务客户端。使用clientconfig的方式:
client, err := clientconfig.NewServiceClient("compute", opts)使用核心库的方式,通过openstack包的工厂函数创建:
client, err := openstack.NewComputeV2(provider, gophercloud.EndpointOpts{ Region: os.Getenv("OS_REGION_NAME"), })openstack包为各服务提供了对应的工厂函数(均定义于 openstack/client.go),例如:
| 函数 | 服务类型 |
|---|---|
NewComputeV2 | compute(Nova) |
NewNetworkV2 | network(Neutron,端点后附加v2.0/) |
NewObjectStorageV1 | object-store(Swift) |
NewBlockStorageV1/V2/V3 | volume / volumev2 / volumev3(Cinder) |
NewImageServiceV2 | image(Glance,附加v2/) |
NewLoadBalancerV2 | load-balancer(Octavia) |
NewDNSV2 | dns(Designate) |
NewIdentityV2/V3 | identity(Keystone) |
NewBareMetalV1/NewBareMetalIntrospectionV1 | baremetal / baremetal-introspection(Ironic) |
NewSharedFileSystemV2 | sharev2(Manila) |
NewKeyManagerV1 | key-manager(Barbican) |
NewWorkflowV2、NewPlacementV1、NewCDNV1、NewDBV1、NewOrchestrationV1、NewClusteringV1、NewMessagingV2、NewContainerV1、NewContainerInfraV1等 | 对应各类服务 |
EndpointOpts 与端点定位
工厂函数接收的gophercloud.EndpointOpts(定义于 endpoint_search.go)用于在服务目录中唯一确定一个端点:
| 字段 | 必填 | 说明 |
|---|---|---|
Type | 是 | 服务类型(如 "compute"、"object-store"),一般由服务客户端函数自动填充 |
Name | 否 | 服务名称(如 "nova")。服务可能同 Type 不同 Name,因此有时两者都需要 |
Region | 视情况 | 端点所在的地理区域,仅对跨区域的服务必需 |
Availability | 否 | 端点可见性:AvailabilityPublic(默认)/AvailabilityInternal/AvailabilityAdmin,对应 v2 的 publicURL/internalURL/adminURL 与 v3 的 Interface |
ServiceClient 的使用
ServiceClient(service_client.go)封装了具体服务的基础 URL 与资源路径,提供Get、Post、Put、Patch、Delete、Head方法,最终都转发到ProviderClient.Request()。它还支持:
Microversion:设置服务微版本,请求时会自动附带对应的版本头(如 Nova 的X-OpenStack-Nova-API-Version)与通用的OpenStack-API-Version头;MoreHeaders:为服务的所有请求统一附加 HTTP 头;ServiceURL(parts...):按资源片段拼接完整 URL。
实战:创建一台云服务器(Provision a server)
使用上面创建的 Compute 服务客户端,即可执行任意 Compute API 操作。以创建新服务器为例,调用Create方法并传入 flavor ID(硬件规格)与 image ID(操作系统镜像):
import "github.com/gophercloud/gophercloud/openstack/compute/v2/servers" server, err := servers.Create(client, servers.CreateOpts{ Name: "My new server!", FlavorRef: "flavor_id", ImageRef: "image_id", }).Extract()上述代码创建了一台带指定参数的新服务器,并把新资源体现在server变量中(一个servers.Server结构体)。Gophercloud 的请求/响应模型是"XxxOpts构造请求 +XxxResult承载响应":servers.Create返回CreateResult,调用其Extract()方法把响应体解析为强类型结构体;若Extract()返回的err非 nil,则表示创建失败。CreateOpts还支持Networks、SecurityGroups、UserData、Metadata等更多字段,具体定义可查阅 servers/requests.go。
高级用法:请求定制与自动重试
Gophercloud 的ProviderClient.Request()支持通过RequestOpts(provider_client.go)精细控制每一次 HTTP 请求:
| 字段 | 说明 |
|---|---|
JSONBody/RawBody | 请求体,二选一:前者会被 JSON 编码(默认 Content-Type 为 application/json),后者直接消费一个io.Reader |
JSONResponse | 非 nil 时,响应体会被解析为 JSON 并填充到该变量 |
OkCodes | 视为成功的 HTTP 状态码列表;不设置时按 HTTP 方法取默认值(GET/HEAD → 200,POST/PUT → 201/202,PATCH → 200/202/204,DELETE → 202/204) |
MoreHeaders/OmitHeaders | 追加 / 移除请求头(OmitHeaders 优先于 MoreHeaders) |
ErrorContext | 自定义错误类型,可根据状态码返回更具体的资源错误 |
KeepResponseBody | 保留响应体以便后续使用(不能与JSONResponse同时使用) |
Request()的完整处理链(见doRequest)包括:编码请求体 → 组装请求头(Content-Type、Accept、User-Agent、X-Auth-Token)→ 发送请求 → 校验状态码 → 按需处理错误。当收到 401 时自动触发重认证并重放请求;收到 429/498(限流)时调用RetryBackoffFunc退避重试,最大次数受MaxBackoffRetries限制(未设置时取DefaultMaxBackoffRetries = 60);其他错误码(400/403/404/405/408/409/500/502/503/504)则映射为对应的ErrDefaultXxx错误类型,若设置了RetryFunc还会把失败交给它决定是否重试。
此外,Gophercloud 的pagination包(vendor/github.com/gophercloud/gophercloud/pagination/)提供Pager、LinkedPage、MarkerPage、SinglePage等分页工具,处理 OpenStack API 的列表类资源;openstack/utils目录下还有版本协商等辅助逻辑。原 README 还提到一份 FAQ 用于定制 Gophercloud 行为的技巧,不过该文件并未包含在本仓库的 vendored 树中,可按需从上游获取。
向后兼容性保证
Gophercloud 的版本号遵循 semver(语义化版本):
- 在
v1.0.0之前没有任何兼容性保证; - 自 v1 起,同一个 major 版本内不会引入破坏性变更(no breaking changes within a major release)。
这意味着在你的go.mod中以v1.x引入 Gophercloud 后,可以放心在 minor/patch 升级中保持代码兼容。上游的版本发布流程说明见其RELEASE.md(同样未随 vendored 树携带,可从上源获取)。
结语与进一步阅读
Gophercloud 把 OpenStack 复杂的 REST API 世界收敛为一套清晰的 Go 类型系统:AuthOptions负责认证信息,ProviderClient持有会话与 token,ServiceClient代表具体服务,XxxOpts/XxxResult构成资源的请求与响应模型。无论你是用clouds.yaml+gophercloud/utils的声明式配置,还是用OS_*环境变量 +AuthOptionsFromEnv()的经典方式,都能在几分钟内完成认证并开始操作云资源。
想深入源码细节,可在本仓库中直接阅读以下文件:
- provider_client.go:Provider 客户端、认证头、自动重认证与退避重试实现;
- openstack/client.go:各服务客户端工厂函数与 v2/v3 认证流程;
- auth_options.go:认证选项字段与认证请求体构建逻辑;
- openstack/auth_env.go:
OS_*环境变量解析与校验; - service_client.go:服务客户端与微版本请求头;
- openstack/compute/v2/servers/requests.go:Compute 服务资源操作(含
CreateOpts)示例。
- 测试
- 云原生
- 质量保障
【免费下载链接】origin
Conformance test suite for OpenShift
相关推荐
Gophercloud:用 Go 语言驱动 OpenStack 云的 SDK 实战指南(含 LinuxKit 集成实例)
Gophercloud:用 Go 语言驱动 OpenStack 云的 SDK 实战指南(含 LinuxKit 集成实例) 本指南以 LinuxKit 仓库中内嵌
操作系统云原生容器运行时使用 Gophercloud v2:面向 Go 开发者的 OpenStack SDK 实战指南(以 kOps 源码为例)
使用 Gophercloud v2:面向 Go 开发者的 OpenStack SDK 实战指南(以 kOps 源码为例) Gophercloud 是 OpenS
云原生集群管理运维IaC基于 Gophercloud v2 AGENTS.md 的 OpenStack Go SDK 工程规范与测试实践指南
基于 Gophercloud v2 AGENTS.md 的 OpenStack Go SDK 工程规范与测试实践指南 本文档源文件: vendor/github
云原生集群管理运维IaC
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考