|
7 | 7 | "fmt"
|
8 | 8 | "log"
|
9 | 9 | "maps"
|
| 10 | + "net/http" |
10 | 11 | "os"
|
11 | 12 | "strings"
|
12 | 13 | "testing"
|
@@ -1426,6 +1427,316 @@ func SetupProjectsAndGetAccessToken(org, billing, pid, service string, config *t
|
1426 | 1427 | return accessToken, nil
|
1427 | 1428 | }
|
1428 | 1429 |
|
| 1430 | +// For bootstrapping Developer Connect git repository link |
| 1431 | +const SharedGitRepositoryLinkIdPrefix = "tf-bootstrap-git-repository-" |
| 1432 | + |
| 1433 | +func BootstrapGitRepository(t *testing.T, gitRepositoryLinkId, location, cloneUri, parentConnectionId string) string { |
| 1434 | + gitRepositoryLinkId = SharedGitRepositoryLinkIdPrefix + gitRepositoryLinkId |
| 1435 | + |
| 1436 | + config := BootstrapConfig(t) |
| 1437 | + if config == nil { |
| 1438 | + t.Fatal("Could not bootstrap config.") |
| 1439 | + } |
| 1440 | + |
| 1441 | + log.Printf("[DEBUG] Getting shared git repository link %q", gitRepositoryLinkId) |
| 1442 | + |
| 1443 | + getURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s/gitRepositoryLinks/%s", |
| 1444 | + config.DeveloperConnectBasePath, config.Project, location, parentConnectionId, gitRepositoryLinkId) |
| 1445 | + |
| 1446 | + headers := make(http.Header) |
| 1447 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1448 | + Config: config, |
| 1449 | + Method: "GET", |
| 1450 | + Project: config.Project, |
| 1451 | + RawURL: getURL, |
| 1452 | + UserAgent: config.UserAgent, |
| 1453 | + Headers: headers, |
| 1454 | + }) |
| 1455 | + |
| 1456 | + if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) { |
| 1457 | + log.Printf("[DEBUG] Git repository link %q not found, bootstrapping", gitRepositoryLinkId) |
| 1458 | + obj := map[string]interface{}{ |
| 1459 | + "clone_uri": cloneUri, |
| 1460 | + "annotations": map[string]string{}, |
| 1461 | + } |
| 1462 | + |
| 1463 | + postURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s/gitRepositoryLinks?gitRepositoryLinkId=%s", |
| 1464 | + config.DeveloperConnectBasePath, config.Project, location, parentConnectionId, gitRepositoryLinkId) |
| 1465 | + headers := make(http.Header) |
| 1466 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1467 | + Config: config, |
| 1468 | + Method: "POST", |
| 1469 | + Project: config.Project, |
| 1470 | + RawURL: postURL, |
| 1471 | + UserAgent: config.UserAgent, |
| 1472 | + Body: obj, |
| 1473 | + Timeout: 20 * time.Minute, |
| 1474 | + Headers: headers, |
| 1475 | + }) |
| 1476 | + if err != nil { |
| 1477 | + t.Fatalf("Error bootstrapping git repository link %q: %s", gitRepositoryLinkId, err) |
| 1478 | + } |
| 1479 | + |
| 1480 | + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1481 | + Config: config, |
| 1482 | + Method: "GET", |
| 1483 | + Project: config.Project, |
| 1484 | + RawURL: getURL, |
| 1485 | + UserAgent: config.UserAgent, |
| 1486 | + Timeout: 20 * time.Minute, |
| 1487 | + Headers: headers, |
| 1488 | + }) |
| 1489 | + if err != nil { |
| 1490 | + t.Fatalf("Error getting git repository link %q: %s", gitRepositoryLinkId, err) |
| 1491 | + } |
| 1492 | + } |
| 1493 | + |
| 1494 | + return gitRepositoryLinkId |
| 1495 | +} |
| 1496 | + |
| 1497 | +const SharedConnectionIdPrefix = "tf-bootstrap-developer-connect-connection-" |
| 1498 | + |
| 1499 | +// For bootstrapping Developer Connect connection resources |
| 1500 | +func BootstrapDeveloperConnection(t *testing.T, connectionId, location, tokenResource string, appInstallationId int) string { |
| 1501 | + connectionId = SharedConnectionIdPrefix + connectionId |
| 1502 | + |
| 1503 | + config := BootstrapConfig(t) |
| 1504 | + if config == nil { |
| 1505 | + t.Fatal("Could not bootstrap config.") |
| 1506 | + } |
| 1507 | + |
| 1508 | + log.Printf("[DEBUG] Getting shared developer connection %q", connectionId) |
| 1509 | + |
| 1510 | + getURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections/%s", |
| 1511 | + config.DeveloperConnectBasePath, config.Project, location, connectionId) |
| 1512 | + |
| 1513 | + headers := make(http.Header) |
| 1514 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1515 | + Config: config, |
| 1516 | + Method: "GET", |
| 1517 | + Project: config.Project, |
| 1518 | + RawURL: getURL, |
| 1519 | + UserAgent: config.UserAgent, |
| 1520 | + Headers: headers, |
| 1521 | + }) |
| 1522 | + |
| 1523 | + if err != nil { |
| 1524 | + log.Printf("[DEBUG] Developer connection %q not found, bootstrapping", connectionId) |
| 1525 | + authorizerCredential := map[string]string{ |
| 1526 | + "oauth_token_secret_version": tokenResource, |
| 1527 | + } |
| 1528 | + githubConfig := map[string]interface{}{ |
| 1529 | + "github_app": "DEVELOPER_CONNECT", |
| 1530 | + "app_installation_id": appInstallationId, |
| 1531 | + "authorizer_credential": authorizerCredential, |
| 1532 | + } |
| 1533 | + obj := map[string]interface{}{ |
| 1534 | + "disabled": false, |
| 1535 | + "github_config": githubConfig, |
| 1536 | + } |
| 1537 | + |
| 1538 | + postURL := fmt.Sprintf("%sprojects/%s/locations/%s/connections?connectionId=%s", |
| 1539 | + config.DeveloperConnectBasePath, config.Project, location, connectionId) |
| 1540 | + headers := make(http.Header) |
| 1541 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1542 | + Config: config, |
| 1543 | + Method: "POST", |
| 1544 | + Project: config.Project, |
| 1545 | + RawURL: postURL, |
| 1546 | + UserAgent: config.UserAgent, |
| 1547 | + Body: obj, |
| 1548 | + Timeout: 20 * time.Minute, |
| 1549 | + Headers: headers, |
| 1550 | + }) |
| 1551 | + if err != nil { |
| 1552 | + t.Fatalf("Error bootstrapping developer connection %q: %s", connectionId, err) |
| 1553 | + } |
| 1554 | + |
| 1555 | + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1556 | + Config: config, |
| 1557 | + Method: "GET", |
| 1558 | + Project: config.Project, |
| 1559 | + RawURL: getURL, |
| 1560 | + UserAgent: config.UserAgent, |
| 1561 | + Timeout: 20 * time.Minute, |
| 1562 | + Headers: headers, |
| 1563 | + }) |
| 1564 | + if err != nil { |
| 1565 | + t.Fatalf("Error getting developer connection %q: %s", connectionId, err) |
| 1566 | + } |
| 1567 | + } |
| 1568 | + |
| 1569 | + return connectionId |
| 1570 | +} |
| 1571 | + |
| 1572 | +const SharedRepositoryGroupPrefix = "tf-bootstrap-repo-group-" |
| 1573 | + |
| 1574 | +func BoostrapSharedRepositoryGroup(t *testing.T, repositoryGroupId, location, labels, codeRepositoryIndexId, resource string) string { |
| 1575 | + repositoryGroupId = SharedRepositoryGroupPrefix + repositoryGroupId |
| 1576 | + |
| 1577 | + config := BootstrapConfig(t) |
| 1578 | + if config == nil { |
| 1579 | + t.Fatal("Could not bootstrap config.") |
| 1580 | + } |
| 1581 | + |
| 1582 | + log.Printf("[DEBUG] Getting shared repository group %q", repositoryGroupId) |
| 1583 | + |
| 1584 | + getURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups/%s", |
| 1585 | + config.GeminiBasePath, config.Project, location, codeRepositoryIndexId, repositoryGroupId) |
| 1586 | + |
| 1587 | + headers := make(http.Header) |
| 1588 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1589 | + Config: config, |
| 1590 | + Method: "GET", |
| 1591 | + Project: config.Project, |
| 1592 | + RawURL: getURL, |
| 1593 | + UserAgent: config.UserAgent, |
| 1594 | + Headers: headers, |
| 1595 | + }) |
| 1596 | + if err != nil { |
| 1597 | + log.Printf("[DEBUG] Repository group %q not found, bootstrapping", codeRepositoryIndexId) |
| 1598 | + repositories := [1]interface{}{map[string]string{ |
| 1599 | + "resource": resource, |
| 1600 | + "branch_pattern": "main", |
| 1601 | + }} |
| 1602 | + postURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s/repositoryGroups?repositoryGroupId=%s", |
| 1603 | + config.GeminiBasePath, config.Project, location, codeRepositoryIndexId, repositoryGroupId) |
| 1604 | + obj := map[string]interface{}{ |
| 1605 | + "repositories": repositories, |
| 1606 | + } |
| 1607 | + if labels != "" { |
| 1608 | + obj["labels"] = labels |
| 1609 | + } |
| 1610 | + |
| 1611 | + headers := make(http.Header) |
| 1612 | + for { |
| 1613 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1614 | + Config: config, |
| 1615 | + Method: "POST", |
| 1616 | + Project: config.Project, |
| 1617 | + RawURL: postURL, |
| 1618 | + UserAgent: config.UserAgent, |
| 1619 | + Body: obj, |
| 1620 | + Timeout: 20 * time.Minute, |
| 1621 | + Headers: headers, |
| 1622 | + }) |
| 1623 | + if err != nil { |
| 1624 | + if transport_tpg.IsGoogleApiErrorWithCode(err, 409) { |
| 1625 | + errMsg := fmt.Sprintf("%s", err) |
| 1626 | + if strings.Contains(errMsg, "unable to queue the operation") { |
| 1627 | + log.Printf("[DEBUG] Waiting for enqueued operation to finish before creating RepositoryGroup: %#v", obj) |
| 1628 | + time.Sleep(10 * time.Second) |
| 1629 | + } else if strings.Contains(errMsg, "parent resource not in ready state") { |
| 1630 | + log.Printf("[DEBUG] Waiting for parent resource to become active before creating RepositoryGroup: %#v", obj) |
| 1631 | + time.Sleep(1 * time.Minute) |
| 1632 | + } else { |
| 1633 | + t.Fatalf("Error creating RepositoryGroup: %s", err) |
| 1634 | + } |
| 1635 | + } else { |
| 1636 | + t.Fatalf("Error creating repository group %q: %s", repositoryGroupId, err) |
| 1637 | + } |
| 1638 | + } else { |
| 1639 | + break |
| 1640 | + } |
| 1641 | + } |
| 1642 | + |
| 1643 | + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1644 | + Config: config, |
| 1645 | + Method: "GET", |
| 1646 | + Project: config.Project, |
| 1647 | + RawURL: getURL, |
| 1648 | + UserAgent: config.UserAgent, |
| 1649 | + Timeout: 20 * time.Minute, |
| 1650 | + Headers: headers, |
| 1651 | + }) |
| 1652 | + if err != nil { |
| 1653 | + t.Errorf("Error getting repository group %q: %s", repositoryGroupId, err) |
| 1654 | + } |
| 1655 | + } |
| 1656 | + |
| 1657 | + return repositoryGroupId |
| 1658 | +} |
| 1659 | + |
| 1660 | +// BootstrapSharedCodeRepositoryIndex will create a code repository index |
| 1661 | +// if it hasn't been created in the test project. |
| 1662 | +// |
| 1663 | +// BootstrapSharedCodeRepositoryIndex returns a persistent code repository index |
| 1664 | +// for a test or set of tests. |
| 1665 | +// |
| 1666 | +// Deletion of code repository index takes a few minutes, and creation of it |
| 1667 | +// currently takes about half an hour. |
| 1668 | +// That is the reason to use the shared code repository indexes for test resources. |
| 1669 | +const SharedCodeRepositoryIndexPrefix = "tf-bootstrap-cri-" |
| 1670 | + |
| 1671 | +func BootstrapSharedCodeRepositoryIndex(t *testing.T, codeRepositoryIndexId, location, kmsKey string, labels map[string]string) string { |
| 1672 | + codeRepositoryIndexId = SharedCodeRepositoryIndexPrefix + codeRepositoryIndexId |
| 1673 | + |
| 1674 | + config := BootstrapConfig(t) |
| 1675 | + if config == nil { |
| 1676 | + t.Fatal("Could not bootstrap config.") |
| 1677 | + } |
| 1678 | + |
| 1679 | + log.Printf("[DEBUG] Getting shared code repository index %q", codeRepositoryIndexId) |
| 1680 | + |
| 1681 | + getURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes/%s", config.GeminiBasePath, config.Project, location, codeRepositoryIndexId) |
| 1682 | + |
| 1683 | + headers := make(http.Header) |
| 1684 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1685 | + Config: config, |
| 1686 | + Method: "GET", |
| 1687 | + Project: config.Project, |
| 1688 | + RawURL: getURL, |
| 1689 | + UserAgent: config.UserAgent, |
| 1690 | + Timeout: 90 * time.Minute, |
| 1691 | + Headers: headers, |
| 1692 | + }) |
| 1693 | + |
| 1694 | + // CRI not found responds with 404 not found |
| 1695 | + if err != nil && transport_tpg.IsGoogleApiErrorWithCode(err, 404) { |
| 1696 | + log.Printf("[DEBUG] Code repository index %q not found, bootstrapping", codeRepositoryIndexId) |
| 1697 | + postURL := fmt.Sprintf("%sprojects/%s/locations/%s/codeRepositoryIndexes?codeRepositoryIndexId=%s", config.GeminiBasePath, config.Project, location, codeRepositoryIndexId) |
| 1698 | + obj := make(map[string]interface{}) |
| 1699 | + if labels != nil { |
| 1700 | + obj["labels"] = labels |
| 1701 | + } |
| 1702 | + if kmsKey != "" { |
| 1703 | + obj["kmsKey"] = kmsKey |
| 1704 | + } |
| 1705 | + |
| 1706 | + headers := make(http.Header) |
| 1707 | + _, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1708 | + Config: config, |
| 1709 | + Method: "POST", |
| 1710 | + Project: config.Project, |
| 1711 | + RawURL: postURL, |
| 1712 | + UserAgent: config.UserAgent, |
| 1713 | + Body: obj, |
| 1714 | + Timeout: 90 * time.Minute, |
| 1715 | + Headers: headers, |
| 1716 | + }) |
| 1717 | + if err != nil { |
| 1718 | + t.Fatalf("Error creating code repository index %q: %s", codeRepositoryIndexId, err) |
| 1719 | + } |
| 1720 | + |
| 1721 | + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ |
| 1722 | + Config: config, |
| 1723 | + Method: "GET", |
| 1724 | + Project: config.Project, |
| 1725 | + RawURL: getURL, |
| 1726 | + UserAgent: config.UserAgent, |
| 1727 | + Timeout: 90 * time.Minute, |
| 1728 | + Headers: headers, |
| 1729 | + }) |
| 1730 | + if err != nil { |
| 1731 | + t.Fatalf("Error getting code repository index %q: %s", codeRepositoryIndexId, err) |
| 1732 | + } |
| 1733 | + } else if err != nil { |
| 1734 | + t.Fatalf("Error getting code repository index %q: %s", codeRepositoryIndexId, err) |
| 1735 | + } |
| 1736 | + |
| 1737 | + return codeRepositoryIndexId |
| 1738 | +} |
| 1739 | + |
1429 | 1740 | const sharedTagKeyPrefix = "tf-bootstrap-tagkey"
|
1430 | 1741 |
|
1431 | 1742 | func BootstrapSharedTestTagKey(t *testing.T, testId string) string {
|
|
0 commit comments