Exemple #1
0
func watchStatus(client client.Client, logger logging.Logger) {
	key, err := types.ToPodUniqueKey(*podUniqueKey)
	if err != nil {
		logger.Fatalf("Could not parse passed pod unique key %q as uuid: %s", *podUniqueKey, err)
	}

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc()
	outCh, err := client.WatchStatus(ctx, key, 1) // 1 so we wait for the key to exist
	if err != nil {
		logger.Fatal(err)
	}

	for i := 0; i < *numIterations; i++ {
		val, ok := <-outCh
		if !ok {
			logger.Fatal("Channel closed unexpectedly")
		}

		if val.Error != nil {
			logger.Fatal(val.Error)
		}

		bytes, err := json.Marshal(val)
		if err != nil {
			logger.Fatal(err)
		}

		fmt.Println(string(bytes))
	}
}
Exemple #2
0
// Deduces a PodUniqueKey from a consul path. This is useful as pod keys are transitioned
// from using node name and pod ID to using UUIDs.
// Input is expected to have 3 '/' separated sections, e.g. 'intent/<node>/<pod_id>' or
// 'intent/<node>/<pod_uuid>' if the prefix is "intent" or "reality"
//
// /hooks is also a valid pod prefix and the key under it will not be a uuid.
func PodUniqueKeyFromConsulPath(consulPath string) (types.PodUniqueKey, error) {
	keyParts := strings.Split(consulPath, "/")
	if len(keyParts) == 0 {
		return "", util.Errorf("Malformed key '%s'", consulPath)
	}

	if keyParts[0] == "hooks" {
		return "", nil
	}

	if len(keyParts) != 3 {
		return "", util.Errorf("Malformed key '%s'", consulPath)
	}

	// Unforunately we can't use kp.INTENT_TREE and kp.REALITY_TREE here because of an import cycle
	if keyParts[0] != "intent" && keyParts[0] != "reality" {
		return "", util.Errorf("Unrecognized key tree '%s' (must be intent or reality)", keyParts[0])
	}

	// Parse() returns nil if the input string does not match the uuid spec
	podUniqueKey, err := types.ToPodUniqueKey(keyParts[2])
	switch {
	case err == types.InvalidUUID:
		// this is okay, it's just a legacy pod
		podUniqueKey = ""
	case err != nil:
		return "", util.Errorf("Could not test whether %s is a valid pod unique key: %s", keyParts[2], err)
	}

	return podUniqueKey, nil
}
Exemple #3
0
func (s store) WatchPodStatus(req *podstore_protos.WatchPodStatusRequest, stream podstore_protos.P2PodStore_WatchPodStatusServer) error {
	if req.StatusNamespace != kp.PreparerPodStatusNamespace.String() {
		// Today this is the only namespace so we just make sure it doesn't diverge from expected
		return grpc.Errorf(codes.InvalidArgument, "%q is not an understood namespace, must be %q", req.StatusNamespace, kp.PreparerPodStatusNamespace)
	}

	podUniqueKey, err := types.ToPodUniqueKey(req.PodUniqueKey)
	if err == types.InvalidUUID {
		return grpc.Errorf(codes.InvalidArgument, "%q does not parse as pod unique key (uuid)", req.PodUniqueKey)
	} else if err != nil {
		return grpc.Errorf(codes.Unavailable, err.Error())
	}

	clientCancel := stream.Context().Done()

	podStatusResultCh := make(chan podStatusResult)
	innerQuit := make(chan struct{})
	defer close(podStatusResultCh)
	waitIndex := req.WaitIndex
	go func() {
		for {
			status, queryMeta, err := s.podStatusStore.WaitForStatus(podUniqueKey, waitIndex)
			select {
			case podStatusResultCh <- podStatusResult{
				status:    status,
				queryMeta: queryMeta,
				err:       err,
			}:
				if err != nil {
					return
				}

				if queryMeta != nil {
					waitIndex = queryMeta.LastIndex
				}
			case <-innerQuit:
				// Client canceled
				return
			}
		}
	}()

	for {
		select {
		case <-clientCancel:
			close(innerQuit)
			return nil
		case result := <-podStatusResultCh:
			resp, err := podStatusResultToResp(result)
			if err != nil {
				return err
			}

			err = stream.Send(resp)
			if err != nil {
				return err
			}
		}
	}
}