diff --git a/.github/actions/constellation_measure/action.yml b/.github/actions/constellation_measure/action.yml index 84f058985..fde20c88f 100644 --- a/.github/actions/constellation_measure/action.yml +++ b/.github/actions/constellation_measure/action.yml @@ -43,14 +43,14 @@ runs: run: | case $CSP in azure) - FIRST_NODE=$(jq -r ".azurebootstrappers | keys | first" constellation-state.json) - CONSTELL_IP=$(jq -r ".azurebootstrappers.\"${FIRST_NODE}\".PublicIP" constellation-state.json) + FIRST_NODE=$(jq -r ".azurecontrolplanes | keys | first" constellation-state.json) + CONSTELL_IP=$(jq -r ".azurecontrolplanes.\"${FIRST_NODE}\".PublicIP" constellation-state.json) pcr-reader --constell-ip ${CONSTELL_IP} -format yaml > measurements.yaml yq e 'del(.[0,6,10,11,12,13,14,15,16,17,18,19,20,21,22,23])' -i measurements.yaml ;; gcp) - FIRST_NODE=$(jq -r ".gcpbootstrappers | keys | first" constellation-state.json) - CONSTELL_IP=$(jq -r ".gcpbootstrappers.\"${FIRST_NODE}\".PublicIP" constellation-state.json) + FIRST_NODE=$(jq -r ".gcpcontrolplanes | keys | first" constellation-state.json) + CONSTELL_IP=$(jq -r ".gcpcontrolplanes.\"${FIRST_NODE}\".PublicIP" constellation-state.json) pcr-reader --constell-ip ${CONSTELL_IP} -format yaml > measurements.yaml yq e 'del(.[11,12,13,14,15,16,17,18,19,20,21,22,23])' -i measurements.yaml ;; diff --git a/CHANGELOG.md b/CHANGELOG.md index 0564e623f..0e1131814 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - User facing WireGuard VPN ### Fixed +- Correctly wait for `bootstrapper` to come online in `constellation init` ### Security - Create Kubernetes CA signed kubelet certificates on activation. diff --git a/internal/grpc/retry/retry.go b/internal/grpc/retry/retry.go index f7f04f4a9..8a1c61dfb 100644 --- a/internal/grpc/retry/retry.go +++ b/internal/grpc/retry/retry.go @@ -2,6 +2,7 @@ package retry import ( "context" + "errors" "strings" "time" @@ -52,13 +53,25 @@ func (r *IntervalRetrier) Do(ctx context.Context) error { // serviceIsUnavailable checks if the error is a grpc status with code Unavailable. // In the special case of an authentication handshake failure, false is returned to prevent further retries. func (r *IntervalRetrier) serviceIsUnavailable(err error) bool { - statusErr, ok := status.FromError(err) + // taken from google.golang.org/grpc/status.FromError + var targetErr interface { + GRPCStatus() *status.Status + Error() string + } + + if !errors.As(err, &targetErr) { + return false + } + + statusErr, ok := status.FromError(targetErr) if !ok { return false } + if statusErr.Code() != codes.Unavailable { return false } + // ideally we would check the error type directly, but grpc only provides a string return !strings.HasPrefix(statusErr.Message(), `connection error: desc = "transport: authentication handshake failed`) } diff --git a/internal/grpc/retry/retry_test.go b/internal/grpc/retry/retry_test.go index 344e11116..df2087896 100644 --- a/internal/grpc/retry/retry_test.go +++ b/internal/grpc/retry/retry_test.go @@ -3,6 +3,7 @@ package retry import ( "context" "errors" + "fmt" "testing" "time" @@ -99,6 +100,13 @@ func TestServiceIsUnavailable(t *testing.T) { err: status.Error(codes.Unavailable, "error"), wantUnavailable: true, }, + "wrapped error": { + err: fmt.Errorf("some wrapping: %w", status.Error(codes.Unavailable, "error")), + wantUnavailable: true, + }, + "code unknown": { + err: status.Error(codes.Unknown, "unknown"), + }, } for name, tc := range testCases {