Skip to content

Commit

Permalink
Merge pull request #50 from ravi-shankar-sap/main
Browse files Browse the repository at this point in the history
GCP Nfs Reconciliation
  • Loading branch information
kyma-bot authored Jan 22, 2024
2 parents 2c9db43 + 1527ef8 commit 2978f73
Show file tree
Hide file tree
Showing 13 changed files with 356 additions and 6 deletions.
39 changes: 39 additions & 0 deletions components/kcp/api/cloud-control/v1beta1/nfsinstance_gcp_types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package v1beta1

type NfsOptionsGcp struct {
// +kubebuilder:validation:Required
Location string `json:"location"`

// +kubebuilder:default=BASIC_HDD
Tier GcpFileTier `json:"tier"`

// +kubebuilder:validation:Pattern="^[a-z][a-z0-9_]*[a-z0-9]$"
// +kubebuilder:default=vol1
FileShareName string `json:"fileShareName"`

// +kubebuilder:default=1024
CapacityGb int `json:"capacityGb"`

// +kubebuilder:default=PRIVATE_SERVICE_ACCESS
ConnectMode GcpConnectMode `json:"connectMode"`
}

// +kubebuilder:validation:Enum=BASIC_HDD;BASIC_SSD;HIGH_SCALE_SSD;ENTERPRISE;ZONAL;REGIONAL
type GcpFileTier string

const (
BASIC_HDD = GcpFileTier("BASIC_HDD")
BASIC_SSD = GcpFileTier("BASIC_SSD")
HIGH_SCALE_SSD = GcpFileTier("HIGH_SCALE_SSD")
ENTERPRISE = GcpFileTier("ENTERPRISE")
ZONAL = GcpFileTier("ZONAL")
REGIONAL = GcpFileTier("REGIONAL")
)

// +kubebuilder:validation:Enum=DIRECT_PEERING;PRIVATE_SERVICE_ACCESS
type GcpConnectMode string

const (
DIRECT_PEERING = GcpConnectMode("DIRECT_PEERING")
PRIVATE_SERVICE_ACCESS = GcpConnectMode("PRIVATE_SERVICE_ACCESS")
)
7 changes: 5 additions & 2 deletions components/kcp/api/cloud-control/v1beta1/nfsinstance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ type NfsInstanceInfo struct {
Aws *NfsInstanceAws `json:"aws,omitempty"`
}

type NfsInstanceGcp struct {
}
type NfsInstanceGcp NfsOptionsGcp

type NfsInstanceAzure struct {
}
Expand All @@ -98,6 +97,10 @@ type NfsInstanceStatus struct {
// +listType=map
// +listMapKey=type
Conditions []metav1.Condition `json:"conditions,omitempty"`

//List of NFS Hosts (DNS Names or IP Addresses) that clients can use to connect
// +optional
Hosts []string `json:"hosts,omitempty"`
}

//+kubebuilder:object:root=true
Expand Down
20 changes: 20 additions & 0 deletions components/kcp/api/cloud-control/v1beta1/zz_generated.deepcopy.go

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

Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,38 @@ spec:
azure:
type: object
gcp:
properties:
capacityGb:
default: 1024
type: integer
connectMode:
default: PRIVATE_SERVICE_ACCESS
enum:
- DIRECT_PEERING
- PRIVATE_SERVICE_ACCESS
type: string
fileShareName:
default: vol1
pattern: ^[a-z][a-z0-9_]*[a-z0-9]$
type: string
location:
type: string
tier:
default: BASIC_HDD
enum:
- BASIC_HDD
- BASIC_SSD
- HIGH_SCALE_SSD
- ENTERPRISE
- ZONAL
- REGIONAL
type: string
required:
- capacityGb
- connectMode
- fileShareName
- location
- tier
type: object
type: object
ipRange:
Expand Down Expand Up @@ -161,6 +193,12 @@ spec:
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
hosts:
description: List of NFS Hosts (DNS Names or IP Addresses) that clients
can use to connect
items:
type: string
type: array
id:
type: string
state:
Expand Down
4 changes: 4 additions & 0 deletions components/kcp/pkg/nfsinstance/loadIpRange.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package nfsinstance
import (
"context"
"fmt"

cloudresourcesv1beta1 "github.com/kyma-project/cloud-manager/components/kcp/api/cloud-control/v1beta1"
types2 "github.com/kyma-project/cloud-manager/components/kcp/pkg/nfsinstance/types"
"github.com/kyma-project/cloud-manager/components/lib/composed"
Expand Down Expand Up @@ -46,5 +47,8 @@ func loadIpRange(ctx context.Context, st composed.State) (error, context.Context
return composed.StopAndForget, nil
}

//Store IPRange into the state object.
state.SetIpRange(ipRange)

return nil, nil
}
3 changes: 2 additions & 1 deletion components/kcp/pkg/nfsinstance/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package nfsinstance

