Skip to content

Commit

Permalink
Merge branch 'migrate-shared-services' of https://github.com/svalabs/…
Browse files Browse the repository at this point in the history
…gargantua into migrate-shared-services
  • Loading branch information
PhilipAB committed Sep 17, 2024
2 parents 762e184 + 246e547 commit dea7d30
Show file tree
Hide file tree
Showing 8 changed files with 112 additions and 50 deletions.
4 changes: 1 addition & 3 deletions v3/pkg/shell/shell.go
Original file line number Diff line number Diff line change
Expand Up @@ -829,11 +829,9 @@ func (sp ShellProxy) VerifyTasksFuncByVMIdGroupWithSemaphore(w http.ResponseWrit
// Handle the error (log, return HTTP error response)
close(errorChan)
glog.Infof("Error in goroutine: %v", err)
util.ReturnHTTPMessage(w, r, 500, "error", "could send command to vm")
util.ReturnHTTPMessage(w, r, 500, "error", "could not send command to vm")
return
default:
// No error in the errorChan
glog.Infof("No Error in goroutine: %v", vm_output_tasks)
jsonStr, _ := json.Marshal(vm_output_tasks)
util.ReturnHTTPContent(w, r, 200, "success", jsonStr)
}
Expand Down
21 changes: 21 additions & 0 deletions v3/pkg/util/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,24 @@ func VerifyTaskContent(vm_tasks []hfv1.VirtualMachineTasks, request proto.Messag
}
return nil
}

func VerifySharedVirtualMachineContent(virtual_machines []hfv1.SharedVirtualMachine, request proto.Message) error {
//Verify that name, description and command are not empty
for _, virtual_machine := range virtual_machines {
if virtual_machine.Name == "" {
glog.Errorf("error: Name (of virtual_machines) is not specified")
return hferrors.GrpcError(codes.InvalidArgument, "name for virtual_machines property is not specified", request)
}

if virtual_machine.Environment == "" {
glog.Errorf("error: Environment (of virtual_machine %s) is not specified", virtual_machine.Name)
return hferrors.GrpcError(codes.InvalidArgument, "name for virtual_machines property is not specified for "+virtual_machine.Name, request)
}

if virtual_machine.VMTemplate == "" {
glog.Errorf("error VMTemplate (of virtual_machine %s) is not specified", virtual_machine.Name)
return hferrors.GrpcError(codes.InvalidArgument, "name for virtual_machines property is not specified for "+virtual_machine.Name, request)
}
}
return nil
}
17 changes: 17 additions & 0 deletions v3/services/authnsvc/internal/authnservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,23 @@ func (a *AuthServer) GetAccessSet(w http.ResponseWriter, r *http.Request) {
util.ReturnHTTPContent(w, r, http.StatusOK, "access_set", encodedAS)
}

func (a AuthServer) DeleteUser(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
user, err := a.internalAuthnServer.AuthN(r.Context(), &authnpb.AuthNRequest{
Token: token,
})
if err != nil {
util.ReturnHTTPMessage(w, r, http.StatusUnauthorized, "unauthorized", "unauthorized")
return
}

_, err = a.userClient.DeleteUser(r.Context(), &generalpb.ResourceId{Id: user.GetId()})

if err != nil {
util.ReturnHTTPMessage(w, r, http.StatusInternalServerError, "error", "Error during account deletion")
}
}

func (a AuthServer) ListScheduledEventsFunc(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
user, err := a.internalAuthnServer.AuthN(r.Context(), &authnpb.AuthNRequest{
Expand Down
1 change: 1 addition & 0 deletions v3/services/authnsvc/internal/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ func (a AuthServer) SetupRoutes(r *mux.Router) {
r.HandleFunc("/auth/settings", a.UpdateSettingsFunc).Methods("POST")
r.HandleFunc("/auth/authenticate", a.LoginFunc).Methods("POST")
r.HandleFunc("/auth/access", a.GetAccessSet).Methods("GET")
r.HandleFunc("/auth/delete", a.DeleteUser).Methods("GET")
r.HandleFunc("/auth/scheduledevents", a.ListScheduledEventsFunc).Methods("GET")
glog.V(2).Infof("set up route")
}
8 changes: 8 additions & 0 deletions v3/services/scheduledeventsvc/internal/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,10 @@ func (s *GrpcScheduledEventServer) CreateScheduledEvent(ctx context.Context, req
VMTemplate: sharedVm.VmTemplate,
})
}
err = util.VerifySharedVirtualMachineContent(sharedVms, req)
if err != nil {
return &generalpb.ResourceId{}, err
}
event.Spec.SharedVirtualMachines = sharedVms
}

