Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .changelog/2847.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:feature
kubernetes: Add `kubernetes_endpoint_slice_v1` data source
```
109 changes: 109 additions & 0 deletions docs/data-sources/endpoint_slice_v1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
---
subcategory: "discovery/v1"
page_title: "Kubernetes: kubernetes_endpoint_slice_v1"
description: |-
An EndpointSlice contains references to a set of network endpoints. This data source allows you to pull data about such endpoint slice.
---

# kubernetes_endpoint_slice_v1

An EndpointSlice contains references to a set of network endpoints. This data source allows you to pull data about such endpoint slice.

<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `metadata` (Block List, Min: 1, Max: 1) Standard endpoint_slice's metadata. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#metadata (see [below for nested schema](#nestedblock--metadata))

### Read-Only

- `address_type` (String) address_type specifies the type of address carried by this EndpointSlice. All addresses in this slice must be the same type. This field is immutable after creation.
- `endpoint` (List of Object) endpoint is a list of unique endpoints in this slice. Each slice may include a maximum of 1000 endpoints. (see [below for nested schema](#nestedatt--endpoint))
- `id` (String) The ID of this resource.
- `port` (List of Object) port specifies the list of network ports exposed by each endpoint in this slice. Each port must have a unique name. Each slice may include a maximum of 100 ports. (see [below for nested schema](#nestedatt--port))

<a id="nestedatt--endpoint"></a>
### Nested Schema for `endpoint`

Read-Only:

- `addresses` (List of String) addresses of this endpoint. The contents of this field are interpreted according to the corresponding EndpointSlice addressType field.
- `condition` (List of Object) condition contains information about the current status of the endpoint. (see [below for nested schema](#nestedobjatt--endpoint--condition))
- `hostname` (String) hostname of this endpoint. This field may be used by consumers of endpoints to distinguish endpoints from each other.
- `node_name` (String) nodeName represents the name of the Node hosting this endpoint. This can be used to determine endpoints local to a Node.
- `target_ref` (List of Object) targetRef is a reference to a Kubernetes object that represents this endpoint. (see [below for nested schema](#nestedobjatt--endpoint--target_ref))
- `zone` (String) zone is the name of the Zone this endpoint exists in.

<a id="nestedobjatt--endpoint--condition"></a>
### Nested Schema for `endpoint.condition`

Read-Only:

- `ready` (Boolean) ready indicates that this endpoint is prepared to receive traffic, according to whatever system is managing the endpoint.
- `serving` (Boolean) serving is identical to ready except that it is set regardless of the terminating state of endpoints.
- `terminating` (Boolean) terminating indicates that this endpoint is terminating.


<a id="nestedobjatt--endpoint--target_ref"></a>
### Nested Schema for `endpoint.target_ref`

Read-Only:

- `field_path` (String) If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].
- `name` (String) Name of the referent.
- `namespace` (String) Namespace of the referent.
- `resource_version` (String) Specific resourceVersion to which this reference is made, if any.
- `uid` (String) If referring to a piece of an object instead of an entire object, this string should contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].



<a id="nestedblock--metadata"></a>
### Nested Schema for `metadata`

Optional:

- `annotations` (Map of String) An unstructured key value map stored with the endpoint_slice that may be used to store arbitrary metadata. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
- `generate_name` (String) Prefix, used by the server, to generate a unique name ONLY IF the `name` field has not been provided. This value will also be combined with a unique suffix. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#idempotency
- `labels` (Map of String) Map of string keys and values that can be used to organize and categorize (scope and select) the endpoint_slice. May match selectors of replication controllers and services. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
- `name` (String) Name of the endpoint_slice, must be unique. Cannot be updated. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
- `namespace` (String) Namespace defines the space within which name of the endpoint_slice must be unique.

Read-Only:

- `generation` (Number) A sequence number representing a specific generation of the desired state.
- `resource_version` (String) An opaque value that represents the internal version of this endpoint_slice that can be used by clients to determine when endpoint_slice has changed. More info: https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency
- `uid` (String) The unique in time and space value for this endpoint_slice. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids


<a id="nestedatt--port"></a>
### Nested Schema for `port`

Read-Only:

- `app_protocol` (String) The application protocol for this port. This is used as a hint for implementations to offer richer behavior for protocols that they understand.
- `name` (String) name represents the name of this port. All ports in an EndpointSlice must have a unique name.
- `port` (String) port represents the port number of the endpoint.
- `protocol` (String) protocol represents the IP protocol for this port. Must be UDP, TCP, or SCTP. Default is TCP.




## Example Usage

```terraform
data "kubernetes_endpoint_slice_v1" "example" {
metadata {
name = "example-endpoint-slice"
namespace = "default"
}
}

output "endpoint_addresses" {
value = flatten([
for e in data.kubernetes_endpoint_slice_v1.example.endpoint :
e.addresses if e.condition[0].ready
])
}
```

89 changes: 89 additions & 0 deletions kubernetes/data_source_kubernetes_endpoint_slice_v1.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
// Copyright (c) IBM Corp. 2017, 2026
// SPDX-License-Identifier: MPL-2.0

package kubernetes

import (
"context"
"log"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func dataSourceKubernetesEndpointSliceV1() *schema.Resource {
return &schema.Resource{
Description: "An EndpointSlice contains references to a set of network endpoints. This data source allows you to pull data about such endpoint slice.",
ReadContext: dataSourceKubernetesEndpointSliceV1Read,
Schema: map[string]*schema.Schema{
"metadata": namespacedMetadataSchema("endpoint_slice", true),
"address_type": {
Type: schema.TypeString,
Description: "address_type specifies the type of address carried by this EndpointSlice. All addresses in this slice must be the same type. This field is immutable after creation.",
Computed: true,
},
"endpoint": {
Type: schema.TypeList,
Description: "endpoint is a list of unique endpoints in this slice. Each slice may include a maximum of 1000 endpoints.",
Computed: true,
Elem: schemaEndpointSliceSubsetEndpoints(),
},
"port": {
Type: schema.TypeList,
Description: "port specifies the list of network ports exposed by each endpoint in this slice. Each port must have a unique name. Each slice may include a maximum of 100 ports.",
Computed: true,
Elem: schemaEndpointSliceSubsetPorts(),
},
},
}
}

func dataSourceKubernetesEndpointSliceV1Read(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
conn, err := meta.(KubeClientsets).MainClientset()
if err != nil {
return diag.FromErr(err)
}

metadata := expandMetadata(d.Get("metadata").([]interface{}))

om := metav1.ObjectMeta{
Namespace: metadata.Namespace,
Name: metadata.Name,
}
d.SetId(buildId(om))

log.Printf("[INFO] Reading endpoint slice %s", metadata.Name)
ep, err := conn.DiscoveryV1().EndpointSlices(metadata.Namespace).Get(ctx, metadata.Name, metav1.GetOptions{})
if err != nil {
if apierrors.IsNotFound(err) {
return nil
}
log.Printf("[DEBUG] Received error: %#v", err)
return diag.Errorf("Failed to read endpoint slice because: %s", err)
}
log.Printf("[INFO] Received endpoint slice: %#v", ep)

err = d.Set("metadata", flattenMetadataFields(ep.ObjectMeta))
if err != nil {
return diag.FromErr(err)
}

err = d.Set("address_type", string(ep.AddressType))
if err != nil {
return diag.FromErr(err)
}

err = d.Set("endpoint", flattenEndpointSliceEndpoints(ep.Endpoints))
if err != nil {
return diag.FromErr(err)
}

err = d.Set("port", flattenEndpointSlicePorts(ep.Ports))
if err != nil {
return diag.FromErr(err)
}

return nil
}
109 changes: 109 additions & 0 deletions kubernetes/data_source_kubernetes_endpoint_slice_v1_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// Copyright (c) IBM Corp. 2017, 2026
// SPDX-License-Identifier: MPL-2.0

//nolint:all
package kubernetes

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
)

func TestAccKubernetesDataSourceEndpointSliceV1_basic(t *testing.T) {
resourceName := "kubernetes_endpoint_slice_v1.test"
dataSourceName := "data.kubernetes_endpoint_slice_v1.test"
name := fmt.Sprintf("tf-acc-test-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccKubernetesEndpointSliceV1Config_basic(name),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "metadata.0.name", name),
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.generation"),
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.resource_version"),
resource.TestCheckResourceAttrSet(resourceName, "metadata.0.uid"),
resource.TestCheckResourceAttr(resourceName, "endpoint.#", "1"),
resource.TestCheckResourceAttr(resourceName, "endpoint.0.condition.#", "0"),
resource.TestCheckResourceAttr(resourceName, "endpoint.0.addresses.#", "1"),
resource.TestCheckResourceAttr(resourceName, "endpoint.0.addresses.0", "129.144.50.56"),
resource.TestCheckResourceAttr(resourceName, "port.#", "1"),
resource.TestCheckResourceAttr(resourceName, "port.0.port", "90"),
resource.TestCheckResourceAttr(resourceName, "port.0.name", "first"),
resource.TestCheckResourceAttr(resourceName, "port.0.app_protocol", "test"),
),
},
{
Config: testAccKubernetesEndpointSliceV1Config_modified(name) + testAccKubernetesDataSourceEndpointSliceV1_read(),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "metadata.0.name", name),
resource.TestCheckResourceAttrSet(dataSourceName, "metadata.0.generation"),
resource.TestCheckResourceAttrSet(dataSourceName, "metadata.0.resource_version"),
resource.TestCheckResourceAttrSet(dataSourceName, "metadata.0.uid"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.condition.#", "1"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.condition.0.ready", "true"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.condition.0.serving", "false"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.condition.0.terminating", "false"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.hostname", "test"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.node_name", "test"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.addresses.#", "2"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.target_ref.0.name", "test"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.addresses.0", "2001:db8:3333:4444:5555:6666:7777:8888"),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.0.addresses.1", "2002:db8:3333:4444:5555:6666:7777:8888"),
resource.TestCheckResourceAttr(dataSourceName, "port.#", "2"),
resource.TestCheckResourceAttr(dataSourceName, "port.0.port", "90"),
resource.TestCheckResourceAttr(dataSourceName, "port.0.name", "first"),
resource.TestCheckResourceAttr(dataSourceName, "port.0.app_protocol", "test"),
resource.TestCheckResourceAttr(dataSourceName, "port.1.port", "900"),
resource.TestCheckResourceAttr(dataSourceName, "port.1.name", "second"),
resource.TestCheckResourceAttr(dataSourceName, "port.1.app_protocol", "test"),
resource.TestCheckResourceAttr(dataSourceName, "address_type", "IPv6"),
),
},
},
})
}

func TestAccKubernetesDataSourceEndpointSliceV1_not_found(t *testing.T) {
dataSourceName := "data.kubernetes_endpoint_slice_v1.test"
name := fmt.Sprintf("ceci-n.est-pas-une-endpoint-%s", acctest.RandStringFromCharSet(10, acctest.CharSetAlphaNum))

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccKubernetesDataSourceEndpointSliceV1_nonexistent(name),
Check: resource.ComposeAggregateTestCheckFunc(
resource.TestCheckResourceAttr(dataSourceName, "metadata.0.name", name),
resource.TestCheckResourceAttr(dataSourceName, "endpoint.#", "0"),
resource.TestCheckResourceAttr(dataSourceName, "port.#", "0"),
),
},
},
})
}

func testAccKubernetesDataSourceEndpointSliceV1_read() string {
return `data "kubernetes_endpoint_slice_v1" "test" {
metadata {
name = "${kubernetes_endpoint_slice_v1.test.metadata.0.name}"
}
}
`
}

func testAccKubernetesDataSourceEndpointSliceV1_nonexistent(name string) string {
return fmt.Sprintf(`data "kubernetes_endpoint_slice_v1" "test" {
metadata {
name = "%s"
}
}
`, name)
}
1 change: 1 addition & 0 deletions kubernetes/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ func Provider() *schema.Provider {
"kubernetes_secret": dataSourceKubernetesSecretV1("Deprecated; use kubernetes_secret_v1."),
"kubernetes_secret_v1": dataSourceKubernetesSecretV1(""),
"kubernetes_endpoints_v1": dataSourceKubernetesEndpointsV1(),
"kubernetes_endpoint_slice_v1": dataSourceKubernetesEndpointSliceV1(),
"kubernetes_service": dataSourceKubernetesServiceV1("Deprecated; use kubernetes_service_v1."),
"kubernetes_service_v1": dataSourceKubernetesServiceV1(""),
"kubernetes_pod": dataSourceKubernetesPodV1("Deprecated; use kubernetes_pod_v1."),
Expand Down
Loading