(ctx context.Context, project *types.Project, name string, n *types.NetworkConfig)
| 1331 | } |
| 1332 | |
| 1333 | func (s *composeService) resolveOrCreateNetwork(ctx context.Context, project *types.Project, name string, n *types.NetworkConfig) (string, error) { //nolint:gocyclo |
| 1334 | // This is containers that could be left after a diverged network was removed |
| 1335 | var dangledContainers Containers |
| 1336 | |
| 1337 | // First, try to find a unique network matching by name or ID |
| 1338 | res, err := s.apiClient().NetworkInspect(ctx, n.Name, client.NetworkInspectOptions{}) |
| 1339 | if err == nil { |
| 1340 | inspect := res.Network |
| 1341 | // NetworkInspect will match on ID prefix, so double check we get the expected one |
| 1342 | // as looking for network named `db` we could erroneously match network ID `db9086999caf` |
| 1343 | if inspect.Name == n.Name || inspect.ID == n.Name { |
| 1344 | p, ok := inspect.Labels[api.ProjectLabel] |
| 1345 | if !ok { |
| 1346 | logrus.Warnf("a network with name %s exists but was not created by compose.\n"+ |
| 1347 | "Set `external: true` to use an existing network", n.Name) |
| 1348 | } else if p != project.Name { |
| 1349 | logrus.Warnf("a network with name %s exists but was not created for project %q.\n"+ |
| 1350 | "Set `external: true` to use an existing network", n.Name, project.Name) |
| 1351 | } |
| 1352 | if inspect.Labels[api.NetworkLabel] != name { |
| 1353 | return "", fmt.Errorf( |
| 1354 | "network %s was found but has incorrect label %s set to %q (expected: %q)", |
| 1355 | n.Name, |
| 1356 | api.NetworkLabel, |
| 1357 | inspect.Labels[api.NetworkLabel], |
| 1358 | name, |
| 1359 | ) |
| 1360 | } |
| 1361 | |
| 1362 | hash := inspect.Labels[api.ConfigHashLabel] |
| 1363 | expected, err := NetworkHash(n) |
| 1364 | if err != nil { |
| 1365 | return "", err |
| 1366 | } |
| 1367 | if hash == "" || hash == expected { |
| 1368 | return inspect.ID, nil |
| 1369 | } |
| 1370 | |
| 1371 | dangledContainers, err = s.removeDivergedNetwork(ctx, project, name, n) |
| 1372 | if err != nil { |
| 1373 | return "", err |
| 1374 | } |
| 1375 | } |
| 1376 | } |
| 1377 | // ignore other errors. Typically, an ambiguous request by name results in some generic `invalidParameter` error |
| 1378 | |
| 1379 | // Either not found, or name is ambiguous - use NetworkList to list by name |
| 1380 | nwList, err := s.apiClient().NetworkList(ctx, client.NetworkListOptions{ |
| 1381 | Filters: make(client.Filters).Add("name", n.Name), |
| 1382 | }) |
| 1383 | if err != nil { |
| 1384 | return "", err |
| 1385 | } |
| 1386 | |
| 1387 | // NetworkList Matches all or part of a network name, so we have to filter for a strict match |
| 1388 | networks := slices.DeleteFunc(nwList.Items, func(net network.Summary) bool { |
| 1389 | return net.Name != n.Name |
| 1390 | }) |
no test coverage detected