Skip to content

Commit

Permalink
Merge pull request #16 from terraform-providers/f-expose-failure-reasons
Browse files Browse the repository at this point in the history
Expose last warnings from eventlog for Pod+PVC+SVC
  • Loading branch information
radeksimko authored Jul 5, 2017
2 parents d557ad2 + 4aaf4a0 commit a0f1d4e
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 23 deletions.
67 changes: 67 additions & 0 deletions kubernetes/event_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package kubernetes

import (
"fmt"
"log"
"sort"

meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
api "k8s.io/kubernetes/pkg/api/v1"
kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
)

func getLastWarningsForObject(conn *kubernetes.Clientset, metadata meta_v1.ObjectMeta, kind string, limit int) ([]api.Event, error) {
fs := fields.Set(map[string]string{
"involvedObject.name": metadata.Name,
"involvedObject.namespace": metadata.Namespace,
"involvedObject.kind": kind,
}).String()
log.Printf("[DEBUG] Looking up events via this selector: %q", fs)
out, err := conn.CoreV1().Events(metadata.Namespace).List(meta_v1.ListOptions{
FieldSelector: fs,
})
if err != nil {
return nil, err
}

// It would be better to sort & filter on the server-side
// but API doesn't seem to support it
var warnings []api.Event

// Bring latest events to the top, for easy access
sort.Slice(out.Items, func(i, j int) bool {
return out.Items[i].LastTimestamp.After(out.Items[j].LastTimestamp.Time)
})

log.Printf("[DEBUG] Received %d events for %s/%s (%s)",
len(out.Items), metadata.Namespace, metadata.Name, kind)

warnCount := 0
uniqueWarnings := make(map[string]api.Event, 0)
for _, e := range out.Items {
if warnCount >= limit {
break
}

if e.Type == api.EventTypeWarning {
_, found := uniqueWarnings[e.Message]
if found {
continue
}
warnings = append(warnings, e)
uniqueWarnings[e.Message] = e
warnCount++
}
}

return warnings, nil
}

func stringifyEvents(events []api.Event) string {
var output string
for _, e := range events {
output += fmt.Sprintf("\n * %s: %s", e.Reason, e.Message)
}
return output
}
24 changes: 4 additions & 20 deletions kubernetes/resource_kubernetes_persistent_volume_claim.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"k8s.io/apimachinery/pkg/api/errors"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
pkgApi "k8s.io/apimachinery/pkg/types"
api "k8s.io/kubernetes/pkg/api/v1"
kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
Expand Down Expand Up @@ -166,7 +165,6 @@ func resourceKubernetesPersistentVolumeClaimCreate(d *schema.ResourceData, meta
name := out.ObjectMeta.Name

if d.Get("wait_until_bound").(bool) {
var lastEvent api.Event
stateConf := &resource.StateChangeConf{
Target: []string{"Bound"},
Pending: []string{"Pending"},
Expand All @@ -178,32 +176,18 @@ func resourceKubernetesPersistentVolumeClaimCreate(d *schema.ResourceData, meta
return out, "", err
}

events, err := conn.CoreV1().Events(metadata.Namespace).List(meta_v1.ListOptions{
FieldSelector: fields.Set(map[string]string{
"involvedObject.name": metadata.Name,
"involvedObject.namespace": metadata.Namespace,
"involvedObject.kind": "PersistentVolumeClaim",
}).String(),
})
if err != nil {
return out, "", err
}
if len(events.Items) > 0 {
lastEvent = events.Items[0]
}

statusPhase := fmt.Sprintf("%v", out.Status.Phase)
log.Printf("[DEBUG] Persistent volume claim %s status received: %#v", out.Name, statusPhase)
return out, statusPhase, nil
},
}
_, err = stateConf.WaitForState()
if err != nil {
reason := ""
if lastEvent.Reason != "" {
reason = fmt.Sprintf(". Reason: %s: %s", lastEvent.Reason, lastEvent.Message)
lastWarnings, wErr := getLastWarningsForObject(conn, out.ObjectMeta, "PersistentVolumeClaim", 3)
if wErr != nil {
return wErr
}
return fmt.Errorf("%s%s", err, reason)
return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings))
}
}
log.Printf("[INFO] Persistent volume claim %s created", out.Name)
Expand Down
6 changes: 5 additions & 1 deletion kubernetes/resource_kubernetes_pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,11 @@ func resourceKubernetesPodCreate(d *schema.ResourceData, meta interface{}) error
}
_, err = stateConf.WaitForState()
if err != nil {
return err
lastWarnings, wErr := getLastWarningsForObject(conn, out.ObjectMeta, "Pod", 3)
if wErr != nil {
return wErr
}
return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings))
}
log.Printf("[INFO] Pod %s created", out.Name)

Expand Down
8 changes: 6 additions & 2 deletions kubernetes/resource_kubernetes_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,14 @@ func resourceKubernetesServiceCreate(d *schema.ResourceData, meta interface{}) e
}

return resource.RetryableError(fmt.Errorf(
"Waiting for load balancer %q to assign IP/hostname", d.Id()))
"Waiting for service %q to assign IP/hostname for a load balancer", d.Id()))
})
if err != nil {
return err
lastWarnings, wErr := getLastWarningsForObject(conn, out.ObjectMeta, "Service", 3)
if wErr != nil {
return wErr
}
return fmt.Errorf("%s%s", err, stringifyEvents(lastWarnings))
}
}

Expand Down

0 comments on commit a0f1d4e

Please sign in to comment.