Commit 602352ce authored by Neelay Shah's avatar Neelay Shah Committed by GitHub
Browse files

chore: rename dynamo (#44)


Co-authored-by: default avatarBiswa Panda <biswa.panda@gmail.com>
parent ecf53ce2
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/mocks"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemasv2"
)
func ToClusterSchemaList(clusters []*models.Cluster) []*schemas.ClusterSchema {
clusterSchemas := make([]*schemas.ClusterSchema, 0)
for _, cluster := range clusters {
clusterSchemas = append(clusterSchemas, ToClusterSchema(cluster))
}
return clusterSchemas
}
func ToClusterSchema(cluster *models.Cluster) *schemas.ClusterSchema {
return &schemas.ClusterSchema{
Creator: mocks.DefaultUser(),
Description: cluster.Description,
ResourceSchema: schemas.ResourceSchema{
Name: cluster.Name,
ResourceType: schemas.ResourceTypeCluster,
BaseSchema: schemas.BaseSchema{
Uid: cluster.GetUid(),
CreatedAt: cluster.CreatedAt,
UpdatedAt: cluster.UpdatedAt,
DeletedAt: &cluster.DeletedAt.Time,
},
},
}
}
func ToClusterFullSchema(cluster *models.Cluster) *schemas.ClusterFullSchema {
clusterSchema := ToClusterSchema(cluster)
return &schemas.ClusterFullSchema{
ClusterSchema: *clusterSchema,
KubeConfig: &cluster.KubeConfig,
Organization: mocks.DefaultOrg(),
}
}
func ToClusterSchemaV2(cluster *models.Cluster, creator *schemas.UserSchema) *schemasv2.ClusterSchema {
return &schemasv2.ClusterSchema{
Description: cluster.Description,
OrganizationName: "nvidia",
Creator: creator,
ResourceSchema: schemas.ResourceSchema{
Name: cluster.Name,
Labels: []schemas.LabelItemSchema{},
BaseSchema: schemas.BaseSchema{
Uid: cluster.Resource.BaseModel.GetUid(),
CreatedAt: cluster.Resource.BaseModel.CreatedAt,
UpdatedAt: cluster.Resource.BaseModel.UpdatedAt,
DeletedAt: nil, // Can assume that this is nil during creation
},
},
}
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"context"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/services"
"github.com/pkg/errors"
)
func ToCompoundComponentSchema(ctx context.Context, compoundComponent *models.CompoundComponent) (*schemas.CompoundComponentSchema, error) {
if compoundComponent == nil {
return nil, nil
}
ss, err := ToCompoundComponentSchemas(ctx, []*models.CompoundComponent{compoundComponent})
if err != nil {
return nil, errors.Wrap(err, "ToCompoundComponentSchemas")
}
return ss[0], nil
}
func ToCompoundComponentSchemas(ctx context.Context, compoundComponents []*models.CompoundComponent) ([]*schemas.CompoundComponentSchema, error) {
resourceSchemasMap := make(map[string]*schemas.ResourceSchema, len(compoundComponents))
for _, component := range compoundComponents {
resourceSchemasMap[component.GetUid()] = ToResourceSchema(&component.Resource, component.GetResourceType())
}
res := make([]*schemas.CompoundComponentSchema, 0, len(compoundComponents))
for _, compoundComponent := range compoundComponents {
cluster, err := services.ClusterService.Get(ctx, compoundComponent.ClusterId)
if err != nil {
return nil, err
}
clusterSchema := ToClusterFullSchema(cluster)
resourceSchema, ok := resourceSchemasMap[compoundComponent.GetUid()]
if !ok {
return nil, errors.Errorf("resource schema not found for CompoundComponent %s", compoundComponent.GetUid())
}
res = append(res, &schemas.CompoundComponentSchema{
ResourceSchema: *resourceSchema,
Cluster: clusterSchema,
Manifest: compoundComponent.Manifest,
Version: compoundComponent.Version,
KubeNamespace: compoundComponent.KubeNamespace,
LatestHeartbeatAt: compoundComponent.LatestHeartbeatAt,
LatestInstalledAt: compoundComponent.LatestInstalledAt,
})
}
return res, nil
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"context"
"fmt"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/mocks"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemasv2"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/services"
)
func ToDeploymentSchema(ctx context.Context, deployment *models.Deployment) (*schemas.DeploymentSchema, error) {
if deployment == nil {
return nil, nil
}
ss, err := ToDeploymentSchemas(ctx, []*models.Deployment{deployment})
if err != nil {
return nil, err
}
return ss[0], nil
}
func ToDeploymentSchemas(ctx context.Context, deployments []*models.Deployment) ([]*schemas.DeploymentSchema, error) {
status_ := schemas.DeploymentRevisionStatusActive
deploymentIds := make([]uint, 0, len(deployments))
for _, deployment := range deployments {
deploymentIds = append(deploymentIds, deployment.ID)
}
deploymentRevisions, _, err := services.DeploymentRevisionService.List(ctx, services.ListDeploymentRevisionOption{
DeploymentIds: &deploymentIds,
Status: &status_,
})
if err != nil {
return nil, err
}
deploymentIdToDeploymentRevisionUid := make(map[uint]string)
for _, deploymentRevision := range deploymentRevisions {
deploymentIdToDeploymentRevisionUid[deploymentRevision.DeploymentId] = deploymentRevision.GetUid()
}
deploymentRevisionSchemas, err := ToDeploymentRevisionSchemas(ctx, deploymentRevisions)
if err != nil {
return nil, err
}
deploymentRevisionSchemasMap := make(map[string]*schemas.DeploymentRevisionSchema)
for _, deploymentRevisionSchema := range deploymentRevisionSchemas {
deploymentRevisionSchemasMap[deploymentRevisionSchema.Uid] = deploymentRevisionSchema
}
resourceSchemaMap := make(map[string]*schemas.ResourceSchema, len(deployments))
for _, deployment := range deployments {
resourceSchemaMap[deployment.GetUid()] = ToResourceSchema(&deployment.Resource, deployment.GetResourceType())
}
res := make([]*schemas.DeploymentSchema, 0, len(deployments))
for _, deployment := range deployments {
deploymentRevisionUid := deploymentIdToDeploymentRevisionUid[deployment.ID]
deploymentRevisionSchema := deploymentRevisionSchemasMap[deploymentRevisionUid]
creatorSchema := mocks.DefaultUser()
cluster, err := services.ClusterService.Get(ctx, deployment.ClusterId)
if err != nil {
return nil, err
}
clusterSchema := ToClusterFullSchema(cluster)
urls := make([]string, 0)
// TODO: implement get ingress urls...
// urls, err := services.DeploymentService.GetURLs(ctx, deployment)
// if err != nil {
// return nil, err
// }
resourceSchema, ok := resourceSchemaMap[deployment.GetUid()]
if !ok {
return nil, fmt.Errorf("resourceSchema not found for deployment %s", deployment.GetUid())
}
res = append(res, &schemas.DeploymentSchema{
ResourceSchema: *resourceSchema,
Creator: creatorSchema,
Cluster: clusterSchema,
Status: deployment.Status,
LatestRevision: deploymentRevisionSchema,
URLs: urls,
KubeNamespace: deployment.KubeNamespace,
})
}
return res, nil
}
func ToDeploymentSchemaV2(ctx context.Context, cluster *models.Cluster, deployment *models.Deployment, creator *schemas.UserSchema) (*schemasv2.DeploymentSchema, error) {
clusterSchema := ToClusterSchemaV2(cluster, creator)
status := schemas.DeploymentRevisionStatusActive
deploymentRevisionListOpts := services.ListDeploymentRevisionOption{
DeploymentId: &deployment.ID,
Status: &status,
}
deploymentRevisions, total, err := services.DeploymentRevisionService.List(ctx, deploymentRevisionListOpts)
if err != nil {
return nil, err
}
var revision *models.DeploymentRevision
if total > 0 {
revision = deploymentRevisions[0]
}
revisionSchema, err := ToDeploymentRevisionSchema(ctx, revision)
if err != nil {
return nil, err
}
return &schemasv2.DeploymentSchema{
ResourceSchema: schemas.ResourceSchema{
Name: deployment.Resource.Name,
Labels: []schemas.LabelItemSchema{},
ResourceType: deployment.GetResourceType(),
BaseSchema: schemas.BaseSchema{
Uid: deployment.Resource.BaseModel.GetUid(),
CreatedAt: deployment.Resource.BaseModel.CreatedAt,
UpdatedAt: deployment.Resource.BaseModel.UpdatedAt,
DeletedAt: nil, // Can assume that this is nil during creation
},
}, // Assuming ResourceSchema can be copied directly
Creator: creator,
Cluster: clusterSchema,
Status: deployment.Status,
URLs: []string{},
LatestRevision: revisionSchema,
KubeNamespace: deployment.KubeNamespace,
}, nil
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"context"
"fmt"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/mocks"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/services"
)
func ToDeploymentRevisionSchema(ctx context.Context, deploymentRevision *models.DeploymentRevision) (*schemas.DeploymentRevisionSchema, error) {
if deploymentRevision == nil {
return nil, nil
}
ss, err := ToDeploymentRevisionSchemas(ctx, []*models.DeploymentRevision{deploymentRevision})
if err != nil {
return nil, err
}
return ss[0], nil
}
func ToDeploymentRevisionSchemas(ctx context.Context, deploymentRevisions []*models.DeploymentRevision) ([]*schemas.DeploymentRevisionSchema, error) {
deploymentRevisionIds := make([]uint, 0, len(deploymentRevisions))
for _, deploymentRevision := range deploymentRevisions {
deploymentRevisionIds = append(deploymentRevisionIds, deploymentRevision.ID)
}
deploymentTargets, _, err := services.DeploymentTargetService.List(ctx, services.ListDeploymentTargetOption{
DeploymentRevisionIds: &deploymentRevisionIds,
})
if err != nil {
return nil, err
}
deploymentTargetsMapping := make(map[uint][]*models.DeploymentTarget)
for _, deploymentTarget := range deploymentTargets {
deploymentTargets, ok := deploymentTargetsMapping[deploymentTarget.DeploymentRevisionId]
if !ok {
deploymentTargets = make([]*models.DeploymentTarget, 0)
}
deploymentTargets = append(deploymentTargets, deploymentTarget)
deploymentTargetsMapping[deploymentTarget.DeploymentRevisionId] = deploymentTargets
}
resourceSchemasMap := make(map[string]*schemas.ResourceSchema, len(deploymentRevisions))
for _, revision := range deploymentRevisions {
resourceSchemasMap[revision.GetUid()] = ToResourceSchema(revisionToResource(revision), revision.GetResourceType())
}
res := make([]*schemas.DeploymentRevisionSchema, 0, len(deploymentRevisions))
for _, deploymentRevision := range deploymentRevisions {
creatorSchema := mocks.DefaultUser()
deploymentTargets := deploymentTargetsMapping[deploymentRevision.ID]
deploymentTargetSchemas, err := ToDeploymentTargetSchemas(ctx, deploymentTargets)
if err != nil {
return nil, err
}
resourceSchema, ok := resourceSchemasMap[deploymentRevision.GetUid()]
if !ok {
return nil, fmt.Errorf("resourceSchema not found for deploymentRevision %s", deploymentRevision.GetUid())
}
res = append(res, &schemas.DeploymentRevisionSchema{
ResourceSchema: *resourceSchema,
Creator: creatorSchema,
Status: deploymentRevision.Status,
Targets: deploymentTargetSchemas,
})
}
return res, nil
}
func revisionToResource(deploymentTarget *models.DeploymentRevision) *models.Resource {
return &models.Resource{
BaseModel: deploymentTarget.BaseModel,
Name: deploymentTarget.GetUid(),
}
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"context"
"fmt"
"strings"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/mocks"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/services"
"github.com/pkg/errors"
)
func ToDeploymentTargetSchema(ctx context.Context, deploymentTarget *models.DeploymentTarget) (*schemas.DeploymentTargetSchema, error) {
if deploymentTarget == nil {
return nil, nil
}
ss, err := ToDeploymentTargetSchemas(ctx, []*models.DeploymentTarget{deploymentTarget})
if err != nil {
return nil, err
}
return ss[0], nil
}
func ToDeploymentTargetSchemas(ctx context.Context, deploymentTargets []*models.DeploymentTarget) ([]*schemas.DeploymentTargetSchema, error) {
resourceSchemasMap := make(map[string]*schemas.ResourceSchema, len(deploymentTargets))
for _, target := range deploymentTargets {
resourceSchemasMap[target.GetUid()] = ToResourceSchema(targetToResource(target), target.GetResourceType())
}
res := make([]*schemas.DeploymentTargetSchema, 0, len(deploymentTargets))
for _, deploymentTarget := range deploymentTargets {
creatorSchema := mocks.DefaultUser()
compoundNimParts := strings.Split(deploymentTarget.CompoundNimVersionTag, ":")
if len(compoundNimParts) != 2 {
return nil, errors.Errorf("Invalid format for CompoundNIM version tag %s. Expected 2 parts got %d", deploymentTarget.CompoundNimVersionTag, len(compoundNimParts))
}
compoundNimVersionFullSchema, err := services.DatastoreService.GetCompoundNimVersion(ctx, compoundNimParts[0], compoundNimParts[1])
if err != nil {
compoundNimVersionFullSchema = nil // We shouldn't fail the request if this info is missing
}
resourceSchema, ok := resourceSchemasMap[deploymentTarget.GetUid()]
if !ok {
return nil, fmt.Errorf("resourceSchema not found for deploymentTarget %s", deploymentTarget.GetUid())
}
res = append(res, &schemas.DeploymentTargetSchema{
ResourceSchema: *resourceSchema,
DeploymentTargetTypeSchema: schemas.DeploymentTargetTypeSchema{
Type: "stable",
},
Creator: creatorSchema,
CompoundNimVersion: compoundNimVersionFullSchema,
Config: deploymentTarget.Config,
})
}
return res, nil
}
func targetToResource(deploymentTarget *models.DeploymentTarget) *models.Resource {
return &models.Resource{
BaseModel: deploymentTarget.BaseModel,
Name: deploymentTarget.GetUid(),
}
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package converters
import (
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
)
func ToResourceSchema(resource *models.Resource, resourceType schemas.ResourceType) *schemas.ResourceSchema {
return &schemas.ResourceSchema{
BaseSchema: ToBaseSchema(resource.BaseModel),
Name: resource.Name,
ResourceType: resourceType,
Labels: []schemas.LabelItemSchema{},
}
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package crds
import corev1 "k8s.io/api/core/v1"
type ExtraPodMetadata struct {
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
}
type ExtraPodSpec struct {
SchedulerName string `json:"schedulerName,omitempty"`
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Affinity *corev1.Affinity `json:"affinity,omitempty"`
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"`
Containers []corev1.Container `json:"containers,omitempty"`
ServiceAccountName string `json:"serviceAccountName,omitempty"`
}
type ResourceItem struct {
CPU string `json:"cpu,omitempty"`
Memory string `json:"memory,omitempty"`
GPU string `json:"gpu,omitempty"`
Custom map[string]string `json:"custom,omitempty"`
}
type Resources struct {
Requests *ResourceItem `json:"requests,omitempty"`
Limits *ResourceItem `json:"limits,omitempty"`
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package crds
import (
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
autoscalingv2beta2 "k8s.io/api/autoscaling/v2beta2"
corev1 "k8s.io/api/core/v1"
)
type Autoscaling struct {
MinReplicas int32 `json:"minReplicas"`
MaxReplicas int32 `json:"maxReplicas"`
Metrics []autoscalingv2beta2.MetricSpec `json:"metrics,omitempty"`
Behavior *autoscalingv2beta2.HorizontalPodAutoscalerBehavior `json:"behavior,omitempty"`
}
type CompoundNimVersionDeploymentIngressTLSSpec struct {
SecretName string `json:"secretName,omitempty"`
}
type CompoundNimVersionDeploymentIngressSpec struct {
Enabled bool `json:"enabled,omitempty"`
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
TLS *CompoundNimVersionDeploymentIngressTLSSpec `json:"tls,omitempty"`
}
type MonitorExporterMountSpec struct {
Path string `json:"path,omitempty"`
ReadOnly bool `json:"readOnly,omitempty"`
corev1.VolumeSource `json:",inline"`
}
type MonitorExporterSpec struct {
Enabled bool `json:"enabled,omitempty"`
Output string `json:"output,omitempty"`
Options map[string]string `json:"options,omitempty"`
StructureOptions []corev1.EnvVar `json:"structureOptions,omitempty"`
Mounts []MonitorExporterMountSpec `json:"mounts,omitempty"`
}
type CompoundNimDeploymentData struct {
Annotations map[string]string `json:"annotations,omitempty"`
Labels map[string]string `json:"labels,omitempty"`
CompoundNimVersion string `json:"compoundAINim"`
Resources schemas.Resources `json:"resources,omitempty"`
Autoscaling *Autoscaling `json:"autoscaling,omitempty"`
Envs []corev1.EnvVar `json:"envs,omitempty"`
ExternalServices map[string]schemas.ExternalService `json:"externalServices,omitempty"`
Ingress CompoundNimVersionDeploymentIngressSpec `json:"ingress,omitempty"`
MonitorExporter *MonitorExporterSpec `json:"monitorExporter,omitempty"`
ExtraPodMetadata *ExtraPodMetadata `json:"extraPodMetadata,omitempty"`
ExtraPodSpec *ExtraPodSpec `json:"extraPodSpec,omitempty"`
LivenessProbe *corev1.Probe `json:"livenessProbe,omitempty"`
ReadinessProbe *corev1.Probe `json:"readinessProbe,omitempty"`
}
type CompoundNimDeploymentConfigurationV1Alpha1 struct {
Data CompoundNimDeploymentData `json:"data"`
Version string `json:"version"`
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package crds
import (
"time"
corev1 "k8s.io/api/core/v1"
)
type CompoundNimRequestData struct {
CompoundNimVersionTag string `json:"bentoTag"`
DownloadURL string `json:"downloadUrl,omitempty"`
ImageBuildTimeout *time.Duration `json:"imageBuildTimeout,omitempty"`
ImageBuilderExtraPodMetadata *ExtraPodMetadata `json:"imageBuilderExtraPodMetadata,omitempty"`
ImageBuilderExtraPodSpec *ExtraPodSpec `json:"imageBuilderExtraPodSpec,omitempty"`
ImageBuilderExtraContainerEnv []corev1.EnvVar `json:"imageBuilderExtraContainerEnv,omitempty"`
ImageBuilderContainerResources *corev1.ResourceRequirements `json:"imageBuilderContainerResources,omitempty"`
DockerConfigJSONSecretName string `json:"dockerConfigJsonSecretName,omitempty"`
DownloaderContainerEnvFrom []corev1.EnvFromSource `json:"downloaderContainerEnvFrom,omitempty"`
}
type CompoundNimRequestConfigurationV1Alpha1 struct {
Data CompoundNimRequestData `json:"data,omitempty"`
Version string `json:"version"`
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package crds
var ApiVersion string = "nvidia.com/v1alpha1"
type CustomResourceType string
const (
CompoundNimRequest CustomResourceType = "CompoundAINimRequest"
CompoundNimDeployment CustomResourceType = "CompoundAINimDeployment"
)
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package database
import (
"context"
"fmt"
"sync"
"github.com/rs/zerolog/log"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/common/utils"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/models"
"gorm.io/driver/postgres"
"gorm.io/gorm"
"gorm.io/gorm/schema"
)
var db *gorm.DB
type databaseUtil struct{}
var DatabaseUtil = databaseUtil{}
type DbCtxKeyType string
const DbSessionKey DbCtxKeyType = "session"
var openDbOnce = sync.Once{}
const (
DB_USER = "DB_USER"
DB_PASSWORD = "DB_PASSWORD"
DB_HOST = "DB_HOST"
DB_NAME = "DB_NAME"
DB_PORT = "DB_PORT"
)
func SetupDB() {
openDbOnce.Do(func() {
var err error
db, err = openDBConnection()
if err != nil {
log.Fatal().Msgf("Could not connect to Postgres database! %s", err.Error())
}
db.AutoMigrate(&models.Cluster{})
db.AutoMigrate(&models.Deployment{})
db.AutoMigrate(&models.DeploymentRevision{})
db.AutoMigrate(&models.DeploymentTarget{})
db.AutoMigrate(&models.CompoundComponent{})
db.Exec("CREATE UNIQUE INDEX uk_cluster_orgId_name ON cluster (organization_id, name);")
db.Exec("CREATE UNIQUE INDEX uk_deployment_clusterId_name ON deployment (cluster_id, name);")
})
}
func openDBConnection() (*gorm.DB, error) {
dbUser, err := utils.MustGetEnv(DB_USER)
if err != nil {
log.Error().Msgf("Failed to get %s from env: %s", DB_USER, err.Error())
return nil, err
}
dbPass, err := utils.MustGetEnv(DB_PASSWORD)
if err != nil {
log.Error().Msgf("Failed to get %s from env: %s", DB_PASSWORD, err.Error())
return nil, err
}
dbHost, err := utils.MustGetEnv(DB_HOST)
if err != nil {
log.Error().Msgf("Failed to get %s from env: %s", DB_HOST, err.Error())
return nil, err
}
dbPort, err := utils.MustGetEnv(DB_PORT)
if err != nil {
log.Error().Msgf("Failed to get %s from env: %s", DB_PORT, err.Error())
return nil, err
}
dbName, err := utils.MustGetEnv(DB_NAME)
if err != nil {
log.Error().Msgf("Failed to get %s from env: %s", DB_NAME, err.Error())
return nil, err
}
uri := fmt.Sprintf("postgres://%s:%s@%s:%s/%s",
dbUser,
dbPass,
dbHost,
dbPort,
dbName,
)
log.Info().Msgf("Connecting to Postgres")
db, err := gorm.Open(postgres.Open(uri), &gorm.Config{
NamingStrategy: schema.NamingStrategy{SingularTable: true},
PrepareStmt: false,
})
if err != nil {
return nil, err
}
log.Info().Msgf("Successfully connected to Postgres")
return db, nil
}
func (d *databaseUtil) GetDB(ctx context.Context) *gorm.DB {
return db.WithContext(ctx)
}
func (d *databaseUtil) GetDBSession(ctx context.Context) *gorm.DB {
session := ctx.Value(DbSessionKey)
if session != nil {
db := session.(*gorm.DB)
return db
}
return d.GetDB(ctx)
}
func (d *databaseUtil) StartTransaction(ctx context.Context) (*gorm.DB, context.Context, func(error), error) {
session := ctx.Value(DbSessionKey)
if session != nil {
db_ := session.(*gorm.DB)
return db_, ctx, func(err error) {}, nil
}
db := d.GetDB(ctx)
tx := db.Begin()
if tx.Error != nil {
return nil, ctx, func(err error) {}, tx.Error
}
ctx = context.WithValue(ctx, DbSessionKey, tx)
return tx, ctx, func(err error) {
select {
case <-ctx.Done():
return
default:
}
// nolint: gocritic
if p := recover(); p != nil {
tx.Rollback()
panic(p)
} else if err != nil {
tx.Rollback()
} else {
tx.Commit()
}
}, nil
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import "github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/runtime"
const (
port = 8181
)
func main() {
runtime.Runtime.StartServer(port)
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package mocks
import (
"time"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
)
var mockedUid = "nvid1a11-1234-5678-9abc-def012345678"
func DefaultUser() *schemas.UserSchema {
return &schemas.UserSchema{
ResourceSchema: schemas.ResourceSchema{
BaseSchema: schemas.BaseSchema{
Uid: mockedUid,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
},
Name: "nvidia-user",
},
FirstName: "Compound",
LastName: "AI",
Email: "compoundai@nvidia.com",
}
}
func DefaultOrg() *schemas.OrganizationSchema {
return &schemas.OrganizationSchema{
ResourceSchema: schemas.ResourceSchema{
BaseSchema: schemas.BaseSchema{
Uid: mockedUid,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
},
Name: "nvidia-org",
ResourceType: schemas.ResourceTypeOrganization,
Labels: []schemas.LabelItemSchema{},
},
Description: "nvidia-org-desc",
}
}
func DefaultOrgMember() *schemas.OrganizationMemberSchema {
return &schemas.OrganizationMemberSchema{
BaseSchema: schemas.BaseSchema{
Uid: mockedUid,
CreatedAt: time.Now(),
UpdatedAt: time.Now(),
DeletedAt: nil,
},
Role: schemas.MemberRoleAdmin,
Creator: DefaultUser(),
User: *DefaultUser(),
Organization: *DefaultOrg(),
}
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
type ClusterAssociate struct {
ClusterId uint `json:"cluster_id"`
AssociatedClusterCache *Cluster `gorm:"foreignkey:ClusterId"`
}
type DeploymentAssociate struct {
DeploymentId uint `json:"deployment_id"`
AssociatedDeploymentCache *Deployment `gorm:"foreignkey:DeploymentId;constraint:OnDelete:CASCADE;"`
}
type DeploymentRevisionAssociate struct {
DeploymentRevisionId uint `json:"deployment_revision_id"`
AssociatedDeploymentRevisionCache *DeploymentRevision `gorm:"foreignkey:DeploymentRevisionId;constraint:OnDelete:CASCADE;"`
}
type CompoundNimVersionAssociate struct {
CompoundNimVersionId string `json:"compound_nim_version_id"`
CompoundNimVersionTag string `json:"compound_nim_version_tag"`
}
type DmsAssociate struct {
KubeRequestId string
KubeDeploymentId string
}
type OrganizationAssociate struct {
OrganizationId string `json:"organization_id"` // Set via http headers
}
type CreatorAssociate struct {
UserId string `json:"user_id"` // Set via http headers
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
type IBaseModel interface {
GetId() uint
GetUid() string
GetCreatedAt() time.Time
GetUpdatedAt() time.Time
GetDeletedAt() gorm.DeletedAt
}
type BaseModel struct {
gorm.Model
Uid uuid.UUID `json:"uid" gorm:"type:uuid;default:gen_random_uuid()"`
}
func (b *BaseModel) GetId() uint {
return b.ID
}
func (b *BaseModel) GetUid() string {
return b.Uid.String()
}
func (b *BaseModel) GetCreatedAt() time.Time {
return b.CreatedAt
}
func (b *BaseModel) GetUpdatedAt() time.Time {
return b.UpdatedAt
}
func (b *BaseModel) GetDeletedAt() gorm.DeletedAt {
return b.DeletedAt
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
type Cluster struct {
Resource
CreatorAssociate
OrganizationAssociate
Description string `json:"description"`
KubeConfig string `json:"kube_config"`
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
import (
"time"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
)
type CompoundComponent struct {
Resource
ClusterAssociate
Version string `json:"version"`
KubeNamespace string `json:"kube_namespace"`
Description string `json:"description"`
Manifest *schemas.CompoundComponentManifestSchema `json:"manifest" type:"jsonb"`
LatestInstalledAt *time.Time `json:"latest_installed_at"`
LatestHeartbeatAt *time.Time `json:"latest_heartbeat_at"`
}
func (d *CompoundComponent) GetResourceType() schemas.ResourceType {
return schemas.ResourceTypeCompoundAIComponent
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
import (
"time"
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
)
type Deployment struct {
Resource
ClusterAssociate
CreatorAssociate
VisibilityLevel
Description string `json:"description"`
Status schemas.DeploymentStatus `json:"status"`
StatusSyncingAt *time.Time `json:"status_syncing_at"`
StatusUpdatedAt *time.Time `json:"status_updated_at"`
KubeDeployToken string `json:"kube_deploy_token"`
KubeNamespace string `json:"kube_namespace"`
}
func (d *Deployment) GetResourceType() schemas.ResourceType {
return schemas.ResourceTypeDeployment
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
type DeployOption struct {
Force bool
}
/*
* SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package models
import (
"github.com/dynemo-ai/dynemo/deploy/compoundai/api-server/api/schemas"
)
type DeploymentRevision struct {
BaseModel
CreatorAssociate
DeploymentAssociate
Status schemas.DeploymentRevisionStatus `json:"status"`
}
func (s *DeploymentRevision) GetName() string {
return s.Uid.String()
}
func (s *DeploymentRevision) GetResourceType() schemas.ResourceType {
return schemas.ResourceTypeDeploymentRevision
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment