Skip to content
This repository has been archived by the owner on Jun 19, 2022. It is now read-only.

Add Workload Identity status condition #714

Merged
merged 9 commits into from
Mar 27, 2020
Merged
Show file tree
Hide file tree
Changes from 5 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
32 changes: 32 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_lifecycle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"knative.dev/pkg/apis"
)

func (s *IdentityStatus) MarkWorkloadIdentityConfigured(cs *apis.ConditionSet) {
cs.Manage(s).MarkTrue(IdentityConfigured)
}

func (s *IdentityStatus) MarkWorkloadIdentityNotConfigured(cs *apis.ConditionSet, reason, messageFormat string, messageA ...interface{}) {
cs.Manage(s).MarkUnknown(IdentityConfigured, reason, messageFormat, messageA...)
}

func (s *IdentityStatus) MarkWorkloadIdentityFailed(cs *apis.ConditionSet, reason, messageFormat string, messageA ...interface{}) {
cs.Manage(s).MarkFalse(IdentityConfigured, reason, messageFormat, messageA...)
// Set ConditionReady to be false.
cs.Manage(s).MarkFalse(apis.ConditionReady, "WorkloadIdentityFailed", messageFormat, messageA...)
grac3gao-zz marked this conversation as resolved.
Show resolved Hide resolved
}
55 changes: 55 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_lifecycle_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2020 Google LLC.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"knative.dev/pkg/apis"
"testing"
)

func TestMarkWorkloadIdentityConfigured(t *testing.T) {
status := &IdentityStatus{}
condSet := apis.NewLivingConditionSet()
status.MarkWorkloadIdentityConfigured(&condSet)
got := status.IsReady()
want := true
if got != want {
t.Errorf("unexpected readiness: want %v, got %v", want, got)
}
}

func TestMarkWorkloadIdentityNotConfigured(t *testing.T) {
status := &IdentityStatus{}
condSet := apis.NewLivingConditionSet()
status.MarkWorkloadIdentityFailed(&condSet, "failed", "failed")
got := status.IsReady()
want := false
if got != want {
t.Errorf("unexpected readiness: want %v, got %v", want, got)
}
}

func TestMarkWorkloadIdentityFailed(t *testing.T) {
status := &IdentityStatus{}
condSet := apis.NewLivingConditionSet()
status.MarkWorkloadIdentityNotConfigured(&condSet, "failed", "failed")
got := status.IsReady()
want := true
if got != false {
t.Errorf("unexpected readiness: want %v, got %v", want, got)
}
}
102 changes: 102 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
Copyright 2020 Google LLC
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"

"knative.dev/pkg/apis"
"knative.dev/pkg/apis/duck"
duckv1 "knative.dev/pkg/apis/duck/v1"
)

// Identity is an Implementable "duck type".
var _ duck.Implementable = (*Identity)(nil)

// +genduck
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

type Identity struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

Spec IdentitySpec `json:"spec"`
Status IdentityStatus `json:"status"`
}
nachocano marked this conversation as resolved.
Show resolved Hide resolved

type IdentitySpec struct {
// ServiceAccount is the GCP service account which has required permissions to poll from a Cloud Pub/Sub subscription.
// If not specified, defaults to use secret.
// +optional
ServiceAccount string `json:"serviceAccount,omitempty"`
grac3gao-zz marked this conversation as resolved.
Show resolved Hide resolved
}

// IdentityStatus inherits duck/v1 Status and adds a ServiceAccountName.
type IdentityStatus struct {
// Inherits duck/v1 Status,, which currently provides:
// * ObservedGeneration - the 'Generation' of the Service that was last processed by the controller.
// * Conditions - the latest available observations of a resource's current state.
duckv1.Status `json:",inline"`
// ServiceAccountName is the k8s service account associated with Google service account.
ServiceAccountName string `json:"serviceAccountName,omitempty"`
nachocano marked this conversation as resolved.
Show resolved Hide resolved
}

const (
IdentityConfigured apis.ConditionType = "WorkloadIdentityConfigured"
)

// IsReady returns true if the resource is ready overall.
func (ss *IdentityStatus) IsReady() bool {
grac3gao-zz marked this conversation as resolved.
Show resolved Hide resolved
for _, c := range ss.Conditions {
switch c.Type {
// Look for the "happy" condition, which is the only condition that
// we can reliably understand to be the overall state of the resource.
case apis.ConditionReady, apis.ConditionSucceeded:
return c.IsTrue()
}
}
return false
}

var (
// Verify Identity resources meet duck contracts.
_ duck.Populatable = (*Identity)(nil)
_ apis.Listable = (*Identity)(nil)
)

// GetFullType implements duck.Implementable
func (*Identity) GetFullType() duck.Populatable {
return &Identity{}
}

// Populate implements duck.Populatable
func (s *Identity) Populate() {
s.Spec.ServiceAccount = ""
}

// GetListType implements apis.Listable
func (*Identity) GetListType() runtime.Object {
return &IdentityList{}
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// IdentityList is a list of Identity resources
type IdentityList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata"`

Items []Identity `json:"items"`
}
nachocano marked this conversation as resolved.
Show resolved Hide resolved
67 changes: 67 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
Copyright 2020 Google LLC.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package v1alpha1

import (
"github.com/google/go-cmp/cmp"
"testing"
)

func TestIdentityGetListType(t *testing.T) {
c := &Identity{}
switch c.GetListType().(type) {
case *IdentityList:
// expected
default:
t.Errorf("expected GetListType to return *ChannelableList, got %T", c.GetListType())
}
}

func TestIdentityPopulate(t *testing.T) {
got := &Identity{}
want := &Identity{
Spec: IdentitySpec{},
}

got.Populate()

if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("Unexpected difference (-want, +got): %v", diff)
}
}

func TestGetFullType(t *testing.T) {
got := &Identity{}
want := &Identity{}

got.GetFullType()

if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("Unexpected difference (-want, +got): %v", diff)
}
}

func TestIsReady(t *testing.T) {
status := &IdentityStatus{}
want := false

got := status.IsReady()

if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("Unexpected difference (-want, +got): %v", diff)
}
}
18 changes: 6 additions & 12 deletions pkg/apis/duck/v1alpha1/pubsub_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,7 @@ type PubSubSpec struct {
// This brings in CloudEventOverrides and Sink.
duckv1.SourceSpec `json:",inline"`

// ServiceAccount is the GCP service account which has required permissions to poll from a Cloud Pub/Sub subscription.
// If not specified, defaults to use secret.
// +optional
ServiceAccount string `json:"serviceAccount,omitempty"`
IdentitySpec `json:",inline"`

// Secret is the credential to use to poll from a Cloud Pub/Sub subscription.
// If not specified, defaults to:
Expand All @@ -71,14 +68,11 @@ type PubSubSpec struct {
// PubSubStatus shows how we expect folks to embed Addressable in
// their Status field.
type PubSubStatus struct {
// inherits duck/v1 SourceStatus, which currently provides:
// * ObservedGeneration - the 'Generation' of the Service that was last
// processed by the controller.
// * Conditions - the latest available observations of a resource's current
// state.
// * SinkURI - the current active sink URI that has been configured for the
// Source.
duckv1.SourceStatus `json:",inline"`
IdentityStatus `json:",inline"`

// SinkURI is the current active sink URI that has been configured for the Source.
// +optional
SinkURI *apis.URL `json:"sinkUri,omitempty"`
grac3gao-zz marked this conversation as resolved.
Show resolved Hide resolved

// ProjectID is the project ID of the Topic, might have been resolved.
// +optional
Expand Down
Loading