github.com/kyma-project/kyma-environment-broker@v0.0.1/internal/reconciler/fake.go (about) 1 package reconciler 2 3 import ( 4 "fmt" 5 "sync" 6 "time" 7 8 reconcilerApi "github.com/kyma-incubator/reconciler/pkg/keb" 9 ) 10 11 /* 12 FakeClient is simulating API and db transactions in Reconciler Inventory 13 14 - registeredCluster is representation of 'inventory_clusters' table 15 each unique clusterVersion should be a separate record 16 - registeredCluster.clusterConfigs is representation of `inventory_cluster_configs` table 17 and it is a map[configVersion]Cluster; it stores different clusterConfigs for the same cluster 18 - registeredCluster.clusterStates is a map[configVersion]State; it simulates returning the status of given cluster in given configVersion 19 - registeredCluster.statusChanges is representation of 'inventory_cluster_config_statuses' table 20 and it is a slice of *StatusChange; it contains all status changes for the cluster 21 22 calling ApplyClusterConfig method on already existing cluster results in adding a new ClusterConfig 23 */ 24 type FakeClient struct { 25 mu sync.Mutex 26 inventoryClusters map[string]*registeredCluster 27 deleted map[string]struct{} 28 } 29 30 type registeredCluster struct { 31 clusterConfigs map[int64]reconcilerApi.Cluster 32 clusterStates map[int64]*reconcilerApi.HTTPClusterResponse 33 statusChanges []*reconcilerApi.StatusChange 34 } 35 36 func NewFakeClient() *FakeClient { 37 return &FakeClient{inventoryClusters: map[string]*registeredCluster{}, deleted: map[string]struct{}{}} 38 } 39 40 // POST /v1/clusters 41 func (c *FakeClient) ApplyClusterConfig(cluster reconcilerApi.Cluster) (*reconcilerApi.HTTPClusterResponse, error) { 42 return c.addToInventory(cluster) 43 } 44 45 // DELETE /v1/clusters/{clusterName} 46 func (c *FakeClient) DeleteCluster(clusterName string) error { 47 c.mu.Lock() 48 defer c.mu.Unlock() 49 _, exists := c.inventoryClusters[clusterName] 50 if !exists { 51 return nil 52 } 53 c.deleted[clusterName] = struct{}{} 54 return nil 55 } 56 57 // GET /v1/clusters/{clusterName}/configs/{configVersion}/status 58 func (c *FakeClient) GetCluster(clusterName string, configVersion int64) (*reconcilerApi.HTTPClusterResponse, error) { 59 c.mu.Lock() 60 defer c.mu.Unlock() 61 62 existingCluster, exists := c.inventoryClusters[clusterName] 63 if !exists { 64 return &reconcilerApi.HTTPClusterResponse{}, fmt.Errorf("not found") 65 } 66 state, exists := existingCluster.clusterStates[configVersion] 67 if !exists { 68 return &reconcilerApi.HTTPClusterResponse{}, fmt.Errorf("not found") 69 } 70 return state, nil 71 } 72 73 // GET v1/clusters/{clusterName}/status 74 func (c *FakeClient) GetLatestCluster(clusterName string) (*reconcilerApi.HTTPClusterResponse, error) { 75 c.mu.Lock() 76 defer c.mu.Unlock() 77 78 existingCluster, exists := c.inventoryClusters[clusterName] 79 if !exists { 80 return &reconcilerApi.HTTPClusterResponse{}, nil 81 } 82 latestConfigVersion := int64(len(existingCluster.clusterStates)) 83 84 return existingCluster.clusterStates[latestConfigVersion], nil 85 } 86 87 // GET v1/clusters/{clusterName}/statusChanges/{offset} 88 // offset is parsed to time.Duration 89 func (c *FakeClient) GetStatusChange(clusterName, offset string) ([]*reconcilerApi.StatusChange, error) { 90 c.mu.Lock() 91 defer c.mu.Unlock() 92 93 existingCluster, exists := c.inventoryClusters[clusterName] 94 if !exists { 95 return []*reconcilerApi.StatusChange{}, nil 96 } 97 return existingCluster.statusChanges, nil 98 } 99 100 func (c *FakeClient) addToInventory(cluster reconcilerApi.Cluster) (*reconcilerApi.HTTPClusterResponse, error) { 101 c.mu.Lock() 102 defer c.mu.Unlock() 103 104 _, exists := c.inventoryClusters[cluster.RuntimeID] 105 106 // initial creation call - cluster does not exist in db 107 if !exists { 108 c.inventoryClusters[cluster.RuntimeID] = ®isteredCluster{ 109 clusterConfigs: map[int64]reconcilerApi.Cluster{ 110 1: cluster, 111 }, 112 clusterStates: map[int64]*reconcilerApi.HTTPClusterResponse{ 113 1: { 114 Cluster: cluster.RuntimeID, 115 ClusterVersion: 1, 116 ConfigurationVersion: 1, 117 Status: "reconcile_pending", 118 }, 119 }, 120 statusChanges: []*reconcilerApi.StatusChange{{ 121 Status: reconcilerApi.StatusReconcilePending, 122 Duration: int64(10 * time.Second), 123 }}, 124 } 125 126 return c.inventoryClusters[cluster.RuntimeID].clusterStates[1], nil 127 } 128 // cluster exists in db - add new configuration version 129 latestConfigVersion := int64(len(c.inventoryClusters[cluster.RuntimeID].clusterStates)) + 1 130 c.inventoryClusters[cluster.RuntimeID].clusterStates[latestConfigVersion] = &reconcilerApi.HTTPClusterResponse{ 131 Cluster: cluster.RuntimeID, 132 ClusterVersion: 1, 133 ConfigurationVersion: latestConfigVersion, 134 Status: "reconcile_pending", 135 } 136 c.inventoryClusters[cluster.RuntimeID].statusChanges = append(c.inventoryClusters[cluster.RuntimeID].statusChanges, &reconcilerApi.StatusChange{ 137 Status: reconcilerApi.StatusReconcilePending, 138 Duration: int64(10 * time.Second), 139 }) 140 c.inventoryClusters[cluster.RuntimeID].clusterConfigs[latestConfigVersion] = cluster 141 142 return c.inventoryClusters[cluster.RuntimeID].clusterStates[latestConfigVersion], nil 143 } 144 145 func (c *FakeClient) ChangeClusterState(clusterName string, clusterVersion int64, desiredState reconcilerApi.Status) { 146 c.mu.Lock() 147 defer c.mu.Unlock() 148 149 c.inventoryClusters[clusterName].clusterStates[clusterVersion].Status = desiredState 150 c.inventoryClusters[clusterName].statusChanges = append(c.inventoryClusters[clusterName].statusChanges, &reconcilerApi.StatusChange{ 151 Status: desiredState, 152 Duration: int64(10 * time.Second), 153 }) 154 } 155 156 func (c *FakeClient) LastClusterConfig(runtimeID string) (*reconcilerApi.Cluster, error) { 157 cluster, found := c.inventoryClusters[runtimeID] 158 if !found { 159 return nil, fmt.Errorf("cluster not found in clusters inventory") 160 } 161 return getLastClusterConfig(cluster) 162 } 163 164 func (c *FakeClient) IsBeingDeleted(id string) bool { 165 c.mu.Lock() 166 defer c.mu.Unlock() 167 _, exists := c.deleted[id] 168 if exists { 169 return true 170 } 171 172 return false 173 } 174 175 func (c *FakeClient) ClusterExists(id string) bool { 176 _, found := c.inventoryClusters[id] 177 return found 178 } 179 180 func getLastClusterConfig(cluster *registeredCluster) (*reconcilerApi.Cluster, error) { 181 clusterConfig, found := cluster.clusterConfigs[int64(len(cluster.clusterConfigs))] 182 if !found { 183 return nil, fmt.Errorf("cluster config not found in cluster configs inventory") 184 } 185 return &clusterConfig, nil 186 }