Skip to content

Commit 4a58d58

Browse files
authored
Add OpenStack LoadBalancerClass config endpoint (#7596)
* Add OpenStack LoadBalancerClass config endpoint and update routes * Remove OpenStack floating networks endpoint and associated code and resolved other comments
1 parent 9a3d771 commit 4a58d58

File tree

13 files changed

+1123
-2
lines changed

13 files changed

+1123
-2
lines changed

modules/api/cmd/kubermatic-api/swagger.json

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21448,6 +21448,110 @@
2144821448
}
2144921449
}
2145021450
},
21451+
"/api/v2/projects/{project_id}/providers/openstack/membersubnets": {
21452+
"get": {
21453+
"description": "Lists load balancer member subnets from openstack",
21454+
"produces": [
21455+
"application/json"
21456+
],
21457+
"tags": [
21458+
"openstack"
21459+
],
21460+
"operationId": "listProjectOpenstackMemberSubnets",
21461+
"parameters": [
21462+
{
21463+
"type": "string",
21464+
"name": "Username",
21465+
"in": "header"
21466+
},
21467+
{
21468+
"type": "string",
21469+
"name": "Password",
21470+
"in": "header"
21471+
},
21472+
{
21473+
"type": "string",
21474+
"name": "Domain",
21475+
"in": "header"
21476+
},
21477+
{
21478+
"type": "string",
21479+
"name": "OpenstackTenant",
21480+
"in": "header"
21481+
},
21482+
{
21483+
"type": "string",
21484+
"name": "OpenstackTenantID",
21485+
"in": "header"
21486+
},
21487+
{
21488+
"type": "string",
21489+
"name": "OpenstackProject",
21490+
"in": "header"
21491+
},
21492+
{
21493+
"type": "string",
21494+
"name": "OpenstackProjectID",
21495+
"in": "header"
21496+
},
21497+
{
21498+
"type": "string",
21499+
"name": "DatacenterName",
21500+
"in": "header"
21501+
},
21502+
{
21503+
"type": "string",
21504+
"name": "ApplicationCredentialID",
21505+
"in": "header"
21506+
},
21507+
{
21508+
"type": "string",
21509+
"name": "ApplicationCredentialSecret",
21510+
"in": "header"
21511+
},
21512+
{
21513+
"type": "boolean",
21514+
"name": "OIDCAuthentication",
21515+
"in": "header"
21516+
},
21517+
{
21518+
"type": "string",
21519+
"name": "Credential",
21520+
"in": "header"
21521+
},
21522+
{
21523+
"type": "string",
21524+
"x-go-name": "NetworkID",
21525+
"name": "network_id",
21526+
"in": "query"
21527+
},
21528+
{
21529+
"type": "string",
21530+
"x-go-name": "ProjectID",
21531+
"name": "project_id",
21532+
"in": "path",
21533+
"required": true
21534+
}
21535+
],
21536+
"responses": {
21537+
"200": {
21538+
"description": "OpenStackLoadBalancerPoolMember",
21539+
"schema": {
21540+
"type": "array",
21541+
"items": {
21542+
"$ref": "#/definitions/OpenStackLoadBalancerPoolMember"
21543+
}
21544+
}
21545+
},
21546+
"default": {
21547+
"description": "errorResponse",
21548+
"schema": {
21549+
"$ref": "#/definitions/errorResponse"
21550+
}
21551+
}
21552+
}
21553+
}
21554+
},
2145121555
"/api/v2/projects/{project_id}/providers/openstack/networks": {
2145221556
"get": {
2145321557
"description": "Lists networks from openstack",
@@ -38177,6 +38281,20 @@
3817738281
},
3817838282
"x-go-package": "k8c.io/dashboard/v2/pkg/api/v2"
3817938283
},
38284+
"OpenStackLoadBalancerPoolMember": {
38285+
"type": "object",
38286+
"properties": {
38287+
"id": {
38288+
"type": "string",
38289+
"x-go-name": "ID"
38290+
},
38291+
"name": {
38292+
"type": "string",
38293+
"x-go-name": "Name"
38294+
}
38295+
},
38296+
"x-go-package": "k8c.io/dashboard/v2/pkg/api/v2"
38297+
},
3818038298
"Openstack": {
3818138299
"type": "object",
3818238300
"properties": {
@@ -38609,6 +38727,14 @@
3860938727
"description": "Name is human-readable name for the subnet",
3861038728
"type": "string",
3861138729
"x-go-name": "Name"
38730+
},
38731+
"tags": {
38732+
"description": "Tags are Neutron subnet tags (if supported by the deployment)",
38733+
"type": "array",
38734+
"items": {
38735+
"type": "string"
38736+
},
38737+
"x-go-name": "Tags"
3861238738
}
3861338739
},
3861438740
"x-go-package": "k8c.io/dashboard/v2/pkg/api/v1"

modules/api/pkg/api/v1/types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -768,6 +768,8 @@ type OpenstackSubnet struct {
768768
Name string `json:"name"`
769769
// IPversion is the IP protocol version (4 or 6)
770770
IPVersion int `json:"ipVersion"`
771+
// Tags are Neutron subnet tags (if supported by the deployment)
772+
Tags []string `json:"tags,omitempty"`
771773
}
772774

773775
// OpenstackTenant is the object representing a openstack tenant.

modules/api/pkg/api/v2/types.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1852,6 +1852,24 @@ type OpenstackSubnetPool struct {
18521852
Prefixes []string `json:"prefixes"`
18531853
}
18541854

1855+
type OpenStackLoadBalancer struct {
1856+
ID string `json:"id"`
1857+
Name string `json:"name"`
1858+
Pools []OpenStackLoadBalancerPool `json:"pools"`
1859+
}
1860+
1861+
type OpenStackLoadBalancerPool struct {
1862+
Name string `json:"name"`
1863+
ID string `json:"id"`
1864+
Members []OpenStackLoadBalancerPoolMember `json:"members"`
1865+
}
1866+
1867+
// swagger:model OpenStackLoadBalancerPoolMember
1868+
type OpenStackLoadBalancerPoolMember struct {
1869+
Name string `json:"name"`
1870+
ID string `json:"id"`
1871+
}
1872+
18551873
// OpenstackServerGroup is the object representing a openstack server group.
18561874
// swagger:model OpenstackServerGroup
18571875
type OpenstackServerGroup struct {

modules/api/pkg/handler/common/provider/openstack.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package provider
1919
import (
2020
"context"
2121
"crypto/x509"
22+
"encoding/json"
2223
"fmt"
2324
"net/http"
2425

@@ -243,6 +244,7 @@ func GetOpenstackSubnets(ctx context.Context, userInfo *provider.UserInfo, seeds
243244
ID: subnet.ID,
244245
Name: subnet.Name,
245246
IPVersion: subnet.IPVersion,
247+
Tags: subnet.Tags,
246248
})
247249
}
248250

@@ -449,6 +451,53 @@ func GetOpenstackServerGroups(ctx context.Context, userInfo *provider.UserInfo,
449451
return apiServerGroups, nil
450452
}
451453

