Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add catalog read-only sharing to all organizations #559

Merged
merged 34 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
83aac1c
Add types needed for read-only catalog sharing
Mar 17, 2023
18324b2
Add catalog parent retrieval to GetCatalogByHref
Mar 17, 2023
c15eaa5
Add catalog parent retrieval to GetAdminCatalogByHref
Mar 17, 2023
d24dcf3
Add functions to handle read-only catalog sharing
Mar 17, 2023
0996b09
Add changelog entries
Mar 17, 2023
3c9000a
Improve error messages
Mar 21, 2023
a4b3a38
Merge branch 'main' into catalog-RO-access-control
Mar 21, 2023
10cf4f9
Merge branch 'main' into catalog-RO-access-control
Mar 22, 2023
4069f10
Add method catalog.WaitForTasks
Jul 18, 2023
d5ab5fd
Add WaitForTasks to catalog creation
Jul 18, 2023
09df34c
Add test for catalog creation completeness
Jul 18, 2023
e9c273f
Merge branch 'main' into catalog-RO-access-control
Jul 19, 2023
4c43eae
Merge branch 'main' into fix-catalog-creation
Jul 20, 2023
f96ca09
Merge branch 'main' into catalog-RO-access-control
Jul 20, 2023
3089c6c
Fix merge issues
Jul 20, 2023
78ca960
Merge branch 'fix-catalog-creation' into catalog-RO-access-control
Jul 24, 2023
baa135e
Merge branch 'main' into catalog-RO-access-control
Jul 26, 2023
6300cee
Improve publishCatalog error message
Jul 31, 2023
93fa931
Merge branch 'main' into catalog-RO-access-control
Jul 31, 2023
fed6eb5
Merge branch 'main' into catalog-RO-access-control
Aug 2, 2023
8d4e4af
Merge branch 'main' into catalog-RO-access-control
Aug 16, 2023
51bda9a
Merge branch 'main' into catalog-RO-access-control
Sep 13, 2023
1f8b8c9
Merge branch 'main' into catalog-RO-access-control
Sep 15, 2023
f2aa6b9
Move changelog items to current version
Oct 2, 2023
6be0423
Add missing assertion to catalog test
Oct 2, 2023
15510eb
Rearrange order of publishing functions
Oct 2, 2023
2b6a389
Merge branch 'main' into catalog-RO-access-control
Oct 4, 2023
e611c09
Add WaitForTasks to catalog creation
Oct 4, 2023
9c3ab5f
Add WaitForTasks to AdminCatalog creation
Oct 4, 2023
da84810
Add function docs
Oct 4, 2023
9bef8a1
Fix missing error check
Oct 4, 2023
e12d571
Update comments
Oct 9, 2023
829fda2
Merge branch 'main' into catalog-RO-access-control
Oct 26, 2023
f241b4f
Merge branch 'main' into catalog-RO-access-control
Nov 7, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .changes/v2.22.0/559-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Added methods `SetReadOnlyAccessControl` and `IsSharedReadOnly` for `Catalog` and `AdminCatalog`, to handle read-only catalog sharing [GH-559]
1 change: 1 addition & 0 deletions .changes/v2.22.0/559-improvements.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* Added catalog parent retrieval to `client.GetCatalogByHref` and `client.GetAdminCatalogByHref` to facilitate tenant context handling [GH-559]
142 changes: 142 additions & 0 deletions govcd/access_control.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,3 +456,145 @@ func checkSanityVdcControlAccess(vdc *Vdc) error {
}
return nil
}

func publishCatalog(client *Client, catalogUrl string, tenantContext *TenantContext, publishCatalog types.PublishCatalogParams) error {
catalogUrl = catalogUrl + "/action/publish"

publishCatalog.Xmlns = types.XMLNamespaceVCloud

if tenantContext != nil {
client.SetCustomHeader(getTenantContextHeader(tenantContext))
}

err := client.ExecuteRequestWithoutResponse(catalogUrl, http.MethodPost,
types.PublishCatalog, "error setting catalog publishing state: %s", publishCatalog)

if tenantContext != nil {
client.RemoveProvidedCustomHeaders(getTenantContextHeader(tenantContext))
}

return err
}

