Skip to content
35 changes: 35 additions & 0 deletions acceptance/clients/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,41 @@ func NewRMSClient() (client *golangsdk.ServiceClient, err error) {
})
}

// NewEPSV1Client returns authenticated EPS v1 client.
// EPS requires domain-scoped authentication. The endpoint is discovered via
// NewEPSV1 (project-scoped catalog), then re-authenticated with domain scope.
func NewEPSV1Client() (client *golangsdk.ServiceClient, err error) {
cc, err := CloudAndClient()
if err != nil {
return nil, err
}
sc, err := openstack.NewEPSV1(cc.ProviderClient, golangsdk.EndpointOpts{
Region: cc.RegionName,
})
if err != nil {
return nil, err
}

// Re-authenticate with domain scope for EPS API
cloud, err := EnvOS.Cloud()
if err != nil {
return nil, err
}
domainOpts := golangsdk.AuthOptions{
IdentityEndpoint: cloud.AuthInfo.AuthURL,
Username: cloud.AuthInfo.Username,
Password: cloud.AuthInfo.Password,
DomainName: cloud.AuthInfo.UserDomainName,
AllowReauth: true,
}
domainProvider, err := openstack.AuthenticatedClient(domainOpts)
if err != nil {
return nil, err
}
sc.ProviderClient = domainProvider
return sc, nil
}

// NewCCIClient returns authenticated CCI v2 client
func NewCCIClient() (client *golangsdk.ServiceClient, err error) {
cc, err := CloudAndClient()
Expand Down
149 changes: 149 additions & 0 deletions acceptance/openstack/eps/v1/projects_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package v1

import (
"fmt"
"testing"
"time"

"github.com/opentelekomcloud/gophertelekomcloud/acceptance/clients"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/eps/v1/projects"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/eps/v1/providers"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/eps/v1/resources"
"github.com/opentelekomcloud/gophertelekomcloud/openstack/eps/v1/versions"
th "github.com/opentelekomcloud/gophertelekomcloud/testhelper"
)

func TestEnterpriseProjectsListAndGet(t *testing.T) {
t.Skip("enterprise project tests not for CI")
client, err := clients.NewEPSV1Client()
th.AssertNoErr(t, err)

allProjects, err := projects.List(client, projects.ListOpts{})
th.AssertNoErr(t, err)

enterpriseProjectID := clients.EnvOS.GetEnv("ENTERPRISE_PROJECT_ID")
if enterpriseProjectID == "" {
if len(allProjects.EnterpriseProjects) == 0 {
t.Skip("no enterprise projects are available")
}
enterpriseProjectID = allProjects.EnterpriseProjects[0].ID
}

p, err := projects.Get(client, enterpriseProjectID)
th.AssertNoErr(t, err)
th.AssertEquals(t, enterpriseProjectID, p.ID)
}

func TestEnterpriseProjectsLifecycle(t *testing.T) {
t.Skip("enterprise project tests not for CI")
client, err := clients.NewEPSV1Client()
th.AssertNoErr(t, err)

suffix := fmt.Sprintf("%d", time.Now().UnixNano()%100000)
createName := "eps-test-" + suffix
updateName := "eps-test-upd-" + suffix

// Create
created, err := projects.Create(client, projects.CreateOpts{
Name: createName,
Description: "Created by gophertelekomcloud acceptance test",
})
th.AssertNoErr(t, err)
th.AssertEquals(t, createName, created.Name)
t.Logf("Created enterprise project: %s (%s)", created.Name, created.ID)

// Ensure cleanup
defer func() {
_ = projects.Action(client, created.ID, projects.ActionOpts{Action: "disable"})
}()

// Update
updated, err := projects.Update(client, created.ID, projects.UpdateOpts{
Name: updateName,
Description: "Updated by acceptance test",
})
th.AssertNoErr(t, err)
th.AssertEquals(t, updateName, updated.Name)

// List with name filter
filtered, err := projects.List(client, projects.ListOpts{
Name: updateName,
})
th.AssertNoErr(t, err)
if filtered.TotalCount < 1 {
t.Fatal("expected at least 1 project in filtered list")
}

// Disable (Action)
err = projects.Action(client, created.ID, projects.ActionOpts{Action: "disable"})
th.AssertNoErr(t, err)
t.Log("Disabled enterprise project")

// Verify disabled
disabled, err := projects.Get(client, created.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, 2, disabled.Status)

// Enable (Action)
err = projects.Action(client, created.ID, projects.ActionOpts{Action: "enable"})
th.AssertNoErr(t, err)
t.Log("Enabled enterprise project")

// Verify enabled
enabled, err := projects.Get(client, created.ID)
th.AssertNoErr(t, err)
th.AssertEquals(t, 1, enabled.Status)
}

func TestVersions(t *testing.T) {
t.Skip("enterprise project tests not for CI")
client, err := clients.NewEPSV1Client()
th.AssertNoErr(t, err)

allVersions, err := versions.List(client)
th.AssertNoErr(t, err)

if len(allVersions) == 0 {
t.Fatal("expected at least one API version")
}
t.Logf("Found %d API version(s)", len(allVersions))
for _, v := range allVersions {
t.Logf(" %s (status: %s)", v.ID, v.Status)
}
}

func TestProviders(t *testing.T) {
t.Skip("enterprise project tests not for CI")
client, err := clients.NewEPSV1Client()
th.AssertNoErr(t, err)

allProviders, err := providers.List(client, providers.ListOpts{})
th.AssertNoErr(t, err)

if len(allProviders) == 0 {
t.Fatal("expected at least one provider")
}
t.Logf("Found %d provider(s)", len(allProviders))
for _, p := range allProviders[:3] {
t.Logf(" %s (%s)", p.Provider, p.ProviderI18nDisplay)
}
}

func TestResourcesFilter(t *testing.T) {
t.Skip("enterprise project tests not for CI")
client, err := clients.NewEPSV1Client()
th.AssertNoErr(t, err)

projectID := clients.EnvOS.GetEnv("PROJECT_ID")
if projectID == "" {
t.Skip("OS_PROJECT_ID is required for resource filtering")
}

result, err := resources.Filter(client, "0", resources.FilterOpts{
Projects: []string{projectID},
ResourceTypes: []string{"ecs"},
Limit: 5,
})
th.AssertNoErr(t, err)
t.Logf("Found %d resource(s) in default project (total: %d)", len(result.Resources), result.TotalCount)
}
14 changes: 14 additions & 0 deletions openstack/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,20 @@ func NewRmsServiceV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts
return initClientOpts(client, eo, "rms")
}

