From ad81fbf4367ea87c4e4953b70cfce349530bdccf Mon Sep 17 00:00:00 2001 From: Jakub Dyszkiewicz Date: Fri, 10 Jan 2025 16:07:07 +0100 Subject: [PATCH] feat(inspect): api for retrieving service hostnames (#11865) ## Motivation We want to see hostnames of Mesh*Service in the Global CP. ## Implementation information While we could add new KDSService to retrieve stats of a resource in specific zones and then aggregate this an easier (less expensive to execute, faster, don't depend on the zone) option is to calculate the hostname. We have all the resources in global CP already (because HostnameGenerator from zone is synced to global for visibility). It's just a matter of relabeling properly. ## Supporting documentation Fix https://github.com/kumahq/kuma/issues/10618 --------- Signed-off-by: Jakub Dyszkiewicz --- api/openapi/specs/api.yaml | 91 +++++++++++ api/openapi/types/zz_generated.api.go | 31 ++++ docs/generated/openapi.yaml | 142 +++++++++++++++--- go.mod | 2 +- pkg/api-server/endpoints_table_test.go | 4 + pkg/api-server/inspect_mesh_service.go | 136 +++++++++++++++++ .../invalid_service_hostnames.golden.json | 7 + .../invalid_service_hostnames.input.yaml | 3 + ...ternalservice_hostnames_global.golden.json | 13 ++ ...xternalservice_hostnames_global.input.yaml | 26 ++++ ...tizoneservice_hostnames_global.golden.json | 13 ++ ...ltizoneservice_hostnames_global.input.yaml | 26 ++++ .../meshservice_hostnames_global.golden.json | 13 ++ .../meshservice_hostnames_global.input.yaml | 33 ++++ ...eshservice_hostnames_not_found.golden.json | 7 + ...meshservice_hostnames_not_found.input.yaml | 3 + ...shservice_hostnames_zone_local.golden.json | 13 ++ ...eshservice_hostnames_zone_local.input.yaml | 34 +++++ ...hservice_hostnames_zone_synced.golden.json | 13 ++ ...shservice_hostnames_zone_synced.input.yaml | 33 ++++ 20 files changed, 621 insertions(+), 22 deletions(-) create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.input.yaml create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.golden.json create mode 100644 pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.input.yaml diff --git a/api/openapi/specs/api.yaml b/api/openapi/specs/api.yaml index ad3b041cb7e2..924179e0a1ec 100644 --- a/api/openapi/specs/api.yaml +++ b/api/openapi/specs/api.yaml @@ -174,6 +174,44 @@ paths: $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/Internal' + /meshes/{mesh}/{serviceType}/{serviceName}/_hostnames: + get: + operationId: inspect-hostnames + summary: Returns hostnames for service + description: Returns hostnames for a service + tags: ["Inspect"] + parameters: + - in: path + name: mesh + example: default + schema: + type: string + required: true + description: The mesh the service is part of + - in: path + name: serviceType + example: meshservices + schema: + type: string + enum: [meshservices, meshmultizoneservices, meshexternalservices] + required: true + description: The type of the service + - in: path + name: serviceName + example: redis + schema: + type: string + required: true + description: The name of the service + responses: + '200': + $ref: '#/components/responses/InspectHostnamesResponse' + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: "./common/error_schema.yaml#/components/responses/NotFound" + '500': + $ref: '#/components/responses/Internal' components: schemas: Index: @@ -438,6 +476,42 @@ components: GlobalInsight: allOf: - $ref: '#/components/schemas/schemas-GlobalInsight' + InspectHostnames: + type: object + title: InspectHostnames + description: A list of hostnames + required: [total, items] + properties: + total: + type: integer + example: 200 + items: + type: array + items: + $ref: '#/components/schemas/InspectHostname' + InspectHostname: + type: object + title: InspectHostname + description: An supported hostname along with the zones it exists in + required: [hostname, zones] + properties: + hostname: + type: string + description: Generated hostname + example: redis.redis-system.svc.east.mesh.local + zones: + type: array + items: + $ref: '#/components/schemas/InspectHostnameZone' + InspectHostnameZone: + type: object + title: InspectHostnameZone + description: A name of the zone in which the hostname is available + required: [name] + properties: + name: + type: string + example: east responses: IndexResponse: description: A response for the index endpoint @@ -481,6 +555,15 @@ components: application/json: schema: $ref: '#/components/schemas/InspectRules' + InspectHostnamesResponse: + description: A response containing hostnames that match a service. + content: + application/json: + schema: + $ref: '#/components/schemas/InspectHostnames' + examples: + ResponseForDataplane: + $ref: '#/components/examples/InspectDataplanesForPolicyExample' BadRequest: description: Bad Request content: @@ -571,3 +654,11 @@ components: name: dp-2 labels: k8s.kuma.io/namespace: kuma-system + InspectHostnamesExample: + value: + total: 100 + items: + - hostname: redis.redis-system.svc.east.mesh.local + zones: + - name: east + - name: west diff --git a/api/openapi/types/zz_generated.api.go b/api/openapi/types/zz_generated.api.go index 055f53a21aa3..43f214e2f945 100644 --- a/api/openapi/types/zz_generated.api.go +++ b/api/openapi/types/zz_generated.api.go @@ -20,6 +20,13 @@ const ( Meshgateways InspectDataplanesRulesParamsResourceType = "meshgateways" ) +// Defines values for InspectHostnamesParamsServiceType. +const ( + Meshexternalservices InspectHostnamesParamsServiceType = "meshexternalservices" + Meshmultizoneservices InspectHostnamesParamsServiceType = "meshmultizoneservices" + Meshservices InspectHostnamesParamsServiceType = "meshservices" +) + // BaseStatus defines model for BaseStatus. type BaseStatus struct { Online int `json:"online"` @@ -88,6 +95,24 @@ type InspectDataplanesForPolicy struct { Total int `json:"total"` } +// InspectHostname An supported hostname along with the zones it exists in +type InspectHostname struct { + // Hostname Generated hostname + Hostname string `json:"hostname"` + Zones []InspectHostnameZone `json:"zones"` +} + +// InspectHostnameZone A name of the zone in which the hostname is available +type InspectHostnameZone struct { + Name string `json:"name"` +} + +// InspectHostnames A list of hostnames +type InspectHostnames struct { + Items []InspectHostname `json:"items"` + Total int `json:"total"` +} + // InspectRules A list of rules for a dataplane type InspectRules struct { HttpMatches []externalRef0.HttpMatch `json:"httpMatches"` @@ -186,6 +211,9 @@ type InspectDataplanesConfigResponse = InspectDataplanesConfig // InspectDataplanesForPolicyResponse A list of proxies type InspectDataplanesForPolicyResponse = InspectDataplanesForPolicy +// InspectHostnamesResponse A list of hostnames +type InspectHostnamesResponse = InspectHostnames + // InspectRulesResponse A list of rules for a dataplane type InspectRulesResponse = InspectRules @@ -222,3 +250,6 @@ type InspectResourcesParams struct { // InspectDataplanesRulesParamsResourceType defines parameters for InspectDataplanesRules. type InspectDataplanesRulesParamsResourceType string + +// InspectHostnamesParamsServiceType defines parameters for InspectHostnames. +type InspectHostnamesParamsServiceType string diff --git a/docs/generated/openapi.yaml b/docs/generated/openapi.yaml index 4274df64ec22..bb80984120c4 100644 --- a/docs/generated/openapi.yaml +++ b/docs/generated/openapi.yaml @@ -192,6 +192,48 @@ paths: $ref: '#/components/responses/BadRequest' '500': $ref: '#/components/responses/Internal' + /meshes/{mesh}/{serviceType}/{serviceName}/_hostnames: + get: + operationId: inspect-hostnames + summary: Returns hostnames for service + description: Returns hostnames for a service + tags: + - Inspect + parameters: + - in: path + name: mesh + example: default + schema: + type: string + required: true + description: The mesh the service is part of + - in: path + name: serviceType + example: meshservices + schema: + type: string + enum: + - meshservices + - meshmultizoneservices + - meshexternalservices + required: true + description: The type of the service + - in: path + name: serviceName + example: redis + schema: + type: string + required: true + description: The name of the service + responses: + '200': + $ref: '#/components/responses/InspectHostnamesResponse' + '400': + $ref: '#/components/responses/BadRequest' + '404': + $ref: '#/components/responses/NotFound' + '500': + $ref: '#/components/responses/Internal' /meshes/{mesh}/meshaccesslogs/{name}: get: operationId: get-mal @@ -2628,6 +2670,47 @@ components: GlobalInsight: allOf: - $ref: '#/components/schemas/schemas-GlobalInsight' + InspectHostnames: + type: object + title: InspectHostnames + description: A list of hostnames + required: + - total + - items + properties: + total: + type: integer + example: 200 + items: + type: array + items: + $ref: '#/components/schemas/InspectHostname' + InspectHostname: + type: object + title: InspectHostname + description: An supported hostname along with the zones it exists in + required: + - hostname + - zones + properties: + hostname: + type: string + description: Generated hostname + example: redis.redis-system.svc.east.mesh.local + zones: + type: array + items: + $ref: '#/components/schemas/InspectHostnameZone' + InspectHostnameZone: + type: object + title: InspectHostnameZone + description: A name of the zone in which the hostname is available + required: + - name + properties: + name: + type: string + example: east InvalidParameters: type: object title: Invalid Parameters @@ -2955,6 +3038,21 @@ components: on. value: description: The value to be used within the operations. + NotFoundError: + allOf: + - $ref: '#/components/schemas/Error' + - type: object + properties: + status: + example: 404 + title: + example: Not Found + type: + example: https://httpstatuses.com/404 + instance: + example: kong:trace:1234567890 + detail: + example: Not found MeshAccessLogItem: type: object required: @@ -3598,21 +3696,6 @@ components: request should correct or be aware of. items: type: string - NotFoundError: - allOf: - - $ref: '#/components/schemas/Error' - - type: object - properties: - status: - example: 404 - title: - example: Not Found - type: - example: https://httpstatuses.com/404 - instance: - example: kong:trace:1234567890 - detail: - example: Not found MeshCircuitBreakerItem: type: object required: @@ -13022,6 +13105,15 @@ components: application/json: schema: $ref: '#/components/schemas/InspectRules' + InspectHostnamesResponse: + description: A response containing hostnames that match a service. + content: + application/json: + schema: + $ref: '#/components/schemas/InspectHostnames' + examples: + ResponseForDataplane: + $ref: '#/components/examples/InspectDataplanesForPolicyExample' BadRequest: description: Bad Request content: @@ -13034,6 +13126,12 @@ components: application/problem+json: schema: $ref: '#/components/schemas/Error' + NotFound: + description: Not Found + content: + application/problem+json: + schema: + $ref: '#/components/schemas/NotFoundError' MeshAccessLogItem: description: Successful response content: @@ -13057,12 +13155,6 @@ components: next: type: string description: URL to the next page - NotFound: - description: Not Found - content: - application/problem+json: - schema: - $ref: '#/components/schemas/NotFoundError' MeshCircuitBreakerItem: description: Successful response content: @@ -13625,4 +13717,12 @@ components: name: dp-2 labels: k8s.kuma.io/namespace: kuma-system + InspectHostnamesExample: + value: + total: 100 + items: + - hostname: redis.redis-system.svc.east.mesh.local + zones: + - name: east + - name: west diff --git a/go.mod b/go.mod index a8e485972ab8..95dd5ce07fc3 100644 --- a/go.mod +++ b/go.mod @@ -252,7 +252,7 @@ require ( go.opentelemetry.io/otel/metric v1.33.0 // indirect go.uber.org/atomic v1.10.0 // indirect golang.org/x/crypto v0.31.0 // indirect - golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e // indirect + golang.org/x/exp v0.0.0-20240904232852-e7e105dedf7e golang.org/x/mod v0.22.0 // indirect golang.org/x/oauth2 v0.24.0 // indirect golang.org/x/term v0.27.0 // indirect diff --git a/pkg/api-server/endpoints_table_test.go b/pkg/api-server/endpoints_table_test.go index 0941f239a099..7e922566cb9f 100644 --- a/pkg/api-server/endpoints_table_test.go +++ b/pkg/api-server/endpoints_table_test.go @@ -33,6 +33,10 @@ var _ = Describe("Endpoints", func() { apiTest(inputFile, apiServer, resourceStore) }, test.EntriesForFolder("resources/inspect/policies/_resources/dataplanes")) + DescribeTable("inspect for policies /meshes/{mesh}/{serviceType}/{policyName}/_hostnames", func(inputFile string) { + apiTest(inputFile, apiServer, resourceStore) + }, test.EntriesForFolder("resources/inspect/services/_resources/hostnames")) + DescribeTable("inspect dataplane rules /meshes/{mesh}/dataplanes/{dpName}/_rules", func(inputFile string) { apiTest(inputFile, apiServer, resourceStore) }, test.EntriesForFolder("resources/inspect/dataplanes/_rules")) diff --git a/pkg/api-server/inspect_mesh_service.go b/pkg/api-server/inspect_mesh_service.go index 254b4b173b06..cf443c72636c 100644 --- a/pkg/api-server/inspect_mesh_service.go +++ b/pkg/api-server/inspect_mesh_service.go @@ -1,15 +1,32 @@ package api_server import ( + "fmt" + "sort" + "strings" + "github.com/emicklei/go-restful/v3" + "golang.org/x/exp/maps" + mesh_proto "github.com/kumahq/kuma/api/mesh/v1alpha1" + "github.com/kumahq/kuma/api/openapi/types" "github.com/kumahq/kuma/pkg/core/resources/access" + hostnamegenerator_api "github.com/kumahq/kuma/pkg/core/resources/apis/hostnamegenerator/api/v1alpha1" + "github.com/kumahq/kuma/pkg/core/resources/apis/hostnamegenerator/hostname" core_mesh "github.com/kumahq/kuma/pkg/core/resources/apis/mesh" + meshexternalservice_api "github.com/kumahq/kuma/pkg/core/resources/apis/meshexternalservice/api/v1alpha1" + mes_hostname "github.com/kumahq/kuma/pkg/core/resources/apis/meshexternalservice/hostname" + meshmultizoneservice_api "github.com/kumahq/kuma/pkg/core/resources/apis/meshmultizoneservice/api/v1alpha1" + mzms_hostname "github.com/kumahq/kuma/pkg/core/resources/apis/meshmultizoneservice/hostname" "github.com/kumahq/kuma/pkg/core/resources/apis/meshservice" meshservice_api "github.com/kumahq/kuma/pkg/core/resources/apis/meshservice/api/v1alpha1" + meshservice_hostname "github.com/kumahq/kuma/pkg/core/resources/apis/meshservice/hostname" "github.com/kumahq/kuma/pkg/core/resources/manager" "github.com/kumahq/kuma/pkg/core/resources/model" "github.com/kumahq/kuma/pkg/core/resources/store" + rest_errors "github.com/kumahq/kuma/pkg/core/rest/errors" + "github.com/kumahq/kuma/pkg/core/validators" + util_maps "github.com/kumahq/kuma/pkg/util/maps" ) func addInspectMeshServiceEndpoints( @@ -24,6 +41,13 @@ func addInspectMeshServiceEndpoints( Param(ws.PathParameter("name", "mesh service name").DataType("string")). Param(ws.PathParameter("mesh", "mesh name").DataType("string")), ) + ws.Route( + ws.GET("/meshes/{mesh}/{serviceType}/{name}/_hostnames"). + To(matchingHostnames(rm)). + Doc("inspect service hostnames"). + Param(ws.PathParameter("name", "mesh service name").DataType("string")). + Param(ws.PathParameter("mesh", "mesh name").DataType("string")), + ) } func matchingDataplanesForMeshServices(resManager manager.ResourceManager, resourceAccess access.ResourceAccess) restful.RouteFunction { @@ -43,3 +67,115 @@ func matchingDataplanesForMeshServices(resManager manager.ResourceManager, resou ) } } + +var availableServiceTypes = []string{ + string(types.Meshservices), + string(types.Meshexternalservices), + string(types.Meshmultizoneservices), +} + +func matchingHostnames(resManager manager.ResourceManager) restful.RouteFunction { + generatorsForType := map[types.InspectHostnamesParamsServiceType]hostname.HostnameGenerator{ + types.Meshservices: meshservice_hostname.NewMeshServiceHostnameGenerator(resManager), + types.Meshexternalservices: mes_hostname.NewMeshExternalServiceHostnameGenerator(resManager), + types.Meshmultizoneservices: mzms_hostname.NewMeshMultiZoneServiceHostnameGenerator(resManager), + } + typeDescForType := map[types.InspectHostnamesParamsServiceType]model.ResourceTypeDescriptor{ + types.Meshservices: meshservice_api.MeshServiceResourceTypeDescriptor, + types.Meshexternalservices: meshexternalservice_api.MeshExternalServiceResourceTypeDescriptor, + types.Meshmultizoneservices: meshmultizoneservice_api.MeshMultiZoneServiceResourceTypeDescriptor, + } + + return func(request *restful.Request, response *restful.Response) { + svcName := request.PathParameter("name") + svcMesh := request.PathParameter("mesh") + svcType := types.InspectHostnamesParamsServiceType(request.PathParameter("serviceType")) + + desc, ok := typeDescForType[svcType] + if !ok { + rest_errors.HandleError( + request.Request.Context(), + response, + &validators.ValidationError{}, + fmt.Sprintf("only %q are available for inspection", strings.Join(availableServiceTypes, ",")), + ) + return + } + + svc := desc.NewObject() + if err := resManager.Get(request.Request.Context(), svc, store.GetByKey(svcName, svcMesh)); err != nil { + rest_errors.HandleError(request.Request.Context(), response, err, "could not retrieve service") + return + } + + hostnameGenerators := hostnamegenerator_api.HostnameGeneratorResourceList{} + if err := resManager.List(request.Request.Context(), &hostnameGenerators); err != nil { + rest_errors.HandleError(request.Request.Context(), response, err, "could not retrieve hostname generators") + return + } + + byHostname := map[string][]types.InspectHostnameZone{} + + for _, hg := range hostnameGenerators.Items { + svcZone := model.ZoneOfResource(svc) + hgZone := model.ZoneOfResource(hg) + hgOrigin, _ := model.ResourceOrigin(hg.GetMeta()) + + // rewrite origin to simulate matching from a perspective of a single zone + var origin mesh_proto.ResourceOrigin + if hgOrigin == mesh_proto.ZoneResourceOrigin && hgZone == svcZone { + origin = mesh_proto.ZoneResourceOrigin + } else { + origin = mesh_proto.GlobalResourceOrigin + } + overridden := ResourceMetaWithOverriddenOrigin{ + ResourceMeta: svc.GetMeta(), + origin: origin, + } + svc.SetMeta(overridden) + + host, err := generatorsForType[svcType].GenerateHostname(svcZone, hg, svc) + if err != nil { + rest_errors.HandleError(request.Request.Context(), response, err, "could not generate hostname") + return + } + if host == "" { + // hostname generator did not match the service + continue + } + byHostname[host] = append(byHostname[host], types.InspectHostnameZone{ + Name: svcZone, + }) + } + + resp := types.InspectHostnames{} + for _, host := range util_maps.SortedKeys(byHostname) { + zones := byHostname[host] + sort.Slice(zones, func(i, j int) bool { + return zones[i].Name < zones[j].Name + }) + resp.Items = append(resp.Items, types.InspectHostname{ + Hostname: host, + Zones: zones, + }) + } + resp.Total = len(resp.Items) + if err := response.WriteAsJson(resp); err != nil { + rest_errors.HandleError(request.Request.Context(), response, err, "Failed writing response") + } + } +} + +type ResourceMetaWithOverriddenOrigin struct { + model.ResourceMeta + origin mesh_proto.ResourceOrigin +} + +func (r ResourceMetaWithOverriddenOrigin) GetLabels() map[string]string { + cloned := maps.Clone(r.ResourceMeta.GetLabels()) + if cloned == nil { + cloned = map[string]string{} + } + cloned[mesh_proto.ResourceOriginLabel] = string(r.origin) + return cloned +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.golden.json new file mode 100644 index 000000000000..d12c1cd5e7df --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.golden.json @@ -0,0 +1,7 @@ +{ + "type": "/std-errors", + "status": 400, + "title": "only \"meshservices,meshexternalservices,meshmultizoneservices\" are available for inspection", + "detail": "Resource is not valid", + "details": "Resource is not valid" +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.input.yaml new file mode 100644 index 000000000000..f44275549e1c --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/invalid_service_hostnames.input.yaml @@ -0,0 +1,3 @@ +#/meshes/default/invalidservice/test-server/_hostnames 400 +type: Mesh +name: default diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.golden.json new file mode 100644 index 000000000000..319a79a2f7e0 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.golden.json @@ -0,0 +1,13 @@ +{ + "items": [ + { + "hostname": "mes-1.extsvc.mesh.local", + "zones": [ + { + "name": "mes-1" + } + ] + } + ], + "total": 1 +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.input.yaml new file mode 100644 index 000000000000..0a6df3dadc27 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshexternalservice_hostnames_global.input.yaml @@ -0,0 +1,26 @@ +#/meshes/default/meshexternalservices/mes-1/_hostnames 200 +type: Mesh +name: default +--- +type: MeshExternalService +name: mes-1 +mesh: default +spec: + match: + type: HostnameGenerator + port: 9090 + protocol: http + endpoints: + - address: 127.0.0.1 + port: 8080 +--- +type: HostnameGenerator +name: synced-meshexternalservice +labels: + kuma.io/origin: global +spec: + template: '{{ .DisplayName }}.extsvc.mesh.local' + selector: + meshExternalService: + matchLabels: + kuma.io/origin: global diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.golden.json new file mode 100644 index 000000000000..034eee2a8201 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.golden.json @@ -0,0 +1,13 @@ +{ + "items": [ + { + "hostname": "test-server.mzsvc.mesh.local", + "zones": [ + { + "name": "test-server" + } + ] + } + ], + "total": 1 +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.input.yaml new file mode 100644 index 000000000000..697872207d99 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshmultizoneservice_hostnames_global.input.yaml @@ -0,0 +1,26 @@ +#/meshes/default/meshmultizoneservices/test-server/_hostnames 200 +type: Mesh +name: default +--- +type: MeshMultiZoneService +name: test-server +mesh: default +spec: + selector: + meshService: + matchLabels: + kuma.io/display-name: test-server + ports: + - port: 80 + appProtocol: http +--- +type: HostnameGenerator +name: synced-meshmultizoneservice +labels: + kuma.io/origin: global +spec: + template: '{{ .DisplayName }}.mzsvc.mesh.local' + selector: + meshMultiZoneService: + matchLabels: + kuma.io/origin: global diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.golden.json new file mode 100644 index 000000000000..5320032d85e4 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.golden.json @@ -0,0 +1,13 @@ +{ + "items": [ + { + "hostname": "test-server.svc.west.mesh.local", + "zones": [ + { + "name": "west" + } + ] + } + ], + "total": 1 +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.input.yaml new file mode 100644 index 000000000000..076ebbbda281 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_global.input.yaml @@ -0,0 +1,33 @@ +#/meshes/default/meshservices/test-server-syncedhash/_hostnames 200 +type: Mesh +name: default +--- +type: MeshService +name: test-server-syncedhash +mesh: default +labels: + kuma.io/origin: zone + kuma.io/env: universal + kuma.io/display-name: test-server + kuma.io/zone: west +spec: + selector: + dataplaneTags: + kuma.io/service: test-server + ports: + - port: 80 + targetPort: 80 + appProtocol: http + name: main-port +--- +type: HostnameGenerator +name: synced-mesh-services +labels: + kuma.io/origin: global +spec: + template: '{{ .DisplayName }}.svc.{{ .Zone }}.mesh.local' + selector: + meshService: + matchLabels: + kuma.io/origin: global + kuma.io/env: universal diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.golden.json new file mode 100644 index 000000000000..20dc10117859 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.golden.json @@ -0,0 +1,7 @@ +{ + "type": "/std-errors", + "status": 404, + "title": "could not retrieve service", + "detail": "Not found", + "details": "Not found" +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.input.yaml new file mode 100644 index 000000000000..7bb8e091e35a --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_not_found.input.yaml @@ -0,0 +1,3 @@ +#/meshes/default/meshservices/test-server/_hostnames 404 +type: Mesh +name: default diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.golden.json new file mode 100644 index 000000000000..907a71efa5b3 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.golden.json @@ -0,0 +1,13 @@ +{ + "items": [ + { + "hostname": "test-server.svc.mesh.local", + "zones": [ + { + "name": "east" + } + ] + } + ], + "total": 1 +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.input.yaml new file mode 100644 index 000000000000..dd1590f4add2 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_local.input.yaml @@ -0,0 +1,34 @@ +#/meshes/default/meshservices/test-server/_hostnames 200 +type: Mesh +name: default +--- +type: MeshService +name: test-server +mesh: default +labels: + kuma.io/origin: zone + kuma.io/env: universal + kuma.io/display-name: test-server + kuma.io/zone: east +spec: + selector: + dataplaneTags: + kuma.io/service: test-server + ports: + - port: 80 + targetPort: 80 + appProtocol: http + name: main-port +--- +type: HostnameGenerator +name: local-mesh-services +labels: + kuma.io/origin: zone + kuma.io/zone: east +spec: + template: '{{ .DisplayName }}.svc.mesh.local' + selector: + meshService: + matchLabels: + kuma.io/origin: zone + kuma.io/env: universal diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.golden.json b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.golden.json new file mode 100644 index 000000000000..5320032d85e4 --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.golden.json @@ -0,0 +1,13 @@ +{ + "items": [ + { + "hostname": "test-server.svc.west.mesh.local", + "zones": [ + { + "name": "west" + } + ] + } + ], + "total": 1 +} diff --git a/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.input.yaml b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.input.yaml new file mode 100644 index 000000000000..f715e83a182f --- /dev/null +++ b/pkg/api-server/testdata/resources/inspect/services/_resources/hostnames/meshservice_hostnames_zone_synced.input.yaml @@ -0,0 +1,33 @@ +#/meshes/default/meshservices/test-server-syncedhash/_hostnames 200 +type: Mesh +name: default +--- +type: MeshService +name: test-server-syncedhash +mesh: default +labels: + kuma.io/origin: global + kuma.io/env: universal + kuma.io/display-name: test-server + kuma.io/zone: west +spec: + selector: + dataplaneTags: + kuma.io/service: test-server + ports: + - port: 80 + targetPort: 80 + appProtocol: http + name: main-port +--- +type: HostnameGenerator +name: synced-mesh-services-syncedhash +labels: + kuma.io/origin: global +spec: + template: '{{ .DisplayName }}.svc.{{ .Zone }}.mesh.local' + selector: + meshService: + matchLabels: + kuma.io/origin: global + kuma.io/env: universal