Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

resource/kubernetes_service: Wait for LoadBalancer ingress #12

Merged
merged 2 commits into from
Jun 28, 2017
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
48 changes: 48 additions & 0 deletions kubernetes/resource_kubernetes_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ package kubernetes
import (
"fmt"
"log"
"time"

"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
"k8s.io/apimachinery/pkg/api/errors"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -120,6 +122,22 @@ func resourceKubernetesService() *schema.Resource {
},
},
},
"load_balancer_ingress": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Computed: true,
},
"hostname": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
},
}
}
Expand All @@ -140,6 +158,31 @@ func resourceKubernetesServiceCreate(d *schema.ResourceData, meta interface{}) e
log.Printf("[INFO] Submitted new service: %#v", out)
d.SetId(buildId(out.ObjectMeta))

if out.Spec.Type == api.ServiceTypeLoadBalancer {
log.Printf("[DEBUG] Waiting for load balancer to assign IP/hostname")

err = resource.Retry(5*time.Minute, func() *resource.RetryError {
svc, err := conn.CoreV1().Services(out.Namespace).Get(out.Name, meta_v1.GetOptions{})
if err != nil {
log.Printf("[DEBUG] Received error: %#v", err)
return resource.NonRetryableError(err)
}

lbIngress := svc.Status.LoadBalancer.Ingress
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to check the status code before acting, or will the Get method above handle returning an error for a non-ok status code?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As discussed via Slack - in case the service suddenly doesn't exist it would get caught by the err check above, if the creation of LB failed then we'd time out after 5 mins. Exposing the reason of failed creation in the timeout error message is a job for a separate PR.


log.Printf("[INFO] Received service status: %#v", svc.Status)
if len(lbIngress) > 0 {
return nil
}

return resource.RetryableError(fmt.Errorf(
"Waiting for load balancer %q to assign IP/hostname", d.Id()))
})
if err != nil {
return err
}
}

return resourceKubernetesServiceRead(d, meta)
}

Expand All @@ -159,6 +202,11 @@ func resourceKubernetesServiceRead(d *schema.ResourceData, meta interface{}) err
return err
}

err = d.Set("load_balancer_ingress", flattenLoadBalancerIngress(svc.Status.LoadBalancer.Ingress))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add a test to check this value?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The K8S always returned empty struct consistently - i.e. svc.Status was never nil so I don't think so.

if err != nil {
return err
}

flattened := flattenServiceSpec(svc.Spec)
log.Printf("[DEBUG] Flattened service spec: %#v", flattened)
err = d.Set("spec", flattened)
Expand Down
4 changes: 0 additions & 4 deletions kubernetes/resource_kubernetes_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,6 @@ func TestAccKubernetesService_loadBalancer(t *testing.T) {
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.1452553500", "10.0.0.4"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.3371212991", "10.0.0.3"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "ext-name-"+name),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_ip", "12.0.0.120"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.#", "2"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.138364083", "10.0.0.5/32"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.445311837", "10.0.0.6/32"),
Expand Down Expand Up @@ -140,7 +139,6 @@ func TestAccKubernetesService_loadBalancer(t *testing.T) {
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.1452553500", "10.0.0.4"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_ips.563283338", "10.0.0.5"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.external_name", "ext-name-modified-"+name),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_ip", "12.0.0.125"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.#", "2"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.2271073252", "10.0.0.1/32"),
resource.TestCheckResourceAttr("kubernetes_service.test", "spec.0.load_balancer_source_ranges.2515041290", "10.0.0.2/32"),
Expand Down Expand Up @@ -415,7 +413,6 @@ resource "kubernetes_service" "test" {
spec {
external_name = "ext-name-%s"
external_ips = ["10.0.0.3", "10.0.0.4"]
load_balancer_ip = "12.0.0.120"
load_balancer_source_ranges = ["10.0.0.5/32", "10.0.0.6/32"]
selector {
App = "MyApp"
Expand All @@ -439,7 +436,6 @@ resource "kubernetes_service" "test" {
spec {
external_name = "ext-name-modified-%s"
external_ips = ["10.0.0.4", "10.0.0.5"]
load_balancer_ip = "12.0.0.125"
load_balancer_source_ranges = ["10.0.0.1/32", "10.0.0.2/32"]
selector {
App = "MyModifiedApp"
Expand Down
13 changes: 13 additions & 0 deletions kubernetes/structure_service_spec.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,19 @@ func flattenServiceSpec(in v1.ServiceSpec) []interface{} {
return []interface{}{att}
}

func flattenLoadBalancerIngress(in []v1.LoadBalancerIngress) []interface{} {
out := make([]interface{}, len(in), len(in))
for i, ingress := range in {
att := make(map[string]interface{})

att["ip"] = ingress.IP
att["hostname"] = ingress.Hostname

out[i] = att
}
return out
}

// Expanders

func expandIntOrString(in int) intstr.IntOrString {
Expand Down