// IsSharedReadOnly returns the state of the catalog read-only sharing to all organizations
func (cat *Catalog) IsSharedReadOnly() (bool, error) {
accessControl, err := cat.GetAccessControl(true)
if err != nil {
return false, err
}
if accessControl.AccessSettings != nil || accessControl.IsSharedToEveryone {
return false, nil
}
err = cat.Refresh()
if err != nil {
return false, err
}
return cat.Catalog.IsPublished, nil
}

// IsSharedReadOnly returns the state of the catalog read-only sharing to all organizations
func (cat *AdminCatalog) IsSharedReadOnly() (bool, error) {
accessControl, err := cat.GetAccessControl(true)
if err != nil {
return false, err
}
if accessControl.AccessSettings != nil || accessControl.IsSharedToEveryone {
return false, nil
}
err = cat.Refresh()
if err != nil {
return false, err
}
return cat.AdminCatalog.IsPublished, nil
}

// publish publishes a catalog read-only access control to all organizations
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved
// This operation is usually the second step for a read-only sharing to all Orgs
func (cat *Catalog) publish(isPublished bool) error {
if cat.Catalog == nil {
return fmt.Errorf("cannot publish catalog, Object is empty")
}

catalogUrl := cat.Catalog.HREF
if catalogUrl == "nil" || catalogUrl == "" {
return fmt.Errorf("cannot publish catalog, HREF is empty")
}

tenantContext, err := cat.getTenantContext()
if err != nil {
return fmt.Errorf("cannot publish catalog, tenant context error: %s", err)
}

publishParameters := types.PublishCatalogParams{
IsPublished: &isPublished,
}
err = publishCatalog(cat.client, catalogUrl, tenantContext, publishParameters)
if err != nil {
return err
}

return cat.Refresh()
}

// publish publishes a catalog read-only access control to all organizations
lvirbalas marked this conversation as resolved.
Show resolved Hide resolved
// This operation is usually the second step for a read-only sharing to all Orgs
func (cat *AdminCatalog) publish(isPublished bool) error {
adezxc marked this conversation as resolved.
Show resolved Hide resolved
if cat.AdminCatalog == nil {
return fmt.Errorf("cannot publish catalog, Object is empty")
}

catalogUrl := cat.AdminCatalog.HREF
if catalogUrl == "nil" || catalogUrl == "" {
adezxc marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("cannot publish catalog, HREF is empty")
}

tenantContext, err := cat.getTenantContext()
if err != nil {
return fmt.Errorf("cannot publish catalog, tenant context error: %s", err)
}

publishParameters := types.PublishCatalogParams{
IsPublished: &isPublished,
}
err = publishCatalog(cat.client, catalogUrl, tenantContext, publishParameters)
if err != nil {
return err
}

err = cat.Refresh()
if err != nil {
return err
}

return err
}

// SetReadOnlyAccessControl will create or rescind the read-only catalog sharing to all organizations
func (cat *Catalog) SetReadOnlyAccessControl(isPublished bool) error {
if cat.Catalog == nil {
return fmt.Errorf("cannot set access control, Object is empty")
}
err := cat.SetAccessControl(&types.ControlAccessParams{
IsSharedToEveryone: false,
EveryoneAccessLevel: addrOf(types.ControlAccessReadOnly),
}, true)
if err != nil {
return fmt.Errorf("error resetting access control record for catalog %s: %s", cat.Catalog.Name, err)
}
return cat.publish(isPublished)
}

// SetReadOnlyAccessControl will create or rescind the read-only AdminCatalog sharing to all organizations
func (cat *AdminCatalog) SetReadOnlyAccessControl(isPublished bool) error {
if cat.AdminCatalog == nil {
return fmt.Errorf("cannot set access control, Object is empty")
}
err := cat.SetAccessControl(&types.ControlAccessParams{
IsSharedToEveryone: false,
EveryoneAccessLevel: addrOf(types.ControlAccessReadOnly),
}, true)
if err != nil {
return err
}
return cat.publish(isPublished)
}
14 changes: 14 additions & 0 deletions govcd/admincatalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -624,6 +624,20 @@ func (client *Client) GetAdminCatalogByHref(catalogHref string) (*AdminCatalog,
return nil, err
}