import (
"context"

cloudresourcesv1beta1 "github.com/kyma-project/cloud-manager/components/kcp/api/cloud-control/v1beta1"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/common/actions/focal"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/common/actions/scope"
Expand Down Expand Up @@ -73,6 +74,6 @@ func (r *NfsInstanceReconciler) newAction() composed.Action {

func (r *NfsInstanceReconciler) newFocalState(name types.NamespacedName) focal.State {
return r.focalStateFactory.NewState(
r.composedStateFactory.NewState(name, &cloudresourcesv1beta1.IpRange{}),
r.composedStateFactory.NewState(name, &cloudresourcesv1beta1.NfsInstance{}),
)
}
29 changes: 28 additions & 1 deletion components/kcp/pkg/provider/gcp/client/gcpConstants.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const ServiceNetworkingServiceConnectionName = "services/servicenetworking.googl
const networkFilter = "network=\"https://www.googleapis.com/compute/v1/projects/%s/global/networks/%s\""
const PsaPeeringName = "servicenetworking-googleapis-com"
const filestoreInstancePattern = "projects/%s/locations/%s/instances/%s"
const filestoreParentPattern = "projects/%s/locations/%s"

func GetVPCPath(projectId, vpcId string) string {
return fmt.Sprintf(vPCPathPattern, projectId, vpcId)
Expand All @@ -25,6 +26,10 @@ func GetFilestoreInstancePath(projectId, location, instanceId string) string {
return fmt.Sprintf(filestoreInstancePattern, projectId, location, instanceId)
}

func GetFilestoreParentPath(projectId, location string) string {
return fmt.Sprintf(filestoreParentPattern, projectId, location)
}

type networkTier string

const (
Expand Down Expand Up @@ -61,9 +66,31 @@ const (
)

const (
//Common States
Deleted v1beta1.StatusState = "Deleted"

//IPRange States
SyncAddress v1beta1.StatusState = "SyncAddress"
SyncPsaConnection v1beta1.StatusState = "SyncPSAConnection"
DeletePsaConnection v1beta1.StatusState = "DeletePSAConnection"
DeleteAddress v1beta1.StatusState = "DeleteAddress"
Deleted v1beta1.StatusState = "Deleted"

//Filestore States
SyncFilestore v1beta1.StatusState = "SyncFilestore"
DeleteFilestore v1beta1.StatusState = "DeleteFilestore"
)

type FilestoreState string

const (
CREATING FilestoreState = "CREATING"
READY FilestoreState = "READY"
REPAIRING FilestoreState = "REPAIRING"
DELETING FilestoreState = "DELETING"
ERROR FilestoreState = "ERROR"
RESTORING FilestoreState = "RESTORING"
SUSPENDED FilestoreState = "SUSPENDED"
SUSPENDING FilestoreState = "SUSPENDING"
RESUMING FilestoreState = "RESUMING"
REVERTING FilestoreState = "REVERTING"
)
66 changes: 66 additions & 0 deletions components/kcp/pkg/provider/gcp/nfsinstance/checkNUpdateState.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package nfsinstance

import (
"context"

"github.com/kyma-project/cloud-manager/components/kcp/api/cloud-control/v1beta1"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/common/actions/focal"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/provider/gcp/client"
"github.com/kyma-project/cloud-manager/components/lib/composed"
"k8s.io/apimachinery/pkg/api/meta"
)

func checkNUpdateState(ctx context.Context, st composed.State) (error, context.Context) {
state := st.(*State)
logger := composed.LoggerFromCtx(ctx)

nfsInstance := state.ObjAsNfsInstance()
logger.WithValues("NfsInstance :", nfsInstance.Name).Info("Updating State Info")

//Compute State Info
//Check and see whether the desiredState == actualState
deleting := !state.Obj().GetDeletionTimestamp().IsZero()

state.operation = focal.NONE
if deleting {
if state.fsInstance == nil {
state.curState = client.Deleted
} else if state.fsInstance.State != string(client.DELETING) {
//If the filestore exists and not DELETING, delete it.
state.operation = focal.DELETE
state.curState = client.SyncFilestore
}
} else {
if state.fsInstance == nil {
//If filestore doesn't exist, add it.
state.operation = focal.ADD
state.curState = client.SyncFilestore
} else if !state.doesFilestoreMatch() {
//If the filestore exists, but does not match, update it.
state.operation = focal.MODIFY
state.curState = client.SyncFilestore
} else if state.fsInstance.State == string(client.READY) {
state.curState = v1beta1.ReadyState
}
}

//Update State Info
state.ObjAsNfsInstance().Status.State = state.curState

if state.curState == v1beta1.ReadyState {
state.ObjAsNfsInstance().Status.Hosts = state.fsInstance.Networks[0].IpAddresses
meta.RemoveStatusCondition(state.ObjAsNfsInstance().Conditions(), v1beta1.ConditionTypeError)
state.AddReadyCondition(ctx, "Filestore Instance provisioned in GCP.")
}

err := state.UpdateObjStatus(ctx)
if err != nil {
return composed.LogErrorAndReturn(err, "Error updating NfsInstance success status", composed.StopWithRequeue, nil)
}

if state.curState == v1beta1.ReadyState {
return composed.StopAndForget, nil
}

return nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@ package client

import (
"context"
"github.com/kyma-project/cloud-manager/components/lib/composed"
"net/http"

"github.com/kyma-project/cloud-manager/components/lib/composed"

gcpclient "github.com/kyma-project/cloud-manager/components/kcp/pkg/provider/gcp/client"
"google.golang.org/api/file/v1"
"google.golang.org/api/option"
Expand Down Expand Up @@ -49,7 +50,7 @@ func (c *filestoreClient) GetFilestoreInstance(ctx context.Context, projectId, l

func (c *filestoreClient) CreateFilestoreInstance(ctx context.Context, projectId, location, instanceId string, instance *file.Instance) (*file.Operation, error) {
logger := composed.LoggerFromCtx(ctx)
operation, err := c.svcFilestore.Projects.Locations.Instances.Create(gcpclient.GetFilestoreInstancePath(projectId, location, instanceId), instance).Do()
operation, err := c.svcFilestore.Projects.Locations.Instances.Create(gcpclient.GetFilestoreParentPath(projectId, location), instance).InstanceId(instanceId).Do()
if err != nil {
logger.Error(err, "CreateFilestoreInstance", "projectId", projectId, "location", location, "instanceId", instanceId)
return nil, err
Expand Down
43 changes: 43 additions & 0 deletions components/kcp/pkg/provider/gcp/nfsinstance/loadNfsInstance.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package nfsinstance

import (
"context"
"errors"

"github.com/kyma-project/cloud-manager/components/kcp/api/cloud-control/v1beta1"
"github.com/kyma-project/cloud-manager/components/lib/composed"
"google.golang.org/api/googleapi"
)

func loadNfsInstance(ctx context.Context, st composed.State) (error, context.Context) {
state := st.(*State)
logger := composed.LoggerFromCtx(ctx)

nfsInstance := state.ObjAsNfsInstance()
logger.WithValues("NfsInstance :", nfsInstance.Name).Info("Loading GCP Filestore Instance")

//Get GCP details.
gcpScope := state.Scope().Spec.Scope.Gcp
project := gcpScope.Project
location := state.getGcpLocation()
name := nfsInstance.Spec.RemoteRef.Name

inst, err := state.filestoreClient.GetFilestoreInstance(ctx, project, location, name)
if err != nil {

var e *googleapi.Error
if ok := errors.As(err, &e); ok {
if e.Code == 404 {
state.fsInstance = nil
return nil, nil
}
}
state.AddErrorCondition(ctx, v1beta1.ReasonGcpError, err)
return composed.LogErrorAndReturn(err, "Error getting Filestore Instance from GCP", composed.StopWithRequeue, nil)
}

//Store the fsInstance in state
state.fsInstance = inst

return nil, nil
}
14 changes: 14 additions & 0 deletions components/kcp/pkg/provider/gcp/nfsinstance/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@ package nfsinstance
import (
"context"
"fmt"

"github.com/kyma-project/cloud-manager/components/kcp/api/cloud-control/v1beta1"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/common/actions/focal"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/nfsinstance/types"
"github.com/kyma-project/cloud-manager/components/kcp/pkg/provider/gcp/client"
"github.com/kyma-project/cloud-manager/components/lib/composed"
)

Expand All @@ -21,6 +24,17 @@ func New(stateFactory StateFactory) composed.Action {
return composed.ComposeActions(
"gcsNfsInstance",
focal.AddFinalizer,
loadNfsInstance,
checkNUpdateState,
syncNfsInstance,
composed.BuildBranchingAction("RunFinalizer", StatePredicate(client.Deleted, ctx, state),
focal.RemoveFinalizer, nil),
)(ctx, state)
}
}

func StatePredicate(status v1beta1.StatusState, ctx context.Context, state *State) composed.Predicate {
return func(ctx context.Context, st composed.State) bool {
return status == state.curState
}
}
Loading

0 comments on commit 2978f73

Please sign in to comment.