Skip to content

Commit

Permalink
resolve refs and refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
gemmahou committed Jul 25, 2024
1 parent 1d676e1 commit 0e8e619
Show file tree
Hide file tree
Showing 14 changed files with 283 additions and 307 deletions.
92 changes: 0 additions & 92 deletions apis/refs/v1beta1/projectref.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,6 @@

package v1beta1

import (
"context"
"fmt"
"strings"

"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
)

// The Project that this resource belongs to.
type ProjectRef struct {
/* The `projectID` field of a project, when not managed by KCC. */
Expand All @@ -39,82 +26,3 @@ type ProjectRef struct {
// +optional
Kind string `json:"kind,omitempty"`
}

// AsProjectRef converts a generic ResourceRef into a ProjectRef
func AsProjectRef(in *v1alpha1.ResourceRef) *ProjectRef {
if in == nil {
return nil
}
return &ProjectRef{
Namespace: in.Namespace,
Name: in.Name,
External: in.External,
Kind: in.Kind,
}
}

type Project struct {
ProjectID string
}

// ResolveProject will resolve a ProjectRef to a Project, with the ProjectID.
func ResolveProject(ctx context.Context, reader client.Reader, src client.Object, ref *ProjectRef) (*Project, error) {
if ref == nil {
return nil, nil
}

if ref.Kind != "" {
if ref.Kind != "Project" {
return nil, fmt.Errorf("kind is optional on project reference, but must be \"Project\" if provided")
}
}

if ref.External != "" {
if ref.Name != "" {
return nil, fmt.Errorf("cannot specify both name and external on project reference")
}

tokens := strings.Split(ref.External, "/")
if len(tokens) == 1 {
return &Project{ProjectID: tokens[0]}, nil
}
if len(tokens) == 2 && tokens[0] == "projects" {
return &Project{ProjectID: tokens[1]}, nil
}
return nil, fmt.Errorf("format of project external=%q was not known (use projects/<projectId> or <projectId>)", ref.External)
}

if ref.Name == "" {
return nil, fmt.Errorf("must specify either name or external on project reference")
}

key := types.NamespacedName{
Namespace: ref.Namespace,
Name: ref.Name,
}
if key.Namespace == "" {
key.Namespace = src.GetNamespace()
}

project := &unstructured.Unstructured{}
project.SetGroupVersionKind(schema.GroupVersionKind{
Group: "resourcemanager.cnrm.cloud.google.com",
Version: "v1beta1",
Kind: "Project",
})
if err := reader.Get(ctx, key, project); err != nil {
if apierrors.IsNotFound(err) {
return nil, fmt.Errorf("referenced Project %v not found", key)
}
return nil, fmt.Errorf("error reading referenced Project %v: %w", key, err)
}

projectID, err := GetResourceID(project)
if err != nil {
return nil, err
}

return &Project{
ProjectID: projectID,
}, nil
}
126 changes: 0 additions & 126 deletions apis/refs/v1beta1/resourceref.go

This file was deleted.

78 changes: 20 additions & 58 deletions apis/refs/v1beta1/util.go → pkg/controller/direct/adapterutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,57 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.

package v1beta1
package direct

import (
"context"
"fmt"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/clients/generated/apis/k8s/v1alpha1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/types"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/resolverefs"

"github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client"

"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)

func ValidateResourceRef(ref *v1alpha1.ResourceRef) error {
if ref == nil {
return nil
}
if ref.Name == "" && ref.External == "" {
return fmt.Errorf("must specify either name or external on reference")
}
if ref.Name != "" && ref.External != "" {
return fmt.Errorf("cannot specify both name and external on reference")
}
return nil
}

func ParseResourceRef(ctx context.Context, reader client.Reader, src client.Object, ref *v1alpha1.ResourceRef, group, version, kind string) (*unstructured.Unstructured, error) {
key := types.NamespacedName{
Namespace: ref.Namespace,
Name: ref.Name,
}
if key.Namespace == "" {
key.Namespace = src.GetNamespace()
}

resource := &unstructured.Unstructured{}
resource.SetGroupVersionKind(schema.GroupVersionKind{
Group: group,
Version: version,
Kind: kind,
})
if err := reader.Get(ctx, key, resource); err != nil {
if apierrors.IsNotFound(err) {
return nil, fmt.Errorf("referenced %s %v not found", kind, key)
}
return nil, fmt.Errorf("error reading referenced %s %v: %w", kind, key, err)
}
return resource, nil
}

func GetResourceID(u *unstructured.Unstructured) (string, error) {
resourceID, _, err := unstructured.NestedString(u.Object, "spec", "resourceID")
if err != nil {
Expand All @@ -74,14 +36,26 @@ func GetResourceID(u *unstructured.Unstructured) (string, error) {
return resourceID, nil
}

// todo(yuhou): Location can be optional. Use default location when it's unset.
func GetLocation(obj *unstructured.Unstructured) (string, error) {
location, _, err := unstructured.NestedString(obj.Object, "spec", "location")
if err != nil {
return "", fmt.Errorf("cannot get location for referenced %s %v: %w", obj.GetKind(), obj.GetNamespace(), err)
}
if location == "" {
return "", fmt.Errorf("cannot get location for referenced %s %v (spec.location not set)", obj.GetKind(), obj.GetNamespace())
}
return location, nil
}

func GetProjectID(ctx context.Context, reader client.Reader, obj *unstructured.Unstructured) (string, error) {
projectRefExternal, _, _ := unstructured.NestedString(obj.Object, "spec", "projectRef", "external")
if projectRefExternal != "" {
projectRef := ProjectRef{
projectRef := v1beta1.ProjectRef{
External: projectRefExternal,
}

project, err := ResolveProject(ctx, reader, obj, &projectRef)
project, err := resolverefs.ResolveProjectRef(ctx, reader, obj, &projectRef)
if err != nil {
return "", fmt.Errorf("cannot parse projectRef.external %q in %v %v/%v: %w", projectRefExternal, obj.GetKind(), obj.GetNamespace(), obj.GetName(), err)
}
Expand All @@ -92,15 +66,15 @@ func GetProjectID(ctx context.Context, reader client.Reader, obj *unstructured.U
if projectRefName != "" {
projectRefNamespace, _, _ := unstructured.NestedString(obj.Object, "spec", "projectRef", "namespace")

projectRef := ProjectRef{
projectRef := v1beta1.ProjectRef{
Name: projectRefName,
Namespace: projectRefNamespace,
}
if projectRef.Namespace == "" {
projectRef.Namespace = obj.GetNamespace()
}

project, err := ResolveProject(ctx, reader, obj, &projectRef)
project, err := resolverefs.ResolveProjectRef(ctx, reader, obj, &projectRef)
if err != nil {
return "", fmt.Errorf("cannot parse projectRef in %v %v/%v: %w", obj.GetKind(), obj.GetNamespace(), obj.GetName(), err)
}
Expand All @@ -113,15 +87,3 @@ func GetProjectID(ctx context.Context, reader client.Reader, obj *unstructured.U

return "", fmt.Errorf("cannot find project id for %v %v/%v", obj.GetKind(), obj.GetNamespace(), obj.GetName())
}

// todo(yuhou): Location can be optional. Use default location when it's unset.
func GetLocation(obj *unstructured.Unstructured) (string, error) {
location, _, err := unstructured.NestedString(obj.Object, "spec", "location")
if err != nil {
return "", fmt.Errorf("cannot get location for referenced %s %v: %w", obj.GetKind(), obj.GetNamespace(), err)
}
if location == "" {
return "", fmt.Errorf("cannot get location for referenced %s %v (spec.location not set)", obj.GetKind(), obj.GetNamespace())
}
return location, nil
}
7 changes: 4 additions & 3 deletions pkg/controller/direct/cloudbuild/workerpool_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import (
"reflect"
"strings"

"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/resolverefs"

gcp "cloud.google.com/go/cloudbuild/apiv1/v2"
cloudbuildpb "cloud.google.com/go/cloudbuild/apiv1/v2/cloudbuildpb"
"google.golang.org/api/option"

krm "github.com/GoogleCloudPlatform/k8s-config-connector/apis/cloudbuild/v1beta1"
refs "github.com/GoogleCloudPlatform/k8s-config-connector/apis/refs/v1beta1"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/config"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/controller/direct/directbase"
Expand Down Expand Up @@ -90,7 +91,7 @@ func (m *model) AdapterForObject(ctx context.Context, reader client.Reader, u *u
}

// Get GCP Project
projectRef, err := refs.ResolveProject(ctx, reader, obj, obj.Spec.ProjectRef)
projectRef, err := resolverefs.ResolveProjectRef(ctx, reader, obj, obj.Spec.ProjectRef)
if err != nil {
return nil, err
}
Expand All @@ -104,7 +105,7 @@ func (m *model) AdapterForObject(ctx context.Context, reader client.Reader, u *u

// Get computeNetwork
if obj.Spec.PrivatePoolConfig.NetworkConfig != nil {
networkRef, err := refs.ResolveComputeNetwork(ctx, reader, obj, &obj.Spec.PrivatePoolConfig.NetworkConfig.PeeredNetworkRef)
networkRef, err := resolverefs.ResolveComputeNetworkRef(ctx, reader, obj, &obj.Spec.PrivatePoolConfig.NetworkConfig.PeeredNetworkRef)
if err != nil {
return nil, err

Expand Down
Loading

0 comments on commit 0e8e619

Please sign in to comment.