github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/storage/postsql/write.go (about)

     1  package postsql
     2  
     3  import (
     4  	"time"
     5  
     6  	"github.com/google/uuid"
     7  	"github.com/kyma-project/kyma-environment-broker/common/events"
     8  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dbmodel"
     9  
    10  	"github.com/gocraft/dbr"
    11  	"github.com/kyma-project/kyma-environment-broker/internal/storage/dberr"
    12  	"github.com/lib/pq"
    13  )
    14  
    15  const (
    16  	UniqueViolationErrorCode = "23505"
    17  )
    18  
    19  type writeSession struct {
    20  	session     *dbr.Session
    21  	transaction *dbr.Tx
    22  }
    23  
    24  func (ws writeSession) InsertInstance(instance dbmodel.InstanceDTO) dberr.Error {
    25  	_, err := ws.insertInto(InstancesTableName).
    26  		Pair("instance_id", instance.InstanceID).
    27  		Pair("runtime_id", instance.RuntimeID).
    28  		Pair("global_account_id", instance.GlobalAccountID).
    29  		Pair("subscription_global_account_id", instance.SubscriptionGlobalAccountID).
    30  		Pair("sub_account_id", instance.SubAccountID).
    31  		Pair("service_id", instance.ServiceID).
    32  		Pair("service_name", instance.ServiceName).
    33  		Pair("service_plan_id", instance.ServicePlanID).
    34  		Pair("service_plan_name", instance.ServicePlanName).
    35  		Pair("dashboard_url", instance.DashboardURL).
    36  		Pair("provisioning_parameters", instance.ProvisioningParameters).
    37  		Pair("provider_region", instance.ProviderRegion).
    38  		Pair("provider", instance.Provider).
    39  		Pair("deleted_at", instance.DeletedAt).
    40  		Pair("expired_at", instance.ExpiredAt).
    41  		Pair("version", instance.Version).
    42  		Exec()
    43  
    44  	if err != nil {
    45  		if err, ok := err.(*pq.Error); ok {
    46  			if err.Code == UniqueViolationErrorCode {
    47  				return dberr.AlreadyExists("operation with id %s already exist", instance.InstanceID)
    48  			}
    49  		}
    50  		return dberr.Internal("Failed to insert record to Instance table: %s", err)
    51  	}
    52  
    53  	return nil
    54  }
    55  
    56  func (ws writeSession) DeleteInstance(instanceID string) dberr.Error {
    57  	_, err := ws.deleteFrom(InstancesTableName).
    58  		Where(dbr.Eq("instance_id", instanceID)).
    59  		Exec()
    60  
    61  	if err != nil {
    62  		return dberr.Internal("Failed to delete record from Instance table: %s", err)
    63  	}
    64  	return nil
    65  }
    66  
    67  func (ws writeSession) UpdateInstance(instance dbmodel.InstanceDTO) dberr.Error {
    68  	res, err := ws.update(InstancesTableName).
    69  		Where(dbr.Eq("instance_id", instance.InstanceID)).
    70  		Where(dbr.Eq("version", instance.Version)).
    71  		Set("instance_id", instance.InstanceID).
    72  		Set("runtime_id", instance.RuntimeID).
    73  		Set("global_account_id", instance.GlobalAccountID).
    74  		Set("subscription_global_account_id", instance.SubscriptionGlobalAccountID).
    75  		Set("service_id", instance.ServiceID).
    76  		Set("service_plan_id", instance.ServicePlanID).
    77  		Set("dashboard_url", instance.DashboardURL).
    78  		Set("provisioning_parameters", instance.ProvisioningParameters).
    79  		Set("provider_region", instance.ProviderRegion).
    80  		Set("provider", instance.Provider).
    81  		Set("updated_at", time.Now()).
    82  		Set("deleted_at", instance.DeletedAt).
    83  		Set("version", instance.Version+1).
    84  		Set("expired_at", instance.ExpiredAt).
    85  		Exec()
    86  	if err != nil {
    87  		return dberr.Internal("Failed to update record to Instance table: %s", err)
    88  	}
    89  	rAffected, err := res.RowsAffected()
    90  	if err != nil {
    91  		// the optimistic locking requires numbers of rows affected
    92  		return dberr.Internal("the DB driver does not support RowsAffected operation")
    93  	}
    94  	if rAffected == int64(0) {
    95  		return dberr.NotFound("Cannot find Instance with ID:'%s' Version: %v", instance.InstanceID, instance.Version)
    96  	}
    97  
    98  	return nil
    99  }
   100  
   101  func (ws writeSession) InsertOperation(op dbmodel.OperationDTO) dberr.Error {
   102  	_, err := ws.insertInto(OperationTableName).
   103  		Pair("id", op.ID).
   104  		Pair("instance_id", op.InstanceID).
   105  		Pair("version", op.Version).
   106  		Pair("created_at", op.CreatedAt).
   107  		Pair("updated_at", op.UpdatedAt).
   108  		Pair("description", op.Description).
   109  		Pair("state", op.State).
   110  		Pair("target_operation_id", op.TargetOperationID).
   111  		Pair("type", op.Type).
   112  		Pair("data", op.Data).
   113  		Pair("orchestration_id", op.OrchestrationID.String).
   114  		Pair("provisioning_parameters", op.ProvisioningParameters.String).
   115  		Pair("finished_stages", op.FinishedStages).
   116  		Exec()
   117  
   118  	if err != nil {
   119  		if err, ok := err.(*pq.Error); ok {
   120  			if err.Code == UniqueViolationErrorCode {
   121  				return dberr.AlreadyExists("operation with id %s already exist", op.ID)
   122  			}
   123  		}
   124  		return dberr.Internal("Failed to insert record to operations table: %s", err)
   125  	}
   126  
   127  	return nil
   128  }
   129  
   130  func (ws writeSession) InsertOrchestration(o dbmodel.OrchestrationDTO) dberr.Error {
   131  	_, err := ws.insertInto(OrchestrationTableName).
   132  		Pair("orchestration_id", o.OrchestrationID).
   133  		Pair("created_at", o.CreatedAt).
   134  		Pair("updated_at", o.UpdatedAt).
   135  		Pair("description", o.Description).
   136  		Pair("state", o.State).
   137  		Pair("type", o.Type).
   138  		Pair("parameters", o.Parameters).
   139  		Exec()
   140  
   141  	if err != nil {
   142  		if err, ok := err.(*pq.Error); ok {
   143  			if err.Code == UniqueViolationErrorCode {
   144  				return dberr.AlreadyExists("Orchestration with id %s already exist", o.OrchestrationID)
   145  			}
   146  		}
   147  		return dberr.Internal("Failed to insert record to orchestration table: %s", err)
   148  	}
   149  
   150  	return nil
   151  }
   152  
   153  func (ws writeSession) UpdateOrchestration(o dbmodel.OrchestrationDTO) dberr.Error {
   154  	res, err := ws.update(OrchestrationTableName).
   155  		Where(dbr.Eq("orchestration_id", o.OrchestrationID)).
   156  		Set("created_at", o.CreatedAt).
   157  		Set("updated_at", o.UpdatedAt).
   158  		Set("description", o.Description).
   159  		Set("state", o.State).
   160  		Set("type", o.Type).
   161  		Set("parameters", o.Parameters).
   162  		Exec()
   163  
   164  	if err != nil {
   165  		if err == dbr.ErrNotFound {
   166  			return dberr.NotFound("Cannot find Orchestration with ID:'%s'", o.OrchestrationID)
   167  		}
   168  		return dberr.Internal("Failed to update record to Orchestration table: %s", err)
   169  	}
   170  	rAffected, e := res.RowsAffected()
   171  	if e != nil {
   172  		// the optimistic locking requires numbers of rows affected
   173  		return dberr.Internal("the DB driver does not support RowsAffected operation")
   174  	}
   175  	if rAffected == int64(0) {
   176  		return dberr.NotFound("Cannot find Orchestration with ID:'%s'", o.OrchestrationID)
   177  	}
   178  
   179  	return nil
   180  }
   181  
   182  func (ws writeSession) InsertRuntimeState(state dbmodel.RuntimeStateDTO) dberr.Error {
   183  	_, err := ws.insertInto(RuntimeStateTableName).
   184  		Pair("id", state.ID).
   185  		Pair("operation_id", state.OperationID).
   186  		Pair("runtime_id", state.RuntimeID).
   187  		Pair("created_at", state.CreatedAt).
   188  		Pair("kyma_version", state.KymaVersion).
   189  		Pair("k8s_version", state.K8SVersion).
   190  		Pair("kyma_config", state.KymaConfig).
   191  		Pair("cluster_config", state.ClusterConfig).
   192  		Pair("cluster_setup", state.ClusterSetup).
   193  		Exec()
   194  
   195  	if err != nil {
   196  		if err, ok := err.(*pq.Error); ok {
   197  			if err.Code == UniqueViolationErrorCode {
   198  				return dberr.AlreadyExists("RuntimeState with id %s already exist", state.ID)
   199  			}
   200  		}
   201  		return dberr.Internal("Failed to insert record to RuntimeState table: %s", err)
   202  	}
   203  
   204  	return nil
   205  }
   206  
   207  func (ws writeSession) UpdateOperation(op dbmodel.OperationDTO) dberr.Error {
   208  	res, err := ws.update(OperationTableName).
   209  		Where(dbr.Eq("id", op.ID)).
   210  		Where(dbr.Eq("version", op.Version)).
   211  		Set("instance_id", op.InstanceID).
   212  		Set("version", op.Version+1).
   213  		Set("created_at", op.CreatedAt).
   214  		Set("updated_at", op.UpdatedAt).
   215  		Set("description", op.Description).
   216  		Set("state", op.State).
   217  		Set("target_operation_id", op.TargetOperationID).
   218  		Set("type", op.Type).
   219  		Set("data", op.Data).
   220  		Set("orchestration_id", op.OrchestrationID.String).
   221  		Set("provisioning_parameters", op.ProvisioningParameters.String).
   222  		Set("finished_stages", op.FinishedStages).
   223  		Exec()
   224  
   225  	if err != nil {
   226  		if err == dbr.ErrNotFound {
   227  			return dberr.NotFound("Cannot find Operation with ID:'%s'", op.ID)
   228  		}
   229  		return dberr.Internal("Failed to update record to Operation table: %s", err)
   230  	}
   231  	rAffected, e := res.RowsAffected()
   232  	if e != nil {
   233  		// the optimistic locking requires numbers of rows affected
   234  		return dberr.Internal("the DB driver does not support RowsAffected operation")
   235  	}
   236  	if rAffected == int64(0) {
   237  		return dberr.NotFound("Cannot find Operation with ID:'%s' Version: %v", op.ID, op.Version)
   238  	}
   239  
   240  	return nil
   241  }
   242  
   243  func (ws writeSession) InsertEvent(level events.EventLevel, message, instanceID, operationID string) dberr.Error {
   244  	_, err := ws.insertInto("events").
   245  		Pair("id", uuid.NewString()).
   246  		Pair("level", level).
   247  		Pair("instance_id", instanceID).
   248  		Pair("operation_id", operationID).
   249  		Pair("message", message).
   250  		Pair("created_at", time.Now()).
   251  		Exec()
   252  	if err != nil {
   253  		return dberr.Internal("Failed to insert event: %s", err)
   254  	}
   255  	return nil
   256  }
   257  
   258  func (ws writeSession) DeleteEvents(until time.Time) dberr.Error {
   259  	_, err := ws.deleteFrom("events").
   260  		Where(dbr.Lte("created_at", until)).
   261  		Exec()
   262  	if err != nil {
   263  		return dberr.Internal("failed to delete events created until %v: %v", until.Format(time.RFC1123Z), err)
   264  	}
   265  	return nil
   266  }
   267  
   268  func (ws writeSession) Commit() dberr.Error {
   269  	err := ws.transaction.Commit()
   270  	if err != nil {
   271  		return dberr.Internal("Failed to commit transaction: %s", err)
   272  	}
   273  
   274  	return nil
   275  }
   276  
   277  func (ws writeSession) RollbackUnlessCommitted() {
   278  	ws.transaction.RollbackUnlessCommitted()
   279  }
   280  
   281  func (ws writeSession) insertInto(table string) *dbr.InsertStmt {
   282  	if ws.transaction != nil {
   283  		return ws.transaction.InsertInto(table)
   284  	}
   285  
   286  	return ws.session.InsertInto(table)
   287  }
   288  
   289  func (ws writeSession) deleteFrom(table string) *dbr.DeleteStmt {
   290  	if ws.transaction != nil {
   291  		return ws.transaction.DeleteFrom(table)
   292  	}
   293  
   294  	return ws.session.DeleteFrom(table)
   295  }
   296  
   297  func (ws writeSession) update(table string) *dbr.UpdateStmt {
   298  	if ws.transaction != nil {
   299  		return ws.transaction.Update(table)
   300  	}
   301  
   302  	return ws.session.Update(table)
   303  }