454+
func GetOpenstackLoadBalancers(ctx context.Context, userInfo *provider.UserInfo, seedsGetter provider.SeedsGetter, credentials *resources.OpenstackCredentials, datacenterName, vipNetworkID string, caBundle *x509.CertPool) ([]apiv2.OpenStackLoadBalancer, error) {
455+
authURL, region, err := getOpenstackAuthURLAndRegion(userInfo, seedsGetter, datacenterName)
456+
if err != nil {
457+
return nil, err
458+
}
459+
460+
loadBalancers, err := openstack.GetLoadBalancers(ctx, authURL, region, vipNetworkID, credentials, caBundle)
461+
if err != nil {
462+
return nil, err
463+
}
464+
465+
apiLoadBalancers := []apiv2.OpenStackLoadBalancer{}
466+
b, err := json.Marshal(loadBalancers)
467+
if err != nil {
468+
return nil, err
469+
}
470+
if err := json.Unmarshal(b, &apiLoadBalancers); err != nil {
471+
return nil, err
472+
}
473+
474+
return apiLoadBalancers, nil
475+
}
476+
477+
func GetOpenstackLoadBalancerPoolMembers(ctx context.Context, userInfo *provider.UserInfo, seedsGetter provider.SeedsGetter, credentials *resources.OpenstackCredentials, datacenterName, poolID string, caBundle *x509.CertPool) ([]apiv2.OpenStackLoadBalancerPoolMember, error) {
478+
authURL, region, err := getOpenstackAuthURLAndRegion(userInfo, seedsGetter, datacenterName)
479+
if err != nil {
480+
return nil, err
481+
}
482+
483+
members, err := openstack.GetLoadBalancerPoolMembers(ctx, authURL, region, poolID, credentials, caBundle)
484+
if err != nil {
485+
return nil, err
486+
}
487+
488+
apiMembers := []apiv2.OpenStackLoadBalancerPoolMember{}
489+
for _, member := range members {
490+
apiMember := apiv2.OpenStackLoadBalancerPoolMember{
491+
ID: member.ID,
492+
Name: member.Name,
493+
}
494+
495+
apiMembers = append(apiMembers, apiMember)
496+
}
497+
498+
return apiMembers, nil
499+
}
500+
452501
func getClusterForOpenstack(ctx context.Context, projectProvider provider.ProjectProvider, privilegedProjectProvider provider.PrivilegedProjectProvider, userInfoGetter provider.UserInfoGetter, projectID string, clusterID string) (*kubermaticv1.Cluster, error) {
453502
cluster, err := handlercommon.GetCluster(ctx, projectProvider, privilegedProjectProvider, userInfoGetter, projectID, clusterID, &provider.ClusterGetOptions{CheckInitStatus: true})
454503
if err != nil {

modules/api/pkg/handler/v2/provider/openstack.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package provider
1919
import (
2020
"context"
2121
"crypto/x509"
22+
"encoding/json"
2223
"fmt"
2324
"net/http"
2425
"strconv"
@@ -27,6 +28,7 @@ import (
2728
"github.com/go-kit/kit/endpoint"
2829

2930
apiv1 "k8c.io/dashboard/v2/pkg/api/v1"
31+
apiv2 "k8c.io/dashboard/v2/pkg/api/v2"
3032
handlercommon "k8c.io/dashboard/v2/pkg/handler/common"
3133
providercommon "k8c.io/dashboard/v2/pkg/handler/common/provider"
3234
"k8c.io/dashboard/v2/pkg/handler/middleware"
@@ -376,6 +378,47 @@ func OpenstackSubnetPoolEndpoint(seedsGetter provider.SeedsGetter, presetProvide
376378
}
377379
}
378380

381+
func OpenstackMemberSubnetsEndpoint(seedsGetter provider.SeedsGetter, presetProvider provider.PresetProvider,
382+
userInfoGetter provider.UserInfoGetter, caBundle *x509.CertPool) endpoint.Endpoint {
383+
return func(ctx context.Context, request interface{}) (interface{}, error) {
384+
req, ok := request.(OpenstackProjectMemberSubnetReq)
385+
if !ok {
386+
return nil, utilerrors.NewBadRequest("invalid request")
387+
}
388+
389+
userInfo, cred, err := GetOpenstackAuthInfo(ctx, req.OpenstackReq, req.GetProjectID(), userInfoGetter, presetProvider)
390+
if err != nil {
391+
return nil, err
392+
}
393+
394+
loadbalancers, err := providercommon.GetOpenstackLoadBalancers(ctx, userInfo, seedsGetter, cred, req.DatacenterName, req.NetworkID, caBundle)
395+
if err != nil {
396+
return nil, err
397+
}
398+
399+
out := make([]apiv2.OpenStackLoadBalancerPoolMember, 0)
400+
for _, lb := range loadbalancers {
401+
for _, pool := range lb.Pools {
402+
members, err := providercommon.GetOpenstackLoadBalancerPoolMembers(ctx, userInfo, seedsGetter, cred, req.DatacenterName, pool.ID, caBundle)
403+
if err != nil {
404+
return nil, err
405+
}
406+
b, err := json.Marshal(members)
407+
if err != nil {
408+
return nil, err
409+
}
410+
var m []apiv2.OpenStackLoadBalancerPoolMember
411+
if err := json.Unmarshal(b, &m); err != nil {
412+
return nil, err
413+
}
414+
out = append(out, m...)
415+
}
416+
}
417+
418+
return out, nil
419+
}
420+
}
421+
379422
// openstackNoCredentialsReq represent a request for openstack
380423
// swagger:parameters listOpenstackSizesNoCredentialsV2 listOpenstackTenantsNoCredentialsV2 listOpenstackNetworksNoCredentialsV2 listOpenstackSecurityGroupsNoCredentialsV2 listOpenstackAvailabilityZonesNoCredentialsV2 listOpenstackServerGroupsNoCredentials
381424
type openstackNoCredentialsReq struct {
@@ -581,13 +624,20 @@ type OpenstackSubnetReq struct {
581624
NetworkID string `json:"network_id,omitempty"`
582625
}
583626

584-
// OpenstackProjectSubnetReq represent a request for openstack subnets within the context of a KKP project.
585-
// swagger:parameters listProjectOpenstackSubnets
627+
// OpenstackProjectSubnetReq represent a request for openstack subnets (or resources requiring a network_id) within the context of a KKP project.
628+
// swagger:parameters listProjectOpenstackSubnets listProjectOpenstackSubnetTags
586629
type OpenstackProjectSubnetReq struct {
587630
OpenstackSubnetReq
588631
common.ProjectReq
589632
}
590633

634+
// OpenstackProjectMemberSubnetReq represent a request for openstack subnets members within the context of a KKP project.
635+
// swagger:parameters listProjectOpenstackMemberSubnets
636+
type OpenstackProjectMemberSubnetReq struct {
637+
OpenstackSubnetReq
638+
common.ProjectReq
639+
}
640+
591641
func DecodeOpenstackReq(_ context.Context, r *http.Request) (interface{}, error) {
592642
var req OpenstackReq
593643

@@ -702,3 +752,25 @@ func DecodeOpenstackProjectSubnetReq(c context.Context, r *http.Request) (interf
702752
OpenstackSubnetReq: openstackReq.(OpenstackSubnetReq),
703753
}, nil
704754
}
755+
756+
func DecodeOpenstackProjectMemberSubnetReq(c context.Context, r *http.Request) (interface{}, error) {
757+
projectReq, err := common.DecodeProjectRequest(c, r)
758+
if err != nil {
759+
return nil, err
760+
}
761+
762+
openstackReq, err := DecodeOpenstackSubnetReq(c, r)
763+
if err != nil {
764+
return nil, err
765+
}
766+
767+
networkID := r.URL.Query().Get("network_id")
768+
if networkID == "" {
769+
return nil, fmt.Errorf("'network_id' is a required parameter and may not be empty")
770+
}
771+
772+
return OpenstackProjectMemberSubnetReq{
773+
ProjectReq: projectReq.(common.ProjectReq),
774+
OpenstackSubnetReq: openstackReq.(OpenstackSubnetReq),
775+
}, nil
776+
}

0 commit comments

Comments
 (0)