// NewEPSV1 creates a ServiceClient that may be used to access the EPS service.
// EPS is a global service — the endpoint URL does not include project_id.
func NewEPSV1(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) {
Comment thread
anton-sidelnikov marked this conversation as resolved.
sc, err := initCommonServiceClient(client, eo, "eps", "v1.0")
if err != nil {
return nil, err
}
if client.ProjectID != "" {
sc.Endpoint = strings.Replace(sc.Endpoint, client.ProjectID+"/", "", 1)
}
sc.ResourceBase = sc.Endpoint
return sc, nil
}

func NewCCIServiceV2(client *golangsdk.ProviderClient, eo golangsdk.EndpointOpts) (*golangsdk.ServiceClient, error) {
sc, err := initClientOpts(client, eo, "ccev2.0")
if err != nil {
Expand Down
22 changes: 22 additions & 0 deletions openstack/eps/v1/projects/Action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package projects

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
)

type ActionOpts struct {
Action string `json:"action" required:"true"`
}

func Action(client *golangsdk.ServiceClient, id string, opts ActionOpts) error {
b, err := build.RequestBody(opts, "")
if err != nil {
return err
}

_, err = client.Post(client.ServiceURL("enterprise-projects", id, "action"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{200, 204},
})
return err
}
30 changes: 30 additions & 0 deletions openstack/eps/v1/projects/Create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package projects

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type CreateOpts struct {
Name string `json:"name" required:"true"`
Description string `json:"description,omitempty"`
}

func Create(client *golangsdk.ServiceClient, opts CreateOpts) (*EnterpriseProject, error) {
b, err := build.RequestBody(opts, "")
if err != nil {
return nil, err
}

raw, err := client.Post(client.ServiceURL("enterprise-projects"), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{200, 201},
})
if err != nil {
return nil, err
}

var res EnterpriseProject
err = extract.IntoStructPtr(raw.Body, &res, "enterprise_project")
return &res, err
}
13 changes: 13 additions & 0 deletions openstack/eps/v1/projects/EnterpriseProject.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package projects

// EnterpriseProject represents an EPS enterprise project.
type EnterpriseProject struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Type string `json:"type"`
Status int `json:"status"`
DeleteFlag bool `json:"delete_flag"`
CreatedAt string `json:"created_at"`
UpdatedAt string `json:"updated_at"`
}
17 changes: 17 additions & 0 deletions openstack/eps/v1/projects/Get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package projects

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

func Get(client *golangsdk.ServiceClient, id string) (*EnterpriseProject, error) {
raw, err := client.Get(client.ServiceURL("enterprise-projects", id), nil, nil)
if err != nil {
return nil, err
}

var res EnterpriseProject
err = extract.IntoStructPtr(raw.Body, &res, "enterprise_project")
return &res, err
}
37 changes: 37 additions & 0 deletions openstack/eps/v1/projects/List.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package projects

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type ListOpts struct {
ID string `q:"id"`
Limit int `q:"limit"`
Name string `q:"name"`
Offset int `q:"offset"`
SortDir string `q:"sort_dir"`
SortKey string `q:"sort_key"`
Status int `q:"status"`
}

type ListResult struct {
EnterpriseProjects []EnterpriseProject `json:"enterprise_projects"`
TotalCount int `json:"total_count"`
}

func List(client *golangsdk.ServiceClient, opts ListOpts) (*ListResult, error) {
q, err := golangsdk.BuildQueryString(&opts)
if err != nil {
return nil, err
}

raw, err := client.Get(client.ServiceURL("enterprise-projects")+q.String(), nil, nil)
if err != nil {
return nil, err
}

var res ListResult
err = extract.Into(raw.Body, &res)
return &res, err
}
31 changes: 31 additions & 0 deletions openstack/eps/v1/projects/Update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package projects

import (
golangsdk "github.com/opentelekomcloud/gophertelekomcloud"
"github.com/opentelekomcloud/gophertelekomcloud/internal/build"
"github.com/opentelekomcloud/gophertelekomcloud/internal/extract"
)

type UpdateOpts struct {
Name string `json:"name" required:"true"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"`
}

func Update(client *golangsdk.ServiceClient, id string, opts UpdateOpts) (*EnterpriseProject, error) {
b, err := build.RequestBody(opts, "")
if err != nil {
return nil, err
}

raw, err := client.Put(client.ServiceURL("enterprise-projects", id), b, nil, &golangsdk.RequestOpts{
OkCodes: []int{200},
})
if err != nil {
return nil, err
}

var res EnterpriseProject
err = extract.IntoStructPtr(raw.Body, &res, "enterprise_project")
return &res, err
}
Loading
Loading