...

Source file src/edge-infra.dev/pkg/edge/api/graph/resolver/cluster_queries.resolvers.go

Documentation: edge-infra.dev/pkg/edge/api/graph/resolver

     1  package resolver
     2  
     3  // This file will be automatically regenerated based on the schema, any resolver implementations
     4  // will be copied through when generating and any unknown code will be moved to the end.
     5  // Code generated by github.com/99designs/gqlgen version v0.17.45
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"edge-infra.dev/pkg/edge/api/apierror"
    12  	"edge-infra.dev/pkg/edge/api/graph/mapper"
    13  	"edge-infra.dev/pkg/edge/api/graph/model"
    14  	"edge-infra.dev/pkg/edge/api/middleware"
    15  	"edge-infra.dev/pkg/edge/api/services"
    16  	"edge-infra.dev/pkg/edge/api/utils"
    17  	clusterApi "edge-infra.dev/pkg/edge/apis/cluster/v1alpha1"
    18  	"edge-infra.dev/pkg/edge/bsl"
    19  	chariotClientApi "edge-infra.dev/pkg/edge/chariot/client"
    20  	"edge-infra.dev/pkg/edge/constants"
    21  	"edge-infra.dev/pkg/edge/constants/api/fleet"
    22  	"edge-infra.dev/pkg/edge/k8objectsutils"
    23  	"github.com/rs/zerolog/log"
    24  	corev1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  )
    27  
    28  // DeleteCluster is the resolver for the deleteCluster field.
    29  func (r *mutationResolver) DeleteCluster(ctx context.Context, clusterEdgeID string, deleteBSLSite *bool) (bool, error) {
    30  	errors := utils.NewErrorWrapper()
    31  	cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
    32  	if err != nil {
    33  		log.Ctx(ctx).Err(err).Msg("failed to get cluster")
    34  		return false, err
    35  	}
    36  	bannerToDelete, err := r.BannerService.GetBanner(ctx, cluster.BannerEdgeID)
    37  	if err != nil {
    38  		log.Ctx(ctx).Err(err).Msg("failed to get cluster")
    39  		return false, err
    40  	}
    41  
    42  	// Delete IENodes from cluster infra cluster. Must be called before
    43  	// SoftDeleteStoreEntry as requires access to the list of terminals in the DB
    44  	if err := r.UpdateClusterIENodesViaChariot(ctx, &cluster.ClusterEdgeID, chariotClientApi.Delete); err != nil {
    45  		errors.AddError(err, "error deleting terminal resources")
    46  	}
    47  
    48  	// Delete a clusters resources in cluster infra clusters and gcp
    49  	if err := r.DeleteClustersInfraAndGCPResources(ctx, cluster); err != nil {
    50  		log.Ctx(ctx).Err(err).Msg("error deleting cluster resources")
    51  		errors.AddError(err, "error deleting cluster resources")
    52  	}
    53  
    54  	// Delete store namespace from foreman cluster via chariot
    55  	storeNsBase64, err := utils.ConvertStructToBase64(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: clusterEdgeID}})
    56  	if err != nil {
    57  		return false, err
    58  	}
    59  	err = r.sendChariotMessage(ctx, r.Config.Bff.TopLevelProjectID, "foreman0", chariotClientApi.Delete, storeNsBase64)
    60  	if err != nil {
    61  		return false, err
    62  	}
    63  
    64  	err = r.StoreClusterService.SoftDeleteStoreEntry(ctx, clusterEdgeID)
    65  	if err != nil {
    66  		log.Ctx(ctx).Err(err).Msg("failed to soft delete store sql entry")
    67  		errors.AddError(err, "error soft deleting store sql entry")
    68  	}
    69  
    70  	clusterInfra, err := r.BannerService.GetClusterInfraInfo(ctx, cluster.BannerEdgeID)
    71  	if err != nil { //nolint: nestif
    72  		log.Ctx(ctx).Err(err).Msg("fail to get cluster infra info")
    73  		errors.AddError(err, "error getting cluster infra info")
    74  	} else {
    75  		banner := &model.Banner{}
    76  
    77  		clusterCR := clusterApi.NewCluster(cluster.Name, cluster.ProjectID, "", "", "", "", "", "", clusterEdgeID, 0, banner)
    78  		obj, err := k8objectsutils.ToBase64JSONString(clusterCR)
    79  		if err != nil { //nolint: nestif
    80  			log.Ctx(ctx).Err(err).Msg("fail to convert cluster object to base64 json string")
    81  			errors.AddError(err, "error converting cluster object to base64 json string")
    82  		} else {
    83  			chariotMessage := chariotClientApi.
    84  				NewChariotMessage().
    85  				SetOperation(chariotClientApi.Delete).
    86  				SetOwner(services.ComponentOwner).
    87  				SetBanner(clusterInfra.ProjectID).
    88  				SetCluster(clusterInfra.ClusterEdgeID).
    89  				AddObject(obj)
    90  			if err := r.ChariotService.InvokeChariotPubsub(ctx, chariotMessage, nil); err != nil {
    91  				log.Ctx(ctx).Err(err).Msg("chariot invocation failed")
    92  				errors.AddError(err, "error invoking chariot")
    93  			}
    94  		}
    95  	}
    96  
    97  	if deleteBSLSite != nil && *deleteBSLSite { //nolint nestif
    98  		if cluster.BslSiteID != nil || *cluster.BslSiteID != "" { //nolint nestif
    99  			inactiveStatus := services.InActiveStatus
   100  			_, errs := r.BSLSiteService.UpdateBSLSiteByID(ctx, bannerToDelete, *cluster.BslSiteID, model.Site{Status: &inactiveStatus})
   101  			if errs != nil {
   102  				log.Ctx(ctx).Err(errs).Msg("delete bsl site failed")
   103  				errors.AddError(errs, "error deleting site")
   104  			}
   105  		} else {
   106  			log.Ctx(ctx).Err(err).Msg("error deleting site, cluster has no associated bsl site")
   107  			errors.AddError(err, "error deleting site, cluster has no associated bsl site")
   108  		}
   109  	}
   110  
   111  	if errors.IsNotNil() {
   112  		return false, errors.GetErrors()
   113  	}
   114  	return true, nil
   115  }
   116  
   117  // UpdateSite is the resolver for the updateSite field.
   118  func (r *mutationResolver) UpdateSite(ctx context.Context, clusterEdgeID string, site model.Site) (*model.StoreSiteInfo, error) {
   119  	cluster, err := r.StoreClusterService.GetClusterByClusterEdgeID(ctx, clusterEdgeID)
   120  	if err != nil {
   121  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error cluster by clusterEdgeID %s", clusterEdgeID))
   122  		return nil, err
   123  	}
   124  	bannerResponse, err := r.BannerService.GetBannerByEdgeID(ctx, cluster.BannerEdgeID)
   125  	if err != nil {
   126  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error getting banner by bannerEdgeID %s", cluster.BannerEdgeID))
   127  		return nil, err
   128  	}
   129  	siteResponse, err := r.BSLSiteService.UpdateBSLSiteByID(ctx, bannerResponse, cluster.BSLSiteID, site)
   130  	if err != nil {
   131  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error updating cluster bsl site by bsl_site_id %s", cluster.BSLSiteID))
   132  		return nil, err
   133  	}
   134  	return siteResponse, nil
   135  }
   136  
   137  // CreateClusterNetworkServices is the resolver for the createClusterNetworkServices field.
   138  func (r *mutationResolver) CreateClusterNetworkServices(ctx context.Context, clusterEdgeID string, networkServicesInfo []*model.CreateNetworkServiceInfo) ([]*model.ClusterNetworkServiceInfo, error) {
   139  	for _, service := range networkServicesInfo {
   140  		if _, ok := constants.ClusterNetworkServiceDefaults[service.ServiceType]; ok {
   141  			return nil, fmt.Errorf("cannot create %s already exists", service.ServiceType)
   142  		}
   143  	}
   144  
   145  	services, err := r.StoreClusterService.CreateClusterNetworkServices(ctx, clusterEdgeID, networkServicesInfo)
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil {
   151  		return services, err
   152  	}
   153  
   154  	return services, nil
   155  }
   156  
   157  // UpdateClusterNetworkServices is the resolver for the updateClusterNetworkServices field.
   158  func (r *mutationResolver) UpdateClusterNetworkServices(ctx context.Context, clusterEdgeID string, networkServicesInfo []*model.UpdateNetworkServiceInfo) ([]*model.ClusterNetworkServiceInfo, error) {
   159  	cluster, err := r.StoreClusterService.GetClusterByClusterEdgeID(ctx, clusterEdgeID)
   160  	if err != nil {
   161  		return nil, err
   162  	}
   163  	networkServices, err := r.StoreClusterService.GetClusterNetworkServices(ctx, clusterEdgeID)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	networkServiceByID := map[string]string{}
   168  	for _, service := range networkServices {
   169  		networkServiceByID[service.NetworkServiceID] = service.ServiceType
   170  	}
   171  
   172  	if err := utils.CheckNetworkServicesUpdatePermitted(cluster.Active, networkServicesInfo, networkServiceByID); err != nil {
   173  		return nil, err
   174  	}
   175  
   176  	services, err := r.StoreClusterService.UpdateClusterNetworkServices(ctx, clusterEdgeID, networkServicesInfo, networkServiceByID)
   177  	if err != nil {
   178  		return nil, err
   179  	}
   180  
   181  	if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil {
   182  		return services, err
   183  	}
   184  
   185  	return services, nil
   186  }
   187  
   188  // DeleteClusterNetworkService is the resolver for the deleteClusterNetworkService field.
   189  func (r *mutationResolver) DeleteClusterNetworkService(ctx context.Context, clusterEdgeID string, networkServiceID string) (bool, error) {
   190  	deletedService, err := r.StoreClusterService.DeleteClusterNetworkService(ctx, clusterEdgeID, networkServiceID)
   191  	if err != nil {
   192  		return deletedService, err
   193  	}
   194  
   195  	if err := r.UpdateClusterIENodesViaChariot(ctx, &clusterEdgeID, chariotClientApi.Create); err != nil {
   196  		return deletedService, err
   197  	}
   198  
   199  	return deletedService, nil
   200  }
   201  
   202  // UpdateClusterName is the resolver for the updateClusterName field.
   203  func (r *mutationResolver) UpdateClusterName(ctx context.Context, clusterEdgeID string, name string) (*model.Cluster, error) {
   204  	err := r.StoreClusterService.UpdateStoreName(ctx, clusterEdgeID, name)
   205  	if err != nil {
   206  		return nil, err
   207  	}
   208  	cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
   209  	if err != nil {
   210  		return cluster, err
   211  	}
   212  
   213  	return cluster, nil
   214  }
   215  
   216  // CreateClusterConfig is the resolver for the createClusterConfig field.
   217  func (r *mutationResolver) CreateClusterConfig(ctx context.Context, clusterEdgeID string, createClusterConfig model.CreateClusterConfig) (*model.ClusterConfig, error) {
   218  	updateClusterCfg := model.UpdateClusterConfig(createClusterConfig)
   219  	return r.UpdateClusterConfig(ctx, clusterEdgeID, updateClusterCfg)
   220  }
   221  
   222  // UpdateClusterConfig is the resolver for the updateClusterConfig field.
   223  func (r *mutationResolver) UpdateClusterConfig(ctx context.Context, clusterEdgeID string, updateClusterConfig model.UpdateClusterConfig) (*model.ClusterConfig, error) {
   224  	clusterConfig, err := r.ClusterConfigService.UpdateClusterConfig(ctx, clusterEdgeID, &updateClusterConfig)
   225  	if err != nil {
   226  		return nil, err
   227  	}
   228  	clusterLabels, err := r.StoreClusterService.GetLabelsForCluster(ctx, clusterEdgeID)
   229  	if err != nil {
   230  		return nil, err
   231  	}
   232  	labelsMap := utils.ClusterLabelsTypeMap(clusterLabels)
   233  	_, gkeExists := labelsMap["gke"]
   234  	_, genericExists := labelsMap["generic"]
   235  
   236  	if !gkeExists && !genericExists {
   237  		if err := r.UpdateBootOptionsViaChariot(ctx, clusterEdgeID, clusterConfig, chariotClientApi.Create); err != nil {
   238  			return nil, err
   239  		}
   240  		if err := r.UpdateTopologyInfoCMViaChariot(ctx, clusterEdgeID, clusterConfig, chariotClientApi.Create); err != nil {
   241  			return nil, err
   242  		}
   243  	}
   244  	return clusterConfig, r.ActivationCodeService.SyncAllToStore(ctx, clusterEdgeID)
   245  }
   246  
   247  // DeleteClusters is the resolver for the deleteClusters field.
   248  func (r *mutationResolver) DeleteClusters(ctx context.Context, clusterEdgeIds []string, deleteBSLSite *bool) (bool, error) {
   249  	deleteErr := apierror.New(apierror.DeleteClustersMessage)
   250  	for _, clusterEdgeID := range clusterEdgeIds {
   251  		message := []string{}
   252  		if val, ok := deleteErr.Ext[apierror.DeleteClustersKey]; ok {
   253  			message = val.([]string)
   254  		}
   255  		_, err := r.DeleteCluster(ctx, clusterEdgeID, deleteBSLSite)
   256  		if err != nil {
   257  			message = append(message, fmt.Sprintf("failed delete cluster, clusterEdgeId: %s, error: %s", clusterEdgeID, err.Error()))
   258  		}
   259  		deleteErr = deleteErr.AddGenericErrorExtension(apierror.DeleteClustersKey, message)
   260  	}
   261  	isDeleted := len(deleteErr.Ext[apierror.DeleteClustersKey].([]string)) == 0
   262  	if isDeleted {
   263  		return isDeleted, nil
   264  	}
   265  	return isDeleted, deleteErr
   266  }
   267  
   268  // AddSiteToStore is the resolver for the addSiteToStore field.
   269  func (r *mutationResolver) AddSiteToStore(ctx context.Context, clusterEdgeID string, siteID *string) (*model.RegistrationResponse, error) {
   270  	var (
   271  		bslInfoForCluster = &bslHolder{siteInfo: &bsl.BSLInfo{}}
   272  	)
   273  
   274  	clusterInfo, bannerInfo, err := r.GetClusterAndBannerInfo(ctx, clusterEdgeID)
   275  	if err != nil {
   276  		return nil, err
   277  	}
   278  
   279  	createSite := utils.IsNullOrEmpty(siteID)
   280  	organization := bsl.GetOrgShortName(middleware.ForContext(ctx).Organization)
   281  	storeInfo := &model.StoreInfo{
   282  		SiteID:          siteID,
   283  		CreateSite:      &createSite,
   284  		BslOrganization: &organization,
   285  	}
   286  	//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
   287  	bslInfoForCluster.siteInfo, _, err = r.BSLSiteService.GetOrCreateSite(ctx, storeInfo, bannerInfo, clusterInfo.ClusterName, clusterEdgeID)
   288  	if err != nil {
   289  		return nil, err
   290  	}
   291  
   292  	//update sql store site entry
   293  	err = r.StoreClusterService.UpdateStoreSiteID(ctx, clusterEdgeID, bslInfoForCluster.siteInfo.ID)
   294  	if err != nil {
   295  		return nil, err
   296  	}
   297  
   298  	return &model.RegistrationResponse{
   299  		ClusterEdgeID: clusterEdgeID,
   300  		SiteID:        &bslInfoForCluster.siteInfo.ID,
   301  	}, nil
   302  }
   303  
   304  // UpdateClusterFleetVersion is the resolver for the updateClusterFleetVersion field.
   305  func (r *mutationResolver) UpdateClusterFleetVersion(ctx context.Context, clusterEdgeID string, fleetVersion string) (*model.Cluster, error) {
   306  	var previousStoreVersion string
   307  	artifactVersions, err := r.ArtifactsService.GetClusterArtifactVersions(ctx, clusterEdgeID)
   308  	if err != nil {
   309  		return nil, err
   310  	}
   311  
   312  	for _, artifact := range artifactVersions {
   313  		if artifact.Name == fleet.Store {
   314  			previousStoreVersion = artifact.Version
   315  		}
   316  	}
   317  
   318  	if err := r.ArtifactsService.UpdateClusterFleetVersionAndArtifact(ctx, clusterEdgeID, fleetVersion); err != nil {
   319  		return nil, err
   320  	}
   321  
   322  	cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
   323  	if err != nil {
   324  		return nil, err
   325  	}
   326  
   327  	if err := r.UpdateClusterDefaultOptionalPallets(ctx, cluster, fleetVersion, previousStoreVersion); err != nil {
   328  		return nil, err
   329  	}
   330  
   331  	return cluster, nil
   332  }
   333  
   334  // Clusters is the resolver for the clusters field.
   335  func (r *queryResolver) Clusters(ctx context.Context, bannerEdgeID string, labels []string) ([]*model.Cluster, error) {
   336  	return r.StoreClusterService.GetClusters(ctx, bannerEdgeID, labels)
   337  }
   338  
   339  // Cluster is the resolver for the cluster field.
   340  func (r *queryResolver) Cluster(ctx context.Context, clusterEdgeID string) (*model.Cluster, error) {
   341  	return r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
   342  }
   343  
   344  // StoreStatus is the resolver for the storeStatus field.
   345  func (r *queryResolver) StoreStatus(ctx context.Context, clusterEdgeID string) (*model.StoreStatusInfo, error) {
   346  	cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
   347  	if err != nil {
   348  		log.Ctx(ctx).Err(err).Msg("failed to get cluster")
   349  		return nil, err
   350  	}
   351  	response := mapper.ToStoreStatusModel(cluster.Name, cluster.BannerEdgeID, nil, nil)
   352  	active := cluster.Active != nil && *cluster.Active
   353  	if !active { //nolint: nestif
   354  		response.Status = &model.ClusterStatus{
   355  			Status:  mapper.Provisioning,
   356  			Message: "status not found",
   357  		}
   358  		return response, nil
   359  	}
   360  
   361  	clusterStatus, err := r.StoreClusterService.GetClusterStatus(ctx, cluster)
   362  	if err != nil || clusterStatus == nil {
   363  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("error in getting store status for cluster %s", cluster.Name))
   364  		response.Status = &model.ClusterStatus{
   365  			Status:  mapper.Provisioning,
   366  			Message: "status not found",
   367  		}
   368  		return response, nil
   369  	}
   370  	response.Status = clusterStatus.Status
   371  	response.KubeVersion = clusterStatus.KubeVersion
   372  	response.BucketStatus = clusterStatus.BucketStatus
   373  	response.KustomizationStatus = clusterStatus.KustomizationStatus
   374  	return response, nil
   375  }
   376  
   377  // Site is the resolver for the site field.
   378  func (r *queryResolver) Site(ctx context.Context, clusterEdgeID string) (*model.StoreSiteInfo, error) {
   379  	cluster, err := r.StoreClusterService.GetCluster(ctx, clusterEdgeID)
   380  	if err != nil {
   381  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error cluster by clusterEdgeID %s", clusterEdgeID))
   382  		return nil, err
   383  	}
   384  
   385  	// check if BSL Site is empty or null
   386  	if utils.IsNullOrEmpty(cluster.BslSiteID) {
   387  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("bsl_site_id data is missing in DB for clusterEdgeID %s", clusterEdgeID))
   388  		return nil, apierror.New("Site ID is missing and/or empty for this cluster")
   389  	}
   390  
   391  	bannerResponse, err := r.BannerService.GetBannerByEdgeID(ctx, cluster.BannerEdgeID)
   392  	if err != nil {
   393  		return nil, err
   394  	}
   395  
   396  	site, err := r.BSLSiteService.GetBSLSiteByID(ctx, *cluster.BslSiteID, bannerResponse)
   397  	if err != nil {
   398  		log.Ctx(ctx).Err(err).Msg(fmt.Sprintf("Error getting bsl site, id: %s", *cluster.BslSiteID))
   399  		return nil, err
   400  	}
   401  	return mapper.ToStoreSiteInfo(site), nil
   402  }
   403  
   404  // ClusterConfig is the resolver for the clusterConfig field.
   405  func (r *queryResolver) ClusterConfig(ctx context.Context, clusterEdgeID string) (*model.ClusterConfig, error) {
   406  	clusterConfig, err := r.ClusterConfigService.GetClusterConfig(ctx, clusterEdgeID)
   407  	if err != nil {
   408  		return nil, err
   409  	}
   410  	return clusterConfig, nil
   411  }
   412  

View as plain text