Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
OpenDAS
dynamo
Commits
1e8b2866
Unverified
Commit
1e8b2866
authored
May 07, 2025
by
hhzhang16
Committed by
GitHub
May 07, 2025
Browse files
feat: add ingress to graph deployments (#960)
parent
a590d103
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
372 additions
and
24 deletions
+372
-24
deploy/cloud/helm/deploy.sh
deploy/cloud/helm/deploy.sh
+3
-1
deploy/cloud/helm/dynamo-platform-values.yaml
deploy/cloud/helm/dynamo-platform-values.yaml
+1
-0
deploy/cloud/helm/network-config-wizard.sh
deploy/cloud/helm/network-config-wizard.sh
+9
-1
deploy/cloud/helm/platform/components/operator/templates/deployment.yaml
...lm/platform/components/operator/templates/deployment.yaml
+3
-0
deploy/cloud/operator/cmd/main.go
deploy/cloud/operator/cmd/main.go
+5
-1
deploy/cloud/operator/internal/consts/consts.go
deploy/cloud/operator/internal/consts/consts.go
+1
-1
deploy/cloud/operator/internal/controller/dynamocomponentdeployment_controller.go
...ternal/controller/dynamocomponentdeployment_controller.go
+3
-3
deploy/cloud/operator/internal/controller/dynamographdeployment_controller.go
...r/internal/controller/dynamographdeployment_controller.go
+4
-1
deploy/cloud/operator/internal/controller_common/predicate.go
...oy/cloud/operator/internal/controller_common/predicate.go
+2
-0
deploy/cloud/operator/internal/dynamo/graph.go
deploy/cloud/operator/internal/dynamo/graph.go
+12
-10
deploy/cloud/operator/internal/dynamo/graph_test.go
deploy/cloud/operator/internal/dynamo/graph_test.go
+290
-1
deploy/helm/chart/templates/deployment.yaml
deploy/helm/chart/templates/deployment.yaml
+1
-1
deploy/sdk/src/dynamo/sdk/cli/serve_dynamo.py
deploy/sdk/src/dynamo/sdk/cli/serve_dynamo.py
+4
-4
deploy/sdk/src/dynamo/sdk/lib/service.py
deploy/sdk/src/dynamo/sdk/lib/service.py
+11
-0
deploy/sdk/src/dynamo/sdk/lib/utils.py
deploy/sdk/src/dynamo/sdk/lib/utils.py
+23
-0
No files found.
deploy/cloud/helm/deploy.sh
View file @
1e8b2866
...
@@ -36,6 +36,7 @@ export INGRESS_ENABLED="${INGRESS_ENABLED:=false}"
...
@@ -36,6 +36,7 @@ export INGRESS_ENABLED="${INGRESS_ENABLED:=false}"
export
ISTIO_ENABLED
=
"
${
ISTIO_ENABLED
:
=false
}
"
export
ISTIO_ENABLED
=
"
${
ISTIO_ENABLED
:
=false
}
"
export
ISTIO_GATEWAY
=
"
${
ISTIO_GATEWAY
:
=istio-system/istio-ingressgateway
}
"
export
ISTIO_GATEWAY
=
"
${
ISTIO_GATEWAY
:
=istio-system/istio-ingressgateway
}
"
export
INGRESS_CLASS
=
"
${
INGRESS_CLASS
:
=nginx
}
"
export
INGRESS_CLASS
=
"
${
INGRESS_CLASS
:
=nginx
}
"
export
VIRTUAL_SERVICE_SUPPORTS_HTTPS
=
"
${
VIRTUAL_SERVICE_SUPPORTS_HTTPS
:
=false
}
"
# Add command line options
# Add command line options
INTERACTIVE
=
false
INTERACTIVE
=
false
...
@@ -140,8 +141,9 @@ echo "ISTIO_ENABLED: $ISTIO_ENABLED"
...
@@ -140,8 +141,9 @@ echo "ISTIO_ENABLED: $ISTIO_ENABLED"
echo
"INGRESS_CLASS:
$INGRESS_CLASS
"
echo
"INGRESS_CLASS:
$INGRESS_CLASS
"
echo
"ISTIO_GATEWAY:
$ISTIO_GATEWAY
"
echo
"ISTIO_GATEWAY:
$ISTIO_GATEWAY
"
echo
"DYNAMO_INGRESS_SUFFIX:
$DYNAMO_INGRESS_SUFFIX
"
echo
"DYNAMO_INGRESS_SUFFIX:
$DYNAMO_INGRESS_SUFFIX
"
echo
"VIRTUAL_SERVICE_SUPPORTS_HTTPS:
$VIRTUAL_SERVICE_SUPPORTS_HTTPS
"
envsubst
'${NAMESPACE} ${RELEASE_NAME} ${DOCKER_USERNAME} ${DOCKER_PASSWORD} ${DOCKER_SERVER} ${IMAGE_TAG} ${DYNAMO_INGRESS_SUFFIX} ${PIPELINES_DOCKER_SERVER} ${PIPELINES_DOCKER_USERNAME} ${PIPELINES_DOCKER_PASSWORD} ${DOCKER_SECRET_NAME} ${INGRESS_ENABLED} ${ISTIO_ENABLED} ${INGRESS_CLASS} ${ISTIO_GATEWAY}'
< dynamo-platform-values.yaml
>
generated-values.yaml
envsubst
'${NAMESPACE} ${RELEASE_NAME} ${DOCKER_USERNAME} ${DOCKER_PASSWORD} ${DOCKER_SERVER} ${IMAGE_TAG} ${DYNAMO_INGRESS_SUFFIX} ${PIPELINES_DOCKER_SERVER} ${PIPELINES_DOCKER_USERNAME} ${PIPELINES_DOCKER_PASSWORD} ${DOCKER_SECRET_NAME} ${INGRESS_ENABLED} ${ISTIO_ENABLED} ${INGRESS_CLASS} ${ISTIO_GATEWAY}
${VIRTUAL_SERVICE_SUPPORTS_HTTPS}
'
< dynamo-platform-values.yaml
>
generated-values.yaml
echo
"generated file contents:"
echo
"generated file contents:"
cat
generated-values.yaml
cat
generated-values.yaml
...
...
deploy/cloud/helm/dynamo-platform-values.yaml
View file @
1e8b2866
...
@@ -40,6 +40,7 @@ dynamo-operator:
...
@@ -40,6 +40,7 @@ dynamo-operator:
username
:
${PIPELINES_DOCKER_USERNAME}
username
:
${PIPELINES_DOCKER_USERNAME}
password
:
${PIPELINES_DOCKER_PASSWORD}
password
:
${PIPELINES_DOCKER_PASSWORD}
imageBuildEngine
:
buildkit
imageBuildEngine
:
buildkit
virtualServiceSupportsHTTPS
:
${VIRTUAL_SERVICE_SUPPORTS_HTTPS}
dynamo-api-store
:
dynamo-api-store
:
namespaceRestriction
:
namespaceRestriction
:
...
...
deploy/cloud/helm/network-config-wizard.sh
View file @
1e8b2866
...
@@ -253,6 +253,14 @@ if [ "$CONFIG_TYPE" = "istio" ]; then
...
@@ -253,6 +253,14 @@ if [ "$CONFIG_TYPE" = "istio" ]; then
fi
fi
fi
fi
# Ask if the Istio gateway supports HTTPS
read
-p
"Does your Istio gateway support HTTPS? (y/n): "
SUPPORTS_HTTPS_REPLY
if
[[
"
$SUPPORTS_HTTPS_REPLY
"
=
~ ^[Yy]
$
]]
;
then
export
VIRTUAL_SERVICE_SUPPORTS_HTTPS
=
true
else
export
VIRTUAL_SERVICE_SUPPORTS_HTTPS
=
false
fi
elif
[
"
$CONFIG_TYPE
"
=
"ingress"
]
;
then
elif
[
"
$CONFIG_TYPE
"
=
"ingress"
]
;
then
echo
-e
"
${
CYAN
}
Configuring Ingress settings...
${
NC
}
"
echo
-e
"
${
CYAN
}
Configuring Ingress settings...
${
NC
}
"
...
@@ -332,4 +340,4 @@ elif [ "$CONFIG_TYPE" = "ingress" ]; then
...
@@ -332,4 +340,4 @@ elif [ "$CONFIG_TYPE" = "ingress" ]; then
fi
fi
print_header
"Wizard Complete"
print_header
"Wizard Complete"
echo
-e
"
${
GREEN
}
Network configuration complete!
${
NC
}
"
echo
-e
"
${
GREEN
}
Network configuration complete!
${
NC
}
"
\ No newline at end of file
deploy/cloud/helm/platform/components/operator/templates/deployment.yaml
View file @
1e8b2866
...
@@ -86,6 +86,9 @@ spec:
...
@@ -86,6 +86,9 @@ spec:
{{
- if .Values.dynamo.ingressHostSuffix
}}
{{
- if .Values.dynamo.ingressHostSuffix
}}
-
--ingress-host-suffix={{ .Values.dynamo.ingressHostSuffix }}
-
--ingress-host-suffix={{ .Values.dynamo.ingressHostSuffix }}
{{
- end
}}
{{
- end
}}
{{
- if .Values.dynamo.virtualServiceSupportsHTTPS
}}
-
--virtual-service-supports-https={{ .Values.dynamo.virtualServiceSupportsHTTPS }}
{{
- end
}}
command
:
command
:
-
/manager
-
/manager
...
...
deploy/cloud/operator/cmd/main.go
View file @
1e8b2866
...
@@ -71,6 +71,7 @@ func main() {
...
@@ -71,6 +71,7 @@ func main() {
var
natsAddr
string
var
natsAddr
string
var
etcdAddr
string
var
etcdAddr
string
var
istioVirtualServiceGateway
string
var
istioVirtualServiceGateway
string
var
virtualServiceSupportsHTTPS
bool
var
ingressControllerClassName
string
var
ingressControllerClassName
string
var
ingressControllerTLSSecretName
string
var
ingressControllerTLSSecretName
string
var
ingressHostSuffix
string
var
ingressHostSuffix
string
...
@@ -91,6 +92,8 @@ func main() {
...
@@ -91,6 +92,8 @@ func main() {
flag
.
StringVar
(
&
etcdAddr
,
"etcdAddr"
,
""
,
"address of the etcd server"
)
flag
.
StringVar
(
&
etcdAddr
,
"etcdAddr"
,
""
,
"address of the etcd server"
)
flag
.
StringVar
(
&
istioVirtualServiceGateway
,
"istio-virtual-service-gateway"
,
""
,
flag
.
StringVar
(
&
istioVirtualServiceGateway
,
"istio-virtual-service-gateway"
,
""
,
"The name of the istio virtual service gateway to use"
)
"The name of the istio virtual service gateway to use"
)
flag
.
BoolVar
(
&
virtualServiceSupportsHTTPS
,
"virtual-service-supports-https"
,
false
,
"If set, assume VirtualService endpoints are HTTPS"
)
flag
.
StringVar
(
&
ingressControllerClassName
,
"ingress-controller-class-name"
,
""
,
flag
.
StringVar
(
&
ingressControllerClassName
,
"ingress-controller-class-name"
,
""
,
"The name of the ingress controller class to use"
)
"The name of the ingress controller class to use"
)
flag
.
StringVar
(
&
ingressControllerTLSSecretName
,
"ingress-controller-tls-secret-name"
,
""
,
flag
.
StringVar
(
&
ingressControllerTLSSecretName
,
"ingress-controller-tls-secret-name"
,
""
,
...
@@ -106,7 +109,8 @@ func main() {
...
@@ -106,7 +109,8 @@ func main() {
utilruntime
.
Must
(
istioclientsetscheme
.
AddToScheme
(
scheme
))
utilruntime
.
Must
(
istioclientsetscheme
.
AddToScheme
(
scheme
))
ctrlConfig
:=
commonController
.
Config
{
ctrlConfig
:=
commonController
.
Config
{
RestrictedNamespace
:
restrictedNamespace
,
RestrictedNamespace
:
restrictedNamespace
,
VirtualServiceSupportsHTTPS
:
virtualServiceSupportsHTTPS
,
}
}
ctrl
.
SetLogger
(
zap
.
New
(
zap
.
UseFlagOptions
(
&
opts
)))
ctrl
.
SetLogger
(
zap
.
New
(
zap
.
UseFlagOptions
(
&
opts
)))
...
...
deploy/cloud/operator/internal/consts/consts.go
View file @
1e8b2866
...
@@ -24,7 +24,7 @@ const (
...
@@ -24,7 +24,7 @@ const (
// nolint: gosec
// nolint: gosec
EnvApiStoreApiToken
=
"API_STORE_API_TOKEN"
EnvApiStoreApiToken
=
"API_STORE_API_TOKEN"
EnvDynamoServicePort
=
"PORT"
EnvDynamoServicePort
=
"
DYNAMO_
PORT"
EnvDockerRegistryServer
=
"DOCKER_REGISTRY_SERVER"
EnvDockerRegistryServer
=
"DOCKER_REGISTRY_SERVER"
EnvDockerRegistrySecret
=
"DOCKER_REGISTRY_SECRET_NAME"
EnvDockerRegistrySecret
=
"DOCKER_REGISTRY_SECRET_NAME"
...
...
deploy/cloud/operator/internal/controller/dynamocomponentdeployment_controller.go
View file @
1e8b2866
...
@@ -740,7 +740,7 @@ func (r *DynamoComponentDeploymentReconciler) generateIngress(ctx context.Contex
...
@@ -740,7 +740,7 @@ func (r *DynamoComponentDeploymentReconciler) generateIngress(ctx context.Contex
Service
:
&
networkingv1
.
IngressServiceBackend
{
Service
:
&
networkingv1
.
IngressServiceBackend
{
Name
:
opt
.
dynamoComponentDeployment
.
Name
,
Name
:
opt
.
dynamoComponentDeployment
.
Name
,
Port
:
networkingv1
.
ServiceBackendPort
{
Port
:
networkingv1
.
ServiceBackendPort
{
Number
:
3000
,
Number
:
commonconsts
.
DynamoServicePort
,
},
},
},
},
},
},
...
@@ -800,7 +800,7 @@ func (r *DynamoComponentDeploymentReconciler) generateVirtualService(ctx context
...
@@ -800,7 +800,7 @@ func (r *DynamoComponentDeploymentReconciler) generateVirtualService(ctx context
Destination
:
&
istioNetworking
.
Destination
{
Destination
:
&
istioNetworking
.
Destination
{
Host
:
opt
.
dynamoComponentDeployment
.
Name
,
Host
:
opt
.
dynamoComponentDeployment
.
Name
,
Port
:
&
istioNetworking
.
PortSelector
{
Port
:
&
istioNetworking
.
PortSelector
{
Number
:
3000
,
Number
:
commonconsts
.
DynamoServicePort
,
},
},
},
},
},
},
...
@@ -1121,7 +1121,7 @@ func (r *DynamoComponentDeploymentReconciler) generatePodTemplateSpec(ctx contex
...
@@ -1121,7 +1121,7 @@ func (r *DynamoComponentDeploymentReconciler) generatePodTemplateSpec(ctx contex
// todo : remove this line when https://github.com/ai-dynamo/dynamo/issues/345 is fixed
// todo : remove this line when https://github.com/ai-dynamo/dynamo/issues/345 is fixed
enableDependsOption
:=
false
enableDependsOption
:=
false
if
len
(
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
)
>
0
&&
enableDependsOption
{
if
len
(
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
)
>
0
&&
enableDependsOption
{
serviceSuffix
:=
fmt
.
Sprintf
(
"%s.svc.cluster.local:
3000
"
,
opt
.
dynamoComponentDeployment
.
Namespace
)
serviceSuffix
:=
fmt
.
Sprintf
(
"%s.svc.cluster.local:
%d
"
,
opt
.
dynamoComponentDeployment
.
Namespace
,
containerPort
)
keys
:=
make
([]
string
,
0
,
len
(
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
))
keys
:=
make
([]
string
,
0
,
len
(
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
))
for
key
:=
range
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
{
for
key
:=
range
opt
.
dynamoComponentDeployment
.
Spec
.
ExternalServices
{
...
...
deploy/cloud/operator/internal/controller/dynamographdeployment_controller.go
View file @
1e8b2866
...
@@ -143,7 +143,7 @@ func (r *DynamoGraphDeploymentReconciler) Reconcile(ctx context.Context, req ctr
...
@@ -143,7 +143,7 @@ func (r *DynamoGraphDeploymentReconciler) Reconcile(ctx context.Context, req ctr
}
}
}
}
if
deployment
.
Spec
.
Ingress
.
Enabled
{
if
deployment
.
Spec
.
Ingress
.
Enabled
{
dynamoDeployment
.
SetEndpointStatus
(
(
r
.
isEndpointSecured
()
)
,
getIngressHost
(
deployment
.
Spec
.
Ingress
))
dynamoDeployment
.
SetEndpointStatus
(
r
.
isEndpointSecured
(),
getIngressHost
(
deployment
.
Spec
.
Ingress
))
}
}
}
}
...
@@ -238,6 +238,9 @@ func (r *DynamoGraphDeploymentReconciler) generateDefaultIngressSpec(dynamoDeplo
...
@@ -238,6 +238,9 @@ func (r *DynamoGraphDeploymentReconciler) generateDefaultIngressSpec(dynamoDeplo
}
}
func
(
r
*
DynamoGraphDeploymentReconciler
)
isEndpointSecured
()
bool
{
func
(
r
*
DynamoGraphDeploymentReconciler
)
isEndpointSecured
()
bool
{
if
r
.
VirtualServiceGateway
!=
""
&&
r
.
Config
.
VirtualServiceSupportsHTTPS
{
return
true
}
return
r
.
IngressControllerTLSSecret
!=
""
return
r
.
IngressControllerTLSSecret
!=
""
}
}
...
...
deploy/cloud/operator/internal/controller_common/predicate.go
View file @
1e8b2866
...
@@ -30,6 +30,8 @@ import (
...
@@ -30,6 +30,8 @@ import (
type
Config
struct
{
type
Config
struct
{
// Enable resources filtering, only the resources belonging to the given namespace will be handled.
// Enable resources filtering, only the resources belonging to the given namespace will be handled.
RestrictedNamespace
string
RestrictedNamespace
string
// If true, assume VirtualService endpoints are HTTPS
VirtualServiceSupportsHTTPS
bool
}
}
func
EphemeralDeploymentEventFilter
(
config
Config
)
predicate
.
Predicate
{
func
EphemeralDeploymentEventFilter
(
config
Config
)
predicate
.
Predicate
{
...
...
deploy/cloud/operator/internal/dynamo/graph.go
View file @
1e8b2866
...
@@ -66,10 +66,12 @@ type Autoscaling struct {
...
@@ -66,10 +66,12 @@ type Autoscaling struct {
}
}
type
Config
struct
{
type
Config
struct
{
Dynamo
*
DynamoConfig
`yaml:"dynamo,omitempty"`
Dynamo
*
DynamoConfig
`yaml:"dynamo,omitempty"`
Resources
*
Resources
`yaml:"resources,omitempty"`
Resources
*
Resources
`yaml:"resources,omitempty"`
Traffic
*
Traffic
`yaml:"traffic,omitempty"`
Traffic
*
Traffic
`yaml:"traffic,omitempty"`
Autoscaling
*
Autoscaling
`yaml:"autoscaling,omitempty"`
Autoscaling
*
Autoscaling
`yaml:"autoscaling,omitempty"`
HttpExposed
bool
`yaml:"http_exposed,omitempty"`
ApiEndpoints
[]
string
`yaml:"api_endpoints,omitempty"`
}
}
type
ServiceConfig
struct
{
type
ServiceConfig
struct
{
...
@@ -250,13 +252,13 @@ func GenerateDynamoComponentsDeployments(ctx context.Context, parentDynamoGraphD
...
@@ -250,13 +252,13 @@ func GenerateDynamoComponentsDeployments(ctx context.Context, parentDynamoGraphD
deployment
.
Spec
.
DynamoNamespace
=
&
dynamoNamespace
deployment
.
Spec
.
DynamoNamespace
=
&
dynamoNamespace
dynamoServices
[
service
.
Name
]
=
fmt
.
Sprintf
(
"%s/%s"
,
service
.
Config
.
Dynamo
.
Name
,
dynamoNamespace
)
dynamoServices
[
service
.
Name
]
=
fmt
.
Sprintf
(
"%s/%s"
,
service
.
Config
.
Dynamo
.
Name
,
dynamoNamespace
)
labels
[
commonconsts
.
KubeLabelDynamoNamespace
]
=
dynamoNamespace
labels
[
commonconsts
.
KubeLabelDynamoNamespace
]
=
dynamoNamespace
}
else
{
// dynamo is not enabled
if
config
.
EntryService
==
service
.
Name
{
// enable virtual service for the entry service
deployment
.
Spec
.
Ingress
=
*
ingressSpec
}
}
}
// Check http_exposed independently
if
config
.
EntryService
==
service
.
Name
&&
service
.
Config
.
HttpExposed
{
deployment
.
Spec
.
Ingress
=
*
ingressSpec
// TODO (maybe): add paths to IngressSpec
}
if
service
.
Config
.
Resources
!=
nil
{
if
service
.
Config
.
Resources
!=
nil
{
deployment
.
Spec
.
Resources
=
&
compounaiCommon
.
Resources
{
deployment
.
Spec
.
Resources
=
&
compounaiCommon
.
Resources
{
Requests
:
&
compounaiCommon
.
ResourceItem
{
Requests
:
&
compounaiCommon
.
ResourceItem
{
...
...
deploy/cloud/operator/internal/dynamo/graph_test.go
View file @
1e8b2866
...
@@ -182,6 +182,7 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -182,6 +182,7 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
Name
:
"service1"
,
Name
:
"service1"
,
Dependencies
:
[]
map
[
string
]
string
{{
"service"
:
"service2"
}},
Dependencies
:
[]
map
[
string
]
string
{{
"service"
:
"service2"
}},
Config
:
Config
{
Config
:
Config
{
HttpExposed
:
true
,
Resources
:
&
Resources
{
Resources
:
&
Resources
{
CPU
:
"1"
,
CPU
:
"1"
,
Memory
:
"1Gi"
,
Memory
:
"1Gi"
,
...
@@ -260,6 +261,10 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -260,6 +261,10 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
},
},
},
},
},
},
Status
:
v1alpha1
.
DynamoComponentDeploymentStatus
{
Conditions
:
nil
,
PodSelector
:
nil
,
},
},
},
"service2"
:
{
"service2"
:
{
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
...
@@ -283,6 +288,18 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -283,6 +288,18 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
commonconsts
.
KubeLabelDynamoComponent
:
"service2"
,
commonconsts
.
KubeLabelDynamoComponent
:
"service2"
,
commonconsts
.
KubeLabelDynamoNamespace
:
"default"
,
commonconsts
.
KubeLabelDynamoNamespace
:
"default"
,
},
},
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
false
,
Host
:
""
,
UseVirtualService
:
false
,
VirtualServiceGateway
:
nil
,
HostPrefix
:
nil
,
Annotations
:
nil
,
Labels
:
nil
,
TLS
:
nil
,
HostSuffix
:
nil
,
IngressControllerClassName
:
nil
,
},
},
},
},
},
},
},
...
@@ -309,6 +326,7 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -309,6 +326,7 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
Name
:
"service1"
,
Name
:
"service1"
,
Dependencies
:
[]
map
[
string
]
string
{{
"service"
:
"service2"
}},
Dependencies
:
[]
map
[
string
]
string
{{
"service"
:
"service2"
}},
Config
:
Config
{
Config
:
Config
{
HttpExposed
:
true
,
Resources
:
&
Resources
{
Resources
:
&
Resources
{
CPU
:
"1"
,
CPU
:
"1"
,
Memory
:
"1Gi"
,
Memory
:
"1Gi"
,
...
@@ -374,12 +392,27 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -374,12 +392,27 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
DeploymentSelectorValue
:
"service2/dynamo-test-dynamographdeployment"
,
DeploymentSelectorValue
:
"service2/dynamo-test-dynamographdeployment"
,
},
},
},
},
Ingress
:
v1alpha1
.
IngressSpec
{},
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
false
,
Host
:
""
,
UseVirtualService
:
false
,
VirtualServiceGateway
:
nil
,
HostPrefix
:
nil
,
Annotations
:
nil
,
Labels
:
nil
,
TLS
:
nil
,
HostSuffix
:
nil
,
IngressControllerClassName
:
nil
,
},
Labels
:
map
[
string
]
string
{
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
},
},
},
},
},
Status
:
v1alpha1
.
DynamoComponentDeploymentStatus
{
Conditions
:
nil
,
PodSelector
:
nil
,
},
},
},
"service2"
:
{
"service2"
:
{
ObjectMeta
:
metav1
.
ObjectMeta
{
ObjectMeta
:
metav1
.
ObjectMeta
{
...
@@ -403,6 +436,18 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -403,6 +436,18 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
commonconsts
.
KubeLabelDynamoComponent
:
"service2"
,
commonconsts
.
KubeLabelDynamoComponent
:
"service2"
,
commonconsts
.
KubeLabelDynamoNamespace
:
"dynamo-test-dynamographdeployment"
,
commonconsts
.
KubeLabelDynamoNamespace
:
"dynamo-test-dynamographdeployment"
,
},
},
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
false
,
Host
:
""
,
UseVirtualService
:
false
,
VirtualServiceGateway
:
nil
,
HostPrefix
:
nil
,
Annotations
:
nil
,
Labels
:
nil
,
TLS
:
nil
,
HostSuffix
:
nil
,
IngressControllerClassName
:
nil
,
},
},
},
},
},
},
},
...
@@ -462,6 +507,250 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
...
@@ -462,6 +507,250 @@ func TestGenerateDynamoComponentsDeployments(t *testing.T) {
},
},
wantErr
:
true
,
wantErr
:
true
,
},
},
{
name
:
"Test GenerateDynamoComponentsDeployments ingress enabled by default"
,
args
:
args
{
parentDynamoGraphDeployment
:
&
v1alpha1
.
DynamoGraphDeployment
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment"
,
Namespace
:
"default"
,
},
Spec
:
v1alpha1
.
DynamoGraphDeploymentSpec
{
DynamoGraph
:
"dynamocomponent:ac4e234"
,
},
},
config
:
&
DynamoGraphConfig
{
DynamoTag
:
"dynamocomponent:MyServiceIngressEnabled"
,
EntryService
:
"service1"
,
Services
:
[]
ServiceConfig
{
{
Name
:
"service1"
,
Config
:
Config
{
HttpExposed
:
true
,
},
},
},
},
ingressSpec
:
&
v1alpha1
.
IngressSpec
{
Enabled
:
true
,
Host
:
"test-dynamographdeployment"
,
},
},
want
:
map
[
string
]
*
v1alpha1
.
DynamoComponentDeployment
{
"service1"
:
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment-service1"
,
Namespace
:
"default"
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
},
Spec
:
v1alpha1
.
DynamoComponentDeploymentSpec
{
DynamoComponent
:
"dynamocomponent:ac4e234"
,
DynamoTag
:
"dynamocomponent:MyServiceIngressEnabled"
,
DynamoComponentDeploymentSharedSpec
:
v1alpha1
.
DynamoComponentDeploymentSharedSpec
{
Annotations
:
nil
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
ServiceName
:
"service1"
,
DynamoNamespace
:
nil
,
Resources
:
nil
,
Autoscaling
:
&
v1alpha1
.
Autoscaling
{
Enabled
:
false
,
MinReplicas
:
0
,
MaxReplicas
:
0
,
Behavior
:
nil
,
Metrics
:
nil
,
},
Envs
:
nil
,
EnvFromSecret
:
nil
,
PVC
:
nil
,
RunMode
:
nil
,
ExternalServices
:
nil
,
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
true
,
Host
:
"test-dynamographdeployment"
,
},
ExtraPodMetadata
:
nil
,
ExtraPodSpec
:
nil
,
LivenessProbe
:
nil
,
ReadinessProbe
:
nil
,
Replicas
:
nil
,
},
},
Status
:
v1alpha1
.
DynamoComponentDeploymentStatus
{
Conditions
:
nil
,
PodSelector
:
nil
,
},
},
},
wantErr
:
false
,
},
{
name
:
"Test GenerateDynamoComponentsDeployments ingress explicitly disabled"
,
args
:
args
{
parentDynamoGraphDeployment
:
&
v1alpha1
.
DynamoGraphDeployment
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment"
,
Namespace
:
"default"
,
},
Spec
:
v1alpha1
.
DynamoGraphDeploymentSpec
{
DynamoGraph
:
"dynamocomponent:ac4e234"
,
},
},
config
:
&
DynamoGraphConfig
{
DynamoTag
:
"dynamocomponent:MyServiceIngressDisabled"
,
Services
:
[]
ServiceConfig
{
{
Name
:
"service1"
,
Config
:
Config
{},
},
},
},
ingressSpec
:
&
v1alpha1
.
IngressSpec
{
Enabled
:
false
,
},
},
want
:
map
[
string
]
*
v1alpha1
.
DynamoComponentDeployment
{
"service1"
:
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment-service1"
,
Namespace
:
"default"
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
},
Spec
:
v1alpha1
.
DynamoComponentDeploymentSpec
{
DynamoComponent
:
"dynamocomponent:ac4e234"
,
DynamoTag
:
"dynamocomponent:MyServiceIngressDisabled"
,
DynamoComponentDeploymentSharedSpec
:
v1alpha1
.
DynamoComponentDeploymentSharedSpec
{
Annotations
:
nil
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
ServiceName
:
"service1"
,
DynamoNamespace
:
nil
,
Resources
:
nil
,
Autoscaling
:
&
v1alpha1
.
Autoscaling
{
Enabled
:
false
,
MinReplicas
:
0
,
MaxReplicas
:
0
,
Behavior
:
nil
,
Metrics
:
nil
,
},
Envs
:
nil
,
EnvFromSecret
:
nil
,
PVC
:
nil
,
RunMode
:
nil
,
ExternalServices
:
nil
,
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
false
,
Host
:
""
,
UseVirtualService
:
false
,
VirtualServiceGateway
:
nil
,
HostPrefix
:
nil
,
Annotations
:
nil
,
Labels
:
nil
,
TLS
:
nil
,
HostSuffix
:
nil
,
IngressControllerClassName
:
nil
,
},
ExtraPodMetadata
:
nil
,
ExtraPodSpec
:
nil
,
LivenessProbe
:
nil
,
ReadinessProbe
:
nil
,
Replicas
:
nil
,
},
},
Status
:
v1alpha1
.
DynamoComponentDeploymentStatus
{
Conditions
:
nil
,
PodSelector
:
nil
,
},
},
},
wantErr
:
false
,
},
{
name
:
"Test GenerateDynamoComponentsDeployments ingress custom host"
,
args
:
args
{
parentDynamoGraphDeployment
:
&
v1alpha1
.
DynamoGraphDeployment
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment"
,
Namespace
:
"default"
,
},
Spec
:
v1alpha1
.
DynamoGraphDeploymentSpec
{
DynamoGraph
:
"dynamocomponent:ac4e234"
,
},
},
config
:
&
DynamoGraphConfig
{
DynamoTag
:
"dynamocomponent:MyServiceIngressCustomHost"
,
EntryService
:
"service1"
,
Services
:
[]
ServiceConfig
{
{
Name
:
"service1"
,
Config
:
Config
{
HttpExposed
:
true
,
},
},
},
},
ingressSpec
:
&
v1alpha1
.
IngressSpec
{
Enabled
:
true
,
Host
:
"custom-host"
,
},
},
want
:
map
[
string
]
*
v1alpha1
.
DynamoComponentDeployment
{
"service1"
:
{
ObjectMeta
:
metav1
.
ObjectMeta
{
Name
:
"test-dynamographdeployment-service1"
,
Namespace
:
"default"
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
},
Spec
:
v1alpha1
.
DynamoComponentDeploymentSpec
{
DynamoComponent
:
"dynamocomponent:ac4e234"
,
DynamoTag
:
"dynamocomponent:MyServiceIngressCustomHost"
,
DynamoComponentDeploymentSharedSpec
:
v1alpha1
.
DynamoComponentDeploymentSharedSpec
{
Annotations
:
nil
,
Labels
:
map
[
string
]
string
{
commonconsts
.
KubeLabelDynamoComponent
:
"service1"
,
},
ServiceName
:
"service1"
,
DynamoNamespace
:
nil
,
Resources
:
nil
,
Autoscaling
:
&
v1alpha1
.
Autoscaling
{
Enabled
:
false
,
MinReplicas
:
0
,
MaxReplicas
:
0
,
Behavior
:
nil
,
Metrics
:
nil
,
},
Envs
:
nil
,
EnvFromSecret
:
nil
,
PVC
:
nil
,
RunMode
:
nil
,
ExternalServices
:
nil
,
Ingress
:
v1alpha1
.
IngressSpec
{
Enabled
:
true
,
Host
:
"custom-host"
,
},
ExtraPodMetadata
:
nil
,
ExtraPodSpec
:
nil
,
LivenessProbe
:
nil
,
ReadinessProbe
:
nil
,
Replicas
:
nil
,
},
},
Status
:
v1alpha1
.
DynamoComponentDeploymentStatus
{
Conditions
:
nil
,
PodSelector
:
nil
,
},
},
},
wantErr
:
false
,
},
}
}
for
_
,
tt
:=
range
tests
{
for
_
,
tt
:=
range
tests
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
t
.
Run
(
tt
.
name
,
func
(
t
*
testing
.
T
)
{
...
...
deploy/helm/chart/templates/deployment.yaml
View file @
1e8b2866
...
@@ -86,7 +86,7 @@ spec:
...
@@ -86,7 +86,7 @@ spec:
-
name
:
WORKERS
-
name
:
WORKERS
value
:
"
{{
.config.workers
}}"
value
:
"
{{
.config.workers
}}"
{{
- end
}}
{{
- end
}}
-
name
:
PORT
-
name
:
DYNAMO_
PORT
value
:
"
3000"
value
:
"
3000"
{{
- if $.Values.natsAddr
}}
{{
- if $.Values.natsAddr
}}
-
name
:
NATS_SERVER
-
name
:
NATS_SERVER
...
...
deploy/sdk/src/dynamo/sdk/cli/serve_dynamo.py
View file @
1e8b2866
...
@@ -37,6 +37,7 @@ from dynamo.runtime import DistributedRuntime, dynamo_endpoint, dynamo_worker
...
@@ -37,6 +37,7 @@ from dynamo.runtime import DistributedRuntime, dynamo_endpoint, dynamo_worker
from
dynamo.sdk
import
dynamo_context
from
dynamo.sdk
import
dynamo_context
from
dynamo.sdk.cli.utils
import
append_dynamo_state
from
dynamo.sdk.cli.utils
import
append_dynamo_state
from
dynamo.sdk.lib.service
import
LinkedServices
from
dynamo.sdk.lib.service
import
LinkedServices
from
dynamo.sdk.lib.utils
import
get_host_port
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -313,16 +314,15 @@ def main(
...
@@ -313,16 +314,15 @@ def main(
if
added_routes
:
if
added_routes
:
# Configure uvicorn with graceful shutdown
# Configure uvicorn with graceful shutdown
# get the port from PORT env var or use 8000 as default
host
,
port
=
get_host_port
()
port
=
int
(
os
.
environ
.
get
(
"PORT"
,
8000
))
config
=
uvicorn
.
Config
(
config
=
uvicorn
.
Config
(
service
.
app
,
host
=
"0.0.0.0"
,
port
=
port
,
log_level
=
"info"
service
.
app
,
host
=
host
,
port
=
port
,
log_level
=
"info"
)
)
server
=
uvicorn
.
Server
(
config
)
server
=
uvicorn
.
Server
(
config
)
# Start the server with graceful shutdown handling
# Start the server with graceful shutdown handling
logger
.
info
(
logger
.
info
(
f
"Starting FastAPI server on
0.0.0.0:
{
port
}
with routes:
{
added_routes
}
"
f
"Starting FastAPI server on
{
config
.
host
}
:
{
config
.
port
}
with routes:
{
added_routes
}
"
)
)
server
.
run
()
server
.
run
()
else
:
else
:
...
...
deploy/sdk/src/dynamo/sdk/lib/service.py
View file @
1e8b2866
...
@@ -133,10 +133,21 @@ class DynamoService(Service[T]):
...
@@ -133,10 +133,21 @@ class DynamoService(Service[T]):
# Register Dynamo endpoints
# Register Dynamo endpoints
self
.
_dynamo_endpoints
:
Dict
[
str
,
DynamoEndpoint
]
=
{}
self
.
_dynamo_endpoints
:
Dict
[
str
,
DynamoEndpoint
]
=
{}
self
.
_api_endpoints
:
list
[
str
]
=
[]
for
field
in
dir
(
inner
):
for
field
in
dir
(
inner
):
value
=
getattr
(
inner
,
field
)
value
=
getattr
(
inner
,
field
)
if
isinstance
(
value
,
DynamoEndpoint
):
if
isinstance
(
value
,
DynamoEndpoint
):
self
.
_dynamo_endpoints
[
value
.
name
]
=
value
self
.
_dynamo_endpoints
[
value
.
name
]
=
value
if
getattr
(
value
,
"is_api"
,
False
):
# Ensure endpoint path starts with '/'
path
=
(
value
.
name
if
value
.
name
.
startswith
(
"/"
)
else
f
"/
{
value
.
name
}
"
)
self
.
_api_endpoints
.
append
(
path
)
# If any API endpoints exist, mark service as HTTP-exposed and list endpoints
if
self
.
_api_endpoints
:
self
.
config
[
"http_exposed"
]
=
True
self
.
config
[
"api_endpoints"
]
=
self
.
_api_endpoints
.
copy
()
self
.
_linked_services
:
List
[
DynamoService
]
=
[]
# Track linked services
self
.
_linked_services
:
List
[
DynamoService
]
=
[]
# Track linked services
...
...
deploy/sdk/src/dynamo/sdk/lib/utils.py
0 → 100644
View file @
1e8b2866
# 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.
import
os
def
get_host_port
():
"""Gets host and port from environment variables. Defaults to 0.0.0.0:8000."""
port
=
int
(
os
.
environ
.
get
(
"DYNAMO_PORT"
,
8000
))
host
=
os
.
environ
.
get
(
"DYNAMO_HOST"
,
"0.0.0.0"
)
return
host
,
port
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment