Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
17 changes: 14 additions & 3 deletions vapi/library/library.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type Subscription struct {
AutomaticSyncEnabled *bool `json:"automatic_sync_enabled,omitempty"`
OnDemand *bool `json:"on_demand,omitempty"`
Password string `json:"password,omitempty"`
SslCertificate string `json:"ssl_certificate,omitempty"`
SslThumbprint string `json:"ssl_thumbprint,omitempty"`
SubscriptionURL string `json:"subscription_url,omitempty"`
UserName string `json:"user_name,omitempty"`
Expand Down Expand Up @@ -126,6 +127,9 @@ func (l *Library) Patch(src *Library) {
if src.Configuration != nil {
l.Configuration = src.Configuration
}
if src.Subscription != nil {
l.Subscription = src.Subscription
}
}

// Manager extends rest.Client, adding content library related methods.
Expand Down Expand Up @@ -177,7 +181,7 @@ func (c *Manager) CreateLibrary(ctx context.Context, library Library) (string, e
if err != nil {
return "", err
}
if u.Scheme == "https" && sub.SslThumbprint == "" {
if u.Scheme == "https" && sub.SslThumbprint == "" && sub.SslCertificate == "" {
thumbprint := c.Thumbprint(u.Host)
if thumbprint == "" {
t := c.DefaultTransport()
Expand Down Expand Up @@ -214,7 +218,9 @@ func (c *Manager) PublishLibrary(ctx context.Context, library *Library, subscrip
return c.Do(ctx, url.Request(http.MethodPost, spec), nil)
}

// UpdateLibrary can update one or both of the tag Description and Name fields.
// UpdateLibrary can update the Name, Description and Configuration fields.
// For a SUBSCRIBED library, the Subscription can also be updated,
// for example to change the subscription URL or SSL certificate.
func (c *Manager) UpdateLibrary(ctx context.Context, l *Library) error {
spec := struct {
Library `json:"update_spec"`
Expand All @@ -225,7 +231,12 @@ func (c *Manager) UpdateLibrary(ctx context.Context, l *Library) error {
Configuration: l.Configuration,
},
}
url := c.Resource(internal.LibraryPath).WithID(l.ID)
path := internal.LibraryPath
if l.Type == "SUBSCRIBED" {
path = internal.SubscribedLibraryPath
spec.Subscription = l.Subscription
}
url := c.Resource(path).WithID(l.ID)
return c.Do(ctx, url.Request(http.MethodPatch, spec), nil)
}

Expand Down
110 changes: 110 additions & 0 deletions vapi/library/library_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,16 @@ package library_test

import (
"context"
"encoding/json"
"strings"
"testing"

"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/simulator"
"github.com/vmware/govmomi/vapi/library"
"github.com/vmware/govmomi/vapi/rest"
"github.com/vmware/govmomi/vim25"
"github.com/vmware/govmomi/vim25/types"

_ "github.com/vmware/govmomi/vapi/simulator"
)
Expand Down Expand Up @@ -202,3 +205,110 @@ func TestManagerLibraryUsage(t *testing.T) {
}
})
}

func TestSubscriptionSslCertificate(t *testing.T) {
const cert = "-----BEGIN CERTIFICATE-----\nMIIB\n-----END CERTIFICATE-----"

b, err := json.Marshal(library.Subscription{
AuthenticationMethod: "NONE",
SslCertificate: cert,
})
if err != nil {
t.Fatal(err)
}

var m map[string]any
if err = json.Unmarshal(b, &m); err != nil {
t.Fatal(err)
}
if m["ssl_certificate"] != cert {
t.Errorf("ssl_certificate=%v, expected %q", m["ssl_certificate"], cert)
}

var sub library.Subscription
if err = json.Unmarshal(b, &sub); err != nil {
t.Fatal(err)
}
if sub.SslCertificate != cert {
t.Errorf("SslCertificate=%q, expected %q", sub.SslCertificate, cert)
}

// optional field is omitted when unset
b, err = json.Marshal(library.Subscription{AuthenticationMethod: "NONE"})
if err != nil {
t.Fatal(err)
}
if strings.Contains(string(b), "ssl_certificate") {
t.Errorf("unexpected ssl_certificate in %s", b)
}
}

func TestManagerUpdateSubscribedLibrary(t *testing.T) {
simulator.Test(func(ctx context.Context, vc *vim25.Client) {
c := rest.NewClient(vc)
if err := c.Login(ctx, simulator.DefaultLogin); err != nil {
t.Fatal(err)
}

ds, err := find.NewFinder(vc).DefaultDatastore(ctx)
if err != nil {
t.Fatal(err)
}

m := library.NewManager(c)
storage := []library.StorageBacking{{
DatastoreID: ds.Reference().Value,
Type: "DATASTORE",
}}

pubID, err := m.CreateLibrary(ctx, library.Library{
Name: "pub",
Type: "LOCAL",
Storage: storage,
Publication: &library.Publication{Published: types.New(true)},
})
if err != nil {
t.Fatal(err)
}
pub, err := m.GetLibraryByID(ctx, pubID)
if err != nil {
t.Fatal(err)
}

subID, err := m.CreateLibrary(ctx, library.Library{
Name: "sub",
Type: "SUBSCRIBED",
Storage: storage,
Subscription: &library.Subscription{
AuthenticationMethod: "NONE",
SubscriptionURL: "http://localhost/invalid",
},
})
if err != nil {
t.Fatal(err)
}

sub, err := m.GetLibraryByID(ctx, subID)
if err != nil {
t.Fatal(err)
}

const cert = "-----BEGIN CERTIFICATE-----\nMIIB\n-----END CERTIFICATE-----"
sub.Subscription.SubscriptionURL = pub.Publication.PublishURL
sub.Subscription.SslCertificate = cert
if err = m.UpdateLibrary(ctx, sub); err != nil {
t.Fatal(err)
}

sub, err = m.GetLibraryByID(ctx, subID)
if err != nil {
t.Fatal(err)
}
if sub.Subscription.SubscriptionURL != pub.Publication.PublishURL {
t.Errorf("SubscriptionURL=%q, expected %q", sub.Subscription.SubscriptionURL, pub.Publication.PublishURL)
}
if sub.Subscription.SslCertificate != cert {
t.Errorf("SslCertificate=%q, expected %q", sub.Subscription.SslCertificate, cert)
}
})
}
Loading