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 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
35 changes: 35 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_lifecycle.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
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.
// ConditionType IdentityConfigured is not included in apis.NewLivingConditionSet{}, so it is not counted for conditionReady.
// This is because if Workload Identity is not enabled, IdentityConfigured will be unknown.
// It will be counted for conditionReady only if it is failed.
cs.Manage(s).MarkFalse(apis.ConditionReady, "WorkloadIdentityFailed", messageFormat, messageA...)
}
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)
}
}
54 changes: 54 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
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"
duckv1 "knative.dev/pkg/apis/duck/v1"
)

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
// TODO rename ServiceAccount, issue https://github.com/google/knative-gcp/issues/723
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
}
33 changes: 33 additions & 0 deletions pkg/apis/duck/v1alpha1/identity_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
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 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)
}
}
23 changes: 11 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,16 @@ 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

// CloudEventAttributes are the specific attributes that the Source uses
// as part of its CloudEvents.
// +optional
CloudEventAttributes []duckv1.CloudEventAttributes `json:"ceAttributes,omitempty"`

// ProjectID is the project ID of the Topic, might have been resolved.
// +optional
Expand Down
48 changes: 47 additions & 1 deletion pkg/apis/duck/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 0 additions & 33 deletions pkg/apis/events/v1alpha1/cloudauditlogssource_lifecycle.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package v1alpha1

import (
duckv1alpha1 "github.com/google/knative-gcp/pkg/apis/duck/v1alpha1"
"knative.dev/pkg/apis"
)

Expand All @@ -41,38 +40,6 @@ func (s *CloudAuditLogsSourceStatus) InitializeConditions() {
auditLogsSourceCondSet.Manage(s).InitializeConditions()
}

// MarkPullSubscriptionFailed sets the condition that the status of underlying PullSubscription
grac3gao-zz marked this conversation as resolved.
Show resolved Hide resolved
// is False and why.
func (s *CloudAuditLogsSourceStatus) MarkPullSubscriptionFailed(reason, messageFormat string, messageA ...interface{}) {
auditLogsSourceCondSet.Manage(s).MarkFalse(duckv1alpha1.PullSubscriptionReady, reason, messageFormat, messageA...)
}

// MarkPullSubscriptionUnknown sets the condition that the status of underlying PullSubscription
// is Unknown and why.
func (s *CloudAuditLogsSourceStatus) MarkPullSubscriptionUnknown(reason, messageFormat string, messageA ...interface{}) {
auditLogsSourceCondSet.Manage(s).MarkUnknown(duckv1alpha1.PullSubscriptionReady, reason, messageFormat, messageA...)
}

// MarkPullSubscriptionReady sets the condition that the underlying PullSubscription is ready.
func (s *CloudAuditLogsSourceStatus) MarkPullSubscriptionReady() {
auditLogsSourceCondSet.Manage(s).MarkTrue(duckv1alpha1.PullSubscriptionReady)
}

// MarkTopicFailed sets the condition that the status of PubSub topic is False and why.
func (s *CloudAuditLogsSourceStatus) MarkTopicFailed(reason, messageFormat string, messageA ...interface{}) {
auditLogsSourceCondSet.Manage(s).MarkFalse(duckv1alpha1.TopicReady, reason, messageFormat, messageA...)
}

// MarkTopicUnknown sets the condition that the status of PubSub topic is Unknown and why.
func (s *CloudAuditLogsSourceStatus) MarkTopicUnknown(reason, messageFormat string, messageA ...interface{}) {
auditLogsSourceCondSet.Manage(s).MarkUnknown(duckv1alpha1.TopicReady, reason, messageFormat, messageA...)
}

// MarkTopicReady sets the condition that the underlying PubSub topic was created successfully.
func (s *CloudAuditLogsSourceStatus) MarkTopicReady() {
auditLogsSourceCondSet.Manage(s).MarkTrue(duckv1alpha1.TopicReady)
}

// MarkSinkNotReady sets the condition that a CloudAuditLogsSource pubsub sink
// has not been configured and why.
func (s *CloudAuditLogsSourceStatus) MarkSinkNotReady(reason, messageFormat string, messageA ...interface{}) {
Expand Down
Loading