# some chart that creates a service
resource "helm_release" "some_service" {
name = "some-service"
chart = "nginx"
}
data "kubernetes_service" "some_service" {
metadata {
name = "nginx-svc"
namespace = helm_release.some_service.namespace
}
}
locals {
ports_map = {
for port in data.kubernetes_service.some_service.spec.port :
port.name => port.port
}
}
output "nginx_ports" {
value = local.ports_map
}
Terraform should wait until the helm chart is deployed before reading the data.kubernetes_service data. It might return a null entry for ports or the service might not be created, but I wouldn't expect to see anything until then.
Some sort of modeling check is done and an error like
2020-10-31 03:23:09,139 INFO:Running Terraform plan
2020-10-31 03:23:15,939 WARNING:error: b'\nError: Unsupported attribute\n\n on locals.tf line 16, in locals:\n 16: for port in data.kubernetes_service.some_service.spec.port :\n\nThis value does not have any attributes.\n\n'
2020-10-31 03:23:15,941 INFO:
2020-10-31 03:23:15,942 ERROR:
Error: Unsupported attribute
on locals.tf line 16, in locals:
16: for port in data.kubernetes_service.some_service.spec.port :
This value does not have any attributes.
occurs during the terraform plan stage
terraform planhelm and kubernetes providers rely on variables and additional data sources (pulling info from EKS API)
2020-10-31T03:36:34.291Z [DEBUG] plugin: plugin process exited: path=.terraform/plugins/registry.terraform.io/hashicorp/kubernetes/1.13.3/linux_amd64/terraform-provider-kubernetes_v1.13.3_x4 pid=122
2020-10-31T03:36:34.291Z [DEBUG] plugin: plugin exited
2020/10/31 03:36:34 [TRACE] [walkValidate] Exiting eval tree: provider["registry.terraform.io/hashicorp/kubernetes"] (close)
2020/10/31 03:36:34 [TRACE] vertex "provider[\"registry.terraform.io/hashicorp/kubernetes\"] (close)": visit complete
2020/10/31 03:36:34 [TRACE] dag/walk: upstream of "root" errored, so skipping
https://github.com/hashicorp/terraform-provider-kubernetes/blob/master/kubernetes/data_source_kubernetes_service.go#L58 data.kubernetes_service schema
I have tried a _lot_ of tricks to defer the local variable assignment or data rendering until post-plan stage, but nothing has worked. If anyone has a trick for simply not having terraform plan fail when (I guess) data.kubernetes_service.svc.spec is empty or missing, that'd probably be fine.
facing the same problem. I was trying to get the IP of an existing service.
Update: data.kubernetes_service.istiocoredns.spec[0]["cluster_ip"] worked for me. apparently spec is a collection
terraform state show data.kubernetes_service.istiocoredns
# data.kubernetes_service.istiocoredns:
data "kubernetes_service" "istiocoredns" {
id = "istio-system/istiocoredns"
load_balancer_ingress = []
spec = [
{
cluster_ip = "172.20.174.78"
external_ips = []
external_name = ""
external_traffic_policy = ""
health_check_node_port = 0
load_balancer_ip = ""
load_balancer_source_ranges = []
port = [
{
name = "dns"
node_port = 0
port = 53
protocol = "UDP"
target_port = "53"
},
{
name = "dns-tcp"
node_port = 0
port = 53
protocol = "TCP"
target_port = "53"
},
]
publish_not_ready_addresses = false
selector = {
"app" = "istiocoredns"
}
session_affinity = "None"
type = "ClusterIP"
},
]
metadata {
annotations = {}
generation = 0
labels = {
"app" = "istiocoredns"
"install.operator.istio.io/owning-resource" = "default"
"install.operator.istio.io/owning-resource-namespace" = "istio-system"
"istio.io/rev" = "default"
"operator.istio.io/component" = "AddonComponents"
"operator.istio.io/managed" = "Reconcile"
"operator.istio.io/version" = "1.7.3"
"release" = "istio"
}
name = "istiocoredns"
namespace = "istio-system"
resource_version = "1822"
self_link = "/api/v1/namespaces/istio-system/services/istiocoredns"
uid = "274de930-7b2b-4357-b525-1a300a15e12c"
}
}
@mariadb-JeffBachtel does it work if you try adding the 0 after spec, like @ishansd94 showed us? That worked for me.
Here is the reproducer I used, which includes a resource containing a spec (the contents are unknown until after terraform plan):
resource "kubernetes_persistent_volume_claim" "test" {
metadata {
name = "testpv"
}
spec {
access_modes = ["ReadWriteOnce"]
resources {
requests = {
storage = "1Gi"
}
}
}
}
data "kubernetes_persistent_volume_claim" "test" {
metadata {
name = kubernetes_persistent_volume_claim.test.metadata[0].name
}
}
output "volume_name" {
value = kubernetes_persistent_volume_claim.test.spec.0.volume_name
}
As you can see in the output below, it creates the resource first, and then reads it, since the field I'm referencing is unknown at plan time. By referencing a field that doesn't exist until the resource is created, we can effectively defer the data source read (otherwise the data source would be evaluated before the resource is created):
$ terraform apply --auto-approve
kubernetes_persistent_volume_claim.test: Creating...
kubernetes_persistent_volume_claim.test: Creation complete after 0s [id=default/testpv]
data.kubernetes_persistent_volume_claim.test: Reading...
data.kubernetes_persistent_volume_claim.test: Read complete after 0s [id=default/testpv]
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
Outputs:
volume_name = "pvc-2bf2fd0b-9fd1-43bd-9aaf-1c9623351f67"
I think this is already what you're doing. Offhand, I'm guessing the field name just needs to be changed from data.kubernetes_service.some_service.spec.port to data.kubernetes_service.some_service.spec.0.port.0.port.
I got that specific path by looking at one of the tests that checks for that field:
Which is created by this terraform config:
(Using terraform show on a resource can also help to construct that path).
I think y'all are correct. Can this be converted to a Documentation issue? The docs for the attributes for the kubernetes_service data source are...kinda bad (no indication spec is a collection, no example of accessing any subattribute from it, weird order that kinda implies port should be at the same level as spec and metadata).
Thanks a ton for your help, though
Related upstream docs issue. https://github.com/hashicorp/terraform-website/issues/1495 (But we still want to create our own docs for this too).
@dak1n1 , I would like to help with the documentation, but I'm not sure how to process the Markdown files in order to produce the result that we can see at https://registry.terraform.io. I quickly went through contributing guidelines but couldn't find further information.
I suppose that part of this documentation is extracted from the *.go files since there is this kubernetes.erb file in the repo, but that's it. :-)
@glasswalk3r Thanks for your interest in this! Here's where you can find the docs file for the service data source: https://github.com/hashicorp/terraform-provider-kubernetes/blob/main/website/docs/d/service.html.markdown
The service resource lives here:
It should show you a preview in github, which can help check that your markdown syntax is correct. Another way to check is by running make website-lint and make website-lint-fix. (That linter will also run when you open a PR).
Other than that, it's just magic on the release engineering side that will deploy it to the Terraform Registry website. That will happen automatically when a new version of the provider is released (which happens at most once per week).
@dak1n1 , since this is my first PR for this project, I created it as a draft. Please review and let me know if I need to change something else.
Most helpful comment
I think y'all are correct. Can this be converted to a Documentation issue? The docs for the attributes for the
kubernetes_servicedata source are...kinda bad (no indicationspecis a collection, no example of accessing any subattribute from it, weird order that kinda impliesportshould be at the same level asspecandmetadata).Thanks a ton for your help, though