github.com/in4it/ecs-deploy@v0.0.42-0.20240508120354-ed77ff16df25/provider/ecs/appmesh.go (about) 1 package ecs 2 3 import ( 4 "time" 5 6 "github.com/aws/aws-sdk-go/aws" 7 "github.com/aws/aws-sdk-go/aws/session" 8 "github.com/aws/aws-sdk-go/service/appmesh" 9 "github.com/in4it/ecs-deploy/service" 10 "github.com/juju/loggo" 11 ) 12 13 // logging 14 var appmeshLogger = loggo.GetLogger("appmesh") 15 16 // AppMesh struct 17 type AppMesh struct { 18 } 19 20 //AppMeshHealthCheck is a struct that contains the healthcheck for the appmesh 21 type AppMeshHealthCheck struct { 22 HealthyThreshold int64 23 IntervalMillis int64 24 Path string 25 Port int64 26 Protocol string 27 TimeoutMillis int64 28 UnhealthyThreshold int64 29 } 30 31 func (a *AppMesh) listVirtualNodes(meshName string) (map[string]string, error) { 32 svc := appmesh.New(session.New()) 33 pageNum := 0 34 result := make(map[string]string) 35 input := &appmesh.ListVirtualNodesInput{ 36 MeshName: aws.String(meshName), 37 } 38 err := svc.ListVirtualNodesPages(input, 39 func(page *appmesh.ListVirtualNodesOutput, lastPage bool) bool { 40 pageNum++ 41 for _, virtualNode := range page.VirtualNodes { 42 result[aws.StringValue(virtualNode.VirtualNodeName)] = aws.StringValue(virtualNode.Arn) 43 } 44 return pageNum <= 100 45 }) 46 if err != nil { 47 appmeshLogger.Errorf(err.Error()) 48 return result, err 49 } 50 return result, nil 51 } 52 53 func (a *AppMesh) listVirtualServices(meshName string) (map[string]string, error) { 54 svc := appmesh.New(session.New()) 55 pageNum := 0 56 result := make(map[string]string) 57 input := &appmesh.ListVirtualServicesInput{ 58 MeshName: aws.String(meshName), 59 } 60 err := svc.ListVirtualServicesPages(input, 61 func(page *appmesh.ListVirtualServicesOutput, lastPage bool) bool { 62 pageNum++ 63 for _, virtualNode := range page.VirtualServices { 64 result[aws.StringValue(virtualNode.VirtualServiceName)] = aws.StringValue(virtualNode.Arn) 65 } 66 return pageNum <= 100 67 }) 68 if err != nil { 69 appmeshLogger.Errorf(err.Error()) 70 return result, err 71 } 72 return result, nil 73 } 74 75 func (a *AppMesh) listVirtualRouters(meshName string) (map[string]string, error) { 76 svc := appmesh.New(session.New()) 77 pageNum := 0 78 result := make(map[string]string) 79 input := &appmesh.ListVirtualRoutersInput{ 80 MeshName: aws.String(meshName), 81 } 82 err := svc.ListVirtualRoutersPages(input, 83 func(page *appmesh.ListVirtualRoutersOutput, lastPage bool) bool { 84 pageNum++ 85 for _, virtualRouter := range page.VirtualRouters { 86 result[aws.StringValue(virtualRouter.VirtualRouterName)] = aws.StringValue(virtualRouter.Arn) 87 } 88 return pageNum <= 100 89 }) 90 if err != nil { 91 appmeshLogger.Errorf(err.Error()) 92 return result, err 93 } 94 return result, nil 95 } 96 97 func (a *AppMesh) createVirtualNode(virtualNodeName, virtualNodeDNS, meshName string, servicePort int64, healthcheck AppMeshHealthCheck, backends []string) error { 98 var appmeshBackends []*appmesh.Backend 99 100 for _, backend := range backends { 101 appmeshBackends = append(appmeshBackends, &appmesh.Backend{ 102 VirtualService: &appmesh.VirtualServiceBackend{ 103 VirtualServiceName: aws.String(backend), 104 }, 105 }) 106 } 107 108 svc := appmesh.New(session.New()) 109 input := &appmesh.CreateVirtualNodeInput{ 110 MeshName: aws.String(meshName), 111 Spec: &appmesh.VirtualNodeSpec{ 112 Backends: appmeshBackends, 113 Listeners: []*appmesh.Listener{ 114 { 115 HealthCheck: &appmesh.HealthCheckPolicy{ 116 HealthyThreshold: aws.Int64(healthcheck.HealthyThreshold), 117 IntervalMillis: aws.Int64(healthcheck.IntervalMillis), 118 Path: aws.String(healthcheck.Path), 119 Port: aws.Int64(healthcheck.Port), 120 Protocol: aws.String(healthcheck.Protocol), 121 TimeoutMillis: aws.Int64(healthcheck.TimeoutMillis), 122 UnhealthyThreshold: aws.Int64(healthcheck.UnhealthyThreshold), 123 }, 124 PortMapping: &appmesh.PortMapping{ 125 Port: aws.Int64(servicePort), 126 Protocol: aws.String("http"), 127 }, 128 }, 129 }, 130 ServiceDiscovery: &appmesh.ServiceDiscovery{ 131 Dns: &appmesh.DnsServiceDiscovery{ 132 Hostname: aws.String(virtualNodeDNS), 133 }, 134 }, 135 }, 136 VirtualNodeName: aws.String(virtualNodeName), 137 } 138 139 _, err := svc.CreateVirtualNode(input) 140 if err != nil { 141 return err 142 } 143 144 return nil 145 } 146 147 func (a *AppMesh) updateVirtualNode(virtualNodeName, virtualNodeDNS, meshName string, servicePort int64, healthcheck AppMeshHealthCheck, backends []string) error { 148 var appmeshBackends []*appmesh.Backend 149 150 for _, backend := range backends { 151 appmeshBackends = append(appmeshBackends, &appmesh.Backend{ 152 VirtualService: &appmesh.VirtualServiceBackend{ 153 VirtualServiceName: aws.String(backend), 154 }, 155 }) 156 } 157 158 svc := appmesh.New(session.New()) 159 input := &appmesh.UpdateVirtualNodeInput{ 160 MeshName: aws.String(meshName), 161 Spec: &appmesh.VirtualNodeSpec{ 162 Backends: appmeshBackends, 163 Listeners: []*appmesh.Listener{ 164 { 165 HealthCheck: &appmesh.HealthCheckPolicy{ 166 HealthyThreshold: aws.Int64(healthcheck.HealthyThreshold), 167 IntervalMillis: aws.Int64(healthcheck.IntervalMillis), 168 Path: aws.String(healthcheck.Path), 169 Port: aws.Int64(healthcheck.Port), 170 Protocol: aws.String(healthcheck.Protocol), 171 TimeoutMillis: aws.Int64(healthcheck.TimeoutMillis), 172 UnhealthyThreshold: aws.Int64(healthcheck.UnhealthyThreshold), 173 }, 174 PortMapping: &appmesh.PortMapping{ 175 Port: aws.Int64(servicePort), 176 Protocol: aws.String("http"), 177 }, 178 }, 179 }, 180 ServiceDiscovery: &appmesh.ServiceDiscovery{ 181 Dns: &appmesh.DnsServiceDiscovery{ 182 Hostname: aws.String(virtualNodeDNS), 183 }, 184 }, 185 }, 186 VirtualNodeName: aws.String(virtualNodeName), 187 } 188 189 _, err := svc.UpdateVirtualNode(input) 190 if err != nil { 191 return err 192 } 193 194 return nil 195 } 196 197 func (a *AppMesh) createVirtualServiceWithVirtualNode(virtualServiceName, virtualNodeName, meshName string) error { 198 svc := appmesh.New(session.New()) 199 input := &appmesh.CreateVirtualServiceInput{ 200 MeshName: aws.String(meshName), 201 Spec: &appmesh.VirtualServiceSpec{ 202 Provider: &appmesh.VirtualServiceProvider{ 203 VirtualNode: &appmesh.VirtualNodeServiceProvider{ 204 VirtualNodeName: aws.String(virtualNodeName), 205 }, 206 }, 207 }, 208 VirtualServiceName: aws.String(virtualServiceName), 209 } 210 211 _, err := svc.CreateVirtualService(input) 212 if err != nil { 213 return err 214 } 215 216 return nil 217 } 218 219 func (a *AppMesh) createVirtualServiceWithVirtualRouter(virtualServiceName, virtualRouterName, meshName string) error { 220 svc := appmesh.New(session.New()) 221 input := &appmesh.CreateVirtualServiceInput{ 222 MeshName: aws.String(meshName), 223 Spec: &appmesh.VirtualServiceSpec{ 224 Provider: &appmesh.VirtualServiceProvider{ 225 VirtualRouter: &appmesh.VirtualRouterServiceProvider{ 226 VirtualRouterName: aws.String(virtualRouterName), 227 }, 228 }, 229 }, 230 VirtualServiceName: aws.String(virtualServiceName), 231 } 232 233 _, err := svc.CreateVirtualService(input) 234 if err != nil { 235 return err 236 } 237 238 return nil 239 } 240 241 func (a *AppMesh) updateVirtualServiceWithVirtualRouter(virtualServiceName, virtualRouterName, meshName string) error { 242 svc := appmesh.New(session.New()) 243 input := &appmesh.UpdateVirtualServiceInput{ 244 MeshName: aws.String(meshName), 245 Spec: &appmesh.VirtualServiceSpec{ 246 Provider: &appmesh.VirtualServiceProvider{ 247 VirtualRouter: &appmesh.VirtualRouterServiceProvider{ 248 VirtualRouterName: aws.String(virtualRouterName), 249 }, 250 }, 251 }, 252 VirtualServiceName: aws.String(virtualServiceName), 253 } 254 255 _, err := svc.UpdateVirtualService(input) 256 if err != nil { 257 return err 258 } 259 260 return nil 261 } 262 263 func (a *AppMesh) createVirtualRouter(virtualRouterName string, meshName string, servicePort int64) error { 264 svc := appmesh.New(session.New()) 265 input := &appmesh.CreateVirtualRouterInput{ 266 MeshName: aws.String(meshName), 267 Spec: &appmesh.VirtualRouterSpec{ 268 Listeners: []*appmesh.VirtualRouterListener{ 269 { 270 PortMapping: &appmesh.PortMapping{ 271 Port: aws.Int64(servicePort), 272 Protocol: aws.String("http"), 273 }, 274 }, 275 }, 276 }, 277 VirtualRouterName: aws.String(virtualRouterName), 278 } 279 280 _, err := svc.CreateVirtualRouter(input) 281 if err != nil { 282 return err 283 } 284 285 return nil 286 } 287 288 func (a *AppMesh) createRoute(routeName, virtualRouterName, virtualNodeName, hostname string, mesh service.DeployAppMesh) error { 289 perRetryTimeout, err := time.ParseDuration(mesh.RetryPolicy.PerRetryTimeout) 290 if err != nil { 291 return err 292 } 293 svc := appmesh.New(session.New()) 294 input := &appmesh.CreateRouteInput{ 295 MeshName: aws.String(mesh.Name), 296 Spec: &appmesh.RouteSpec{ 297 HttpRoute: &appmesh.HttpRoute{ 298 Match: &appmesh.HttpRouteMatch{ 299 Prefix: aws.String("/"), 300 /*Headers: []*appmesh.HttpRouteHeader{ 301 { 302 Name: aws.String("Host"), 303 Match: &appmesh.HeaderMatchMethod{ 304 Exact: aws.String(hostname), 305 }, 306 }, 307 },*/ 308 }, 309 Action: &appmesh.HttpRouteAction{ 310 WeightedTargets: []*appmesh.WeightedTarget{ 311 { 312 VirtualNode: aws.String(virtualNodeName), 313 Weight: aws.Int64(100), 314 }, 315 }, 316 }, 317 RetryPolicy: &appmesh.HttpRetryPolicy{ 318 HttpRetryEvents: aws.StringSlice(mesh.RetryPolicy.HTTPRetryEvents), 319 MaxRetries: aws.Int64(mesh.RetryPolicy.MaxRetries), 320 PerRetryTimeout: &appmesh.Duration{ 321 Unit: aws.String("ms"), 322 Value: aws.Int64(perRetryTimeout.Milliseconds()), 323 }, 324 TcpRetryEvents: aws.StringSlice(mesh.RetryPolicy.TcpRetryEvents), 325 }, 326 }, 327 Priority: aws.Int64(100), 328 }, 329 RouteName: aws.String(routeName), 330 VirtualRouterName: aws.String(virtualRouterName), 331 } 332 333 _, err = svc.CreateRoute(input) 334 if err != nil { 335 return err 336 } 337 338 return nil 339 }