package resolver // This file will be automatically regenerated based on the schema, any resolver implementations // will be copied through when generating and any unknown code will be moved to the end. // Code generated by github.com/99designs/gqlgen version v0.17.45 import ( "context" "fmt" "edge-infra.dev/pkg/edge/api/apierror" "edge-infra.dev/pkg/edge/api/graph/mapper" "edge-infra.dev/pkg/edge/api/graph/model" "edge-infra.dev/pkg/edge/api/middleware" "edge-infra.dev/pkg/edge/api/services" "edge-infra.dev/pkg/edge/api/utils" clusterApi "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1" "edge-infra.dev/pkg/edge/bsl" chariotClientApi "edge-infra.dev/pkg/edge/chariot/client" "edge-infra.dev/pkg/edge/constants" "edge-infra.dev/pkg/edge/constants/api/fleet" "edge-infra.dev/pkg/edge/k8objectsutils" "github.com/rs/zerolog/log" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // DeleteCluster is the resolver for the deleteCluster field. func (r *mutationResolver) DeleteCluster(ctx context.Context, clusterEdgeID string, deleteBSLSite *bool) (bool, error) { errors := utils.NewErrorWrapper() cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg("failed to get cluster") return false, err } bannerToDelete, err := r.BannerService.GetBanner(ctx, cluster.BannerEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg("failed to get cluster") return false, err } // Delete IENodes from cluster infra cluster. Must be called before // SoftDeleteStoreEntry as requires access to the list of terminals in the DB if err := r.UpdateClusterIENodesViaChariot(ctx, &cluster.ClusterEdgeID, chariotClientApi.Delete); err != nil { errors.AddError(err, "error deleting terminal resources") } // Delete a clusters resources in cluster infra clusters and gcp if err := r.DeleteClustersInfraAndGCPResources(ctx, cluster); err != nil { log.Ctx(ctx).Err(err).Msg("error deleting cluster resources") errors.AddError(err, "error deleting cluster resources") } // Delete store namespace from foreman cluster via chariot storeNsBase64, err := utils.ConvertStructToBase64(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: clusterEdgeID}}) if err != nil { return false, err } err = r.sendChariotMessage(ctx, r.Config.Bff.TopLevelProjectID, "foreman0", chariotClientApi.Delete, storeNsBase64) if err != nil { return false, err } err = r.StoreClusterService.SoftDeleteStoreEntry(ctx, clusterEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg("failed to soft delete store sql entry") errors.AddError(err, "error soft deleting store sql entry") } clusterInfra, err := r.BannerService.GetClusterInfraInfo(ctx, cluster.BannerEdgeID) if err != nil { //nolint: nestif log.Ctx(ctx).Err(err).Msg("fail to get cluster infra info") errors.AddError(err, "error getting cluster infra info") } else { banner := &model.Banner{} clusterCR := clusterApi.NewCluster(cluster.Name, cluster.ProjectID, "", "", "", "", "", "", clusterEdgeID, 0, banner) obj, err := k8objectsutils.ToBase64JSONString(clusterCR) if err != nil { //nolint: nestif log.Ctx(ctx).Err(err).Msg("fail to convert cluster object to base64 json string") errors.AddError(err, "error converting cluster object to base64 json string") } else { chariotMessage := chariotClientApi. NewChariotMessage(). SetOperation(chariotClientApi.Delete). SetOwner(services.ComponentOwner). SetBanner(clusterInfra.ProjectID). SetCluster(clusterInfra.ClusterEdgeID). AddObject(obj) if err := r.ChariotService.InvokeChariotPubsub(ctx, chariotMessage, nil); err != nil { log.Ctx(ctx).Err(err).Msg("chariot invocation failed") errors.AddError(err, "error invoking chariot") } } } if deleteBSLSite != nil && *deleteBSLSite { //nolint nestif if cluster.BslSiteID != nil || *cluster.BslSiteID != "" { //nolint nestif inactiveStatus := services.InActiveStatus _, errs := r.BSLSiteService.UpdateBSLSiteByID(ctx, bannerToDelete, *cluster.BslSiteID, model.Site{Status: &inactiveStatus}) if errs != nil { log.Ctx(ctx).Err(errs).Msg("delete bsl site failed") errors.AddError(errs, "error deleting site") } } else { log.Ctx(ctx).Err(err).Msg("error deleting site, cluster has no associated bsl site") errors.AddError(err, "error deleting site, cluster has no associated bsl site") } } if errors.IsNotNil() { return false, errors.GetErrors() } return true, nil } // UpdateSite is the resolver for the updateSite field. func (r *mutationResolver) UpdateSite(ctx context.Context, clusterEdgeID string, site model.Site) (*model.StoreSiteInfo, error) { cluster, err := r.StoreClusterService.GetClusterByClusterEdgeID(ctx, clusterEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error cluster by clusterEdgeID %s", clusterEdgeID)) return nil, err } bannerResponse, err := r.BannerService.GetBannerByEdgeID(ctx, cluster.BannerEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error getting banner by bannerEdgeID %s", cluster.BannerEdgeID)) return nil, err } siteResponse, err := r.BSLSiteService.UpdateBSLSiteByID(ctx, bannerResponse, cluster.BSLSiteID, site) if err != nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error updating cluster bsl site by bsl_site_id %s", cluster.BSLSiteID)) return nil, err } return siteResponse, nil } // CreateClusterNetworkServices is the resolver for the createClusterNetworkServices field. func (r *mutationResolver) CreateClusterNetworkServices(ctx context.Context, clusterEdgeID string, networkServicesInfo []*model.CreateNetworkServiceInfo) ([]*model.ClusterNetworkServiceInfo, error) { for _, service := range networkServicesInfo { if _, ok := constants.ClusterNetworkServiceDefaults[service.ServiceType]; ok { return nil, fmt.Errorf("cannot create %s already exists", service.ServiceType) } } services, err := r.StoreClusterService.CreateClusterNetworkServices(ctx, clusterEdgeID, networkServicesInfo) if err != nil { return nil, err } if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil { return services, err } return services, nil } // UpdateClusterNetworkServices is the resolver for the updateClusterNetworkServices field. func (r *mutationResolver) UpdateClusterNetworkServices(ctx context.Context, clusterEdgeID string, networkServicesInfo []*model.UpdateNetworkServiceInfo) ([]*model.ClusterNetworkServiceInfo, error) { cluster, err := r.StoreClusterService.GetClusterByClusterEdgeID(ctx, clusterEdgeID) if err != nil { return nil, err } networkServices, err := r.StoreClusterService.GetClusterNetworkServices(ctx, clusterEdgeID) if err != nil { return nil, err } networkServiceByID := map[string]string{} for _, service := range networkServices { networkServiceByID[service.NetworkServiceID] = service.ServiceType } if err := utils.CheckNetworkServicesUpdatePermitted(cluster.Active, networkServicesInfo, networkServiceByID); err != nil { return nil, err } services, err := r.StoreClusterService.UpdateClusterNetworkServices(ctx, clusterEdgeID, networkServicesInfo, networkServiceByID) if err != nil { return nil, err } if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil { return services, err } return services, nil } // DeleteClusterNetworkService is the resolver for the deleteClusterNetworkService field. func (r *mutationResolver) DeleteClusterNetworkService(ctx context.Context, clusterEdgeID string, networkServiceID string) (bool, error) { deletedService, err := r.StoreClusterService.DeleteClusterNetworkService(ctx, clusterEdgeID, networkServiceID) if err != nil { return deletedService, err } if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil { return deletedService, err } return deletedService, nil } // UpdateClusterName is the resolver for the updateClusterName field. func (r *mutationResolver) UpdateClusterName(ctx context.Context, clusterEdgeID string, name string) (*model.Cluster, error) { err := r.StoreClusterService.UpdateStoreName(ctx, clusterEdgeID, name) if err != nil { return nil, err } cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID) if err != nil { return cluster, err } return cluster, nil } // CreateClusterConfig is the resolver for the createClusterConfig field. func (r *mutationResolver) CreateClusterConfig(ctx context.Context, clusterEdgeID string, createClusterConfig model.CreateClusterConfig) (*model.ClusterConfig, error) { updateClusterCfg := model.UpdateClusterConfig(createClusterConfig) return r.UpdateClusterConfig(ctx, clusterEdgeID, updateClusterCfg) } // UpdateClusterConfig is the resolver for the updateClusterConfig field. func (r *mutationResolver) UpdateClusterConfig(ctx context.Context, clusterEdgeID string, updateClusterConfig model.UpdateClusterConfig) (*model.ClusterConfig, error) { clusterConfig, err := r.ClusterConfigService.UpdateClusterConfig(ctx, clusterEdgeID, &updateClusterConfig) if err != nil { return nil, err } clusterLabels, err := r.StoreClusterService.GetLabelsForCluster(ctx, clusterEdgeID) if err != nil { return nil, err } labelsMap := utils.ClusterLabelsTypeMap(clusterLabels) _, gkeExists := labelsMap["gke"] _, genericExists := labelsMap["generic"] if !gkeExists && !genericExists { if err := r.UpdateBootOptionsViaChariot(ctx, clusterEdgeID, clusterConfig, chariotClientApi.Create); err != nil { return nil, err } if err := r.UpdateTopologyInfoCMViaChariot(ctx, clusterEdgeID, clusterConfig, chariotClientApi.Create); err != nil { return nil, err } } return clusterConfig, r.ActivationCodeService.SyncAllToStore(ctx, clusterEdgeID) } // DeleteClusters is the resolver for the deleteClusters field. func (r *mutationResolver) DeleteClusters(ctx context.Context, clusterEdgeIds []string, deleteBSLSite *bool) (bool, error) { deleteErr := apierror.New(apierror.DeleteClustersMessage) for _, clusterEdgeID := range clusterEdgeIds { message := []string{} if val, ok := deleteErr.Ext[apierror.DeleteClustersKey]; ok { message = val.([]string) } _, err := r.DeleteCluster(ctx, clusterEdgeID, deleteBSLSite) if err != nil { message = append(message, fmt.Sprintf("failed delete cluster, clusterEdgeId: %s, error: %s", clusterEdgeID, err.Error())) } deleteErr = deleteErr.AddGenericErrorExtension(apierror.DeleteClustersKey, message) } isDeleted := len(deleteErr.Ext[apierror.DeleteClustersKey].([]string)) == 0 if isDeleted { return isDeleted, nil } return isDeleted, deleteErr } // AddSiteToStore is the resolver for the addSiteToStore field. func (r *mutationResolver) AddSiteToStore(ctx context.Context, clusterEdgeID string, siteID *string) (*model.RegistrationResponse, error) { var ( bslInfoForCluster = &bslHolder{siteInfo: &bsl.BSLInfo{}} ) clusterInfo, bannerInfo, err := r.GetClusterAndBannerInfo(ctx, clusterEdgeID) if err != nil { return nil, err } createSite := utils.IsNullOrEmpty(siteID) organization := bsl.GetOrgShortName(middleware.ForContext(ctx).Organization) storeInfo := &model.StoreInfo{ SiteID: siteID, CreateSite: &createSite, BslOrganization: &organization, } //check if the site is valid or not, if it is valid, it will check if the site is attached to a cluster, else create a new site bslInfoForCluster.siteInfo, _, err = r.BSLSiteService.GetOrCreateSite(ctx, storeInfo, bannerInfo, clusterInfo.ClusterName, clusterEdgeID) if err != nil { return nil, err } //update sql store site entry err = r.StoreClusterService.UpdateStoreSiteID(ctx, clusterEdgeID, bslInfoForCluster.siteInfo.ID) if err != nil { return nil, err } return &model.RegistrationResponse{ ClusterEdgeID: clusterEdgeID, SiteID: &bslInfoForCluster.siteInfo.ID, }, nil } // UpdateClusterFleetVersion is the resolver for the updateClusterFleetVersion field. func (r *mutationResolver) UpdateClusterFleetVersion(ctx context.Context, clusterEdgeID string, fleetVersion string) (*model.Cluster, error) { var previousStoreVersion string artifactVersions, err := r.ArtifactsService.GetClusterArtifactVersions(ctx, clusterEdgeID) if err != nil { return nil, err } for _, artifact := range artifactVersions { if artifact.Name == fleet.Store { previousStoreVersion = artifact.Version } } if err := r.ArtifactsService.UpdateClusterFleetVersionAndArtifact(ctx, clusterEdgeID, fleetVersion); err != nil { return nil, err } cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID) if err != nil { return nil, err } if err := r.UpdateClusterDefaultOptionalPallets(ctx, cluster, fleetVersion, previousStoreVersion); err != nil { return nil, err } return cluster, nil } // Clusters is the resolver for the clusters field. func (r *queryResolver) Clusters(ctx context.Context, bannerEdgeID string, labels []string) ([]*model.Cluster, error) { return r.StoreClusterService.GetClusters(ctx, bannerEdgeID, labels) } // Cluster is the resolver for the cluster field. func (r *queryResolver) Cluster(ctx context.Context, clusterEdgeID string) (*model.Cluster, error) { return r.StoreClusterService.GetCluster(ctx, clusterEdgeID) } // StoreStatus is the resolver for the storeStatus field. func (r *queryResolver) StoreStatus(ctx context.Context, clusterEdgeID string) (*model.StoreStatusInfo, error) { cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg("failed to get cluster") return nil, err } response := mapper.ToStoreStatusModel(cluster.Name, cluster.BannerEdgeID, nil, nil) active := cluster.Active != nil && *cluster.Active if !active { //nolint: nestif response.Status = &model.ClusterStatus{ Status: mapper.Provisioning, Message: "status not found", } return response, nil } clusterStatus, err := r.StoreClusterService.GetClusterStatus(ctx, cluster) if err != nil || clusterStatus == nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("error in getting store status for cluster %s", cluster.Name)) response.Status = &model.ClusterStatus{ Status: mapper.Provisioning, Message: "status not found", } return response, nil } response.Status = clusterStatus.Status response.KubeVersion = clusterStatus.KubeVersion response.BucketStatus = clusterStatus.BucketStatus response.KustomizationStatus = clusterStatus.KustomizationStatus return response, nil } // Site is the resolver for the site field. func (r *queryResolver) Site(ctx context.Context, clusterEdgeID string) (*model.StoreSiteInfo, error) { cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID) if err != nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error cluster by clusterEdgeID %s", clusterEdgeID)) return nil, err } // check if BSL Site is empty or null if utils.IsNullOrEmpty(cluster.BslSiteID) { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("bsl_site_id data is missing in DB for clusterEdgeID %s", clusterEdgeID)) return nil, apierror.New("Site ID is missing and/or empty for this cluster") } bannerResponse, err := r.BannerService.GetBannerByEdgeID(ctx, cluster.BannerEdgeID) if err != nil { return nil, err } site, err := r.BSLSiteService.GetBSLSiteByID(ctx, *cluster.BslSiteID, bannerResponse) if err != nil { log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error getting bsl site, id: %s", *cluster.BslSiteID)) return nil, err } return mapper.ToStoreSiteInfo(site), nil } // ClusterConfig is the resolver for the clusterConfig field. func (r *queryResolver) ClusterConfig(ctx context.Context, clusterEdgeID string) (*model.ClusterConfig, error) { clusterConfig, err := r.ClusterConfigService.GetClusterConfig(ctx, clusterEdgeID) if err != nil { return nil, err } return clusterConfig, nil }