Expand Down Expand Up @@ -317,6 +321,10 @@ func (s *GrpcScheduledEventServer) UpdateScheduledEvent(ctx context.Context, req
VMTemplate: sharedVm.VmTemplate,
})
}
err = util.VerifySharedVirtualMachineContent(sharedVms, req)
if err != nil {
return err
}
event.Spec.SharedVirtualMachines = sharedVms
}

Expand Down
66 changes: 41 additions & 25 deletions v3/services/usersvc/internal/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import (
hflabels "github.com/hobbyfarm/gargantua/v3/pkg/labels"
"github.com/hobbyfarm/gargantua/v3/pkg/util"
generalpb "github.com/hobbyfarm/gargantua/v3/protos/general"
rbacpb "github.com/hobbyfarm/gargantua/v3/protos/rbac"
sessionpb "github.com/hobbyfarm/gargantua/v3/protos/session"
userpb "github.com/hobbyfarm/gargantua/v3/protos/user"
"golang.org/x/crypto/bcrypt"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/wrapperspb"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/retry"
Expand All @@ -40,9 +42,10 @@ type GrpcUserServer struct {
userLister listerv2.UserLister
userSynced cache.InformerSynced
sessionClient sessionpb.SessionSvcClient
rbacClient rbacpb.RbacSvcClient
}

func NewGrpcUserServer(hfClientSet hfClientset.Interface, hfInformerFactory hfInformers.SharedInformerFactory, sessionClient sessionpb.SessionSvcClient) (*GrpcUserServer, error) {
func NewGrpcUserServer(hfClientSet hfClientset.Interface, hfInformerFactory hfInformers.SharedInformerFactory, sessionClient sessionpb.SessionSvcClient, rbacClient rbacpb.RbacSvcClient) (*GrpcUserServer, error) {
inf := hfInformerFactory.Hobbyfarm().V2().Users().Informer()
indexers := map[string]cache.IndexFunc{emailIndex: emailIndexer}
err := inf.AddIndexers(indexers)
Expand All @@ -56,6 +59,7 @@ func NewGrpcUserServer(hfClientSet hfClientset.Interface, hfInformerFactory hfIn
userLister: hfInformerFactory.Hobbyfarm().V2().Users().Lister(),
userSynced: inf.HasSynced,
sessionClient: sessionClient,
rbacClient: rbacClient,
}, nil
}

Expand Down Expand Up @@ -408,25 +412,53 @@ func (u *GrpcUserServer) DeleteUser(ctx context.Context, userId *generalpb.Resou
}

if len(sessionList.Sessions) > 0 {
// there are sessions present but they may be expired. let's check
for _, s := range sessionList.Sessions {
if !s.Status.Finished {
now := time.Now().Format(time.UnixDate)

// This will set the expiration time to now, leading to the session being cleaned up
_, err = u.sessionClient.UpdateSessionStatus(ctx, &sessionpb.UpdateSessionStatusRequest{
Id: s.GetId(),
Active: wrapperspb.Bool(false),
ExpirationTime: now,
})

if err != nil {
glog.Errorf("error marking session as expired: %s", hferrors.GetErrorMessage(err))
return &emptypb.Empty{}, hferrors.GrpcError(
codes.Internal,
"cannot delete user, existing sessions found",
"error marking session as finished for user %s",
userId,
userId.GetId(),
)
}
}
}

// Delete role bindings that belong to the user
bindings, err := u.rbacClient.GetHobbyfarmRoleBindings(ctx, &generalpb.ResourceId{
Id: user.Name,
})

// getting here means there are sessions present but they are not active
// let's delete them for cleanliness' sake
if ok, err := u.deleteSessions(ctx, sessionList.Sessions); !ok {
glog.Errorf("error deleting old sessions for user %s: %s", id, err)
if err != nil {
glog.Errorf("error getting hobbyfarm rolebindings for user %s: %v", user.Name, err)
return &emptypb.Empty{}, hferrors.GrpcError(
codes.Internal,
"error getting rolebindings list for user %s",
userId,
userId.GetId(),
)
}
for _, rb := range bindings.GetRolebindings() {
_, err = u.rbacClient.DeleteRolebinding(ctx, &generalpb.ResourceId{
Id: rb.Name,
})
if err != nil {
glog.Errorf("error deleting rolebindings %s for user %s: %v", rb.Name, user.Name, err)
return &emptypb.Empty{}, hferrors.GrpcError(
codes.Internal,
"cannot delete user, error removing old sessions",
"error deleting rolebinding for user %s",
userId,
userId.GetId(),
)
}
}
Expand All @@ -446,19 +478,3 @@ func (u *GrpcUserServer) DeleteUser(ctx context.Context, userId *generalpb.Resou
}
return &emptypb.Empty{}, nil
}

func (u *GrpcUserServer) deleteSessions(ctx context.Context, sessions []*sessionpb.Session) (bool, error) {
for _, s := range sessions {
retryErr := retry.RetryOnConflict(retry.DefaultRetry, func() error {
// @TODO: Use gRPC SessionClient here!
_, err := u.sessionClient.DeleteSession(ctx, &generalpb.ResourceId{Id: s.Id})
return err
})

if retryErr != nil {
return false, retryErr
}
}

return true, nil
}
2 changes: 1 addition & 1 deletion v3/services/usersvc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func main() {
sessionClient := sessionpb.NewSessionSvcClient(connections[microservices.Session])

gs := microservices.CreateGRPCServer(serviceConfig.ServerCert)
us, err := userservice.NewGrpcUserServer(hfClient, hfInformerFactory, sessionClient)
us, err := userservice.NewGrpcUserServer(hfClient, hfInformerFactory, sessionClient, rbacClient)

if err != nil {
glog.Fatalf("starting grpc user server failed: %v", err)
Expand Down
43 changes: 22 additions & 21 deletions v3/services/vmsvc/internal/vmservice.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"net/http"

hfv1 "github.com/hobbyfarm/gargantua/v3/pkg/apis/hobbyfarm.io/v1"
hferrors "github.com/hobbyfarm/gargantua/v3/pkg/errors"
hflabels "github.com/hobbyfarm/gargantua/v3/pkg/labels"
"github.com/hobbyfarm/gargantua/v3/pkg/rbac"
Expand All @@ -24,25 +25,25 @@ const (
)

type PreparedVirtualMachine struct {
Id string `json:"id"`
VirtualMachineTemplateId string `json:"vm_template_id"`
SshUsername string `json:"ssh_username"`
Protocol string `json:"protocol"`
SecretName string `json:"secret_name"` // this refers to the secret name for the keypair
VirtualMachineClaimId string `json:"vm_claim_id"`
UserId string `json:"user"`
Provision bool `json:"provision"`
VirtualMachineSetId string `json:"vm_set_id"`
Status string `json:"status"` // default is nothing, but could be one of the following: readyforprovisioning, provisioning, running, terminating
Allocated bool `json:"allocated"`
Tainted bool `json:"tainted"`
PublicIP string `json:"public_ip"`
PrivateIP string `json:"private_ip"`
EnvironmentId string `json:"environment_id"`
Hostname string `json:"hostname"` // ideally <hostname>.<enviroment dnssuffix> should be the FQDN to this machine
TFState string `json:"tfstate,omitempty"` // Terraform state name
WsEndpoint string `json:"ws_endpoint"`
IsShared bool `json:"is_shared"`
Id string `json:"id"`
VirtualMachineTemplateId string `json:"vm_template_id"`
SshUsername string `json:"ssh_username"`
Protocol string `json:"protocol"`
SecretName string `json:"secret_name"` // this refers to the secret name for the keypair
VirtualMachineClaimId string `json:"vm_claim_id"`
UserId string `json:"user"`
Provision bool `json:"provision"`
VirtualMachineSetId string `json:"vm_set_id"`
Status string `json:"status"` // default is nothing, but could be one of the following: readyforprovisioning, provisioning, running, terminating
Allocated bool `json:"allocated"`
Tainted bool `json:"tainted"`
PublicIP string `json:"public_ip"`
PrivateIP string `json:"private_ip"`
EnvironmentId string `json:"environment_id"`
Hostname string `json:"hostname"` // ideally <hostname>.<enviroment dnssuffix> should be the FQDN to this machine
TFState string `json:"tfstate,omitempty"` // Terraform state name
WsEndpoint string `json:"ws_endpoint"`
VirtualMachineType hfv1.VirtualMachineType `json:"vm_type"`
}

/*
Expand Down Expand Up @@ -258,7 +259,7 @@ func (vms VMServer) GetAllVMListFunc(w http.ResponseWriter, r *http.Request) {
}

func (vms VMServer) GetSharedVirtualMachinesFunc(w http.ResponseWriter, r *http.Request) {
// Check if User has access to VMs
// TODO Check if User has access to VMs
_, err := rbac.AuthenticateRequest(r, vms.authnClient)
if err != nil {
util.ReturnHTTPMessage(w, r, 403, "forbidden", "no access to get shared vms")
Expand Down Expand Up @@ -334,6 +335,6 @@ func getPreparedVM(vm *vmpb.VM) PreparedVirtualMachine {
Hostname: vm.GetStatus().GetHostname(),
TFState: vm.GetStatus().GetTfstate(),
WsEndpoint: vm.GetStatus().GetWsEndpoint(),
IsShared: vm.GetVmType() == vmpb.VirtualMachineType_SHARED,
VirtualMachineType: util.ConvertToStringEnum(vm.GetVmType(), vmpb.VirtualMachineType_name, hfv1.VirtualMachineTypeUser),
}
}

0 comments on commit dea7d30

Please sign in to comment.