summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--client/go/internal/cli/cmd/cert.go6
-rw-r--r--client/go/internal/cli/cmd/curl.go2
-rw-r--r--client/go/internal/cli/cmd/deploy.go6
-rw-r--r--client/go/internal/cli/cmd/document.go2
-rw-r--r--client/go/internal/cli/cmd/feed.go2
-rw-r--r--client/go/internal/cli/cmd/query.go2
-rw-r--r--client/go/internal/cli/cmd/root.go4
-rw-r--r--client/go/internal/cli/cmd/status.go52
-rw-r--r--client/go/internal/cli/cmd/status_test.go33
-rw-r--r--client/go/internal/cli/cmd/test.go2
-rw-r--r--client/go/internal/cli/cmd/waiter.go7
-rw-r--r--client/go/internal/vespa/target.go8
-rw-r--r--client/go/internal/vespa/target_test.go6
-rw-r--r--client/js/app/yarn.lock349
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java9
-rw-r--r--config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java6
-rw-r--r--config-model/src/test/derived/array_of_struct_attribute/test.sd2
-rw-r--r--config-model/src/test/derived/bolding_dynamic_summary/test.sd8
-rw-r--r--config-model/src/test/derived/map_of_struct_attribute/test.sd4
-rw-r--r--config-model/src/test/derived/multiplesummaries/multiplesummaries.sd50
-rw-r--r--config-model/src/test/derived/nearestneighbor/test.sd2
-rw-r--r--config-model/src/test/derived/ngram/chunk.sd2
-rw-r--r--config-model/src/test/derived/reference_fields/ad.sd2
-rw-r--r--config-model/src/test/derived/reference_from_several/bar.sd2
-rw-r--r--config-model/src/test/derived/reference_from_several/foo.sd2
-rw-r--r--config-model/src/test/derived/schemainheritance/child.sd2
-rw-r--r--config-model/src/test/derived/schemainheritance/parent.sd2
-rw-r--r--config-model/src/test/examples/multiplesummaries.sd6
-rw-r--r--config-model/src/test/examples/nextgen/summaryfield.sd4
-rw-r--r--config-model/src/test/examples/outsidesummary.sd6
-rw-r--r--config-model/src/test/examples/summaryfieldcollision.sd4
-rw-r--r--config-model/src/test/java/com/yahoo/schema/SchemaTestCase.java10
-rw-r--r--config-model/src/test/java/com/yahoo/schema/SummaryTestCase.java28
-rw-r--r--config-model/src/test/java/com/yahoo/schema/derived/SummaryTestCase.java6
-rw-r--r--config-model/src/test/java/com/yahoo/schema/processing/MatchedElementsOnlyResolverTestCase.java4
-rw-r--r--config-model/src/test/java/com/yahoo/schema/processing/SummaryConsistencyTestCase.java2
-rw-r--r--config-model/src/test/java/com/yahoo/schema/processing/SummaryDiskAccessValidatorTestCase.java2
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudDataPlaneFilterTest.java5
-rw-r--r--config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudTokenDataPlaneFilterTest.java29
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationMutex.java (renamed from config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionLock.java)4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationTransaction.java4
-rw-r--r--config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java2
-rw-r--r--configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java4
-rw-r--r--configserver/src/test/java/com/yahoo/vespa/config/server/MockProvisioner.java6
-rw-r--r--container-core/abi-spec.json9
-rw-r--r--container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java6
-rw-r--r--container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def3
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java87
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java64
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java4
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java31
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatus.java30
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java2
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java12
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingReporterMock.java10
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java6
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/StatusHistory.java35
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/DeploymentFailureMails.java12
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java33
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PriceInformation.java29
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/Prices.java8
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java24
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java14
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/package-info.java5
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java21
-rw-r--r--controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Email.java2
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java43
-rw-r--r--controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatusTest.java18
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/MailVerifier.java6
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainer.java4
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java2
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/FormattedNotification.java3
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/MailTemplating.java32
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatter.java86
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/Notifier.java47
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java5
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java1
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java10
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java9
-rw-r--r--controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java218
-rw-r--r--controller-server/src/main/resources/mail/mail-verification.vm6
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java8
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java33
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainerTest.java20
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatterTest.java19
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java5
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java2
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java4
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java12
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java10
-rw-r--r--controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java185
-rw-r--r--controller-server/src/test/resources/mail/notification.html8
-rw-r--r--controller-server/src/test/resources/mail/trial-expired.html8
-rw-r--r--controller-server/src/test/resources/mail/trial-expiring-immediately.html8
-rw-r--r--controller-server/src/test/resources/mail/trial-expiring-soon.html8
-rw-r--r--controller-server/src/test/resources/mail/trial-reminder.html8
-rw-r--r--controller-server/src/test/resources/mail/welcome.html8
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java18
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java3
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java6
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java4
-rw-r--r--node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisioner.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/applications/ApplicationsTest.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java4
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java6
-rw-r--r--node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java4
115 files changed, 891 insertions, 1179 deletions
diff --git a/client/go/internal/cli/cmd/cert.go b/client/go/internal/cli/cmd/cert.go
index aca8de88fbe..1cc50b1faea 100644
--- a/client/go/internal/cli/cmd/cert.go
+++ b/client/go/internal/cli/cmd/cert.go
@@ -32,8 +32,10 @@ package specified as an argument to this command (default '.').
It's possible to override the private key and certificate used through
environment variables. This can be useful in continuous integration systems.
-It's also possible override the CA certificate which can be useful when using self-signed certificates with a
-self-hosted Vespa service. See https://docs.vespa.ai/en/operations-selfhosted/mtls.html for more information.
+It's also possible override the CA certificate which can be useful when using
+self-signed certificates with a self-hosted Vespa service.
+See https://docs.vespa.ai/en/operations-selfhosted/mtls.html for more
+information.
Example of setting the CA certificate, certificate and key in-line:
diff --git a/client/go/internal/cli/cmd/curl.go b/client/go/internal/cli/cmd/curl.go
index 3d81a5d2c0e..4a919d18d49 100644
--- a/client/go/internal/cli/cmd/curl.go
+++ b/client/go/internal/cli/cmd/curl.go
@@ -41,7 +41,7 @@ $ vespa curl -- -v --data-urlencode "yql=select * from music where album contain
}
var service *vespa.Service
useDeploy := curlService == "deploy"
- waiter := cli.waiter(false, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
if useDeploy {
if cli.config.cluster() != "" {
return fmt.Errorf("cannot specify cluster for service %s", curlService)
diff --git a/client/go/internal/cli/cmd/deploy.go b/client/go/internal/cli/cmd/deploy.go
index 0a4d72a8a48..aee26975901 100644
--- a/client/go/internal/cli/cmd/deploy.go
+++ b/client/go/internal/cli/cmd/deploy.go
@@ -73,7 +73,7 @@ $ vespa deploy -t cloud -z perf.aws-us-east-1c`,
return err
}
}
- waiter := cli.waiter(false, timeout)
+ waiter := cli.waiter(timeout)
if _, err := waiter.DeployService(target); err != nil {
return err
}
@@ -158,7 +158,7 @@ func newActivateCmd(cli *CLI) *cobra.Command {
return err
}
timeout := time.Duration(waitSecs) * time.Second
- waiter := cli.waiter(false, timeout)
+ waiter := cli.waiter(timeout)
if _, err := waiter.DeployService(target); err != nil {
return err
}
@@ -179,7 +179,7 @@ func waitForDeploymentReady(cli *CLI, target vespa.Target, sessionOrRunID int64,
if timeout == 0 {
return nil
}
- waiter := cli.waiter(false, timeout)
+ waiter := cli.waiter(timeout)
if _, err := waiter.Deployment(target, sessionOrRunID); err != nil {
return err
}
diff --git a/client/go/internal/cli/cmd/document.go b/client/go/internal/cli/cmd/document.go
index 090060d578c..a98e9867d34 100644
--- a/client/go/internal/cli/cmd/document.go
+++ b/client/go/internal/cli/cmd/document.go
@@ -298,7 +298,7 @@ func documentService(cli *CLI, waitSecs int) (*vespa.Service, error) {
if err != nil {
return nil, err
}
- waiter := cli.waiter(false, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
return waiter.Service(target, cli.config.cluster())
}
diff --git a/client/go/internal/cli/cmd/feed.go b/client/go/internal/cli/cmd/feed.go
index 5cdd0d7d63b..1a32ac7110d 100644
--- a/client/go/internal/cli/cmd/feed.go
+++ b/client/go/internal/cli/cmd/feed.go
@@ -108,7 +108,7 @@ func createServices(n int, timeout time.Duration, waitSecs int, cli *CLI) ([]uti
}
services := make([]util.HTTPClient, 0, n)
baseURL := ""
- waiter := cli.waiter(false, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
for i := 0; i < n; i++ {
service, err := waiter.Service(target, cli.config.cluster())
if err != nil {
diff --git a/client/go/internal/cli/cmd/query.go b/client/go/internal/cli/cmd/query.go
index 6fb571dc36b..bf2272ca981 100644
--- a/client/go/internal/cli/cmd/query.go
+++ b/client/go/internal/cli/cmd/query.go
@@ -64,7 +64,7 @@ func query(cli *CLI, arguments []string, timeoutSecs, waitSecs int, curl bool) e
if err != nil {
return err
}
- waiter := cli.waiter(false, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
service, err := waiter.Service(target, cli.config.cluster())
if err != nil {
return err
diff --git a/client/go/internal/cli/cmd/root.go b/client/go/internal/cli/cmd/root.go
index 352ddbcd152..068a7ed90b6 100644
--- a/client/go/internal/cli/cmd/root.go
+++ b/client/go/internal/cli/cmd/root.go
@@ -345,9 +345,7 @@ func (c *CLI) confirm(question string, confirmByDefault bool) (bool, error) {
}
}
-func (c *CLI) waiter(once bool, timeout time.Duration) *Waiter {
- return &Waiter{Once: once, Timeout: timeout, cli: c}
-}
+func (c *CLI) waiter(timeout time.Duration) *Waiter { return &Waiter{Timeout: timeout, cli: c} }
// target creates a target according the configuration of this CLI and given opts.
func (c *CLI) target(opts targetOptions) (vespa.Target, error) {
diff --git a/client/go/internal/cli/cmd/status.go b/client/go/internal/cli/cmd/status.go
index 001f4ba43f1..a0602494bff 100644
--- a/client/go/internal/cli/cmd/status.go
+++ b/client/go/internal/cli/cmd/status.go
@@ -42,7 +42,8 @@ $ vespa status --cluster mycluster --wait 600`,
if err != nil {
return err
}
- waiter := cli.waiter(true, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
+ var failingContainers []*vespa.Service
if cluster == "" {
services, err := waiter.Services(t)
if err != nil {
@@ -52,23 +53,41 @@ $ vespa status --cluster mycluster --wait 600`,
return errHint(fmt.Errorf("no services exist"), "Deployment may not be ready yet", "Try 'vespa status deployment'")
}
for _, s := range services {
- printReadyService(s, cli)
+ if !printServiceStatus(s, waiter, cli) {
+ failingContainers = append(failingContainers, s)
+ }
}
- return nil
} else {
s, err := waiter.Service(t, cluster)
if err != nil {
return err
}
- printReadyService(s, cli)
- return nil
+ if !printServiceStatus(s, waiter, cli) {
+ failingContainers = append(failingContainers, s)
+ }
}
+ return failingServicesErr(failingContainers...)
},
}
cli.bindWaitFlag(cmd, 0, &waitSecs)
return cmd
}
+func failingServicesErr(services ...*vespa.Service) error {
+ if len(services) == 0 {
+ return nil
+ }
+ var nameOrURL []string
+ for _, s := range services {
+ if s.Name != "" {
+ nameOrURL = append(nameOrURL, s.Name)
+ } else {
+ nameOrURL = append(nameOrURL, s.BaseURL)
+ }
+ }
+ return fmt.Errorf("services not ready: %s", strings.Join(nameOrURL, ", "))
+}
+
func newStatusDeployCmd(cli *CLI) *cobra.Command {
var waitSecs int
cmd := &cobra.Command{
@@ -83,12 +102,14 @@ func newStatusDeployCmd(cli *CLI) *cobra.Command {
if err != nil {
return err
}
- waiter := cli.waiter(true, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
s, err := waiter.DeployService(t)
if err != nil {
return err
}
- printReadyService(s, cli)
+ if !printServiceStatus(s, waiter, cli) {
+ return failingServicesErr(s)
+ }
return nil
},
}
@@ -128,7 +149,7 @@ $ vespa status deployment -t local [session-id] --wait 600
if err != nil {
return err
}
- waiter := cli.waiter(true, time.Duration(waitSecs)*time.Second)
+ waiter := cli.waiter(time.Duration(waitSecs) * time.Second)
id, err := waiter.Deployment(t, wantedID)
if err != nil {
return err
@@ -146,8 +167,19 @@ $ vespa status deployment -t local [session-id] --wait 600
return cmd
}
-func printReadyService(s *vespa.Service, cli *CLI) {
+func printServiceStatus(s *vespa.Service, waiter *Waiter, cli *CLI) bool {
desc := s.Description()
desc = strings.ToUpper(string(desc[0])) + string(desc[1:])
- log.Print(desc, " at ", color.CyanString(s.BaseURL), " is ", color.GreenString("ready"))
+ err := s.Wait(waiter.Timeout)
+ var sb strings.Builder
+ sb.WriteString(fmt.Sprintf("%s at %s is ", desc, color.CyanString(s.BaseURL)))
+ if err == nil {
+ sb.WriteString(color.GreenString("ready"))
+ } else {
+ sb.WriteString(color.RedString("not ready"))
+ sb.WriteString(": ")
+ sb.WriteString(err.Error())
+ }
+ fmt.Fprintln(cli.Stdout, sb.String())
+ return err == nil
}
diff --git a/client/go/internal/cli/cmd/status_test.go b/client/go/internal/cli/cmd/status_test.go
index 1e6c3230db3..1473e39ff54 100644
--- a/client/go/internal/cli/cmd/status_test.go
+++ b/client/go/internal/cli/cmd/status_test.go
@@ -38,12 +38,18 @@ func TestStatusCommandMultiCluster(t *testing.T) {
mockServiceStatus(client)
assert.NotNil(t, cli.Run("status"))
assert.Equal(t, "Error: no services exist\nHint: Deployment may not be ready yet\nHint: Try 'vespa status deployment'\n", stderr.String())
+ stderr.Reset()
mockServiceStatus(client, "foo", "bar")
- assert.Nil(t, cli.Run("status"))
+ client.NextStatus(200)
+ client.NextStatus(400) // One cluster is unavilable
+ assert.NotNil(t, cli.Run("status"))
assert.Equal(t, `Container bar at http://127.0.0.1:8080 is ready
-Container foo at http://127.0.0.1:8080 is ready
+Container foo at http://127.0.0.1:8080 is not ready: unhealthy container foo: status 400 at http://127.0.0.1:8080/status.html: aborting wait: got status 400
`, stdout.String())
+ assert.Equal(t,
+ "Error: services not ready: foo\n",
+ stderr.String())
stdout.Reset()
mockServiceStatus(client, "foo", "bar")
@@ -60,7 +66,7 @@ func TestStatusCommandMultiClusterWait(t *testing.T) {
client.NextStatus(400)
assert.NotNil(t, cli.Run("status", "--cluster", "foo", "--wait", "10"))
assert.Equal(t, "Waiting up to 10s for cluster discovery...\nWaiting up to 10s for container foo...\n"+
- "Error: unhealthy container foo after waiting up to 10s: status 400 at http://127.0.0.1:8080/ApplicationStatus: aborting wait: got status 400\n", stderr.String())
+ "Error: unhealthy container foo after waiting up to 10s: status 400 at http://127.0.0.1:8080/status.html: aborting wait: got status 400\n", stderr.String())
}
func TestStatusCommandWithUrlTarget(t *testing.T) {
@@ -75,18 +81,25 @@ func TestStatusError(t *testing.T) {
client := &mock.HTTPClient{}
mockServiceStatus(client, "default")
client.NextStatus(500)
- cli, _, stderr := newTestCLI(t)
+ cli, stdout, stderr := newTestCLI(t)
cli.httpClient = client
assert.NotNil(t, cli.Run("status", "container"))
assert.Equal(t,
- "Error: unhealthy container default: status 500 at http://127.0.0.1:8080/ApplicationStatus: wait timed out\n",
+ "Container default at http://127.0.0.1:8080 is not ready: unhealthy container default: status 500 at http://127.0.0.1:8080/status.html: wait timed out\n",
+ stdout.String())
+ assert.Equal(t,
+ "Error: services not ready: default\n",
stderr.String())
+ stdout.Reset()
stderr.Reset()
client.NextResponseError(io.EOF)
assert.NotNil(t, cli.Run("status", "container", "-t", "http://example.com"))
assert.Equal(t,
- "Error: unhealthy container at http://example.com/ApplicationStatus: EOF\n",
+ "Container at http://example.com is not ready: unhealthy container at http://example.com/status.html: EOF\n",
+ stdout.String())
+ assert.Equal(t,
+ "Error: services not ready: http://example.com\n",
stderr.String())
}
@@ -189,7 +202,7 @@ func assertStatus(expectedTarget string, args []string, t *testing.T) {
clusterName = "foo"
mockServiceStatus(client, clusterName)
}
- client.NextResponse(mock.HTTPResponse{URI: "/ApplicationStatus", Status: 200})
+ client.NextResponse(mock.HTTPResponse{URI: "/status.html", Status: 200})
}
cli, stdout, _ := newTestCLI(t)
cli.httpClient = client
@@ -200,14 +213,14 @@ func assertStatus(expectedTarget string, args []string, t *testing.T) {
prefix += " " + clusterName
}
assert.Equal(t, prefix+" at "+expectedTarget+" is ready\n", stdout.String())
- assert.Equal(t, expectedTarget+"/ApplicationStatus", client.LastRequest.URL.String())
+ assert.Equal(t, expectedTarget+"/status.html", client.LastRequest.URL.String())
// Test legacy command
statusArgs = []string{"status query"}
stdout.Reset()
assert.Nil(t, cli.Run(append(statusArgs, args...)...))
assert.Equal(t, prefix+" at "+expectedTarget+" is ready\n", stdout.String())
- assert.Equal(t, expectedTarget+"/ApplicationStatus", client.LastRequest.URL.String())
+ assert.Equal(t, expectedTarget+"/status.html", client.LastRequest.URL.String())
}
func assertDocumentStatus(target string, args []string, t *testing.T) {
@@ -223,5 +236,5 @@ func assertDocumentStatus(target string, args []string, t *testing.T) {
"Container (document API) at "+target+" is ready\n",
stdout.String(),
"vespa status container")
- assert.Equal(t, target+"/ApplicationStatus", client.LastRequest.URL.String())
+ assert.Equal(t, target+"/status.html", client.LastRequest.URL.String())
}
diff --git a/client/go/internal/cli/cmd/test.go b/client/go/internal/cli/cmd/test.go
index e842cab606e..f0432dd4f70 100644
--- a/client/go/internal/cli/cmd/test.go
+++ b/client/go/internal/cli/cmd/test.go
@@ -220,7 +220,7 @@ func verify(step step, defaultCluster string, defaultParameters map[string]strin
service, ok = context.clusters[cluster]
if !ok {
// Cache service so we don't have to discover it for every step
- waiter := context.cli.waiter(false, time.Duration(waitSecs)*time.Second)
+ waiter := context.cli.waiter(time.Duration(waitSecs) * time.Second)
service, err = waiter.Service(target, cluster)
if err != nil {
return "", "", err
diff --git a/client/go/internal/cli/cmd/waiter.go b/client/go/internal/cli/cmd/waiter.go
index 302bc679885..0cfb3aa76d5 100644
--- a/client/go/internal/cli/cmd/waiter.go
+++ b/client/go/internal/cli/cmd/waiter.go
@@ -11,17 +11,12 @@ import (
// Waiter waits for Vespa services to become ready, within a timeout.
type Waiter struct {
- // Once species whether we should wait at least one time, irregardless of timeout.
- Once bool
-
// Timeout specifies how long we should wait for an operation to complete.
Timeout time.Duration // TODO(mpolden): Consider making this a budget
cli *CLI
}
-func (w *Waiter) wait() bool { return w.Once || w.Timeout > 0 }
-
// DeployService returns the service providing the deploy API on given target,
func (w *Waiter) DeployService(target vespa.Target) (*vespa.Service, error) {
s, err := target.DeployService()
@@ -74,8 +69,6 @@ func (w *Waiter) Services(target vespa.Target) ([]*vespa.Service, error) {
func (w *Waiter) maybeWaitFor(service *vespa.Service) error {
if w.Timeout > 0 {
w.cli.printInfo("Waiting up to ", color.CyanString(w.Timeout.String()), " for ", service.Description(), "...")
- }
- if w.wait() {
return service.Wait(w.Timeout)
}
return nil
diff --git a/client/go/internal/vespa/target.go b/client/go/internal/vespa/target.go
index 662e7383f97..5b29990fe4e 100644
--- a/client/go/internal/vespa/target.go
+++ b/client/go/internal/vespa/target.go
@@ -125,12 +125,8 @@ func (s *Service) SetClient(client util.HTTPClient) { s.httpClient = client }
// Wait polls the health check of this service until it succeeds or timeout passes.
func (s *Service) Wait(timeout time.Duration) error {
- url := s.BaseURL
- if s.deployAPI {
- url += "/status.html" // because /ApplicationStatus is not publicly reachable in Vespa Cloud
- } else {
- url += "/ApplicationStatus"
- }
+ // A path that does not need authentication, on any target
+ url := strings.TrimRight(s.BaseURL, "/") + "/status.html"
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return err
diff --git a/client/go/internal/vespa/target_test.go b/client/go/internal/vespa/target_test.go
index 25e38a30151..4c2fda8368e 100644
--- a/client/go/internal/vespa/target_test.go
+++ b/client/go/internal/vespa/target_test.go
@@ -88,7 +88,7 @@ func TestCustomTargetWait(t *testing.T) {
client.NextResponseError(io.EOF)
}
// Then succeeds
- client.NextResponse(mock.HTTPResponse{URI: "/ApplicationStatus", Status: 200})
+ client.NextResponse(mock.HTTPResponse{URI: "/status.html", Status: 200})
assertService(t, false, target, "", time.Second)
}
@@ -153,10 +153,10 @@ func TestCloudTargetWait(t *testing.T) {
assert.Equal(t, 2, len(services))
client.NextResponse(response)
- client.NextResponse(mock.HTTPResponse{URI: "/ApplicationStatus", Status: 500})
+ client.NextResponse(mock.HTTPResponse{URI: "/status.html", Status: 500})
assertService(t, true, target, "default", 0)
client.NextResponse(response)
- client.NextResponse(mock.HTTPResponse{URI: "/ApplicationStatus", Status: 200})
+ client.NextResponse(mock.HTTPResponse{URI: "/status.html", Status: 200})
assertService(t, false, target, "feed", 0)
}
diff --git a/client/js/app/yarn.lock b/client/js/app/yarn.lock
index 08e663cadb3..4c3b5946c46 100644
--- a/client/js/app/yarn.lock
+++ b/client/js/app/yarn.lock
@@ -1523,6 +1523,17 @@ array-includes@^3.1.6:
get-intrinsic "^1.1.3"
is-string "^1.0.7"
+array-includes@^3.1.7:
+ version "3.1.7"
+ resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda"
+ integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ get-intrinsic "^1.2.1"
+ is-string "^1.0.7"
+
array-union@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d"
@@ -1533,16 +1544,16 @@ array-unique@^0.3.2:
resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428"
integrity sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==
-array.prototype.findlastindex@^1.2.2:
- version "1.2.2"
- resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.2.tgz#bc229aef98f6bd0533a2bc61ff95209875526c9b"
- integrity sha512-tb5thFFlUcp7NdNF6/MpDk/1r/4awWG1FIz3YqDf+/zJSTezBb+/5WViH41obXULHVpDzoiCLpJ/ZO9YbJMsdw==
+array.prototype.findlastindex@^1.2.3:
+ version "1.2.3"
+ resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207"
+ integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
es-shim-unscopables "^1.0.0"
- get-intrinsic "^1.1.3"
+ get-intrinsic "^1.2.1"
array.prototype.flat@^1.3.1:
version "1.3.1"
@@ -1554,6 +1565,16 @@ array.prototype.flat@^1.3.1:
es-abstract "^1.20.4"
es-shim-unscopables "^1.0.0"
+array.prototype.flat@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18"
+ integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-shim-unscopables "^1.0.0"
+
array.prototype.flatmap@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz#1aae7903c2100433cb8261cd4ed310aab5c4a183"
@@ -1564,6 +1585,16 @@ array.prototype.flatmap@^1.3.1:
es-abstract "^1.20.4"
es-shim-unscopables "^1.0.0"
+array.prototype.flatmap@^1.3.2:
+ version "1.3.2"
+ resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527"
+ integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+ es-shim-unscopables "^1.0.0"
+
array.prototype.tosorted@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.1.tgz#ccf44738aa2b5ac56578ffda97c03fd3e23dd532"
@@ -1575,14 +1606,15 @@ array.prototype.tosorted@^1.1.1:
es-shim-unscopables "^1.0.0"
get-intrinsic "^1.1.3"
-arraybuffer.prototype.slice@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz#9b5ea3868a6eebc30273da577eb888381c0044bb"
- integrity sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==
+arraybuffer.prototype.slice@^1.0.2:
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12"
+ integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==
dependencies:
array-buffer-byte-length "^1.0.0"
call-bind "^1.0.2"
define-properties "^1.2.0"
+ es-abstract "^1.22.1"
get-intrinsic "^1.2.1"
is-array-buffer "^3.0.2"
is-shared-array-buffer "^1.0.2"
@@ -1820,13 +1852,14 @@ cache-base@^1.0.1:
union-value "^1.0.0"
unset-value "^1.0.0"
-call-bind@^1.0.0, call-bind@^1.0.2:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
- integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
+call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5:
+ version "1.0.5"
+ resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513"
+ integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==
dependencies:
- function-bind "^1.1.1"
- get-intrinsic "^1.0.2"
+ function-bind "^1.1.2"
+ get-intrinsic "^1.2.1"
+ set-function-length "^1.1.1"
callsites@^3.0.0:
version "3.1.0"
@@ -2104,16 +2137,26 @@ default-browser@^4.0.0:
execa "^7.1.1"
titleize "^3.0.0"
+define-data-property@^1.0.1, define-data-property@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3"
+ integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==
+ dependencies:
+ get-intrinsic "^1.2.1"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.0"
+
define-lazy-prop@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz#dbb19adfb746d7fc6d734a06b72f4a00d021255f"
integrity sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==
define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5"
- integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.1.tgz#10781cc616eb951a80a034bafcaa7377f6af2b6c"
+ integrity sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==
dependencies:
+ define-data-property "^1.0.1"
has-property-descriptors "^1.0.0"
object-keys "^1.1.1"
@@ -2206,25 +2249,25 @@ error-ex@^1.3.1:
is-arrayish "^0.2.1"
es-abstract@^1.20.4, es-abstract@^1.22.1:
- version "1.22.1"
- resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.1.tgz#8b4e5fc5cefd7f1660f0f8e1a52900dfbc9d9ccc"
- integrity sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==
+ version "1.22.3"
+ resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32"
+ integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==
dependencies:
array-buffer-byte-length "^1.0.0"
- arraybuffer.prototype.slice "^1.0.1"
+ arraybuffer.prototype.slice "^1.0.2"
available-typed-arrays "^1.0.5"
- call-bind "^1.0.2"
+ call-bind "^1.0.5"
es-set-tostringtag "^2.0.1"
es-to-primitive "^1.2.1"
- function.prototype.name "^1.1.5"
- get-intrinsic "^1.2.1"
+ function.prototype.name "^1.1.6"
+ get-intrinsic "^1.2.2"
get-symbol-description "^1.0.0"
globalthis "^1.0.3"
gopd "^1.0.1"
- has "^1.0.3"
has-property-descriptors "^1.0.0"
has-proto "^1.0.1"
has-symbols "^1.0.3"
+ hasown "^2.0.0"
internal-slot "^1.0.5"
is-array-buffer "^3.0.2"
is-callable "^1.2.7"
@@ -2232,23 +2275,23 @@ es-abstract@^1.20.4, es-abstract@^1.22.1:
is-regex "^1.1.4"
is-shared-array-buffer "^1.0.2"
is-string "^1.0.7"
- is-typed-array "^1.1.10"
+ is-typed-array "^1.1.12"
is-weakref "^1.0.2"
- object-inspect "^1.12.3"
+ object-inspect "^1.13.1"
object-keys "^1.1.1"
object.assign "^4.1.4"
- regexp.prototype.flags "^1.5.0"
- safe-array-concat "^1.0.0"
+ regexp.prototype.flags "^1.5.1"
+ safe-array-concat "^1.0.1"
safe-regex-test "^1.0.0"
- string.prototype.trim "^1.2.7"
- string.prototype.trimend "^1.0.6"
- string.prototype.trimstart "^1.0.6"
+ string.prototype.trim "^1.2.8"
+ string.prototype.trimend "^1.0.7"
+ string.prototype.trimstart "^1.0.7"
typed-array-buffer "^1.0.0"
typed-array-byte-length "^1.0.0"
typed-array-byte-offset "^1.0.0"
typed-array-length "^1.0.4"
unbox-primitive "^1.0.2"
- which-typed-array "^1.1.10"
+ which-typed-array "^1.1.13"
es-iterator-helpers@^1.0.12:
version "1.0.14"
@@ -2271,20 +2314,20 @@ es-iterator-helpers@^1.0.12:
safe-array-concat "^1.0.0"
es-set-tostringtag@^2.0.1:
- version "2.0.1"
- resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8"
- integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9"
+ integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==
dependencies:
- get-intrinsic "^1.1.3"
- has "^1.0.3"
+ get-intrinsic "^1.2.2"
has-tostringtag "^1.0.0"
+ hasown "^2.0.0"
es-shim-unscopables@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241"
- integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763"
+ integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==
dependencies:
- has "^1.0.3"
+ hasown "^2.0.0"
es-to-primitive@^1.2.1:
version "1.2.1"
@@ -2352,7 +2395,7 @@ escape-string-regexp@^4.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
-eslint-import-resolver-node@^0.3.7:
+eslint-import-resolver-node@^0.3.9:
version "0.3.9"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==
@@ -2369,25 +2412,25 @@ eslint-module-utils@^2.8.0:
debug "^3.2.7"
eslint-plugin-import@^2:
- version "2.28.1"
- resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz#63b8b5b3c409bfc75ebaf8fb206b07ab435482c4"
- integrity sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==
- dependencies:
- array-includes "^3.1.6"
- array.prototype.findlastindex "^1.2.2"
- array.prototype.flat "^1.3.1"
- array.prototype.flatmap "^1.3.1"
+ version "2.29.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.0.tgz#8133232e4329ee344f2f612885ac3073b0b7e155"
+ integrity sha512-QPOO5NO6Odv5lpoTkddtutccQjysJuFxoPS7fAHO+9m9udNHvTCPSAMW9zGAYj8lAIdr40I8yPCdUYrncXtrwg==
+ dependencies:
+ array-includes "^3.1.7"
+ array.prototype.findlastindex "^1.2.3"
+ array.prototype.flat "^1.3.2"
+ array.prototype.flatmap "^1.3.2"
debug "^3.2.7"
doctrine "^2.1.0"
- eslint-import-resolver-node "^0.3.7"
+ eslint-import-resolver-node "^0.3.9"
eslint-module-utils "^2.8.0"
- has "^1.0.3"
- is-core-module "^2.13.0"
+ hasown "^2.0.0"
+ is-core-module "^2.13.1"
is-glob "^4.0.3"
minimatch "^3.1.2"
- object.fromentries "^2.0.6"
- object.groupby "^1.0.0"
- object.values "^1.1.6"
+ object.fromentries "^2.0.7"
+ object.groupby "^1.0.1"
+ object.values "^1.1.7"
semver "^6.3.1"
tsconfig-paths "^3.14.2"
@@ -2797,12 +2840,12 @@ fsevents@^2.3.2, fsevents@~2.3.2:
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
-function-bind@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
- integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
+function-bind@^1.1.1, function-bind@^1.1.2:
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
+ integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
-function.prototype.name@^1.1.5:
+function.prototype.name@^1.1.5, function.prototype.name@^1.1.6:
version "1.1.6"
resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd"
integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==
@@ -2827,15 +2870,15 @@ get-caller-file@^2.0.5:
resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e"
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
-get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1:
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82"
- integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==
+get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b"
+ integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==
dependencies:
- function-bind "^1.1.1"
- has "^1.0.3"
+ function-bind "^1.1.2"
has-proto "^1.0.1"
has-symbols "^1.0.3"
+ hasown "^2.0.0"
get-nonce@^1.0.0:
version "1.0.1"
@@ -2957,11 +3000,11 @@ has-flag@^4.0.0:
integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==
has-property-descriptors@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861"
- integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340"
+ integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==
dependencies:
- get-intrinsic "^1.1.1"
+ get-intrinsic "^1.2.2"
has-proto@^1.0.1:
version "1.0.1"
@@ -3012,11 +3055,16 @@ has-values@^1.0.0:
kind-of "^4.0.0"
has@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
- integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6"
+ integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==
+
+hasown@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c"
+ integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==
dependencies:
- function-bind "^1.1.1"
+ function-bind "^1.1.2"
hoist-non-react-statics@^3.3.1:
version "3.3.2"
@@ -3089,7 +3137,7 @@ inherits@2:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-internal-slot@^1.0.3, internal-slot@^1.0.5:
+internal-slot@^1.0.3:
version "1.0.5"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986"
integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==
@@ -3098,6 +3146,15 @@ internal-slot@^1.0.3, internal-slot@^1.0.5:
has "^1.0.3"
side-channel "^1.0.4"
+internal-slot@^1.0.5:
+ version "1.0.6"
+ resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930"
+ integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==
+ dependencies:
+ get-intrinsic "^1.2.2"
+ hasown "^2.0.0"
+ side-channel "^1.0.4"
+
invariant@^2.2.4:
version "2.2.4"
resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6"
@@ -3172,13 +3229,20 @@ is-ci@^2.0.0:
dependencies:
ci-info "^2.0.0"
-is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.9.0:
+is-core-module@^2.11.0, is-core-module@^2.9.0:
version "2.13.0"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.0.tgz#bb52aa6e2cbd49a30c2ba68c42bf3435ba6072db"
integrity sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==
dependencies:
has "^1.0.3"
+is-core-module@^2.13.0, is-core-module@^2.13.1:
+ version "2.13.1"
+ resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
+ integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
+ dependencies:
+ hasown "^2.0.0"
+
is-data-descriptor@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56"
@@ -3373,7 +3437,7 @@ is-symbol@^1.0.2, is-symbol@^1.0.3:
dependencies:
has-symbols "^1.0.2"
-is-typed-array@^1.1.10, is-typed-array@^1.1.9:
+is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9:
version "1.1.12"
resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a"
integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==
@@ -4300,10 +4364,10 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
-object-inspect@^1.12.3, object-inspect@^1.9.0:
- version "1.12.3"
- resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9"
- integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==
+object-inspect@^1.13.1, object-inspect@^1.9.0:
+ version "1.13.1"
+ resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2"
+ integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==
object-keys@^1.1.1:
version "1.1.1"
@@ -4345,7 +4409,16 @@ object.fromentries@^2.0.6:
define-properties "^1.1.4"
es-abstract "^1.20.4"
-object.groupby@^1.0.0:
+object.fromentries@^2.0.7:
+ version "2.0.7"
+ resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616"
+ integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
+
+object.groupby@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee"
integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==
@@ -4370,7 +4443,7 @@ object.pick@^1.3.0:
dependencies:
isobject "^3.0.1"
-object.values@^1.1.6:
+object.values@^1.1.6, object.values@^1.1.7:
version "1.1.7"
resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a"
integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==
@@ -4753,7 +4826,7 @@ regex-not@^1.0.0, regex-not@^1.0.2:
extend-shallow "^3.0.2"
safe-regex "^1.1.0"
-regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0:
+regexp.prototype.flags@^1.4.3:
version "1.5.0"
resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz#fe7ce25e7e4cca8db37b6634c8a2c7009199b9cb"
integrity sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==
@@ -4762,6 +4835,15 @@ regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0:
define-properties "^1.2.0"
functions-have-names "^1.2.3"
+regexp.prototype.flags@^1.5.1:
+ version "1.5.1"
+ resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e"
+ integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==
+ dependencies:
+ call-bind "^1.0.2"
+ define-properties "^1.2.0"
+ set-function-name "^2.0.0"
+
remove-trailing-separator@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef"
@@ -4818,7 +4900,7 @@ resolve@^1.19.0:
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
-resolve@^1.20.0, resolve@^1.22.4:
+resolve@^1.20.0:
version "1.22.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.4.tgz#1dc40df46554cdaf8948a486a10f6ba1e2026c34"
integrity sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==
@@ -4827,6 +4909,15 @@ resolve@^1.20.0, resolve@^1.22.4:
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
+resolve@^1.22.4:
+ version "1.22.8"
+ resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
+ integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
+ dependencies:
+ is-core-module "^2.13.0"
+ path-parse "^1.0.7"
+ supports-preserve-symlinks-flag "^1.0.0"
+
resolve@^2.0.0-next.4:
version "2.0.0-next.4"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.4.tgz#3d37a113d6429f496ec4752d2a2e58efb1fd4660"
@@ -4879,13 +4970,13 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
-safe-array-concat@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.0.tgz#2064223cba3c08d2ee05148eedbc563cd6d84060"
- integrity sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==
+safe-array-concat@^1.0.0, safe-array-concat@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c"
+ integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==
dependencies:
call-bind "^1.0.2"
- get-intrinsic "^1.2.0"
+ get-intrinsic "^1.2.1"
has-symbols "^1.0.3"
isarray "^2.0.5"
@@ -4944,6 +5035,25 @@ semver@^7.5.3, semver@^7.5.4:
dependencies:
lru-cache "^6.0.0"
+set-function-length@^1.1.1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed"
+ integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ==
+ dependencies:
+ define-data-property "^1.1.1"
+ get-intrinsic "^1.2.1"
+ gopd "^1.0.1"
+ has-property-descriptors "^1.0.0"
+
+set-function-name@^2.0.0:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a"
+ integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==
+ dependencies:
+ define-data-property "^1.0.1"
+ functions-have-names "^1.2.3"
+ has-property-descriptors "^1.0.0"
+
set-value@^2.0.0, set-value@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b"
@@ -5129,32 +5239,32 @@ string.prototype.matchall@^4.0.8:
regexp.prototype.flags "^1.4.3"
side-channel "^1.0.4"
-string.prototype.trim@^1.2.7:
- version "1.2.7"
- resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz#a68352740859f6893f14ce3ef1bb3037f7a90533"
- integrity sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==
+string.prototype.trim@^1.2.8:
+ version "1.2.8"
+ resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd"
+ integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
-string.prototype.trimend@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz#c4a27fa026d979d79c04f17397f250a462944533"
- integrity sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==
+string.prototype.trimend@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e"
+ integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
-string.prototype.trimstart@^1.0.6:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz#e90ab66aa8e4007d92ef591bbf3cd422c56bdcf4"
- integrity sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==
+string.prototype.trimstart@^1.0.7:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298"
+ integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==
dependencies:
call-bind "^1.0.2"
- define-properties "^1.1.4"
- es-abstract "^1.20.4"
+ define-properties "^1.2.0"
+ es-abstract "^1.22.1"
strip-ansi@^6.0.0, strip-ansi@^6.0.1:
version "6.0.1"
@@ -5542,7 +5652,18 @@ which-collection@^1.0.1:
is-weakmap "^2.0.1"
is-weakset "^2.0.1"
-which-typed-array@^1.1.10, which-typed-array@^1.1.11, which-typed-array@^1.1.9:
+which-typed-array@^1.1.11, which-typed-array@^1.1.13:
+ version "1.1.13"
+ resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36"
+ integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==
+ dependencies:
+ available-typed-arrays "^1.0.5"
+ call-bind "^1.0.4"
+ for-each "^0.3.3"
+ gopd "^1.0.1"
+ has-tostringtag "^1.0.0"
+
+which-typed-array@^1.1.9:
version "1.1.11"
resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.11.tgz#99d691f23c72aab6768680805a271b69761ed61a"
integrity sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
index c75aca7a5fa..20c3826721b 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/http/ssl/HostedSslConnectorFactory.java
@@ -10,6 +10,7 @@ import java.time.Duration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
+import java.util.Set;
/**
* Component specification for {@link com.yahoo.jdisc.http.server.jetty.ConnectorFactory} with hosted specific configuration.
@@ -25,6 +26,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
private final Duration endpointConnectionTtl;
private final List<String> remoteAddressHeaders;
private final List<String> remotePortHeaders;
+ private final Set<String> knownServerNames;
public static Builder builder(String name, int listenPort) { return new Builder(name, listenPort); }
@@ -37,6 +39,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
this.endpointConnectionTtl = builder.endpointConnectionTtl;
this.remoteAddressHeaders = List.copyOf(builder.remoteAddressHeaders);
this.remotePortHeaders = List.copyOf(builder.remotePortHeaders);
+ this.knownServerNames = Set.copyOf(builder.knownServerNames);
}
private static SslProvider createSslProvider(Builder builder) {
@@ -70,7 +73,8 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
.maxConnectionLife(endpointConnectionTtl != null ? endpointConnectionTtl.toSeconds() : 0)
.accessLog(new ConnectorConfig.AccessLog.Builder()
.remoteAddressHeaders(remoteAddressHeaders)
- .remotePortHeaders(remotePortHeaders));
+ .remotePortHeaders(remotePortHeaders))
+ .serverName.known(knownServerNames);
}
@@ -89,6 +93,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
String tlsCaCertificatesPem;
String tlsCaCertificatesPath;
boolean tokenEndpoint;
+ Set<String> knownServerNames = Set.of();
private Builder(String name, int port) { this.name = name; this.port = port; }
public Builder clientAuth(SslClientAuth auth) { clientAuth = auth; return this; }
@@ -101,7 +106,7 @@ public class HostedSslConnectorFactory extends ConnectorFactory {
public Builder tokenEndpoint(boolean enable) { this.tokenEndpoint = enable; return this; }
public Builder remoteAddressHeader(String header) { this.remoteAddressHeaders.add(header); return this; }
public Builder remotePortHeader(String header) { this.remotePortHeaders.add(header); return this; }
-
+ public Builder knownServerNames(Set<String> knownServerNames) { this.knownServerNames = Set.copyOf(knownServerNames); return this; }
public HostedSslConnectorFactory build() { return new HostedSslConnectorFactory(this); }
}
}
diff --git a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
index 2093d0cfbe3..18020f5df5d 100644
--- a/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
+++ b/config-model/src/main/java/com/yahoo/vespa/model/container/xml/ContainerModelBuilder.java
@@ -606,6 +606,11 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
var endpointCert = state.endpointCertificateSecrets().orElse(null);
if (endpointCert != null) {
builder.endpointCertificate(endpointCert);
+ Set<String> mtlsEndpointNames = state.getEndpoints().stream()
+ .filter(endpoint -> endpoint.authMethod() == ApplicationClusterEndpoint.AuthMethod.mtls)
+ .flatMap(endpoint -> endpoint.names().stream())
+ .collect(Collectors.toSet());
+ builder.knownServerNames(mtlsEndpointNames);
boolean isPublic = state.zone().system().isPublic();
List<X509Certificate> clientCertificates = getClientCertificates(cluster);
if (isPublic) {
@@ -659,6 +664,7 @@ public class ContainerModelBuilder extends ConfigModelBuilder<ContainerModel> {
.remoteAddressHeader("X-Forwarded-For")
.remotePortHeader("X-Forwarded-Port")
.clientAuth(SslClientAuth.NEED)
+ .knownServerNames(tokenEndpoints)
.build();
server.addConnector(connector);
diff --git a/config-model/src/test/derived/array_of_struct_attribute/test.sd b/config-model/src/test/derived/array_of_struct_attribute/test.sd
index ce6e3db7310..3e46aea986a 100644
--- a/config-model/src/test/derived/array_of_struct_attribute/test.sd
+++ b/config-model/src/test/derived/array_of_struct_attribute/test.sd
@@ -17,6 +17,6 @@ schema test {
}
}
document-summary rename {
- summary new_elem_array type array<elem> { source: elem_array }
+ summary new_elem_array { source: elem_array }
}
}
diff --git a/config-model/src/test/derived/bolding_dynamic_summary/test.sd b/config-model/src/test/derived/bolding_dynamic_summary/test.sd
index bf7455df3c9..3d054c65839 100644
--- a/config-model/src/test/derived/bolding_dynamic_summary/test.sd
+++ b/config-model/src/test/derived/bolding_dynamic_summary/test.sd
@@ -31,19 +31,19 @@ schema test {
}
}
document-summary dyn {
- summary str_3_dyn type string {
+ summary str_3_dyn {
source: str_3
dynamic
}
- summary arr_3_dyn type array<string> {
+ summary arr_3_dyn {
source: arr_3
dynamic
}
- summary str_4_bold type string {
+ summary str_4_bold {
source: str_4
bolding: on
}
- summary arr_4_bold type array<string> {
+ summary arr_4_bold {
source: arr_4
bolding: on
}
diff --git a/config-model/src/test/derived/map_of_struct_attribute/test.sd b/config-model/src/test/derived/map_of_struct_attribute/test.sd
index 7001b95d09f..617f761c7e7 100644
--- a/config-model/src/test/derived/map_of_struct_attribute/test.sd
+++ b/config-model/src/test/derived/map_of_struct_attribute/test.sd
@@ -30,7 +30,7 @@ schema test {
}
}
document-summary rename {
- summary new_str_elem_map type map<string,elem> { source: str_elem_map }
- summary new_int_elem_map type map<int,elem> { source: int_elem_map }
+ summary new_str_elem_map { source: str_elem_map }
+ summary new_int_elem_map { source: int_elem_map }
}
}
diff --git a/config-model/src/test/derived/multiplesummaries/multiplesummaries.sd b/config-model/src/test/derived/multiplesummaries/multiplesummaries.sd
index b19b04c8222..221e888adc7 100644
--- a/config-model/src/test/derived/multiplesummaries/multiplesummaries.sd
+++ b/config-model/src/test/derived/multiplesummaries/multiplesummaries.sd
@@ -80,35 +80,35 @@ schema multiplesummaries {
document-summary third {
- summary a type string {
+ summary a {
}
- summary adynamic type string {
+ summary adynamic {
}
- summary d type string {
+ summary d {
}
- summary e type string {
+ summary e {
}
summary f {
}
- summary g type array<int> {
+ summary g {
}
- summary h type weightedset<string> {
+ summary h {
}
}
document-summary attributesonly1 {
- summary a type string {
+ summary a {
}
- summary c type string {
+ summary c {
}
}
@@ -116,10 +116,10 @@ schema multiplesummaries {
# Since a here is a dynamic summary field, it will be fetched from disk
document-summary notattributesonly1 {
- summary adynamic type string { # Should still be dynamic here
+ summary adynamic { # Should still be dynamic here
}
- summary c type string {
+ summary c {
}
}
@@ -127,25 +127,25 @@ schema multiplesummaries {
# Since a here is a dynamic summary, it will be fetched from disk
document-summary anothernotattributesonly2 {
- summary adynamic2 type string { # Should still be dynamic here
+ summary adynamic2 { # Should still be dynamic here
source: a
dynamic
}
- summary c type string {
+ summary c {
}
- summary alltags type array<string> {
+ summary alltags {
source: mytags
}
- summary sometags type array<string> {
+ summary sometags {
source: mytags
matched-elements-only
}
- summary anothera type string {
+ summary anothera {
source: a
}
- summary anotherb type string {
+ summary anotherb {
source: b
}
}
@@ -153,21 +153,21 @@ schema multiplesummaries {
# Not attributes only because d is bolded
document-summary notattributesonly3 {
- summary a type string {
+ summary a {
}
- summary d type string {
+ summary d {
}
}
document-summary attributesonly2 {
- summary anotdynamic type string { # Should not be dynamic here
+ summary anotdynamic { # Should not be dynamic here
source: adynamic
}
- summary c type string {
+ summary c {
}
summary loc_position type long {
@@ -178,10 +178,10 @@ schema multiplesummaries {
document-summary attributesonly3 {
- summary a type string {
+ summary a {
}
- summary anotbolded type string {
+ summary anotbolded {
source: a
}
@@ -192,19 +192,19 @@ schema multiplesummaries {
document-summary notattributesonly4 {
- summary abolded2 type string {
+ summary abolded2 {
source: a
bolding: on
}
- summary c type string {
+ summary c {
}
}
document-summary notattributesonly5 {
- summary aboldeddynamic type string {
+ summary aboldeddynamic {
source: a
dynamic
bolding: on
diff --git a/config-model/src/test/derived/nearestneighbor/test.sd b/config-model/src/test/derived/nearestneighbor/test.sd
index 7d08a5279bc..5b891049480 100644
--- a/config-model/src/test/derived/nearestneighbor/test.sd
+++ b/config-model/src/test/derived/nearestneighbor/test.sd
@@ -23,6 +23,6 @@ schema test {
}
}
document-summary minimal {
- summary id type int {}
+ summary id {}
}
}
diff --git a/config-model/src/test/derived/ngram/chunk.sd b/config-model/src/test/derived/ngram/chunk.sd
index ab309f57548..84d806ef074 100644
--- a/config-model/src/test/derived/ngram/chunk.sd
+++ b/config-model/src/test/derived/ngram/chunk.sd
@@ -12,7 +12,7 @@ schema chunk {
}
document-summary content-summary inherits default {
- summary content_dynamic type string {
+ summary content_dynamic {
source: content
dynamic
}
diff --git a/config-model/src/test/derived/reference_fields/ad.sd b/config-model/src/test/derived/reference_fields/ad.sd
index 390f8f6a154..097a6ed5bc9 100644
--- a/config-model/src/test/derived/reference_fields/ad.sd
+++ b/config-model/src/test/derived/reference_fields/ad.sd
@@ -12,6 +12,6 @@ schema ad {
}
}
document-summary explicit_summary {
- summary yet_another_ref type reference<campaign> {}
+ summary yet_another_ref {}
}
}
diff --git a/config-model/src/test/derived/reference_from_several/bar.sd b/config-model/src/test/derived/reference_from_several/bar.sd
index 12cf8e63378..02c912153ef 100644
--- a/config-model/src/test/derived/reference_from_several/bar.sd
+++ b/config-model/src/test/derived/reference_from_several/bar.sd
@@ -10,7 +10,7 @@ schema bar {
}
import field bpref.x as barsximp {}
document-summary other {
- summary bartitle type string {}
+ summary bartitle {}
summary barsximp type int {}
}
}
diff --git a/config-model/src/test/derived/reference_from_several/foo.sd b/config-model/src/test/derived/reference_from_several/foo.sd
index 5ef42ee6f0d..26ba07ea1fd 100644
--- a/config-model/src/test/derived/reference_from_several/foo.sd
+++ b/config-model/src/test/derived/reference_from_several/foo.sd
@@ -11,6 +11,6 @@ schema foo {
import field myref.x as myx {}
document-summary small {
summary myx type int {}
- summary foo type string {}
+ summary foo {}
}
}
diff --git a/config-model/src/test/derived/schemainheritance/child.sd b/config-model/src/test/derived/schemainheritance/child.sd
index 77daf2ba34f..ea3ff9b85da 100644
--- a/config-model/src/test/derived/schemainheritance/child.sd
+++ b/config-model/src/test/derived/schemainheritance/child.sd
@@ -36,7 +36,7 @@ schema child inherits parent {
}
document-summary child_summary inherits parent_summary {
- summary cf1 type string {}
+ summary cf1 {}
}
import field importedschema_ref.importedfield2 as child_imported {}
diff --git a/config-model/src/test/derived/schemainheritance/parent.sd b/config-model/src/test/derived/schemainheritance/parent.sd
index 03392b428ed..ab2b703ba57 100644
--- a/config-model/src/test/derived/schemainheritance/parent.sd
+++ b/config-model/src/test/derived/schemainheritance/parent.sd
@@ -32,7 +32,7 @@ schema parent {
file: small_constants_and_functions.onnx
}
document-summary parent_summary {
- summary pf1 type string {
+ summary pf1 {
}
}
import field importedschema_ref.importedfield1 as parent_imported {
diff --git a/config-model/src/test/examples/multiplesummaries.sd b/config-model/src/test/examples/multiplesummaries.sd
index 7e298b4e7a3..a7e3a78fe6d 100644
--- a/config-model/src/test/examples/multiplesummaries.sd
+++ b/config-model/src/test/examples/multiplesummaries.sd
@@ -19,13 +19,13 @@ search multiplesummaries {
document-summary other {
- summary field1 type weightedset<string> {
+ summary field1 {
}
- summary field2 type tag {
+ summary field2 {
}
- summary field3 type array<int> {
+ summary field3 {
}
}
diff --git a/config-model/src/test/examples/nextgen/summaryfield.sd b/config-model/src/test/examples/nextgen/summaryfield.sd
index 06cc980ea73..5a5747359a0 100644
--- a/config-model/src/test/examples/nextgen/summaryfield.sd
+++ b/config-model/src/test/examples/nextgen/summaryfield.sd
@@ -13,10 +13,10 @@ search summaryfield {
summary cox type string {
source: bar
}
- summary alltags type array<string> {
+ summary alltags {
source: mytags
}
- summary sometags type array<string> {
+ summary sometags {
source: mytags
matched-elements-only
}
diff --git a/config-model/src/test/examples/outsidesummary.sd b/config-model/src/test/examples/outsidesummary.sd
index 5fadc1948f0..a95cbb0c628 100644
--- a/config-model/src/test/examples/outsidesummary.sd
+++ b/config-model/src/test/examples/outsidesummary.sd
@@ -3,17 +3,17 @@ search outsidesummary {
document-summary other {
- summary sa type string {
+ summary sa {
dynamic
source: a
}
- summary sa2 type string {
+ summary sa2 {
full
source: a
}
- summary a type string {
+ summary a {
}
}
diff --git a/config-model/src/test/examples/summaryfieldcollision.sd b/config-model/src/test/examples/summaryfieldcollision.sd
index 6a8cb2eeb31..2235abce422 100644
--- a/config-model/src/test/examples/summaryfieldcollision.sd
+++ b/config-model/src/test/examples/summaryfieldcollision.sd
@@ -13,13 +13,13 @@ search summaryfieldcollision {
}
document-summary sum1 {
- summary f type string {
+ summary f {
source: title
}
}
document-summary sum2 {
- summary f type string {
+ summary f {
source: description
}
}
diff --git a/config-model/src/test/java/com/yahoo/schema/SchemaTestCase.java b/config-model/src/test/java/com/yahoo/schema/SchemaTestCase.java
index 798252c9a34..c959634019d 100644
--- a/config-model/src/test/java/com/yahoo/schema/SchemaTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/SchemaTestCase.java
@@ -143,10 +143,10 @@ public class SchemaTestCase {
" file: models/my_model.onnx" +
" }" +
" document-summary parent_summary1 {" +
- " summary pf1 type string {}" +
+ " summary pf1 {}" +
" }" +
" document-summary parent_summary2 {" +
- " summary pf2 type string {}" +
+ " summary pf2 {}" +
" }" +
" import field parentschema_ref.name as parent_imported {}" +
" raw-as-base64-in-summary" +
@@ -177,7 +177,7 @@ public class SchemaTestCase {
" file: models/my_model.onnx" +
" }" +
" document-summary child1_summary inherits parent_summary1 {" +
- " summary c1f1 type string {}" +
+ " summary c1f1 {}" +
" }" +
" import field parentschema_ref.name as child1_imported {}" +
"}");
@@ -208,7 +208,7 @@ public class SchemaTestCase {
" file: models/my_model.onnx" +
" }" +
" document-summary child2_summary inherits parent_summary1, parent_summary2 {" +
- " summary c2f1 type string {}" +
+ " summary c2f1 {}" +
" }" +
" import field parentschema_ref.name as child2_imported {}" +
"}");
@@ -340,7 +340,7 @@ public class SchemaTestCase {
" file: models/my_model.onnx" +
" }" +
" document-summary parent_summary {" +
- " summary pf1 type string {}" +
+ " summary pf1 {}" +
" }" +
" import field parentschema_ref.name as parent_imported {}" +
" raw-as-base64-in-summary" +
diff --git a/config-model/src/test/java/com/yahoo/schema/SummaryTestCase.java b/config-model/src/test/java/com/yahoo/schema/SummaryTestCase.java
index c9fa3ce145a..3c83e79157a 100644
--- a/config-model/src/test/java/com/yahoo/schema/SummaryTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/SummaryTestCase.java
@@ -48,8 +48,8 @@ public class SummaryTestCase {
String sd = joinLines(
"schema disksummary {",
" document-summary foobar {",
- " summary foo1 type string { source: inmemory }",
- " summary foo2 type string { source: ondisk }",
+ " summary foo1 { source: inmemory }",
+ " summary foo2 { source: ondisk }",
" }",
" document disksummary {",
" field inmemory type string {",
@@ -84,8 +84,8 @@ public class SummaryTestCase {
" }",
" }",
" document-summary foobar {",
- " summary foo1 type string { source: inmemory }",
- " summary foo2 type string { source: ondisk }",
+ " summary foo1 { source: inmemory }",
+ " summary foo2 { source: ondisk }",
" from-disk",
" }",
"}");
@@ -114,7 +114,7 @@ public class SummaryTestCase {
" }",
" }",
" document-summary filtered {",
- " summary elem_array_filtered type array<elem> {",
+ " summary elem_array_filtered {",
" source: elem_array",
" matched-elements-only",
" }",
@@ -141,17 +141,17 @@ public class SummaryTestCase {
" }",
" }",
" document-summary title {",
- " summary title type string {",
+ " summary title {",
" source: title",
" }",
" }",
" document-summary title_artist inherits title {",
- " summary artist type string {",
+ " summary artist {",
" source: artist",
" }",
" }",
" document-summary everything inherits title_artist {",
- " summary album type string {",
+ " summary album {",
" source: album",
" }",
" }",
@@ -201,12 +201,12 @@ public class SummaryTestCase {
" }",
" }",
" document-summary title {",
- " summary title type string {",
+ " summary title {",
" source: title",
" }",
" }",
" document-summary title2 inherits title {",
- " summary title type string {",
+ " summary title {",
" source: title_short",
" }",
" }",
@@ -297,12 +297,12 @@ public class SummaryTestCase {
}
}
document-summary parent1 {
- summary s1 type string {
+ summary s1 {
source: field1
}
}
document-summary parent2 {
- summary field1 type string {
+ summary field1 {
source: field1
}
}
@@ -326,7 +326,7 @@ public class SummaryTestCase {
" }" +
" }" +
" document-summary parent_summary {" +
- " summary pf1 type string {}" +
+ " summary pf1 {}" +
" }" +
"}");
String child = joinLines(
@@ -337,7 +337,7 @@ public class SummaryTestCase {
" }" +
" }" +
" document-summary child_summary inherits parent_summary {" +
- " summary cf1 type string {}" +
+ " summary cf1 {}" +
" }" +
"}");
DeployLoggerStub logger = new DeployLoggerStub();
diff --git a/config-model/src/test/java/com/yahoo/schema/derived/SummaryTestCase.java b/config-model/src/test/java/com/yahoo/schema/derived/SummaryTestCase.java
index a1d726473be..2fb7955546c 100644
--- a/config-model/src/test/java/com/yahoo/schema/derived/SummaryTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/derived/SummaryTestCase.java
@@ -131,7 +131,7 @@ public class SummaryTestCase extends AbstractSchemaTestCase {
" }",
" }",
" document-summary my_summary {",
- " summary other_campaign_ref type reference<campaign> {}",
+ " summary other_campaign_ref {}",
" }",
"}"));
builder.build(true);
@@ -146,11 +146,11 @@ public class SummaryTestCase extends AbstractSchemaTestCase {
" field foo type string { indexing: summary }",
" }",
" document-summary bar {",
- " summary foo type string {}",
+ " summary foo {}",
" omit-summary-features",
" }",
" document-summary baz {",
- " summary foo type string {}",
+ " summary foo {}",
" }",
"}");
var search = ApplicationBuilder.createFromString(sd).getSchema();
diff --git a/config-model/src/test/java/com/yahoo/schema/processing/MatchedElementsOnlyResolverTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/MatchedElementsOnlyResolverTestCase.java
index e8f8ba4193f..91cd2418eef 100644
--- a/config-model/src/test/java/com/yahoo/schema/processing/MatchedElementsOnlyResolverTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/processing/MatchedElementsOnlyResolverTestCase.java
@@ -72,7 +72,7 @@ public class MatchedElementsOnlyResolverTestCase {
@Test
void explicit_complex_summary_field_can_use_filter_transform_with_reference_to_source_field() throws ParseException {
String documentSummary = joinLines("document-summary my_summary {",
- " summary my_filter_field type map<string, string> {",
+ " summary my_filter_field {",
" source: my_field",
" matched-elements-only",
" }",
@@ -123,7 +123,7 @@ public class MatchedElementsOnlyResolverTestCase {
@Test
void explicit_summary_field_can_use_filter_transform_with_reference_to_attribute_source_field() throws ParseException {
String documentSummary = joinLines("document-summary my_summary {",
- " summary my_filter_field type array<string> {",
+ " summary my_filter_field {",
" source: my_field",
" matched-elements-only",
" }",
diff --git a/config-model/src/test/java/com/yahoo/schema/processing/SummaryConsistencyTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/SummaryConsistencyTestCase.java
index d2938371c5b..9eca2106c5e 100644
--- a/config-model/src/test/java/com/yahoo/schema/processing/SummaryConsistencyTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/processing/SummaryConsistencyTestCase.java
@@ -32,7 +32,7 @@ public class SummaryConsistencyTestCase {
" }",
" }",
" document-summary unfiltered {",
- " summary elem_array_unfiltered type array<elem> {",
+ " summary elem_array_unfiltered {",
" source: elem_array",
" }",
" }",
diff --git a/config-model/src/test/java/com/yahoo/schema/processing/SummaryDiskAccessValidatorTestCase.java b/config-model/src/test/java/com/yahoo/schema/processing/SummaryDiskAccessValidatorTestCase.java
index ab376e539ec..a5145588136 100644
--- a/config-model/src/test/java/com/yahoo/schema/processing/SummaryDiskAccessValidatorTestCase.java
+++ b/config-model/src/test/java/com/yahoo/schema/processing/SummaryDiskAccessValidatorTestCase.java
@@ -25,7 +25,7 @@ public class SummaryDiskAccessValidatorTestCase {
" }",
" }",
" document-summary my_sum {",
- " summary str_map type map<string, string> { source: str_map }",
+ " summary str_map { source: str_map }",
" }",
"}");
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudDataPlaneFilterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudDataPlaneFilterTest.java
index 937052df122..49ed1972afe 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudDataPlaneFilterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudDataPlaneFilterTest.java
@@ -1,6 +1,8 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.model.container.xml;
+import com.yahoo.config.model.api.ApplicationClusterEndpoint;
+import com.yahoo.config.model.api.ContainerEndpoint;
import com.yahoo.config.model.api.EndpointCertificateSecrets;
import com.yahoo.config.model.builder.xml.test.DomBuilderTest;
import com.yahoo.config.model.deploy.DeployState;
@@ -38,6 +40,7 @@ import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;
+import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
@@ -91,6 +94,7 @@ public class CloudDataPlaneFilterTest extends ContainerModelBuilderTestBase {
var caCerts = X509CertificateUtils.certificateListFromPem(connectorConfig.ssl().caCertificate());
assertEquals(1, caCerts.size());
assertEquals(List.of(certificate), caCerts);
+ assertEquals(List.of("foo.bar"), connectorConfig.serverName().known());
var srvCfg = root.getConfig(ServerConfig.class, "container/http");
assertEquals("cloud-data-plane-insecure", srvCfg.defaultFilters().get(0).filterId());
assertEquals(8080, srvCfg.defaultFilters().get(0).localPort());
@@ -191,6 +195,7 @@ public class CloudDataPlaneFilterTest extends ContainerModelBuilderTestBase {
.setEndpointCertificateSecrets(Optional.of(new EndpointCertificateSecrets("CERT", "KEY")))
.setHostedVespa(true))
.zone(new Zone(SystemName.PublicCd, Environment.dev, RegionName.defaultName()))
+ .endpoints(Set.of(new ContainerEndpoint("foo", ApplicationClusterEndpoint.Scope.zone, List.of("foo.bar"))))
.build();
return createModel(root, state, null, clusterElem);
}
diff --git a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudTokenDataPlaneFilterTest.java b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudTokenDataPlaneFilterTest.java
index 1642e0ff8f2..c89ea421b39 100644
--- a/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudTokenDataPlaneFilterTest.java
+++ b/config-model/src/test/java/com/yahoo/vespa/model/container/xml/CloudTokenDataPlaneFilterTest.java
@@ -14,9 +14,12 @@ import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
+import com.yahoo.jdisc.http.ConnectorConfig;
import com.yahoo.jdisc.http.filter.security.cloud.config.CloudTokenDataPlaneFilterConfig;
import com.yahoo.processing.response.Data;
+import com.yahoo.vespa.model.container.ApplicationContainer;
import com.yahoo.vespa.model.container.ContainerModel;
+import com.yahoo.vespa.model.container.http.ConnectorFactory;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
@@ -127,6 +130,21 @@ public class CloudTokenDataPlaneFilterTest extends ContainerModelBuilderTestBase
assertFalse(root.getConfigIds().stream().anyMatch(id -> id.contains("DataplaneProxyConfigurator")));
}
+ @Test
+ void configuresCorrectConnectors() throws IOException {
+ var certFile = securityFolder.resolve("foo.pem");
+ var clusterElem = DomBuilderTest.parse(servicesXmlTemplate.formatted(applicationFolder.toPath().relativize(certFile).toString()));
+ createCertificate(certFile);
+ buildModel(Set.of(tokenEndpoint, mtlsEndpoint), defaultTokens, clusterElem);
+
+ ConnectorConfig connectorConfig8443 = connectorConfig(8443);
+ assertEquals(List.of("mtls"),connectorConfig8443.serverName().known());
+
+ ConnectorConfig connectorConfig8444 = connectorConfig(8444);
+ assertEquals(List.of("token"),connectorConfig8444.serverName().known());
+
+ }
+
private static CloudTokenDataPlaneFilterConfig.Clients.Tokens tokenConfig(
String id, Collection<String> fingerprints, Collection<String> accessCheckHashes, Collection<String> expirations) {
return new CloudTokenDataPlaneFilterConfig.Clients.Tokens.Builder()
@@ -150,4 +168,15 @@ public class CloudTokenDataPlaneFilterTest extends ContainerModelBuilderTestBase
.build();
return createModel(root, state, null, clusterElem);
}
+
+ private ConnectorConfig connectorConfig(int port) {
+ ApplicationContainer container = (ApplicationContainer) root.getProducer("container/container.0");
+ List<ConnectorFactory> connectorFactories = container.getHttp().getHttpServer().get().getConnectorFactories();
+ ConnectorFactory tlsPort = connectorFactories.stream().filter(connectorFactory -> connectorFactory.getListenPort() == port).findFirst().orElseThrow();
+
+ ConnectorConfig.Builder builder = new ConnectorConfig.Builder();
+ tlsPort.getConfig(builder);
+
+ return new ConnectorConfig(builder);
+ }
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionLock.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationMutex.java
index bf683eddc4c..f147bde65f7 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ProvisionLock.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationMutex.java
@@ -10,12 +10,12 @@ import java.util.Objects;
*
* @author mpolden
*/
-public class ProvisionLock implements AutoCloseable {
+public class ApplicationMutex implements Mutex {
private final ApplicationId application;
private final Mutex lock;
- public ProvisionLock(ApplicationId application, Mutex lock) {
+ public ApplicationMutex(ApplicationId application, Mutex lock) {
this.application = Objects.requireNonNull(application);
this.lock = Objects.requireNonNull(lock);
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationTransaction.java b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationTransaction.java
index bc755e02af7..e7c4ed65c46 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationTransaction.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/ApplicationTransaction.java
@@ -13,10 +13,10 @@ import java.util.Objects;
*/
public class ApplicationTransaction implements Closeable {
- private final ProvisionLock lock;
+ private final ApplicationMutex lock;
private final NestedTransaction transaction;
- public ApplicationTransaction(ProvisionLock lock, NestedTransaction transaction) {
+ public ApplicationTransaction(ApplicationMutex lock, NestedTransaction transaction) {
this.lock = Objects.requireNonNull(lock);
this.transaction = Objects.requireNonNull(transaction);
}
diff --git a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
index 38ab69d364c..4d1433cf5e9 100644
--- a/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
+++ b/config-provisioning/src/main/java/com/yahoo/config/provision/Provisioner.java
@@ -37,6 +37,6 @@ public interface Provisioner {
void restart(ApplicationId application, HostFilter filter);
/** Returns a provision lock for the given application */
- ProvisionLock lock(ApplicationId application);
+ ApplicationMutex lock(ApplicationId application);
}
diff --git a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
index 95471fcdea0..c7877c23323 100644
--- a/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
+++ b/configserver/src/main/java/com/yahoo/vespa/config/server/deploy/Deployment.java
@@ -11,7 +11,7 @@ import com.yahoo.config.provision.ApplicationLockException;
import com.yahoo.config.provision.ApplicationTransaction;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.TransientException;
import com.yahoo.transaction.NestedTransaction;
@@ -313,7 +313,7 @@ public class Deployment implements com.yahoo.config.provision.Deployment {
() -> "Timeout exceeded while waiting for application resources of '" + session.getApplicationId() + "'" +
Optional.ofNullable(lastException.get()).map(e -> ". Last exception: " + e.getMessage()).orElse(""));
- try (ProvisionLock lock = provisioner.get().lock(session.getApplicationId())) {
+ try (ApplicationMutex lock = provisioner.get().lock(session.getApplicationId())) {
// Call to activate to make sure that everything is ready, but do not commit the transaction
ApplicationTransaction transaction = new ApplicationTransaction(lock, new NestedTransaction());
provisioner.get().activate(preparedHosts, context, transaction);
diff --git a/configserver/src/test/java/com/yahoo/vespa/config/server/MockProvisioner.java b/configserver/src/test/java/com/yahoo/vespa/config/server/MockProvisioner.java
index 256545313cd..d93ee19085a 100644
--- a/configserver/src/test/java/com/yahoo/vespa/config/server/MockProvisioner.java
+++ b/configserver/src/test/java/com/yahoo/vespa/config/server/MockProvisioner.java
@@ -9,7 +9,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.exception.LoadBalancerServiceException;
@@ -59,8 +59,8 @@ public class MockProvisioner implements Provisioner {
}
@Override
- public ProvisionLock lock(ApplicationId application) {
- return new ProvisionLock(application, () -> {});
+ public ApplicationMutex lock(ApplicationId application) {
+ return new ApplicationMutex(application, () -> {});
}
}
diff --git a/container-core/abi-spec.json b/container-core/abi-spec.json
index 2b5e4386e94..f29c4c2a8f7 100644
--- a/container-core/abi-spec.json
+++ b/container-core/abi-spec.json
@@ -1261,10 +1261,13 @@
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder fallback(java.lang.String)",
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.lang.String)",
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder allowed(java.util.Collection)",
+ "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder known(java.lang.String)",
+ "public com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder known(java.util.Collection)",
"public com.yahoo.jdisc.http.ConnectorConfig$ServerName build()"
],
"fields" : [
- "public java.util.List allowed"
+ "public java.util.List allowed",
+ "public java.util.List known"
]
},
"com.yahoo.jdisc.http.ConnectorConfig$ServerName" : {
@@ -1278,7 +1281,9 @@
"public void <init>(com.yahoo.jdisc.http.ConnectorConfig$ServerName$Builder)",
"public java.lang.String fallback()",
"public java.util.List allowed()",
- "public java.lang.String allowed(int)"
+ "public java.lang.String allowed(int)",
+ "public java.util.List known()",
+ "public java.lang.String known(int)"
],
"fields" : [ ]
},
diff --git a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
index e699b9f200c..983adec034d 100644
--- a/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
+++ b/container-core/src/main/java/com/yahoo/jdisc/http/server/jetty/JDiscServerConnector.java
@@ -11,8 +11,8 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
-import java.util.Optional;
/**
* @author bjorncs
@@ -26,6 +26,7 @@ class JDiscServerConnector extends ServerConnector {
private final Metric metric;
private final String connectorName;
private final int listenPort;
+ private final List<String> knownServerNames;
JDiscServerConnector(ConnectorConfig config, Metric metric, Server server, JettyConnectionLogger connectionLogger,
ConnectionMetricAggregator connectionMetricAggregator, ConnectionFactory... factories) {
@@ -35,6 +36,7 @@ class JDiscServerConnector extends ServerConnector {
this.connectorName = config.name();
this.listenPort = config.listenPort();
this.metricCtx = metric.createContext(createConnectorDimensions(listenPort, connectorName, 0));
+ this.knownServerNames = List.copyOf(config.serverName().known());
this.statistics = new ConnectionStatistics();
setAcceptedTcpNoDelay(config.tcpNoDelay());
@@ -69,7 +71,7 @@ class JDiscServerConnector extends ServerConnector {
dimensions.put(MetricDefinitions.SCHEME_DIMENSION, scheme);
dimensions.put(MetricDefinitions.CLIENT_AUTHENTICATED_DIMENSION, Boolean.toString(clientAuthenticated));
dimensions.put(MetricDefinitions.PROTOCOL_DIMENSION, request.getProtocol());
- String serverName = Optional.ofNullable(request.getServerName()).orElse("unknown");
+ String serverName = knownServerNames.stream().filter(name -> name.equalsIgnoreCase(request.getServerName())).findFirst().orElse("unknown");
dimensions.put(MetricDefinitions.REQUEST_SERVER_NAME_DIMENSION, serverName);
dimensions.putAll(extraDimensions);
return metric.createContext(dimensions);
diff --git a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
index c1c0944d7eb..b4a513e0de8 100644
--- a/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
+++ b/container-core/src/main/resources/configdefinitions/jdisc.http.jdisc.http.connector.def
@@ -139,6 +139,9 @@ serverName.fallback string default=""
# The list of accepted server names. Empty list to accept any. Elements follows format of 'serverName.default'.
serverName.allowed[] string
+# The list of known server names. Used for e.g matching metric dimensions.
+serverName.known[] string
+
# HTTP request headers that contain remote address
accessLog.remoteAddressHeaders[] string
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java
new file mode 100644
index 00000000000..872cbd67780
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrls.java
@@ -0,0 +1,87 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ApplicationName;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.TenantName;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
+
+import java.net.URI;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Generates URLs to various views in the Console. Prefer to create new methods and return
+ * String instead of URI to make it easier to track which views are linked from where.
+ *
+ * @author freva
+ */
+public class ConsoleUrls {
+ private final String root;
+ public ConsoleUrls(URI root) {
+ this.root = root.toString().replaceFirst("/$", ""); // Remove trailing slash
+ }
+
+ public String root() {
+ return root;
+ }
+
+ public String tenantOverview(TenantName tenantName) {
+ return "%s/tenant/%s".formatted(root, tenantName.value());
+ }
+
+ /** Returns URL to notification settings view for the given tenant */
+ public String tenantNotifications(TenantName tenantName) {
+ return "%s/tenant/%s/account/notifications".formatted(root, tenantName.value());
+ }
+
+ public String prodApplicationOverview(TenantName tenantName, ApplicationName applicationName) {
+ return "%s/tenant/%s/application/%s/prod/instance".formatted(root, tenantName.value(), applicationName.value());
+ }
+
+ public String instanceOverview(ApplicationId application, Environment environment) {
+ return "%s/tenant/%s/application/%s/%s/instance/%s".formatted(root,
+ application.tenant().value(),
+ application.application().value(),
+ environment.isManuallyDeployed() ? environment.value() : "prod",
+ application.instance().value());
+ }
+
+ public String clusterOverview(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId) {
+ return cluster(application, zone, clusterId, null);
+ }
+
+ public String clusterReindexing(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId) {
+ return cluster(application, zone, clusterId, "reindexing");
+ }
+
+ public String deploymentRun(RunId id) {
+ return "%s/job/%s/run/%s".formatted(
+ instanceOverview(id.application(), id.type().environment()), id.type().jobName(), id.number());
+ }
+
+ /** Returns URL used to request support from the Vespa team. */
+ public String support() {
+ return root + "/support";
+ }
+
+ /** Returns URL to verify an email address with the given verification code */
+ public String verifyEmail(String verifyCode) {
+ return "%s/verify?%s".formatted(root, queryParam("code", verifyCode));
+ }
+
+ public String termsOfService() { return root + "/terms-of-service-trial.html"; }
+
+ private String cluster(ApplicationId application, ZoneId zone, ClusterSpec.Id clusterId, String viewOrNull) {
+ return instanceOverview(application, zone.environment()) + '?' +
+ queryParam("%s.%s.%s".formatted(application.instance().value(), zone.environment().value(), zone.region().value()),
+ "clusters," + clusterId.value() + (viewOrNull == null ? "" : '=' + viewOrNull));
+ }
+
+ private static String queryParam(String key, String value) {
+ return URLEncoder.encode(key, StandardCharsets.UTF_8) + '=' + URLEncoder.encode(value, StandardCharsets.UTF_8);
+ }
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java
deleted file mode 100644
index b451df87727..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/MockPricingController.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration;
-
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.ApplicationResources;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PriceInformation;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.Prices;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingController;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-import static com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo.SupportLevel.BASIC;
-import static java.math.BigDecimal.ZERO;
-
-public class MockPricingController implements PricingController {
-
- private static final BigDecimal cpuCost = new BigDecimal("1.00");
- private static final BigDecimal memoryCost = new BigDecimal("0.10");
- private static final BigDecimal diskCost = new BigDecimal("0.005");
-
- @Override
- public Prices priceForApplications(List<ApplicationResources> applicationResources, PricingInfo pricingInfo, Plan plan) {
- List<PriceInformation> appPrices = applicationResources.stream()
- .map(resources -> {
- BigDecimal listPrice = resources.vcpu().multiply(cpuCost)
- .add(resources.memoryGb().multiply(memoryCost))
- .add(resources.diskGb().multiply(diskCost))
- .add(resources.enclaveVcpu().multiply(cpuCost))
- .add(resources.enclaveMemoryGb().multiply(memoryCost))
- .add(resources.enclaveDiskGb().multiply(diskCost));
-
- BigDecimal supportLevelCost = pricingInfo.supportLevel() == BASIC ? new BigDecimal("-1.00") : new BigDecimal("8.00");
- BigDecimal listPriceWithSupport = listPrice.add(supportLevelCost);
- BigDecimal enclaveDiscount = isEnclave(resources) ? new BigDecimal("-0.15") : BigDecimal.ZERO;
- BigDecimal volumeDiscount = new BigDecimal("-0.1");
- BigDecimal appTotalAmount = listPrice.add(supportLevelCost).add(enclaveDiscount).add(volumeDiscount);
-
- return new PriceInformation(listPriceWithSupport,
- volumeDiscount,
- ZERO,
- enclaveDiscount,
- appTotalAmount);
- })
- .toList();
-
- PriceInformation sum = PriceInformation.sum(appPrices);
- System.out.println(pricingInfo.committedHourlyAmount());
- var committedAmountDiscount = pricingInfo.committedHourlyAmount().compareTo(ZERO) > 0 ? new BigDecimal("-0.2") : ZERO;
- var totalAmount = sum.totalAmount().add(committedAmountDiscount);
- var enclave = ZERO;
- if (applicationResources.stream().anyMatch(ApplicationResources::enclave) && totalAmount.compareTo(new BigDecimal("14.00")) < 0)
- enclave = new BigDecimal("14.00").subtract(totalAmount);
- var totalPrice = new PriceInformation(ZERO, ZERO, committedAmountDiscount, enclave, totalAmount);
-
- return new Prices(appPrices, totalPrice);
- }
-
- private static boolean isEnclave(ApplicationResources resources) {
- return resources.enclaveVcpu().compareTo(ZERO) > 0;
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
index 0eead322df5..e39a8cf38b7 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/ServiceRegistry.java
@@ -32,8 +32,8 @@ import com.yahoo.vespa.hosted.controller.api.integration.organization.OwnershipI
import com.yahoo.vespa.hosted.controller.api.integration.organization.SystemMonitor;
import com.yahoo.vespa.hosted.controller.api.integration.resource.CostReportConsumer;
import com.yahoo.vespa.hosted.controller.api.integration.resource.ResourceDatabaseClient;
-import com.yahoo.vespa.hosted.controller.api.integration.secrets.GcpSecretStore;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.EndpointSecretManager;
+import com.yahoo.vespa.hosted.controller.api.integration.secrets.GcpSecretStore;
import com.yahoo.vespa.hosted.controller.api.integration.secrets.TenantSecretService;
import com.yahoo.vespa.hosted.controller.api.integration.user.RoleMaintainer;
import com.yahoo.vespa.hosted.controller.api.integration.vcmr.ChangeRequestClient;
@@ -90,6 +90,8 @@ public interface ServiceRegistry {
ZoneRegistry zoneRegistry();
+ ConsoleUrls consoleUrls();
+
ResourceTagger resourceTagger();
EnclaveAccessService enclaveAccessService();
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java
index 1acb4964ea6..e7959d2057a 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/Bill.java
@@ -8,16 +8,11 @@ import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.zone.ZoneId;
import java.math.BigDecimal;
-import java.time.Clock;
import java.time.LocalDate;
-import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.List;
-import java.util.Map;
import java.util.Objects;
import java.util.Optional;
-import java.util.SortedMap;
-import java.util.TreeMap;
import java.util.UUID;
import java.util.function.Function;
@@ -69,7 +64,7 @@ public class Bill {
return tenant;
}
- public String status() {
+ public BillStatus status() {
return statusHistory.current();
}
@@ -389,28 +384,4 @@ public class Bill {
}
}
- public static class StatusHistory {
- SortedMap<ZonedDateTime, String> history;
-
- public StatusHistory(SortedMap<ZonedDateTime, String> history) {
- this.history = history;
- }
-
- public static StatusHistory open(Clock clock) {
- var now = clock.instant().atZone(ZoneOffset.UTC);
- return new StatusHistory(
- new TreeMap<>(Map.of(now, "OPEN"))
- );
- }
-
- public String current() {
- return history.get(history.lastKey());
- }
-
- public SortedMap<ZonedDateTime, String> getHistory() {
- return history;
- }
-
- }
-
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatus.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatus.java
new file mode 100644
index 00000000000..d6c6262069b
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatus.java
@@ -0,0 +1,30 @@
+package com.yahoo.vespa.hosted.controller.api.integration.billing;
+
+/**
+ * @author gjoranv
+ */
+public enum BillStatus {
+ OPEN, // All bills start in this state. The bill can be modified and exported/synced to external systems.
+ FROZEN, // Syncing to external systems is switched off. Reviews should be done in this state.
+ CLOSED, // End state for a valid bill.
+ VOID; // End state, indicating that the bill is not valid.
+
+ private static final String LEGACY_ISSUED = "ISSUED"; // Legacy state, used by historical bills
+ private static final String LEGACY_EXPORTED = "EXPORTED"; // Legacy state, used by historical bills
+
+ private final String value;
+
+ BillStatus() {
+ this.value = name();
+ }
+
+ public String value() {
+ return value;
+ }
+
+ public static BillStatus from(String status) {
+ if (LEGACY_ISSUED.equals(status) || LEGACY_EXPORTED.equals(status)) return OPEN;
+ return Enum.valueOf(BillStatus.class, status.toUpperCase());
+ }
+
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
index 45c22c0db28..0aae466feb2 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingController.java
@@ -90,7 +90,7 @@ public interface BillingController {
boolean deleteInstrument(TenantName tenant, String userId, String instrumentId);
/** Change the status of the given bill */
- void updateBillStatus(Bill.Id billId, String agent, String status);
+ void updateBillStatus(Bill.Id billId, String agent, BillStatus status);
/** Add a line item to the given bill */
void addLineItem(TenantName tenant, String description, BigDecimal amount, Optional<Bill.Id> billId, String agent);
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java
index 3e24314ba5c..c5859cd7d2f 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClient.java
@@ -69,7 +69,7 @@ public interface BillingDatabaseClient {
* @param agent The agent that added the status
* @param status The new status of the bill
*/
- void setStatus(Bill.Id billId, String agent, String status);
+ void setStatus(Bill.Id billId, String agent, BillStatus status);
List<Bill.LineItem> getUnusedLineItems(TenantName tenantName);
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java
index ee7679f54ca..a6bcc9bf0ed 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingDatabaseClientMock.java
@@ -26,7 +26,7 @@ public class BillingDatabaseClientMock implements BillingDatabaseClient {
private final Map<Bill.Id, List<Bill.LineItem>> lineItems = new HashMap<>();
private final Map<TenantName, List<Bill.LineItem>> uncommittedLineItems = new HashMap<>();
- private final Map<Bill.Id, Bill.StatusHistory> statuses = new HashMap<>();
+ private final Map<Bill.Id, StatusHistory> statuses = new HashMap<>();
private final Map<Bill.Id, ZonedDateTime> startTimes = new HashMap<>();
private final Map<Bill.Id, ZonedDateTime> endTimes = new HashMap<>();
private final Map<Bill.Id, String> exportedInvoiceIds = new HashMap<>();
@@ -54,7 +54,7 @@ public class BillingDatabaseClientMock implements BillingDatabaseClient {
.findFirst();
}
- public String getStatus(Bill.Id invoiceId) {
+ public BillStatus getStatus(Bill.Id invoiceId) {
return statuses.get(invoiceId).current();
}
@@ -62,7 +62,7 @@ public class BillingDatabaseClientMock implements BillingDatabaseClient {
public Bill.Id createBill(TenantName tenant, ZonedDateTime startTime, ZonedDateTime endTime, String agent) {
var invoiceId = Bill.Id.generate();
invoices.put(invoiceId, tenant);
- statuses.computeIfAbsent(invoiceId, l -> Bill.StatusHistory.open(clock));
+ statuses.computeIfAbsent(invoiceId, l -> StatusHistory.open(clock));
startTimes.put(invoiceId, startTime);
endTimes.put(invoiceId, endTime);
return invoiceId;
@@ -72,7 +72,7 @@ public class BillingDatabaseClientMock implements BillingDatabaseClient {
public Optional<Bill> readBill(Bill.Id billId) {
var invoice = Optional.ofNullable(invoices.get(billId));
var lines = lineItems.getOrDefault(billId, List.of());
- var status = statuses.getOrDefault(billId, Bill.StatusHistory.open(clock));
+ var status = statuses.getOrDefault(billId, StatusHistory.open(clock));
var start = startTimes.getOrDefault(billId, startTime);
var end = endTimes.getOrDefault(billId, endTime);
var exportedId = exportedInvoiceId(billId);
@@ -90,8 +90,8 @@ public class BillingDatabaseClientMock implements BillingDatabaseClient {
}
@Override
- public void setStatus(Bill.Id invoiceId, String agent, String status) {
- statuses.computeIfAbsent(invoiceId, k -> Bill.StatusHistory.open(clock))
+ public void setStatus(Bill.Id invoiceId, String agent, BillStatus status) {
+ statuses.computeIfAbsent(invoiceId, k -> StatusHistory.open(clock))
.getHistory()
.put(ZonedDateTime.now(), status);
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingReporterMock.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingReporterMock.java
index 4985033d378..689ecc356dc 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingReporterMock.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillingReporterMock.java
@@ -4,7 +4,10 @@ package com.yahoo.vespa.hosted.controller.api.integration.billing;
import com.yahoo.vespa.hosted.controller.tenant.BillingReference;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
+import java.math.BigDecimal;
import java.time.Clock;
+import java.time.ZonedDateTime;
+import java.util.Optional;
import java.util.UUID;
public class BillingReporterMock implements BillingReporter {
@@ -23,7 +26,8 @@ public class BillingReporterMock implements BillingReporter {
@Override
public InvoiceUpdate maintainInvoice(Bill bill) {
- return new InvoiceUpdate(0,0,1);
+ dbClient.addLineItem(bill.tenant(), maintainedMarkerItem(), Optional.of(bill.id()));
+ return new InvoiceUpdate(1,0,0);
}
@Override
@@ -34,4 +38,8 @@ public class BillingReporterMock implements BillingReporter {
return exportedId;
}
+ private static Bill.LineItem maintainedMarkerItem() {
+ return new Bill.LineItem("maintained", "", BigDecimal.valueOf(0.0), "", "", ZonedDateTime.now());
+ }
+
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
index 7a4a787fb11..f8e83b44510 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/MockBillingController.java
@@ -74,7 +74,7 @@ public class MockBillingController implements BillingController {
.add(new Bill(
billId,
tenant,
- Bill.StatusHistory.open(clock),
+ StatusHistory.open(clock),
List.of(),
startTime,
endTime
@@ -119,7 +119,7 @@ public class MockBillingController implements BillingController {
}
@Override
- public void updateBillStatus(Bill.Id billId, String agent, String status) {
+ public void updateBillStatus(Bill.Id billId, String agent, BillStatus status) {
var now = clock.instant().atZone(ZoneOffset.UTC);
committedBills.values().stream()
.flatMap(List::stream)
@@ -238,6 +238,6 @@ public class MockBillingController implements BillingController {
private Bill emptyBill() {
var start = clock.instant().atZone(ZoneOffset.UTC);
var end = clock.instant().atZone(ZoneOffset.UTC);
- return new Bill(Bill.Id.of("empty"), TenantName.defaultName(), Bill.StatusHistory.open(clock), List.of(), start, end);
+ return new Bill(Bill.Id.of("empty"), TenantName.defaultName(), StatusHistory.open(clock), List.of(), start, end);
}
}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/StatusHistory.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/StatusHistory.java
new file mode 100644
index 00000000000..6335ada1396
--- /dev/null
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/billing/StatusHistory.java
@@ -0,0 +1,35 @@
+package com.yahoo.vespa.hosted.controller.api.integration.billing;
+
+import java.time.Clock;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * @author ogronnesby
+ */
+public class StatusHistory {
+ SortedMap<ZonedDateTime, BillStatus> history;
+
+ public StatusHistory(SortedMap<ZonedDateTime, BillStatus> history) {
+ this.history = history;
+ }
+
+ public static StatusHistory open(Clock clock) {
+ var now = clock.instant().atZone(ZoneOffset.UTC);
+ return new StatusHistory(
+ new TreeMap<>(Map.of(now, BillStatus.OPEN))
+ );
+ }
+
+ public BillStatus current() {
+ return history.get(history.lastKey());
+ }
+
+ public SortedMap<ZonedDateTime, BillStatus> getHistory() {
+ return history;
+ }
+
+}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/DeploymentFailureMails.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/DeploymentFailureMails.java
index ef08c3a9adc..72728966dbc 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/DeploymentFailureMails.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/organization/DeploymentFailureMails.java
@@ -1,9 +1,9 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.organization;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
-import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import java.util.Collection;
@@ -14,10 +14,10 @@ import java.util.Collection;
*/
public class DeploymentFailureMails {
- private final ZoneRegistry registry;
+ private final ConsoleUrls consoleUrls;
- public DeploymentFailureMails(ZoneRegistry registry) {
- this.registry = registry;
+ public DeploymentFailureMails(ConsoleUrls consoleUrls) {
+ this.consoleUrls = consoleUrls;
}
public Mail nodeAllocationFailure(RunId id, Collection<String> recipients) {
@@ -66,8 +66,8 @@ public class DeploymentFailureMails {
jobToString(id.type()),
id.application(),
messageDetail,
- registry.dashboardUrl(id),
- registry.supportUrl()));
+ consoleUrls.deploymentRun(id),
+ consoleUrls.support()));
}
private String jobToString(JobType type) {
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java
deleted file mode 100644
index 106d9ab6bbe..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/ApplicationResources.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import java.math.BigDecimal;
-
-import static java.math.BigDecimal.ZERO;
-
-/**
- * @param vcpu vcpus summed over all clusters, instances, zones
- * @param memoryGb memory in Gb summed over all clusters, instances, zones
- * @param diskGb disk in Gb summed over all clusters, instances, zones
- * @param gpuMemoryGb GPU memory in Gb summed over all clusters, instances, zones
- * @param enclaveVcpu vcpus summed over all clusters, instances, zones
- * @param enclaveMemoryGb memory in Gb summed over all clusters, instances, zones
- * @param enclaveDiskGb disk in Gb summed over all clusters, instances, zones
- * @param enclaveGpuMemoryGb GPU memory in Gb summed over all clusters, instances, zones
- */
-public record ApplicationResources(BigDecimal vcpu, BigDecimal memoryGb, BigDecimal diskGb,
- BigDecimal gpuMemoryGb, BigDecimal enclaveVcpu, BigDecimal enclaveMemoryGb,
- BigDecimal enclaveDiskGb, BigDecimal enclaveGpuMemoryGb) {
-
- public static ApplicationResources create(BigDecimal vcpu, BigDecimal memoryGb,
- BigDecimal diskGb, BigDecimal gpuMemoryGb) {
- return new ApplicationResources(vcpu, memoryGb, diskGb, gpuMemoryGb, ZERO, ZERO, ZERO, ZERO);
- }
-
- public static ApplicationResources createEnclave(BigDecimal vcpu, BigDecimal memoryGb,
- BigDecimal diskGb, BigDecimal gpuMemoryGb) {
- return new ApplicationResources(ZERO, ZERO, ZERO, ZERO, vcpu, memoryGb, diskGb, gpuMemoryGb);
- }
-
- public boolean enclave() { return enclaveVcpu().compareTo(ZERO) > 0; }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PriceInformation.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PriceInformation.java
deleted file mode 100644
index 50463553f8e..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PriceInformation.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import java.math.BigDecimal;
-import java.util.List;
-
-import static java.math.BigDecimal.ZERO;
-
-public record PriceInformation(BigDecimal listPriceWithSupport, BigDecimal volumeDiscount,
- BigDecimal committedAmountDiscount, BigDecimal enclaveDiscount, BigDecimal totalAmount) {
-
- public static PriceInformation empty() { return new PriceInformation(ZERO, ZERO, ZERO, ZERO, ZERO); }
-
- public static PriceInformation sum(List<PriceInformation> priceInformationList) {
- var result = PriceInformation.empty();
- for (var prices : priceInformationList)
- result = result.add(prices);
- return result;
- }
-
- public PriceInformation add(PriceInformation priceInformation) {
- return new PriceInformation(this.listPriceWithSupport().add(priceInformation.listPriceWithSupport()),
- this.volumeDiscount().add(priceInformation.volumeDiscount()),
- this.committedAmountDiscount().add(priceInformation.committedAmountDiscount()),
- this.enclaveDiscount().add(priceInformation.enclaveDiscount()),
- this.totalAmount().add(priceInformation.totalAmount()));
- }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/Prices.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/Prices.java
deleted file mode 100644
index 650a07c51e0..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/Prices.java
+++ /dev/null
@@ -1,8 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import java.util.List;
-
-public record Prices(List<PriceInformation> priceInformationApplications, PriceInformation totalPriceInformation) {
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java
deleted file mode 100644
index 7b082932588..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingController.java
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
-
-import java.util.List;
-
-/**
- * A service that calculates price information based on cluster resources, plan, service level etc.
- *
- * @author hmusum
- */
-public interface PricingController {
-
- /**
- *
- * @param applicationResources resources used by an application
- * @param pricingInfo pricing info
- * @param plan the plan to use for this calculation
- * @return a PriceInformation instance
- */
- Prices priceForApplications(List<ApplicationResources> applicationResources, PricingInfo pricingInfo, Plan plan);
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java
deleted file mode 100644
index ba6f1939fc5..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/PricingInfo.java
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import java.math.BigDecimal;
-
-import static java.math.BigDecimal.ZERO;
-
-public record PricingInfo(SupportLevel supportLevel, BigDecimal committedHourlyAmount) {
-
- public enum SupportLevel { BASIC, COMMERCIAL, ENTERPRISE }
-
- public static PricingInfo empty() { return new PricingInfo(SupportLevel.COMMERCIAL, ZERO); }
-
-}
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/package-info.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/package-info.java
deleted file mode 100644
index 649ab2a80f4..00000000000
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/pricing/package-info.java
+++ /dev/null
@@ -1,5 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-@ExportPackage
-package com.yahoo.vespa.hosted.controller.api.integration.pricing;
-
-import com.yahoo.osgi.annotation.ExportPackage;
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
index 747c6b72172..92c0a6b1fbb 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/api/integration/zone/ZoneRegistry.java
@@ -1,8 +1,6 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.api.integration.zone;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
@@ -18,7 +16,6 @@ import com.yahoo.config.provision.zone.ZoneFilter;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import java.net.URI;
import java.time.Duration;
@@ -97,24 +94,6 @@ public interface ZoneRegistry {
/** Returns the routing method used by given zone */
RoutingMethod routingMethod(ZoneId zone);
- /** Returns a URL where an informative dashboard can be found. */
- URI dashboardUrl();
-
- /** Returns a URL which displays information about the given tenant. */
- URI dashboardUrl(TenantName id);
-
- /** Returns a URL which displays information about the given application. */
- URI dashboardUrl(TenantName tenantName, ApplicationName applicationName);
-
- /** Returns a URL which displays information about the given application instance. */
- URI dashboardUrl(ApplicationId id);
-
- /** Returns a URL which displays information about the given job run. */
- URI dashboardUrl(RunId id);
-
- /** Returns a URL used to request support from the Vespa team. */
- URI supportUrl();
-
/** Returns a URL to the controller's api endpoint */
URI apiUrl();
diff --git a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Email.java b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Email.java
index 995f1b1864f..c1c8a780df1 100644
--- a/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Email.java
+++ b/controller-api/src/main/java/com/yahoo/vespa/hosted/controller/tenant/Email.java
@@ -25,7 +25,7 @@ public class Email {
}
public static Email empty() {
- return new Email("", true);
+ return new Email("", false);
}
public Email withEmailAddress(String emailAddress) {
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java
new file mode 100644
index 00000000000..62e79c3be50
--- /dev/null
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/ConsoleUrlsTest.java
@@ -0,0 +1,43 @@
+// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
+package com.yahoo.vespa.hosted.controller.api.integration;
+
+import com.yahoo.config.provision.ApplicationId;
+import com.yahoo.config.provision.ClusterSpec;
+import com.yahoo.config.provision.Environment;
+import com.yahoo.config.provision.zone.ZoneId;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
+import org.junit.jupiter.api.Test;
+
+import java.net.URI;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author freva
+ */
+class ConsoleUrlsTest {
+
+ private final ConsoleUrls urls = new ConsoleUrls(URI.create("https://console.tld/"));
+
+ @Test
+ void urls() {
+ ApplicationId app = ApplicationId.from("t1", "a1", "i1");
+ ZoneId prod = ZoneId.from("prod", "us-north-1");
+ ZoneId dev = ZoneId.from("dev", "eu-west-2");
+ ZoneId test = ZoneId.from("test", "ap-east-3");
+ ClusterSpec.Id cluster = ClusterSpec.Id.from("c1");
+
+ assertEquals("https://console.tld", urls.root());
+ assertEquals("https://console.tld/tenant/t1", urls.tenantOverview(app.tenant()));
+ assertEquals("https://console.tld/tenant/t1/account/notifications", urls.tenantNotifications(app.tenant()));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance", urls.prodApplicationOverview(app.tenant(), app.application()));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1", urls.instanceOverview(app, Environment.test));
+ assertEquals("https://console.tld/tenant/t1/application/a1/dev/instance/i1?i1.dev.eu-west-2=clusters%2Cc1", urls.clusterOverview(app, dev, cluster));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1?i1.prod.us-north-1=clusters%2Cc1%3Dreindexing", urls.clusterReindexing(app, prod, cluster));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1/job/production-us-north-1/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(prod), 1)));
+ assertEquals("https://console.tld/tenant/t1/application/a1/prod/instance/i1/job/system-test/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(test), 1)));
+ assertEquals("https://console.tld/tenant/t1/application/a1/dev/instance/i1/job/dev-eu-west-2/run/1", urls.deploymentRun(new RunId(app, JobType.deploymentTo(dev), 1)));
+ assertEquals("https://console.tld/verify?code=test123", urls.verifyEmail("test123"));
+ }
+}
diff --git a/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatusTest.java b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatusTest.java
new file mode 100644
index 00000000000..9647a11a4ba
--- /dev/null
+++ b/controller-api/src/test/java/com/yahoo/vespa/hosted/controller/api/integration/billing/BillStatusTest.java
@@ -0,0 +1,18 @@
+package com.yahoo.vespa.hosted.controller.api.integration.billing;
+
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * @author gjoranv
+ */
+public class BillStatusTest {
+
+ @Test
+ void legacy_states_are_converted() {
+ assertEquals(BillStatus.OPEN, BillStatus.from("ISSUED"));
+ assertEquals(BillStatus.OPEN, BillStatus.from("EXPORTED"));
+ }
+
+}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
index bab86e7bfde..0b693bb9894 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/Controller.java
@@ -131,10 +131,10 @@ public class Controller extends AbstractComponent {
auditLogger = new AuditLogger(curator, clock);
jobControl = new JobControl(new JobControlFlags(curator, flagSource));
archiveBucketDb = new CuratorArchiveBucketDb(this);
- notifier = new Notifier(curator, serviceRegistry.zoneRegistry(), serviceRegistry.mailer(), flagSource);
+ notifier = new Notifier(curator, serviceRegistry.consoleUrls(), serviceRegistry.mailer(), flagSource);
notificationsDb = new NotificationsDb(this);
supportAccessControl = new SupportAccessControl(this);
- mailVerifier = new MailVerifier(serviceRegistry.zoneRegistry(), tenantController, serviceRegistry.mailer(), curator, clock);
+ mailVerifier = new MailVerifier(serviceRegistry.consoleUrls(), tenantController, serviceRegistry.mailer(), curator, clock);
dataplaneTokenService = new DataplaneTokenService(this);
// Record the version of this controller
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/MailVerifier.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/MailVerifier.java
index 7d8f0d260fc..9ff3206ee06 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/MailVerifier.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/application/MailVerifier.java
@@ -4,9 +4,9 @@ package com.yahoo.vespa.hosted.controller.application;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.LockedTenant;
import com.yahoo.vespa.hosted.controller.TenantController;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mail;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mailer;
-import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.notification.MailTemplating;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
@@ -35,12 +35,12 @@ public class MailVerifier {
private final Clock clock;
private final MailTemplating mailTemplating;
- public MailVerifier(ZoneRegistry zoneRegistry, TenantController tenantController, Mailer mailer, CuratorDb curatorDb, Clock clock) {
+ public MailVerifier(ConsoleUrls consoleUrls, TenantController tenantController, Mailer mailer, CuratorDb curatorDb, Clock clock) {
this.tenantController = tenantController;
this.mailer = mailer;
this.curatorDb = curatorDb;
this.clock = clock;
- this.mailTemplating = new MailTemplating(zoneRegistry);
+ this.mailTemplating = new MailTemplating(consoleUrls);
}
public PendingMailVerification sendMailVerification(TenantName tenantName, String email, PendingMailVerification.MailType mailType) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
index c9719c3dd55..d62e477a51f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/deployment/InternalStepRunner.java
@@ -86,7 +86,6 @@ import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.running;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.success;
import static com.yahoo.vespa.hosted.controller.deployment.RunStatus.testFailure;
import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.succeeded;
-import static com.yahoo.vespa.hosted.controller.deployment.Step.Status.unfinished;
import static com.yahoo.vespa.hosted.controller.deployment.Step.copyVespaLogs;
import static com.yahoo.vespa.hosted.controller.deployment.Step.deactivateReal;
import static com.yahoo.vespa.hosted.controller.deployment.Step.deactivateTester;
@@ -128,7 +127,7 @@ public class InternalStepRunner implements StepRunner {
public InternalStepRunner(Controller controller) {
this.controller = controller;
this.testConfigSerializer = new TestConfigSerializer(controller.system());
- this.mails = new DeploymentFailureMails(controller.zoneRegistry());
+ this.mails = new DeploymentFailureMails(controller.serviceRegistry().consoleUrls());
this.timeouts = Timeouts.of(controller.system());
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainer.java
index a12c341c1d1..7868c3fe611 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainer.java
@@ -5,7 +5,7 @@ import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.LockedTenant;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.BillStatus;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingDatabaseClient;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingReporter;
@@ -66,7 +66,7 @@ public class BillingReportMaintainer extends ControllerMaintainer {
InvoiceUpdate maintainInvoices() {
var billsNeedingMaintenance = databaseClient.readBills().stream()
.filter(bill -> bill.getExportedId().isPresent())
- .filter(exported -> ! exported.status().equals("ISSUED")) // TODO: This status does not yet exist.
+ .filter(exported -> exported.status() == BillStatus.OPEN)
.toList();
var updates = new InvoiceUpdate.Counter();
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
index d0426416349..9121c139b00 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/maintenance/CloudTrialExpirer.java
@@ -166,7 +166,7 @@ public class CloudTrialExpirer extends ControllerMaintainer {
.with("mailMessageTemplate", "cloud-trial-notification")
.with("cloudTrialMessage", emailMsg)
.with("mailTitle", emailSubject)
- .with("consoleLink", controller().zoneRegistry().dashboardUrl(tenant.name()).toString())
+ .with("consoleLink", controller().serviceRegistry().consoleUrls().tenantOverview(tenant.name()))
.build());
var source = NotificationSource.from(tenant.name());
// Remove previous notification to ensure new notification is sent by email
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/FormattedNotification.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/FormattedNotification.java
index 9402092f789..bed053d592f 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/FormattedNotification.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/FormattedNotification.java
@@ -1,7 +1,6 @@
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package com.yahoo.vespa.hosted.controller.notification;
-import java.net.URI;
import java.util.Objects;
/**
@@ -10,7 +9,7 @@ import java.util.Objects;
*
* @author enygaard
*/
-public record FormattedNotification(Notification notification, String prettyType, String messagePrefix, URI uri) {
+public record FormattedNotification(Notification notification, String prettyType, String messagePrefix, String uri) {
public FormattedNotification {
Objects.requireNonNull(prettyType);
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/MailTemplating.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/MailTemplating.java
index e8fb7289f4c..1c05330702e 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/MailTemplating.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/MailTemplating.java
@@ -1,10 +1,8 @@
// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-
package com.yahoo.vespa.hosted.controller.notification;
import com.yahoo.config.provision.TenantName;
-import com.yahoo.restapi.UriBuilder;
-import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.tenant.PendingMailVerification;
import com.yahoo.yolean.Exceptions;
import org.apache.velocity.VelocityContext;
@@ -15,7 +13,6 @@ import org.apache.velocity.runtime.resource.util.StringResourceRepository;
import org.apache.velocity.tools.generic.EscapeTool;
import java.io.StringWriter;
-import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Map;
@@ -43,19 +40,19 @@ public class MailTemplating {
private final VelocityEngine velocity;
private final EscapeTool escapeTool = new EscapeTool();
- private final URI dashboardUri;
+ private final ConsoleUrls consoleUrls;
- public MailTemplating(ZoneRegistry zoneRegistry) {
+ public MailTemplating(ConsoleUrls consoleUrls) {
this.velocity = createTemplateEngine();
- this.dashboardUri = zoneRegistry.dashboardUrl();
+ this.consoleUrls = consoleUrls;
}
public String generateDefaultMailHtml(Template mailBodyTemplate, Map<String, Object> params, TenantName tenant) {
var ctx = createVelocityContext();
- ctx.put("accountNotificationLink", accountNotificationsUri(tenant));
+ ctx.put("accountNotificationLink", consoleUrls.tenantNotifications(tenant));
ctx.put("privacyPolicyLink", "https://legal.yahoo.com/xw/en/yahoo/privacy/topic/b2bprivacypolicy/index.html");
- ctx.put("termsOfServiceLink", consoleUri("terms-of-service-trial.html"));
- ctx.put("supportLink", consoleUri("support"));
+ ctx.put("termsOfServiceLink", consoleUrls.termsOfService());
+ ctx.put("supportLink", consoleUrls.support());
ctx.put("mailBodyTemplate", mailBodyTemplate.getId());
params.forEach(ctx::put);
return render(ctx, Template.MAIL);
@@ -63,9 +60,8 @@ public class MailTemplating {
public String generateMailVerificationHtml(PendingMailVerification pmf) {
var ctx = createVelocityContext();
- ctx.put("consoleLink", dashboardUri.getHost());
+ ctx.put("verifyLink", consoleUrls.verifyEmail(pmf.getVerificationCode()));
ctx.put("email", pmf.getMailAddress());
- ctx.put("code", pmf.getVerificationCode());
return render(ctx, Template.MAIL_VERIFICATION);
}
@@ -102,16 +98,4 @@ public class MailTemplating {
});
repo.putStringResource(name, templateStr);
}
-
- private String accountNotificationsUri(TenantName tenant) {
- return new UriBuilder(dashboardUri)
- .append("tenant/")
- .append(tenant.value())
- .append("account/notifications")
- .toString();
- }
-
- private String consoleUri(String path) {
- return new UriBuilder(dashboardUri).append(path).toString();
- }
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatter.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatter.java
index de99d03cc82..243e1af8f35 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatter.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatter.java
@@ -2,17 +2,13 @@
package com.yahoo.vespa.hosted.controller.notification;
import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.Environment;
import com.yahoo.text.Text;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
-import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
-import org.apache.http.client.utils.URIBuilder;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
-import java.net.URI;
-import java.net.URISyntaxException;
import java.util.Objects;
import java.util.Optional;
-import java.util.function.Function;
+
+import static com.yahoo.vespa.hosted.controller.notification.Notifier.notificationLink;
/**
* Created a NotificationContent for a given Notification.
@@ -22,10 +18,10 @@ import java.util.function.Function;
* @author enygaard
*/
public class NotificationFormatter {
- private final ZoneRegistry zoneRegistry;
+ private final ConsoleUrls consoleUrls;
- public NotificationFormatter(ZoneRegistry zoneRegistry) {
- this.zoneRegistry = Objects.requireNonNull(zoneRegistry);
+ public NotificationFormatter(ConsoleUrls consoleUrls) {
+ this.consoleUrls = Objects.requireNonNull(consoleUrls);
}
public FormattedNotification format(Notification n) {
@@ -35,7 +31,7 @@ public class NotificationFormatter {
case testPackage -> testPackage(n);
case reindex -> reindex(n);
case feedBlock -> feedBlock(n);
- default -> new FormattedNotification(n, n.type().name(), "", zoneRegistry.dashboardUrl(n.source().tenant()));
+ default -> new FormattedNotification(n, n.type().name(), "", consoleUrls.tenantOverview(n.source().tenant()));
};
}
@@ -47,8 +43,7 @@ public class NotificationFormatter {
application,
instance,
levelText(n.level(), n.messages().size()));
- var uri = zoneRegistry.dashboardUrl(ApplicationId.from(source.tenant(), application, instance));
- return new FormattedNotification(n, "Application package", message, uri);
+ return new FormattedNotification(n, "Application package", message, notificationLink(consoleUrls, n.source()));
}
private FormattedNotification deployment(Notification n) {
@@ -58,7 +53,7 @@ public class NotificationFormatter {
requirePresent(source.application(), "application"),
requirePresent(source.instance(), "instance"),
levelText(n.level(), n.messages().size()));
- return new FormattedNotification(n,"Deployment", message, jobLink(n.source()));
+ return new FormattedNotification(n,"Deployment", message, notificationLink(consoleUrls, n.source()));
}
private FormattedNotification testPackage(Notification n) {
@@ -68,68 +63,23 @@ public class NotificationFormatter {
n.messages().size() > 1 ? "are problems" : "is a problem",
application,
source.instance().map(i -> "."+i).orElse(""));
- var uri = zoneRegistry.dashboardUrl(source.tenant(), application);
- return new FormattedNotification(n, "Test package", message, uri);
+ return new FormattedNotification(n, "Test package", message, notificationLink(consoleUrls, n.source()));
}
private FormattedNotification reindex(Notification n) {
var message = Text.format("%s is reindexing", clusterInfo(n.source()));
- var source = n.source();
- var application = requirePresent(source.application(), "application");
- var instance = requirePresent(source.instance(), "instance");
- var clusterId = requirePresent(source.clusterId(), "clusterId");
- var zone = requirePresent(source.zoneId(), "zoneId");
- var instanceURI = zoneRegistry.dashboardUrl(ApplicationId.from(source.tenant(), application, instance));
- try {
- var uri = new URIBuilder(instanceURI)
- .setParameter(
- String.format("%s.%s.%s", instance, zone.environment(), zone.region()),
- String.format("clusters,%s=status", clusterId.value()))
- .build();
- return new FormattedNotification(n, "Reindex", message, uri);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
+ var application = requirePresent(n.source().application(), "application");
+ var instance = requirePresent(n.source().instance(), "instance");
+ var clusterId = requirePresent(n.source().clusterId(), "clusterId");
+ var zone = requirePresent(n.source().zoneId(), "zoneId");
+ return new FormattedNotification(n, "Reindex", message,
+ consoleUrls.clusterReindexing(ApplicationId.from(n.source().tenant(), application, instance), zone, clusterId));
}
private FormattedNotification feedBlock(Notification n) {
- String type;
- if (n.level() == Notification.Level.warning) {
- type = "Nearly feed blocked";
- } else {
- type = "Feed blocked";
- }
+ String type = n.level() == Notification.Level.warning ? "Nearly feed blocked" : "Feed blocked";
var message = Text.format("%s is %s", clusterInfo(n.source()), type.toLowerCase());
- var source = n.source();
- var application = requirePresent(source.application(), "application");
- var instance = requirePresent(source.instance(), "instance");
- var clusterId = requirePresent(source.clusterId(), "clusterId");
- var zone = requirePresent(source.zoneId(), "zoneId");
- var instanceURI = zoneRegistry.dashboardUrl(ApplicationId.from(source.tenant(), application, instance));
- try {
- var uri = new URIBuilder(instanceURI)
- .setParameter(
- String.format("%s.%s.%s", instance, zone.environment(), zone.region()),
- String.format("clusters,%s", clusterId.value()))
- .build();
- return new FormattedNotification(n, type, message, uri);
- } catch (URISyntaxException e) {
- throw new IllegalArgumentException(e);
- }
- }
-
- private URI jobLink(NotificationSource source) {
- var application = requirePresent(source.application(), "application");
- var instance = requirePresent(source.instance(), "instance");
- var jobType = requirePresent(source.jobType(), "jobType");
- var runNumber = source.runNumber().orElseThrow(() -> new MissingOptionalException("runNumber"));
- var applicationId = ApplicationId.from(source.tenant(), application, instance);
- Function<Environment, URI> link = (Environment env) -> zoneRegistry.dashboardUrl(new RunId(applicationId, jobType, runNumber));
- var environment = jobType.zone().environment();
- return switch (environment) {
- case dev, perf -> link.apply(environment);
- default -> link.apply(Environment.prod);
- };
+ return new FormattedNotification(n, type, message, notificationLink(consoleUrls, n.source()));
}
private String jobText(NotificationSource source) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/Notifier.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/Notifier.java
index e3bfb8b4c56..b0b43866fae 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/Notifier.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/notification/Notifier.java
@@ -2,21 +2,22 @@
package com.yahoo.vespa.hosted.controller.notification;
import com.google.common.annotations.VisibleForTesting;
+import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.Environment;
-import com.yahoo.restapi.UriBuilder;
+import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.text.Text;
import com.yahoo.vespa.flags.FetchVector;
import com.yahoo.vespa.flags.FlagSource;
import com.yahoo.vespa.flags.PermanentFlags;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
+import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mail;
import com.yahoo.vespa.hosted.controller.api.integration.organization.Mailer;
import com.yahoo.vespa.hosted.controller.api.integration.organization.MailerException;
-import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import com.yahoo.vespa.hosted.controller.persistence.CuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
import com.yahoo.vespa.hosted.controller.tenant.TenantContacts;
-import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -34,8 +35,8 @@ public class Notifier {
private final CuratorDb curatorDb;
private final Mailer mailer;
private final FlagSource flagSource;
+ private final ConsoleUrls consoleUrls;
private final NotificationFormatter formatter;
- private final URI dashboardUri;
private final MailTemplating mailTemplating;
private static final Logger log = Logger.getLogger(Notifier.class.getName());
@@ -43,13 +44,13 @@ public class Notifier {
// Minimal url pattern matcher to detect hardcoded URLs in Notification messages
private static final Pattern urlPattern = Pattern.compile("https://[\\w\\d./]+");
- public Notifier(CuratorDb curatorDb, ZoneRegistry zoneRegistry, Mailer mailer, FlagSource flagSource) {
+ public Notifier(CuratorDb curatorDb, ConsoleUrls consoleUrls, Mailer mailer, FlagSource flagSource) {
this.curatorDb = Objects.requireNonNull(curatorDb);
this.mailer = Objects.requireNonNull(mailer);
this.flagSource = Objects.requireNonNull(flagSource);
- this.formatter = new NotificationFormatter(zoneRegistry);
- this.dashboardUri = zoneRegistry.dashboardUrl();
- this.mailTemplating = new MailTemplating(zoneRegistry);
+ this.consoleUrls = Objects.requireNonNull(consoleUrls);
+ this.formatter = new NotificationFormatter(consoleUrls);
+ this.mailTemplating = new MailTemplating(consoleUrls);
}
public void dispatch(List<Notification> notifications, NotificationSource source) {
@@ -133,7 +134,7 @@ public class Notifier {
.with("mailTitle", "Vespa Cloud Notifications")
.with("notificationHeader", f.messagePrefix())
.with("notificationItems", items)
- .with("consoleLink", notificationLink(f.notification().source()))
+ .with("consoleLink", notificationLink(consoleUrls, f.notification().source()))
.build();
}
@@ -150,24 +151,16 @@ public class Notifier {
return sb.toString();
}
- private String notificationLink(NotificationSource source) {
- var uri = new UriBuilder(dashboardUri);
- uri = uri.append("tenant").append(source.tenant().value());
- if (source.application().isPresent())
- uri = uri.append("application").append(source.application().get().value());
- if (source.isProduction()) {
- uri = uri.append("prod/instance");
- if (source.jobType().isPresent()) {
- uri = uri.append(source.instance().get().value());
- }
- }
- else {
- uri = uri.append("dev/instance/").append(source.instance().get().value());
- }
- if (source.jobType().isPresent()) {
- uri = uri.append("job").append(source.jobType().get().jobName()).append("run").append(String.valueOf(source.runNumber().getAsLong()));
- }
- return uri.toString();
+ static String notificationLink(ConsoleUrls consoleUrls, NotificationSource source) {
+ if (source.application().isEmpty()) return consoleUrls.tenantOverview(source.tenant());
+ if (source.instance().isEmpty()) return consoleUrls.prodApplicationOverview(source.tenant(), source.application().get());
+
+ ApplicationId application = ApplicationId.from(source.tenant(), source.application().get(), source.instance().get());
+ if (source.jobType().isPresent())
+ return consoleUrls.deploymentRun(new RunId(application, source.jobType().get(), source.runNumber().getAsLong()));
+ if (source.clusterId().isPresent())
+ return consoleUrls.clusterOverview(application, source.zoneId().get(), source.clusterId().get());
+ return consoleUrls.instanceOverview(application, source.zoneId().map(ZoneId::environment).orElse(Environment.prod));
}
private static String capitalise(String m) {
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
index 4404063456c..d5bb47c94b0 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializer.java
@@ -282,13 +282,10 @@ public class TenantSerializer {
}
private TenantBilling tenantInfoBillingContactFromSlime(Inspector billingObject) {
- //TODO: Remove validity check once emailVerified has been written for all tenants
- var emailVerified = billingObject.field("emailVerified").valid() ?
- billingObject.field("emailVerified").asBool() : true;
return TenantBilling.empty()
.withContact(TenantContact.from(
billingObject.field("name").asString(),
- new Email(billingObject.field("email").asString(), emailVerified),
+ new Email(billingObject.field("email").asString(), billingObject.field("emailVerified").asBool()),
billingObject.field("phone").asString()))
.withAddress(tenantInfoAddressFromSlime(billingObject.field("address")));
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
index 03e6125a73a..6a6c8a51d72 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiHandler.java
@@ -692,6 +692,7 @@ public class ApplicationApiHandler extends AuditLoggingRequestHandler {
var contact = root.setObject("contact");
contact.setString("name", billingContact.contact().name());
contact.setString("email", billingContact.contact().email().getEmailAddress());
+ contact.setBool("emailVerified", billingContact.contact().email().isVerified());
contact.setString("phone", billingContact.contact().phone());
toSlime(billingContact.address(), root); // will create "address" on the parent
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
index 696f759d16e..6dc29ebe08c 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandler.java
@@ -19,12 +19,14 @@ import com.yahoo.vespa.hosted.controller.ApplicationController;
import com.yahoo.vespa.hosted.controller.Controller;
import com.yahoo.vespa.hosted.controller.TenantController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.BillStatus;
import com.yahoo.vespa.hosted.controller.api.integration.billing.BillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod;
import com.yahoo.vespa.hosted.controller.api.integration.billing.InstrumentOwner;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PaymentInstrument;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistry;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.StatusHistory;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.api.role.SecurityContext;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponses;
@@ -238,7 +240,7 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler {
private HttpResponse setBillStatus(HttpRequest request, String billId, String userId) {
Inspector inspector = inspectorOrThrow(request);
String status = getInspectorFieldOrThrow(inspector, "status");
- billingController.updateBillStatus(Bill.Id.of(billId), userId, status);
+ billingController.updateBillStatus(Bill.Id.of(billId), userId, BillStatus.from(status));
return new MessageResponse("Updated status of invoice " + billId);
}
@@ -380,7 +382,7 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler {
billCursor.setString("to", bill.getEndDate().format(DATE_TIME_FORMATTER));
billCursor.setString("amount", bill.sum().toString());
- billCursor.setString("status", bill.status());
+ billCursor.setString("status", bill.status().value());
var statusCursor = billCursor.setArray("statusHistory");
renderStatusHistory(statusCursor, bill.statusHistory());
@@ -392,14 +394,14 @@ public class BillingApiHandler extends ThreadedHttpRequestHandler {
});
}
- private void renderStatusHistory(Cursor cursor, Bill.StatusHistory statusHistory) {
+ private void renderStatusHistory(Cursor cursor, StatusHistory statusHistory) {
statusHistory.getHistory()
.entrySet()
.stream()
.forEach(entry -> {
var c = cursor.addObject();
c.setString("at", entry.getKey().format(DATE_TIME_FORMATTER));
- c.setString("status", entry.getValue());
+ c.setString("status", entry.getValue().value());
});
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
index 35d09fd541b..edec869f559 100644
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
+++ b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerV2.java
@@ -25,6 +25,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistry;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Quota;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.StatusHistory;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.api.role.SecurityContext;
import com.yahoo.vespa.hosted.controller.restapi.ErrorResponses;
@@ -461,7 +462,7 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
slime.setString("from", bill.getStartDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
slime.setString("to", bill.getEndDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
slime.setString("total", bill.sum().toString());
- slime.setString("status", bill.status());
+ slime.setString("status", bill.status().value());
}
private void usageToSlime(Cursor slime, Bill bill) {
@@ -476,16 +477,16 @@ public class BillingApiHandlerV2 extends RestApiRequestHandler<BillingApiHandler
slime.setString("from", bill.getStartDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
slime.setString("to", bill.getEndDate().format(DateTimeFormatter.ISO_LOCAL_DATE));
slime.setString("total", bill.sum().toString());
- slime.setString("status", bill.status());
+ slime.setString("status", bill.status().value());
toSlime(slime.setArray("statusHistory"), bill.statusHistory());
toSlime(slime.setArray("items"), bill.lineItems());
}
- private void toSlime(Cursor slime, Bill.StatusHistory history) {
+ private void toSlime(Cursor slime, StatusHistory history) {
history.getHistory().forEach((key, value) -> {
var c = slime.addObject();
c.setString("at", key.format(DateTimeFormatter.ISO_OFFSET_DATE_TIME));
- c.setString("status", value);
+ c.setString("status", value.value());
});
}
diff --git a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java b/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java
deleted file mode 100644
index 8ca2936eee7..00000000000
--- a/controller-server/src/main/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandler.java
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.restapi.pricing;
-
-import com.yahoo.collections.Pair;
-import com.yahoo.component.annotation.Inject;
-import com.yahoo.config.provision.ClusterResources;
-import com.yahoo.container.jdisc.HttpRequest;
-import com.yahoo.container.jdisc.HttpResponse;
-import com.yahoo.container.jdisc.ThreadedHttpRequestHandler;
-import com.yahoo.restapi.ErrorResponse;
-import com.yahoo.restapi.Path;
-import com.yahoo.restapi.SlimeJsonResponse;
-import com.yahoo.slime.Cursor;
-import com.yahoo.slime.Slime;
-import com.yahoo.text.Text;
-import com.yahoo.vespa.hosted.controller.Controller;
-import com.yahoo.vespa.hosted.controller.api.integration.billing.Plan;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.ApplicationResources;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PriceInformation;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.Prices;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingController;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo;
-import com.yahoo.vespa.hosted.controller.restapi.ErrorResponses;
-import com.yahoo.yolean.Exceptions;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.net.URLDecoder;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-import java.util.logging.Logger;
-
-import static com.yahoo.jdisc.http.HttpRequest.Method.GET;
-import static com.yahoo.restapi.ErrorResponse.methodNotAllowed;
-import static com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo.SupportLevel;
-import static java.math.BigDecimal.ZERO;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-/**
- * API for calculating price information
- *
- * @author hmusum
- */
-@SuppressWarnings("unused") // Handler
-public class PricingApiHandler extends ThreadedHttpRequestHandler {
-
- private static final Logger log = Logger.getLogger(PricingApiHandler.class.getName());
-
- private final Controller controller;
- private final PricingController pricingController;
-
- @Inject
- public PricingApiHandler(Context parentCtx, Controller controller, PricingController pricingController) {
- super(parentCtx);
- this.controller = controller;
- this.pricingController = pricingController;
- }
-
- @Override
- public HttpResponse handle(HttpRequest request) {
- if (request.getMethod() != GET)
- return methodNotAllowed("Method '" + request.getMethod() + "' is not supported");
-
- try {
- return handleGET(request);
- } catch (IllegalArgumentException e) {
- return ErrorResponse.badRequest(Exceptions.toMessageString(e));
- } catch (RuntimeException e) {
- return ErrorResponses.logThrowing(request, log, e);
- }
- }
-
- private HttpResponse handleGET(HttpRequest request) {
- Path path = new Path(request.getUri());
- if (path.matches("/pricing/v1/pricing")) return pricing(request);
-
- return ErrorResponse.notFoundError(Text.format("No '%s' handler at '%s'", request.getMethod(),
- request.getUri().getPath()));
- }
-
- private HttpResponse pricing(HttpRequest request) {
- String rawQuery = request.getUri().getRawQuery();
- var priceParameters = parseQuery(rawQuery);
- Prices price = calculatePrice(priceParameters);
- return response(price, priceParameters);
- }
-
- private Prices calculatePrice(PriceParameters priceParameters) {
- return pricingController.priceForApplications(priceParameters.appResources, priceParameters.pricingInfo, priceParameters.plan);
- }
-
- private PriceParameters parseQuery(String rawQuery) {
- if (rawQuery == null) throw new IllegalArgumentException("No price information found in query");
- List<String> elements = Arrays.stream(URLDecoder.decode(rawQuery, UTF_8).split("&")).toList();
- return parseQuery(elements);
- }
-
- private PriceParameters parseQuery(List<String> elements) {
- var supportLevel = SupportLevel.BASIC;
- var enclave = false;
- var committedSpend = ZERO;
- var applicationName = "default";
- var plan = controller.serviceRegistry().planRegistry().defaultPlan(); // fallback to default plan if not supplied
- List<ApplicationResources> appResources = new ArrayList<>();
-
- for (Pair<String, String> entry : keysAndValues(elements)) {
- var value = entry.getSecond();
- switch (entry.getFirst().toLowerCase()) {
- case "committedspend" -> committedSpend = new BigDecimal(value);
- case "planid" -> plan = plan(value).orElseThrow(() -> new IllegalArgumentException("Unknown plan id " + value));
- case "supportlevel" -> supportLevel = SupportLevel.valueOf(value.toUpperCase());
- case "application" -> appResources.add(applicationResources(value));
- default -> throw new IllegalArgumentException("Unknown query parameter '" + entry.getFirst() + '\'');
- }
- }
-
- PricingInfo pricingInfo = new PricingInfo(supportLevel, committedSpend);
- return new PriceParameters(List.of(), pricingInfo, plan, appResources);
- }
-
- private ApplicationResources applicationResources(String appResourcesString) {
- List<String> elements = List.of(appResourcesString.split(","));
-
- var vcpu = ZERO;
- var memoryGb = ZERO;
- var diskGb = ZERO;
- var gpuMemoryGb = ZERO;
- var enclaveVcpu = ZERO;
- var enclaveMemoryGb = ZERO;
- var enclaveDiskGb = ZERO;
- var enclaveGpuMemoryGb = ZERO;
-
- for (var element : keysAndValues(elements)) {
- var value = element.getSecond();
- switch (element.getFirst().toLowerCase()) {
- case "vcpu" -> vcpu = new BigDecimal(value);
- case "memorygb" -> memoryGb = new BigDecimal(value);
- case "diskgb" -> diskGb = new BigDecimal(value);
- case "gpumemorygb" -> gpuMemoryGb = new BigDecimal(value);
-
- case "enclavevcpu" -> enclaveVcpu = new BigDecimal(value);
- case "enclavememorygb" -> enclaveMemoryGb = new BigDecimal(value);
- case "enclavediskgb" -> enclaveDiskGb = new BigDecimal(value);
- case "enclavegpumemorygb" -> enclaveGpuMemoryGb = new BigDecimal(value);
-
- default -> throw new IllegalArgumentException("Unknown key '" + element.getFirst() + '\'');
- }
- }
-
- return new ApplicationResources(vcpu, memoryGb, diskGb, gpuMemoryGb,
- enclaveVcpu, enclaveMemoryGb, enclaveDiskGb, enclaveGpuMemoryGb);
- }
-
- private List<Pair<String, String>> keysAndValues(List<String> elements) {
- return elements.stream().map(element -> {
- var index = element.indexOf("=");
- if (index <= 0 || index == element.length() - 1)
- throw new IllegalArgumentException("Error in query parameter, expected '=' between key and value: '" + element + '\'');
- return new Pair<>(element.substring(0, index), element.substring(index + 1));
- })
- .toList();
- }
-
- private Optional<Plan> plan(String element) {
- return controller.serviceRegistry().planRegistry().plan(element);
- }
-
- private static SlimeJsonResponse response(Prices prices, PriceParameters priceParameters) {
- var slime = new Slime();
- Cursor cursor = slime.setObject();
-
- var applicationsArray = cursor.setArray("applications");
- applicationPrices(applicationsArray, prices.priceInformationApplications(), priceParameters);
-
- var priceInfoArray = cursor.setArray("priceInfo");
- addItem(priceInfoArray, "Enclave (minimum $10k per month)", prices.totalPriceInformation().enclaveDiscount());
- addItem(priceInfoArray, "Committed spend", prices.totalPriceInformation().committedAmountDiscount());
-
- setBigDecimal(cursor, "totalAmount", prices.totalPriceInformation().totalAmount());
-
- return new SlimeJsonResponse(slime);
- }
-
- private static void applicationPrices(Cursor applicationPricesArray, List<PriceInformation> applicationPrices, PriceParameters priceParameters) {
- applicationPrices.forEach(priceInformation -> {
- var element = applicationPricesArray.addObject();
- var array = element.setArray("priceInfo");
- addItem(array, supportLevelDescription(priceParameters), priceInformation.listPriceWithSupport());
- addItem(array, "Enclave", priceInformation.enclaveDiscount());
- addItem(array, "Volume discount", priceInformation.volumeDiscount());
- });
- }
-
- private static String supportLevelDescription(PriceParameters priceParameters) {
- String supportLevel = priceParameters.pricingInfo.supportLevel().name();
- return supportLevel.substring(0,1).toUpperCase() + supportLevel.substring(1).toLowerCase() + " support unit price";
- }
-
- private static void addItem(Cursor array, String name, BigDecimal amount) {
- if (amount.compareTo(BigDecimal.ZERO) != 0) {
- var o = array.addObject();
- o.setString("description", name);
- setBigDecimal(o, "amount", amount);
- }
- }
-
- private static void setBigDecimal(Cursor cursor, String name, BigDecimal value) {
- cursor.setString(name, value.setScale(2, RoundingMode.HALF_UP).toPlainString());
- }
-
- private record PriceParameters(List<ClusterResources> clusterResources, PricingInfo pricingInfo, Plan plan,
- List<ApplicationResources> appResources) {
-
- }
-
-}
diff --git a/controller-server/src/main/resources/mail/mail-verification.vm b/controller-server/src/main/resources/mail/mail-verification.vm
index 6905a292ee7..340895812ca 100644
--- a/controller-server/src/main/resources/mail/mail-verification.vm
+++ b/controller-server/src/main/resources/mail/mail-verification.vm
@@ -411,7 +411,7 @@
valign="middle"
>
<a
- href="https://$consoleUrl/verify?code=$code"
+ href="$verifyLink"
style="
display: inline-block;
background: #3b9fde;
@@ -471,9 +471,9 @@
<a
target="_blank"
rel="noopener noreferrer"
- href="https://$consoleUrl/verify?code=$code"
+ href="$verifyLink"
style="color: #3b9fde"
- >https://$consoleUrl/verify?code=$code</a
+ >$verifyLink</a
>
</p>
</div>
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java
index a7af0916e59..4fbf39f8d8b 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/MailVerifierTest.java
@@ -30,7 +30,7 @@ class MailVerifierTest {
private final ControllerTester tester = new ControllerTester(SystemName.Public);
private final MockMailer mailer = tester.serviceRegistry().mailer();
- private final MailVerifier mailVerifier = new MailVerifier(tester.zoneRegistry(), tester.controller().tenants(), mailer, tester.curator(), tester.clock());
+ private final MailVerifier mailVerifier = new MailVerifier(tester.serviceRegistry().consoleUrls(), tester.controller().tenants(), mailer, tester.curator(), tester.clock());
private static final TenantName tenantName = TenantName.from("scoober");
private static final String mail = "unverified@bar.com";
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
index 5c6853bccdb..39d867d813d 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ServiceRegistryMock.java
@@ -10,6 +10,7 @@ import com.yahoo.config.provision.HostName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.test.ManualClock;
import com.yahoo.vespa.hosted.controller.api.identifiers.ControllerVersion;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.ServiceRegistry;
import com.yahoo.vespa.hosted.controller.api.integration.archive.ArchiveService;
import com.yahoo.vespa.hosted.controller.api.integration.archive.MockArchiveService;
@@ -54,6 +55,7 @@ import com.yahoo.vespa.hosted.controller.api.integration.user.RoleMaintainer;
import com.yahoo.vespa.hosted.controller.api.integration.user.RoleMaintainerMock;
import com.yahoo.vespa.hosted.controller.api.integration.vcmr.MockChangeRequestClient;
+import java.net.URI;
import java.time.Instant;
import java.util.Optional;
@@ -68,6 +70,7 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
private final ControllerVersion controllerVersion;
private final ZoneRegistryMock zoneRegistryMock;
private final ConfigServerMock configServerMock;
+ private final ConsoleUrls consoleUrls = new ConsoleUrls(URI.create("https://console.tld"));
private final MemoryNameService memoryNameService = new MemoryNameService();
private final MockVpcEndpointService vpcEndpointService = new MockVpcEndpointService(clock, memoryNameService);
private final MockMailer mockMailer = new MockMailer();
@@ -218,6 +221,11 @@ public class ServiceRegistryMock extends AbstractComponent implements ServiceReg
}
@Override
+ public ConsoleUrls consoleUrls() {
+ return consoleUrls;
+ }
+
+ @Override
public MockResourceTagger resourceTagger() {
return mockResourceTagger;
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
index 70198ae35fd..c5b11fe21b0 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/integration/ZoneRegistryMock.java
@@ -2,8 +2,6 @@
package com.yahoo.vespa.hosted.controller.integration;
import com.yahoo.component.AbstractComponent;
-import com.yahoo.config.provision.ApplicationId;
-import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.AthenzDomain;
import com.yahoo.config.provision.CloudAccount;
import com.yahoo.config.provision.CloudName;
@@ -21,7 +19,6 @@ import com.yahoo.text.Text;
import com.yahoo.vespa.athenz.api.AthenzIdentity;
import com.yahoo.vespa.athenz.api.AthenzService;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
-import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.zone.ZoneRegistry;
import java.net.URI;
@@ -220,36 +217,6 @@ public class ZoneRegistryMock extends AbstractComponent implements ZoneRegistry
}
@Override
- public URI dashboardUrl() {
- return URI.create("https://dashboard.tld");
- }
-
- @Override
- public URI dashboardUrl(ApplicationId id) {
- return URI.create("https://dashboard.tld/" + id);
- }
-
- @Override
- public URI dashboardUrl(TenantName tenantName, ApplicationName applicationName) {
- return URI.create("https://dashboard.tld/" + tenantName + "/" + applicationName);
- }
-
- @Override
- public URI dashboardUrl(TenantName tenantName) {
- return URI.create("https://dashboard.tld/" + tenantName);
- }
-
- @Override
- public URI dashboardUrl(RunId id) {
- return URI.create("https://dashboard.tld/" + id.application() + "/" + id.type().jobName() + "/" + id.number());
- }
-
- @Override
- public URI supportUrl() {
- return URI.create("https://help.tld");
- }
-
- @Override
public URI apiUrl() {
return URI.create("https://api.tld:4443/");
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainerTest.java
index a224af83401..5cb46664a75 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/maintenance/BillingReportMaintainerTest.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.controller.maintenance;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.ControllerTester;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.BillStatus;
import com.yahoo.vespa.hosted.controller.api.integration.billing.InvoiceUpdate;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanRegistryMock;
import com.yahoo.vespa.hosted.controller.tenant.BillingReference;
@@ -43,25 +44,38 @@ public class BillingReportMaintainerTest {
}
@Test
- void only_bills_with_exported_id_are_maintained() {
+ void only_open_bills_with_exported_id_are_maintained() {
var t1 = tester.createTenant("t1");
var billingController = tester.controller().serviceRegistry().billingController();
var billingDb = tester.controller().serviceRegistry().billingDatabase();
var start = LocalDate.of(2020, 5, 23).atStartOfDay(ZoneOffset.UTC);
var end = start.toLocalDate().plusDays(6).atStartOfDay(ZoneOffset.UTC);
+
var bill1 = billingDb.createBill(t1, start, end, "non-exported");
var bill2 = billingDb.createBill(t1, start, end, "exported");
+ var bill3 = billingDb.createBill(t1, start, end, "exported-and-frozen");
+ billingDb.setStatus(bill3, "foo", BillStatus.FROZEN);
billingController.setPlan(t1, PlanRegistryMock.paidPlan.id(), false, true);
tester.controller().serviceRegistry().billingReporter().exportBill(billingDb.readBill(bill2).get(), "FOO", cloudTenant(t1));
+ tester.controller().serviceRegistry().billingReporter().exportBill(billingDb.readBill(bill3).get(), "FOO", cloudTenant(t1));
var updates = maintainer.maintainInvoices();
- assertEquals(new InvoiceUpdate(0, 0, 1), updates);
+ assertEquals(new InvoiceUpdate(1, 0, 0), updates);
+
+ assertTrue(billingDb.readBill(bill1).get().getExportedId().isEmpty());
var exportedBill = billingDb.readBill(bill2).get();
assertEquals("EXT-ID-123", exportedBill.getExportedId().get());
- assertTrue(billingDb.readBill(bill1).get().getExportedId().isEmpty());
+ var lineItems = exportedBill.lineItems();
+ assertEquals(1, lineItems.size());
+ assertEquals("maintained", lineItems.get(0).id());
+
+ var frozenBill = billingDb.readBill(bill3).get();
+ assertEquals("EXT-ID-123", frozenBill.getExportedId().get());
+ assertEquals(0, frozenBill.lineItems().size());
+
}
private CloudTenant cloudTenant(TenantName tenantName) {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatterTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatterTest.java
index 751d0123e40..875487144d9 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatterTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationFormatterTest.java
@@ -6,16 +6,16 @@ import com.yahoo.config.provision.ApplicationName;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.RegionName;
-import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.config.provision.zone.ZoneId;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.JobType;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId;
-import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import org.junit.jupiter.api.Test;
+import java.net.URI;
import java.time.Instant;
import java.util.List;
@@ -31,9 +31,8 @@ public class NotificationFormatterTest {
private final ApplicationId applicationId = ApplicationId.from(tenant, application, instance);
private final DeploymentId deploymentId = new DeploymentId(applicationId, ZoneId.defaultId());
private final ClusterSpec.Id cluster = new ClusterSpec.Id("content");
- private final ZoneRegistryMock zoneRegistry = new ZoneRegistryMock(SystemName.Public);
- private final NotificationFormatter formatter = new NotificationFormatter(zoneRegistry);
+ private final NotificationFormatter formatter = new NotificationFormatter(new ConsoleUrls(URI.create("https://console.tld")));
@Test
void applicationPackage() {
@@ -41,7 +40,7 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Application package", content.prettyType());
assertEquals("Application package for myapp.beta has 2 warnings", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober.myapp.beta", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance/beta", content.uri());
}
@Test
@@ -51,7 +50,7 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Deployment", content.prettyType());
assertEquals("production-default #1001 for myapp.beta has a warning", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober.myapp.beta/production-default/1001", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance/beta/job/production-default/run/1001", content.uri());
}
@Test
@@ -61,7 +60,7 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Deployment", content.prettyType());
assertEquals("production-default #1001 for myapp.beta has failed", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober.myapp.beta/production-default/1001", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance/beta/job/production-default/run/1001", content.uri());
}
@Test
@@ -70,7 +69,7 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Test package", content.prettyType());
assertEquals("There is a problem with tests for myapp", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober/myapp", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance", content.uri());
}
@Test
@@ -79,7 +78,7 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Reindex", content.prettyType());
assertEquals("Cluster content in prod.default for myapp.beta is reindexing", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober.myapp.beta?beta.prod.default=clusters%2Ccontent%3Dstatus", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance/beta?beta.prod.default=clusters%2Ccontent%3Dreindexing", content.uri());
}
@Test
@@ -88,6 +87,6 @@ public class NotificationFormatterTest {
var content = formatter.format(notification);
assertEquals("Nearly feed blocked", content.prettyType());
assertEquals("Cluster content in prod.default for myapp.beta is nearly feed blocked", content.messagePrefix());
- assertEquals("https://dashboard.tld/scoober.myapp.beta?beta.prod.default=clusters%2Ccontent", content.uri().toString());
+ assertEquals("https://console.tld/tenant/scoober/application/myapp/prod/instance/beta?beta.prod.default=clusters%2Ccontent", content.uri());
}
}
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
index 003a7f59eef..39c3f0f2b74 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotificationsDbTest.java
@@ -14,13 +14,13 @@ import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.flags.PermanentFlags;
import com.yahoo.vespa.hosted.controller.api.application.v4.model.ClusterMetrics;
import com.yahoo.vespa.hosted.controller.api.identifiers.DeploymentId;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.integration.configserver.ApplicationReindexing;
import com.yahoo.vespa.hosted.controller.api.integration.deployment.RunId;
import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer;
import com.yahoo.vespa.hosted.controller.application.TenantAndApplicationId;
import com.yahoo.vespa.hosted.controller.deployment.DeploymentContext;
-import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
@@ -31,6 +31,7 @@ import com.yahoo.vespa.hosted.controller.tenant.TenantInfo;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
+import java.net.URI;
import java.time.Instant;
import java.util.ArrayList;
import java.util.Arrays;
@@ -84,7 +85,7 @@ public class NotificationsDbTest {
private final MockCuratorDb curatorDb = new MockCuratorDb(SystemName.Public);
private final MockMailer mailer = new MockMailer();
private final FlagSource flagSource = new InMemoryFlagSource().withBooleanFlag(PermanentFlags.NOTIFICATION_DISPATCH_FLAG.id(), true);
- private final NotificationsDb notificationsDb = new NotificationsDb(clock, curatorDb, new Notifier(curatorDb, new ZoneRegistryMock(SystemName.cd), mailer, flagSource));
+ private final NotificationsDb notificationsDb = new NotificationsDb(clock, curatorDb, new Notifier(curatorDb, new ConsoleUrls(URI.create("https://console.tld")), mailer, flagSource));
@Test
void list_test() {
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java
index f64ed3740d2..55531dff72d 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/notification/NotifierTest.java
@@ -9,9 +9,9 @@ import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.flags.InMemoryFlagSource;
import com.yahoo.vespa.flags.PermanentFlags;
+import com.yahoo.vespa.hosted.controller.api.integration.ConsoleUrls;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
import com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMailer;
-import com.yahoo.vespa.hosted.controller.integration.ZoneRegistryMock;
import com.yahoo.vespa.hosted.controller.persistence.MockCuratorDb;
import com.yahoo.vespa.hosted.controller.tenant.ArchiveAccess;
import com.yahoo.vespa.hosted.controller.tenant.CloudTenant;
@@ -23,6 +23,7 @@ import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.IOException;
+import java.net.URI;
import java.time.Instant;
import java.util.List;
import java.util.Map;
@@ -64,7 +65,7 @@ public class NotifierTest {
void dispatch() throws IOException {
var mailer = new MockMailer();
var flagSource = new InMemoryFlagSource().withBooleanFlag(PermanentFlags.NOTIFICATION_DISPATCH_FLAG.id(), true);
- var notifier = new Notifier(curatorDb, new ZoneRegistryMock(SystemName.cd), mailer, flagSource);
+ var notifier = new Notifier(curatorDb, new ConsoleUrls(URI.create("https://console.tld")), mailer, flagSource);
var notification = new Notification(Instant.now(), Notification.Type.testPackage, Notification.Level.warning,
NotificationSource.from(ApplicationId.from(tenant, ApplicationName.defaultName(), InstanceName.defaultName())),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
index cb867c76f1f..9de856971c9 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/persistence/TenantSerializerTest.java
@@ -212,7 +212,7 @@ public class TenantSerializerTest {
Slime slime = new Slime();
Cursor parentObject = slime.setObject();
serializer.toSlime(partialInfo, parentObject);
- assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":true,\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString());
+ assertEquals("{\"info\":{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":false,\"address\":{\"addressLines\":\"\",\"postalCodeOrZip\":\"\",\"city\":\"Hønefoss\",\"stateRegionProvince\":\"\",\"country\":\"\"}}}", slime.toString());
}
@Test
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
index 6103b715744..3ada598f4f8 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/ControllerContainerTest.java
@@ -77,7 +77,6 @@ public class ControllerContainerTest {
<component id='com.yahoo.vespa.hosted.controller.Controller'/>
<component id='com.yahoo.vespa.hosted.controller.integration.ConfigServerProxyMock'/>
<component id='com.yahoo.vespa.hosted.controller.maintenance.ControllerMaintenance'/>
- <component id='com.yahoo.vespa.hosted.controller.api.integration.MockPricingController'/>
<component id='com.yahoo.vespa.hosted.controller.api.integration.stubs.MockMavenRepository'/>
<component id='com.yahoo.vespa.hosted.controller.api.integration.stubs.MockUserManagement'/>
<component id='com.yahoo.vespa.hosted.controller.integration.SecretStoreMock'/>
@@ -118,9 +117,6 @@ public class ControllerContainerTest {
<handler id='com.yahoo.vespa.hosted.controller.restapi.changemanagement.ChangeManagementApiHandler'>
<binding>http://localhost/changemanagement/v1/*</binding>
</handler>
- <handler id='com.yahoo.vespa.hosted.controller.restapi.pricing.PricingApiHandler'>
- <binding>http://localhost/pricing/v1/*</binding>
- </handler>
%s
</container>
""".formatted(system().value(), variablePartXml());
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
index 90bd2323cb3..2b01d87c903 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/application/ApplicationApiCloudTest.java
@@ -78,7 +78,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
void tenant_info_profile() {
var request = request("/application/v4/tenant/scoober/info/profile", GET)
.roles(Set.of(Role.reader(tenantName)));
- tester.assertResponse(request, "{\"contact\":{\"name\":\"\",\"email\":\"\",\"emailVerified\":true},\"tenant\":{\"company\":\"\",\"website\":\"\"}}", 200);
+ tester.assertResponse(request, "{\"contact\":{\"name\":\"\",\"email\":\"\",\"emailVerified\":false},\"tenant\":{\"company\":\"\",\"website\":\"\"}}", 200);
var updateRequest = request("/application/v4/tenant/scoober/info/profile", PUT)
.data("{\"contact\":{\"name\":\"Some Name\",\"email\":\"foo@example.com\"},\"tenant\":{\"company\":\"Scoober, Inc.\",\"website\":\"https://example.com/\"}}")
@@ -100,7 +100,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
void tenant_info_billing() {
var request = request("/application/v4/tenant/scoober/info/billing", GET)
.roles(Set.of(Role.reader(tenantName)));
- tester.assertResponse(request, "{\"contact\":{\"name\":\"\",\"email\":\"\",\"phone\":\"\"}}", 200);
+ tester.assertResponse(request, "{\"contact\":{\"name\":\"\",\"email\":\"\",\"emailVerified\":false,\"phone\":\"\"}}", 200);
var fullAddress = "{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}";
var fullBillingContact = "{\"contact\":{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\"},\"address\":" + fullAddress + "}";
@@ -110,7 +110,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
.roles(Set.of(Role.administrator(tenantName)));
tester.assertResponse(updateRequest, "{\"message\":\"Tenant info updated\"}", 200);
- tester.assertResponse(request, "{\"contact\":{\"name\":\"name\",\"email\":\"foo@example\",\"phone\":\"phone\"},\"address\":{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}}", 200);
+ tester.assertResponse(request, "{\"contact\":{\"name\":\"name\",\"email\":\"foo@example\",\"emailVerified\":false,\"phone\":\"phone\"},\"address\":{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}}", 200);
}
@Test
@@ -133,7 +133,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
var infoRequest =
request("/application/v4/tenant/scoober/info", GET)
.roles(Set.of(Role.reader(tenantName)));
- tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":true,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200);
+ tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":false,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200);
String partialInfo = "{\"contactName\":\"newName\", \"contactEmail\": \"foo@example.com\", \"billingContact\":{\"name\":\"billingName\"}}";
var postPartial =
@@ -150,7 +150,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
tester.assertResponse(postPartialContacts, "{\"message\":\"Tenant info updated\"}", 200);
// Read back the updated info
- tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"contactEmailVerified\":false,\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"emailVerified\":true,\"phone\":\"\"},\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false}]}", 200);
+ tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"newName\",\"contactEmail\":\"foo@example.com\",\"contactEmailVerified\":false,\"billingContact\":{\"name\":\"billingName\",\"email\":\"\",\"emailVerified\":false,\"phone\":\"\"},\"contacts\":[{\"audiences\":[\"tenant\"],\"email\":\"contact1@example.com\",\"emailVerified\":false}]}", 200);
String fullAddress = "{\"addressLines\":\"addressLines\",\"postalCodeOrZip\":\"postalCodeOrZip\",\"city\":\"city\",\"stateRegionProvince\":\"stateRegionProvince\",\"country\":\"country\"}";
String fullBillingContact = "{\"name\":\"name\",\"email\":\"foo@example\",\"emailVerified\":false,\"phone\":\"phone\",\"address\":" + fullAddress + "}";
@@ -188,7 +188,7 @@ public class ApplicationApiCloudTest extends ControllerContainerCloudTest {
var infoRequest =
request("/application/v4/tenant/scoober/info", GET)
.roles(Set.of(Role.reader(tenantName)));
- tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":true,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200);
+ tester.assertResponse(infoRequest, "{\"name\":\"\",\"email\":\"\",\"website\":\"\",\"contactName\":\"\",\"contactEmail\":\"\",\"contactEmailVerified\":false,\"contacts\":[{\"audiences\":[\"tenant\",\"notifications\"],\"email\":\"developer@scoober\",\"emailVerified\":true}]}", 200);
// name needs to be present and not blank
var partialInfoMissingName = "{\"contactName\": \" \"}";
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
index 7f68fbf6909..f3147d2adde 100644
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
+++ b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/billing/BillingApiHandlerTest.java
@@ -4,9 +4,11 @@ package com.yahoo.vespa.hosted.controller.restapi.billing;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
import com.yahoo.vespa.hosted.controller.api.integration.billing.Bill;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.BillStatus;
import com.yahoo.vespa.hosted.controller.api.integration.billing.CollectionMethod;
import com.yahoo.vespa.hosted.controller.api.integration.billing.MockBillingController;
import com.yahoo.vespa.hosted.controller.api.integration.billing.PlanId;
+import com.yahoo.vespa.hosted.controller.api.integration.billing.StatusHistory;
import com.yahoo.vespa.hosted.controller.api.role.Role;
import com.yahoo.vespa.hosted.controller.restapi.ContainerTester;
import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest;
@@ -26,12 +28,10 @@ import java.util.Optional;
import java.util.Set;
import java.util.TreeMap;
-import static com.yahoo.application.container.handler.Request.Method.DELETE;
import static com.yahoo.application.container.handler.Request.Method.GET;
import static com.yahoo.application.container.handler.Request.Method.PATCH;
import static com.yahoo.application.container.handler.Request.Method.POST;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author olaa
@@ -152,14 +152,14 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
void adding_new_status() {
billingController.addBill(tenant, createBill(), true);
- var requestBody = "{\"status\":\"DONE\"}";
+ var requestBody = "{\"status\":\"CLOSED\"}";
var request = request("/billing/v1/invoice/id-1/status", POST)
.data(requestBody)
.roles(financeAdmin);
tester.assertResponse(request, "{\"message\":\"Updated status of invoice id-1\"}");
var bill = billingController.getBillsForTenant(tenant).get(0);
- assertEquals("DONE", bill.status());
+ assertEquals(BillStatus.CLOSED, bill.status());
}
@Test
@@ -211,7 +211,7 @@ public class BillingApiHandlerTest extends ControllerContainerCloudTest {
static Bill createBill() {
var start = LocalDate.of(2020, 5, 23).atStartOfDay(ZoneOffset.UTC);
var end = start.toLocalDate().plusDays(6).atStartOfDay(ZoneOffset.UTC);
- var statusHistory = new Bill.StatusHistory(new TreeMap<>(Map.of(start, "OPEN")));
+ var statusHistory = new StatusHistory(new TreeMap<>(Map.of(start, BillStatus.OPEN)));
return new Bill(
Bill.Id.of("id-1"),
TenantName.defaultName(),
diff --git a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java b/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java
deleted file mode 100644
index f2ce0dfeef2..00000000000
--- a/controller-server/src/test/java/com/yahoo/vespa/hosted/controller/restapi/pricing/PricingApiHandlerTest.java
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
-package com.yahoo.vespa.hosted.controller.restapi.pricing;
-
-import com.yahoo.config.provision.SystemName;
-import com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo;
-import com.yahoo.vespa.hosted.controller.restapi.ContainerTester;
-import com.yahoo.vespa.hosted.controller.restapi.ControllerContainerCloudTest;
-import org.junit.jupiter.api.Test;
-
-import java.net.URLEncoder;
-
-import static com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo.SupportLevel.BASIC;
-import static com.yahoo.vespa.hosted.controller.api.integration.pricing.PricingInfo.SupportLevel.COMMERCIAL;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-/**
- * @author hmusum
- */
-public class PricingApiHandlerTest extends ControllerContainerCloudTest {
-
- @Test
- void testPricingInfoBasic() {
- tester().assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0"),
- """
- { "applications": [ ], "priceInfo": [ ], "totalAmount": "0.00" }
- """,
- 200);
-
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformation1App(BASIC));
- tester().assertJsonResponse(request, """
- {
- "applications": [
- {
- "priceInfo": [
- {"description": "Basic support unit price", "amount": "4.30"},
- {"description": "Volume discount", "amount": "-0.10"}
- ]
- }
- ],
- "priceInfo": [
- {"description": "Committed spend", "amount": "-0.20"}
- ],
- "totalAmount": "4.00"
- }
- """,
- 200);
- }
-
- @Test
- void testPricingInfoBasicEnclave() {
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformation1AppEnclave(BASIC));
- tester().assertJsonResponse(request, """
- {
- "applications": [
- {
- "priceInfo": [
- {"description": "Basic support unit price", "amount": "4.30"},
- {"description": "Enclave", "amount": "-0.15"},
- {"description": "Volume discount", "amount": "-0.10"}
- ]
- }
- ],
- "priceInfo": [
- {"description": "Enclave (minimum $10k per month)", "amount": "10.15"},
- {"description": "Committed spend", "amount": "-0.20"}
- ],
- "totalAmount": "3.85"
- }
- """,
- 200);
- }
-
- @Test
- void testPricingInfoCommercialEnclave() {
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformation1AppEnclave(COMMERCIAL));
- tester().assertJsonResponse(request, """
- {
- "applications": [
- {
- "priceInfo": [
- {"description": "Commercial support unit price", "amount": "13.30"},
- {"description": "Enclave", "amount": "-0.15"},
- {"description": "Volume discount", "amount": "-0.10"}
- ]
- }
- ],
- "priceInfo": [
- {"description": "Enclave (minimum $10k per month)", "amount": "1.15"},
- {"description": "Committed spend", "amount": "-0.20"}
- ],
- "totalAmount": "12.85"
- }
- """,
- 200);
- }
-
- @Test
- void testPricingInfoCommercialEnclave2Apps() {
- var request = request("/pricing/v1/pricing?" + urlEncodedPriceInformation2AppsEnclave(COMMERCIAL));
- tester().assertJsonResponse(request, """
- {
- "applications": [
- {
- "priceInfo": [
- {"description": "Commercial support unit price", "amount": "13.30"},
- {"description": "Enclave", "amount": "-0.15"},
- {"description": "Volume discount", "amount": "-0.10"}
- ]
- },
- {
- "priceInfo": [
- {"description": "Commercial support unit price", "amount": "13.30"},
- {"description": "Enclave", "amount": "-0.15"},
- {"description": "Volume discount", "amount": "-0.10"}
- ]
- }
- ],
- "priceInfo": [ ],
- "totalAmount": "26.10"
- }
- """,
- 200);
- }
-
- @Test
- void testInvalidRequests() {
- ContainerTester tester = tester();
- tester.assertJsonResponse(request("/pricing/v1/pricing"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"No price information found in query\"}",
- 400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Error in query parameter, expected '=' between key and value: ''\"}",
- 400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&resources"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Error in query parameter, expected '=' between key and value: 'resources'\"}",
- 400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&resources="),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Error in query parameter, expected '=' between key and value: 'resources='\"}",
- 400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&key=value"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown query parameter 'key'\"}",
- 400);
- tester.assertJsonResponse(request("/pricing/v1/pricing?supportLevel=basic&committedSpend=0&application=key%3Dvalue"),
- "{\"error-code\":\"BAD_REQUEST\",\"message\":\"Unknown key 'key'\"}",
- 400);
- }
-
- private ContainerTester tester() {
- ContainerTester tester = new ContainerTester(container, null);
- assertEquals(SystemName.Public, tester.controller().system());
- return tester;
- }
-
- /**
- * 1 app, with 2 clusters (with total resources for all clusters with each having
- * 1 node, with 4 vcpu, 8 Gb memory, 100 Gb disk and no GPU,
- * price will be 20000 + 2000 + 200
- */
- String urlEncodedPriceInformation1App(PricingInfo.SupportLevel supportLevel) {
- return "application=" + URLEncoder.encode("vcpu=4,memoryGb=8,diskGb=100,gpuMemoryGb=0", UTF_8) +
- "&supportLevel=" + supportLevel.name().toLowerCase() + "&committedSpend=20";
- }
-
- /**
- * 1 app, with 2 clusters (with total resources for all clusters with each having
- * 1 node, with 4 vcpu, 8 Gb memory, 100 Gb disk and no GPU,
- * price will be 20000 + 2000 + 200
- */
- String urlEncodedPriceInformation1AppEnclave(PricingInfo.SupportLevel supportLevel) {
- return "application=" + URLEncoder.encode("enclaveVcpu=4,enclaveMemoryGb=8,enclaveDiskGb=100,enclaveGpuMemoryGb=0", UTF_8) +
- "&supportLevel=" + supportLevel.name().toLowerCase() + "&committedSpend=20";
- }
-
- /**
- * 2 apps, with 1 cluster (with total resources for all clusters with each having
- * 1 node, with 4 vcpu, 8 Gb memory, 100 Gb disk and no GPU,
- */
- String urlEncodedPriceInformation2AppsEnclave(PricingInfo.SupportLevel supportLevel) {
- return "application=" + URLEncoder.encode("enclaveVcpu=4,enclaveMemoryGb=8,enclaveDiskGb=100,enclaveGpuMemoryGb=0", UTF_8) +
- "&application=" + URLEncoder.encode("enclaveVcpu=4,enclaveMemoryGb=8,enclaveDiskGb=100,enclaveGpuMemoryGb=0", UTF_8) +
- "&supportLevel=" + supportLevel.name().toLowerCase() + "&committedSpend=0";
- }
-
-}
diff --git a/controller-server/src/test/resources/mail/notification.html b/controller-server/src/test/resources/mail/notification.html
index c8d0037426b..2a0edeea7e1 100644
--- a/controller-server/src/test/resources/mail/notification.html
+++ b/controller-server/src/test/resources/mail/notification.html
@@ -488,7 +488,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/tenant/tenant1/application/default/prod/instance"
+ href="https://console.tld/tenant/tenant1/application/default/prod/instance/default"
style="
display: inline-block;
background: #005a8e;
@@ -606,7 +606,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -616,7 +616,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -625,7 +625,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/tenant1/account/notifications"
+ href="https://console.tld/tenant/tenant1/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/controller-server/src/test/resources/mail/trial-expired.html b/controller-server/src/test/resources/mail/trial-expired.html
index 4e6fda61b33..bdeafe8c7d3 100644
--- a/controller-server/src/test/resources/mail/trial-expired.html
+++ b/controller-server/src/test/resources/mail/trial-expired.html
@@ -485,7 +485,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/trial-tenant"
+ href="https://console.tld/tenant/trial-tenant"
style="
display: inline-block;
background: #005a8e;
@@ -603,7 +603,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -613,7 +613,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -622,7 +622,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/trial-tenant/account/notifications"
+ href="https://console.tld/tenant/trial-tenant/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/controller-server/src/test/resources/mail/trial-expiring-immediately.html b/controller-server/src/test/resources/mail/trial-expiring-immediately.html
index 4b16619fe9c..db89eca195a 100644
--- a/controller-server/src/test/resources/mail/trial-expiring-immediately.html
+++ b/controller-server/src/test/resources/mail/trial-expiring-immediately.html
@@ -485,7 +485,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/trial-tenant"
+ href="https://console.tld/tenant/trial-tenant"
style="
display: inline-block;
background: #005a8e;
@@ -603,7 +603,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -613,7 +613,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -622,7 +622,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/trial-tenant/account/notifications"
+ href="https://console.tld/tenant/trial-tenant/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/controller-server/src/test/resources/mail/trial-expiring-soon.html b/controller-server/src/test/resources/mail/trial-expiring-soon.html
index b4c85173171..17c59240cc4 100644
--- a/controller-server/src/test/resources/mail/trial-expiring-soon.html
+++ b/controller-server/src/test/resources/mail/trial-expiring-soon.html
@@ -485,7 +485,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/trial-tenant"
+ href="https://console.tld/tenant/trial-tenant"
style="
display: inline-block;
background: #005a8e;
@@ -603,7 +603,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -613,7 +613,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -622,7 +622,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/trial-tenant/account/notifications"
+ href="https://console.tld/tenant/trial-tenant/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/controller-server/src/test/resources/mail/trial-reminder.html b/controller-server/src/test/resources/mail/trial-reminder.html
index 2644b187764..fbe0d573538 100644
--- a/controller-server/src/test/resources/mail/trial-reminder.html
+++ b/controller-server/src/test/resources/mail/trial-reminder.html
@@ -485,7 +485,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/trial-tenant"
+ href="https://console.tld/tenant/trial-tenant"
style="
display: inline-block;
background: #005a8e;
@@ -603,7 +603,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -613,7 +613,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -622,7 +622,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/trial-tenant/account/notifications"
+ href="https://console.tld/tenant/trial-tenant/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/controller-server/src/test/resources/mail/welcome.html b/controller-server/src/test/resources/mail/welcome.html
index a21a7cdf45f..2e652532db8 100644
--- a/controller-server/src/test/resources/mail/welcome.html
+++ b/controller-server/src/test/resources/mail/welcome.html
@@ -485,7 +485,7 @@
valign="middle"
>
<a
- href="https://dashboard.tld/trial-tenant"
+ href="https://console.tld/tenant/trial-tenant"
style="
display: inline-block;
background: #005a8e;
@@ -603,7 +603,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/terms-of-service-trial.html"
+ href="https://console.tld/terms-of-service-trial.html"
><span style="color: #005a8e"
>Terms of Service</span
></a
@@ -613,7 +613,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: #005a8e"
- href="https://dashboard.tld/support"
+ href="https://console.tld/support"
><span style="color: #005a8e">Support</span></a
>
</p>
@@ -622,7 +622,7 @@
target="_blank"
rel="noopener noreferrer"
style="color: inherit; text-decoration: none"
- href="https://dashboard.tld/tenant/trial-tenant/account/notifications"
+ href="https://console.tld/tenant/trial-tenant/account/notifications"
>Click
<span style="color: #005a8e"><u>here</u></span>
to manage your notifications setting.</a
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
index fdf4a7ae838..e68b2f6103b 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/applications/Applications.java
@@ -4,6 +4,7 @@ package com.yahoo.vespa.hosted.provision.applications;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationLockException;
import com.yahoo.config.provision.ApplicationTransaction;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.transaction.Mutex;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.hosted.provision.persistence.CuratorDb;
@@ -63,24 +64,19 @@ public class Applications {
db.deleteApplication(transaction);
}
- public record Lock(Mutex mutex, ApplicationId application) implements Mutex {
- @Override
- public void close() { mutex.close(); }
- }
-
/** Create a lock which provides exclusive rights to making changes to the given application */
- public Lock lock(ApplicationId application) {
- return new Lock(db.lock(application), application);
+ public ApplicationMutex lock(ApplicationId application) {
+ return new ApplicationMutex(application, db.lock(application));
}
/** Create a lock with a timeout which provides exclusive rights to making changes to the given application */
- public Lock lock(ApplicationId application, Duration timeout) {
- return new Lock(db.lock(application, timeout), application);
+ public ApplicationMutex lock(ApplicationId application, Duration timeout) {
+ return new ApplicationMutex(application, db.lock(application, timeout));
}
/** Create a lock which provides exclusive rights to perform a maintenance deployment */
- public Lock lockMaintenance(ApplicationId application) {
- return new Lock(db.lockMaintenance(application), application);
+ public ApplicationMutex lockMaintenance(ApplicationId application) {
+ return new ApplicationMutex(application, db.lockMaintenance(application));
}
}
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
index 8a79263946f..c352dca1656 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/node/Nodes.java
@@ -7,6 +7,7 @@ import com.yahoo.config.provision.ApplicationTransaction;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.Zone;
import com.yahoo.time.TimeBudget;
import com.yahoo.transaction.Mutex;
@@ -224,7 +225,7 @@ public class Nodes {
}
/** Sets the exclusiveToApplicationId field. The nodes must be tenant hosts without the field already. */
- public void setExclusiveToApplicationId(List<Node> hosts, Applications.Lock lock) {
+ public void setExclusiveToApplicationId(List<Node> hosts, ApplicationMutex lock) {
List<Node> hostsToWrite = hosts.stream()
.filter(host -> !host.exclusiveToApplicationId().equals(Optional.of(lock.application())))
.peek(host -> {
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
index 2eb21caa6a0..e2f1b7358cf 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/NodeRepositoryProvisioner.java
@@ -12,7 +12,7 @@ import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
import com.yahoo.config.provision.Zone;
@@ -157,8 +157,8 @@ public class NodeRepositoryProvisioner implements Provisioner {
}
@Override
- public ProvisionLock lock(ApplicationId application) {
- return new ProvisionLock(application, nodeRepository.applications().lock(application));
+ public ApplicationMutex lock(ApplicationId application) {
+ return new ApplicationMutex(application, nodeRepository.applications().lock(application));
}
/**
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
index 9f1cb454fa7..9cbd3765cf8 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/provisioning/Preparer.java
@@ -8,6 +8,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeAllocationException;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.jdisc.Metric;
import com.yahoo.text.internal.SnippetGenerator;
import com.yahoo.transaction.Mutex;
@@ -18,7 +19,6 @@ import com.yahoo.vespa.hosted.provision.LockedNodeList;
import com.yahoo.vespa.hosted.provision.Node;
import com.yahoo.vespa.hosted.provision.NodeList;
import com.yahoo.vespa.hosted.provision.NodeRepository;
-import com.yahoo.vespa.hosted.provision.applications.Applications;
import com.yahoo.vespa.hosted.provision.node.Agent;
import com.yahoo.vespa.hosted.provision.node.IP;
import com.yahoo.vespa.hosted.provision.provisioning.HostProvisioner.HostSharing;
@@ -95,7 +95,7 @@ public class Preparer {
/// Note that this will write to the node repo.
private List<Node> prepareWithLocks(ApplicationId application, ClusterSpec cluster, NodeSpec requested, NodeIndices indices, boolean makeExclusive) {
try (Mutex lock = nodeRepository.applications().lock(application);
- Applications.Lock tenantHostLock = makeExclusive ? nodeRepository.applications().lock(InfrastructureApplication.TENANT_HOST.id()) : null;
+ ApplicationMutex tenantHostLock = makeExclusive ? nodeRepository.applications().lock(InfrastructureApplication.TENANT_HOST.id()) : null;
Mutex allocationLock = nodeRepository.nodes().lockUnallocated()) {
LockedNodeList allNodes = nodeRepository.nodes().list(allocationLock);
NodeAllocation allocation = prepareAllocation(application, cluster, requested, indices::next, allNodes, makeExclusive);
diff --git a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisioner.java b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisioner.java
index 377b1b3d4b4..e130f53fab5 100644
--- a/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisioner.java
+++ b/node-repository/src/main/java/com/yahoo/vespa/hosted/provision/testutils/MockProvisioner.java
@@ -8,7 +8,7 @@ import com.yahoo.config.provision.Capacity;
import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.HostFilter;
import com.yahoo.config.provision.HostSpec;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.ProvisionLogger;
import com.yahoo.config.provision.Provisioner;
@@ -36,7 +36,7 @@ public class MockProvisioner implements Provisioner {
public void restart(ApplicationId application, HostFilter filter) { }
@Override
- public ProvisionLock lock(ApplicationId application) {
+ public ApplicationMutex lock(ApplicationId application) {
return null;
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
index f152cbb7a52..ad55b400735 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/RealDataScenarioTest.java
@@ -16,7 +16,7 @@ import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeResources;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
@@ -119,7 +119,7 @@ public class RealDataScenarioTest {
.flatMap(Collection::stream)
.toList();
NestedTransaction transaction = new NestedTransaction();
- tester.provisioner().activate(hostSpecs, new ActivationContext(0), new ApplicationTransaction(new ProvisionLock(app, () -> {}), transaction));
+ tester.provisioner().activate(hostSpecs, new ActivationContext(0), new ApplicationTransaction(new ApplicationMutex(app, () -> {}), transaction));
transaction.commit();
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/applications/ApplicationsTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/applications/ApplicationsTest.java
index d378cb9a31b..1a5d5f0a37f 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/applications/ApplicationsTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/applications/ApplicationsTest.java
@@ -3,7 +3,7 @@ package com.yahoo.vespa.hosted.provision.applications;
import com.yahoo.config.provision.ApplicationId;
import com.yahoo.config.provision.ApplicationTransaction;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.transaction.NestedTransaction;
import com.yahoo.vespa.hosted.provision.NodeRepositoryTester;
import org.junit.Test;
@@ -53,8 +53,8 @@ public class ApplicationsTest {
assertEquals(List.of(), applications.ids());
}
- private ProvisionLock provisionLock(ApplicationId application) {
- return new ProvisionLock(application, () -> {});
+ private ApplicationMutex provisionLock(ApplicationId application) {
+ return new ApplicationMutex(application, () -> {});
}
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
index cc414cc50c2..691e67d945c 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/MetricsReporterTest.java
@@ -11,7 +11,7 @@ import com.yahoo.config.provision.ClusterSpec;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.jdisc.Metric;
import com.yahoo.transaction.Mutex;
import com.yahoo.transaction.NestedTransaction;
@@ -216,7 +216,7 @@ public class MetricsReporterTest {
NestedTransaction transaction = new NestedTransaction();
nodeRepository.nodes().activate(nodeRepository.nodes().list().nodeType(NodeType.host).asList(),
- new ApplicationTransaction(new ProvisionLock(InfrastructureApplication.TENANT_HOST.id(), () -> { }), transaction));
+ new ApplicationTransaction(new ApplicationMutex(InfrastructureApplication.TENANT_HOST.id(), () -> { }), transaction));
transaction.commit();
Orchestrator orchestrator = mock(Orchestrator.class);
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
index 05d5afa2c8a..7e3a9d1ea88 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/RebalancerTest.java
@@ -10,7 +10,7 @@ import com.yahoo.config.provision.Environment;
import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.Zone;
import com.yahoo.config.provisioning.FlavorsConfig;
@@ -85,7 +85,7 @@ public class RebalancerTest {
// --- Making the system stable enables rebalancing
NestedTransaction tx = new NestedTransaction();
tester.nodeRepository().nodes().deactivate(List.of(cpuSkewedNode),
- new ApplicationTransaction(new ProvisionLock(cpuApp, () -> {}), tx));
+ new ApplicationTransaction(new ApplicationMutex(cpuApp, () -> {}), tx));
tx.commit();
assertEquals(1, tester.getNodes(Node.State.dirty).size());
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java
index 023047f17e6..9fefc9d34e1 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/maintenance/SpareCapacityMaintainerTest.java
@@ -11,7 +11,7 @@ import com.yahoo.config.provision.Flavor;
import com.yahoo.config.provision.NodeFlavors;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.Zone;
import com.yahoo.test.ManualClock;
@@ -321,7 +321,7 @@ public class SpareCapacityMaintainerTest {
}
nodes = nodeRepository.nodes().reserve(nodes);
var transaction = new NestedTransaction();
- nodes = nodeRepository.nodes().activate(nodes, new ApplicationTransaction(new ProvisionLock(application, () -> { }), transaction));
+ nodes = nodeRepository.nodes().activate(nodes, new ApplicationTransaction(new ApplicationMutex(application, () -> { }), transaction));
transaction.commit();
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java
index 72582e47621..ff5ffd82bf1 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/DynamicAllocationTest.java
@@ -13,7 +13,7 @@ import com.yahoo.config.provision.HostSpec;
import com.yahoo.config.provision.NodeAllocationException;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.Zone;
@@ -542,7 +542,7 @@ public class DynamicAllocationTest {
tester.nodeRepository().nodes().addNodes(List.of(node1aAllocation), Agent.system);
NestedTransaction transaction = new NestedTransaction().add(new CuratorTransaction(tester.getCurator()));
- tester.nodeRepository().nodes().activate(List.of(node1aAllocation), new ApplicationTransaction(new ProvisionLock(id, () -> { }), transaction));
+ tester.nodeRepository().nodes().activate(List.of(node1aAllocation), new ApplicationTransaction(new ApplicationMutex(id, () -> { }), transaction));
transaction.commit();
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
index 8c35f89234d..b091603aaeb 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/ProvisioningTester.java
@@ -22,7 +22,7 @@ import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeResources.DiskSpeed;
import com.yahoo.config.provision.NodeResources.StorageType;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
@@ -220,7 +220,7 @@ public class ProvisioningTester {
NestedTransaction t = new NestedTransaction();
if (parent.ipConfig().primary().isEmpty())
parent = parent.with(IP.Config.of(List.of("::" + 0 + ":0"), List.of("::" + 0 + ":2")));
- nodeRepository.nodes().activate(List.of(parent), new ApplicationTransaction(new ProvisionLock(application, () -> { }), t));
+ nodeRepository.nodes().activate(List.of(parent), new ApplicationTransaction(new ApplicationMutex(application, () -> { }), t));
t.commit();
}
}
@@ -271,7 +271,7 @@ public class ProvisioningTester {
public void deactivate(ApplicationId applicationId) {
try (var lock = nodeRepository.applications().lock(applicationId)) {
NestedTransaction deactivateTransaction = new NestedTransaction();
- nodeRepository.remove(new ApplicationTransaction(new ProvisionLock(applicationId, lock),
+ nodeRepository.remove(new ApplicationTransaction(new ApplicationMutex(applicationId, lock),
deactivateTransaction));
deactivateTransaction.commit();
}
diff --git a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
index 3edd41049f0..9a6fdedb213 100644
--- a/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
+++ b/node-repository/src/test/java/com/yahoo/vespa/hosted/provision/provisioning/VirtualNodeProvisioningTest.java
@@ -15,7 +15,7 @@ import com.yahoo.config.provision.InstanceName;
import com.yahoo.config.provision.NodeAllocationException;
import com.yahoo.config.provision.NodeResources;
import com.yahoo.config.provision.NodeType;
-import com.yahoo.config.provision.ProvisionLock;
+import com.yahoo.config.provision.ApplicationMutex;
import com.yahoo.config.provision.RegionName;
import com.yahoo.config.provision.SystemName;
import com.yahoo.config.provision.TenantName;
@@ -594,7 +594,7 @@ public class VirtualNodeProvisioningTest {
tester.activate(app1, cluster1, Capacity.from(new ClusterResources(5, 1, r)));
tester.activate(app1, cluster1, Capacity.from(new ClusterResources(2, 1, r)));
- var tx = new ApplicationTransaction(new ProvisionLock(app1, tester.nodeRepository().applications().lock(app1)), new NestedTransaction());
+ var tx = new ApplicationTransaction(new ApplicationMutex(app1, tester.nodeRepository().applications().lock(app1)), new NestedTransaction());
tester.nodeRepository().nodes().deactivate(tester.nodeRepository().nodes().list(Node.State.active).owner(app1).retired().asList(), tx);
tx.nested().commit();