// Setting the catalog parent, necessary to handle the tenant context
org := NewAdminOrg(client)
for _, link := range cat.AdminCatalog.Link {
if link.Rel == "up" && link.Type == types.MimeAdminOrg {
_, err = client.ExecuteRequest(link.HREF, http.MethodGet,
"", "error retrieving parent Org: %s", nil, org.AdminOrg)
if err != nil {
return nil, fmt.Errorf("error retrieving catalog parent: %s", err)
}
break
}
}

cat.parent = org
return cat, nil
}

Expand Down
4 changes: 4 additions & 0 deletions govcd/adminorg.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func (adminOrg *AdminOrg) CreateCatalog(name, description string) (AdminCatalog,
if err != nil {
return AdminCatalog{}, err
}
err = adminCatalog.WaitForTasks()
if err != nil {
return AdminCatalog{}, err
}
return *adminCatalog, nil
}

Expand Down
31 changes: 23 additions & 8 deletions govcd/catalog.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ func (catalog *Catalog) Delete(force, recursive bool) error {
// A catalog cannot be removed if it has active tasks, or if any of its items have active tasks
err = catalog.consumeTasks()
if err != nil {
return err
return fmt.Errorf("error while consuming tasks from catalog %s: %s", catalog.Catalog.Name, err)
}
}

Expand Down Expand Up @@ -94,7 +94,7 @@ func (catalog *Catalog) consumeTasks() error {
"status": "running,preRunning,queued",
})
if err != nil {
return err
return fmt.Errorf("error getting task list from catalog %s: %s", catalog.Catalog.Name, err)
}
var taskList []string
addTask := func(status, href string) {
Expand All @@ -119,7 +119,7 @@ func (catalog *Catalog) consumeTasks() error {
}
catalogItemRefs, err := catalog.QueryCatalogItemList()
if err != nil {
return err
return fmt.Errorf("error getting catalog %s items list: %s", catalog.Catalog.Name, err)
}
for _, task := range allTasks {
for _, ref := range catalogItemRefs {
Expand All @@ -131,7 +131,10 @@ func (catalog *Catalog) consumeTasks() error {
}
}
_, err = catalog.client.WaitTaskListCompletion(taskList, true)
return err
if err != nil {
return fmt.Errorf("error while waiting for task list completion for catalog %s: %s", catalog.Catalog.Name, err)
}
return nil
}

// Envelope is a ovf description root element. File contains information for vmdk files.
Expand Down Expand Up @@ -1079,12 +1082,12 @@ func (cat *Catalog) PublishToExternalOrganizations(publishExternalCatalog types.
return fmt.Errorf("cannot publish to external organization, Object is empty")
}

url := cat.Catalog.HREF
if url == "nil" || url == "" {
catalogUrl := cat.Catalog.HREF
if catalogUrl == "nil" || catalogUrl == "" {
return fmt.Errorf("cannot publish to external organization, HREF is empty")
}

err := publishToExternalOrganizations(cat.client, url, nil, publishExternalCatalog)
err := publishToExternalOrganizations(cat.client, catalogUrl, nil, publishExternalCatalog)
if err != nil {
return err
}
Expand Down Expand Up @@ -1171,7 +1174,19 @@ func (client *Client) GetCatalogByHref(catalogHref string) (*Catalog, error) {
if err != nil {
return nil, err
}

// Setting the catalog parent, necessary to handle the tenant context
org := NewOrg(client)
for _, link := range cat.Catalog.Link {
if link.Rel == "up" && link.Type == types.MimeOrg {
_, err = client.ExecuteRequest(link.HREF, http.MethodGet,
"", "error retrieving parent Org: %s", nil, org.Org)
if err != nil {
return nil, fmt.Errorf("error retrieving catalog parent: %s", err)
}
break
}
}
cat.parent = org
return cat, nil
}

Expand Down
Loading