Skip to content

Conversation

@paaragon
Copy link
Contributor

@paaragon paaragon commented Dec 3, 2025

Summary

This PR refactors the way we access to the environment variables centralizing them into one single class (one for the client and one for the gateway)

Details and comments

@paaragon paaragon requested a review from a team as a code owner December 3, 2025 10:22
@paaragon paaragon marked this pull request as draft December 3, 2025 10:22
@paaragon paaragon marked this pull request as ready for review December 3, 2025 10:43
Copy link
Contributor

@avilches avilches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally, not sure if creating one single PR for the gateway and the client, which are two completely separate projects in the same repo, is the best idea. It makes the PRs unnecessary larger. Just to be clear, I'm not asking you to make another PR for the client, I'm just mentioning it for the next ones...

Comment on lines 1 to 133
"""Constants for environment variable names."""

# Version and Debug
VERSION = "VERSION"
DEBUG = "DEBUG"

# Security
DJANGO_SECRET_KEY = "DJANGO_SECRET_KEY"
ALLOWED_HOSTS = "ALLOWED_HOSTS"
CSRF_TRUSTED_ORIGINS = "CSRF_TRUSTED_ORIGINS"
CORS_ALLOWED_ORIGIN_REGEXES = "CORS_ALLOWED_ORIGIN_REGEXES"

# Database
DATABASE_NAME = "DATABASE_NAME"
DATABASE_USER = "DATABASE_USER"
DATABASE_PASSWORD = "DATABASE_PASSWORD"
DATABASE_HOST = "DATABASE_HOST"
DATABASE_PORT = "DATABASE_PORT"

# Authentication
SETTINGS_AUTH_MECHANISM = "SETTINGS_AUTH_MECHANISM"
SETTINGS_AUTH_MOCK_TOKEN = "SETTINGS_AUTH_MOCK_TOKEN"
SETTINGS_AUTH_MOCKPROVIDER_REGISTRY = "SETTINGS_AUTH_MOCKPROVIDER_REGISTRY"
QUANTUM_PLATFORM_API_BASE_URL = "QUANTUM_PLATFORM_API_BASE_URL"
SETTINGS_TOKEN_AUTH_VERIFICATION_FIELD = "SETTINGS_TOKEN_AUTH_VERIFICATION_FIELD"

# Site
SITE_HOST = "SITE_HOST"

# Resource Limits
LIMITS_JOBS_PER_USER = "LIMITS_JOBS_PER_USER"
LIMITS_MAX_CLUSTERS = "LIMITS_MAX_CLUSTERS"
LIMITS_MAX_GPU_CLUSTERS = "LIMITS_MAX_GPU_CLUSTERS"
LIMITS_CPU_PER_TASK = "LIMITS_CPU_PER_TASK"
LIMITS_GPU_PER_TASK = "LIMITS_GPU_PER_TASK"
LIMITS_MEMORY_PER_TASK = "LIMITS_MEMORY_PER_TASK"
MAINTENANCE = "MAINTENANCE"

# Ray Cluster Configuration
RAY_KUBERAY_NAMESPACE = "RAY_KUBERAY_NAMESPACE"
RAY_CLUSTER_MODE_LOCAL = "RAY_CLUSTER_MODE_LOCAL"
RAY_CLUSTER_MODE_LOCAL_HOST = "RAY_CLUSTER_MODE_LOCAL_HOST"
RAY_NODE_IMAGE = "RAY_NODE_IMAGE"
RAY_CLUSTER_WORKER_REPLICAS = "RAY_CLUSTER_WORKER_REPLICAS"
RAY_CLUSTER_WORKER_REPLICAS_MAX = "RAY_CLUSTER_WORKER_REPLICAS_MAX"
RAY_CLUSTER_WORKER_MIN_REPLICAS = "RAY_CLUSTER_WORKER_MIN_REPLICAS"
RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX = "RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX"
RAY_CLUSTER_WORKER_MAX_REPLICAS = "RAY_CLUSTER_WORKER_MAX_REPLICAS"
RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX = "RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX"
RAY_CLUSTER_WORKER_AUTO_SCALING = "RAY_CLUSTER_WORKER_AUTO_SCALING"
RAY_CLUSTER_MAX_READINESS_TIME = "RAY_CLUSTER_MAX_READINESS_TIME"
RAY_SETUP_MAX_RETRIES = "RAY_SETUP_MAX_RETRIES"
RAY_CLUSTER_NO_DELETE_ON_COMPLETE = "RAY_CLUSTER_NO_DELETE_ON_COMPLETE"
RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL = "RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL"
RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL = "RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL"

# Program Configuration
PROGRAM_TIMEOUT = "PROGRAM_TIMEOUT"
GATEWAY_ALLOWLIST_CONFIG = "GATEWAY_ALLOWLIST_CONFIG"
GATEWAY_GPU_JOBS_CONFIG = "GATEWAY_GPU_JOBS_CONFIG"
GATEWAY_DYNAMIC_DEPENDENCIES = "GATEWAY_DYNAMIC_DEPENDENCIES"

# IBM Cloud and Qiskit
QISKIT_IBM_URL = "QISKIT_IBM_URL"
IQP_QCON_API_BASE_URL = "IQP_QCON_API_BASE_URL"
IAM_IBM_CLOUD_BASE_URL = "IAM_IBM_CLOUD_BASE_URL"
RESOURCE_CONTROLLER_IBM_CLOUD_BASE_URL = "RESOURCE_CONTROLLER_IBM_CLOUD_BASE_URL"
RESOURCE_PLANS_ID_ALLOWED = "RESOURCE_PLANS_ID_ALLOWED"

# Custom Image
CUSTOM_IMAGE_PACKAGE_NAME = "CUSTOM_IMAGE_PACKAGE_NAME"
CUSTOM_IMAGE_PACKAGE_PATH = "CUSTOM_IMAGE_PACKAGE_PATH"

# Functions
FUNCTIONS_LOGS_SIZE_LIMIT = "FUNCTIONS_LOGS_SIZE_LIMIT"

# OpenTelemetry
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
OTEL_EXPORTER_OTLP_TRACES_INSECURE = "OTEL_EXPORTER_OTLP_TRACES_INSECURE"
OTEL_ENABLED = "OTEL_ENABLED"

# Default values
VERSION_DEFAULT = "UNKNOWN"
DEBUG_DEFAULT = "1"
DJANGO_SECRET_KEY_DEFAULT = (
"django-insecure-&)i3b5aue*#-i6k9i-03qm(d!0h&662lbhj12on_*gimn3x8p7"
)
ALLOWED_HOSTS_DEFAULT = "*"
CSRF_TRUSTED_ORIGINS_DEFAULT = "http://localhost"
CORS_ALLOWED_ORIGIN_REGEXES_DEFAULT = "http://localhost"
DATABASE_NAME_DEFAULT = "serverlessdb"
DATABASE_USER_DEFAULT = "serverlessuser"
DATABASE_PASSWORD_DEFAULT = "serverlesspassword"
DATABASE_HOST_DEFAULT = "localhost"
DATABASE_PORT_DEFAULT = "5432"
SETTINGS_AUTH_MECHANISM_DEFAULT = "default"
SETTINGS_AUTH_MOCK_TOKEN_DEFAULT = "awesome_token"
SITE_HOST_DEFAULT = "http://localhost:8000"
LIMITS_JOBS_PER_USER_DEFAULT = "2"
LIMITS_MAX_CLUSTERS_DEFAULT = "6"
LIMITS_MAX_GPU_CLUSTERS_DEFAULT = "1"
LIMITS_CPU_PER_TASK_DEFAULT = "4"
LIMITS_GPU_PER_TASK_DEFAULT = "1"
LIMITS_MEMORY_PER_TASK_DEFAULT = "8"
RAY_KUBERAY_NAMESPACE_DEFAULT = "qiskit-serverless"
RAY_CLUSTER_MODE_LOCAL_DEFAULT = "0"
RAY_CLUSTER_MODE_LOCAL_HOST_DEFAULT = "http://localhost:8265"
RAY_NODE_IMAGE_DEFAULT = "icr.io/quantum-public/qiskit-serverless/ray-node:0.27.1"
RAY_CLUSTER_WORKER_REPLICAS_DEFAULT = "1"
RAY_CLUSTER_WORKER_REPLICAS_MAX_DEFAULT = "5"
RAY_CLUSTER_WORKER_MIN_REPLICAS_DEFAULT = "1"
RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX_DEFAULT = "2"
RAY_CLUSTER_WORKER_MAX_REPLICAS_DEFAULT = "4"
RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX_DEFAULT = "10"
RAY_CLUSTER_MAX_READINESS_TIME_DEFAULT = "120"
RAY_SETUP_MAX_RETRIES_DEFAULT = "30"
RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL_DEFAULT = (
"ibm-cloud.kubernetes.io/worker-pool-name: default"
)
RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL_DEFAULT = (
"ibm-cloud.kubernetes.io/worker-pool-name: gpu-workers"
)
PROGRAM_TIMEOUT_DEFAULT = "14"
GATEWAY_ALLOWLIST_CONFIG_DEFAULT = "api/v1/allowlist.json"
GATEWAY_GPU_JOBS_CONFIG_DEFAULT = "api/v1/gpu-jobs.json"
GATEWAY_DYNAMIC_DEPENDENCIES_DEFAULT = "requirements-dynamic-dependencies.txt"
QISKIT_IBM_URL_DEFAULT = "https://cloud.ibm.com"
CUSTOM_IMAGE_PACKAGE_NAME_DEFAULT = "runner"
CUSTOM_IMAGE_PACKAGE_PATH_DEFAULT = "/runner"
FUNCTIONS_LOGS_SIZE_LIMIT_DEFAULT = "50"
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_DEFAULT = "http://otel-collector:4317"
OTEL_EXPORTER_OTLP_TRACES_INSECURE_DEFAULT = "0"
OTEL_ENABLED_DEFAULT = "0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we really want this kind of file now, when we are using a Config class which is the only place that's actually using these constants? I mean, it makes sense to have all these constants and their defaults if we are going to use os.environ.get() calls anywhere in our code, so that if a variable name changes or a default is changed, we only have to do it in one place (the constant.py file). But if all accesses to these variables are made from Config, which is the new source of truth, what's the point of adding this level of indirection? I would just hardcode both the variables and the defaults within each method. That way, it's the only place where these values are hardcoded, and it's easier to see and modify.

Comment on lines 1 to 133
"""Constants for environment variable names."""

# Version and Debug
VERSION = "VERSION"
DEBUG = "DEBUG"

# Security
DJANGO_SECRET_KEY = "DJANGO_SECRET_KEY"
ALLOWED_HOSTS = "ALLOWED_HOSTS"
CSRF_TRUSTED_ORIGINS = "CSRF_TRUSTED_ORIGINS"
CORS_ALLOWED_ORIGIN_REGEXES = "CORS_ALLOWED_ORIGIN_REGEXES"

# Database
DATABASE_NAME = "DATABASE_NAME"
DATABASE_USER = "DATABASE_USER"
DATABASE_PASSWORD = "DATABASE_PASSWORD"
DATABASE_HOST = "DATABASE_HOST"
DATABASE_PORT = "DATABASE_PORT"

# Authentication
SETTINGS_AUTH_MECHANISM = "SETTINGS_AUTH_MECHANISM"
SETTINGS_AUTH_MOCK_TOKEN = "SETTINGS_AUTH_MOCK_TOKEN"
SETTINGS_AUTH_MOCKPROVIDER_REGISTRY = "SETTINGS_AUTH_MOCKPROVIDER_REGISTRY"
QUANTUM_PLATFORM_API_BASE_URL = "QUANTUM_PLATFORM_API_BASE_URL"
SETTINGS_TOKEN_AUTH_VERIFICATION_FIELD = "SETTINGS_TOKEN_AUTH_VERIFICATION_FIELD"

# Site
SITE_HOST = "SITE_HOST"

# Resource Limits
LIMITS_JOBS_PER_USER = "LIMITS_JOBS_PER_USER"
LIMITS_MAX_CLUSTERS = "LIMITS_MAX_CLUSTERS"
LIMITS_MAX_GPU_CLUSTERS = "LIMITS_MAX_GPU_CLUSTERS"
LIMITS_CPU_PER_TASK = "LIMITS_CPU_PER_TASK"
LIMITS_GPU_PER_TASK = "LIMITS_GPU_PER_TASK"
LIMITS_MEMORY_PER_TASK = "LIMITS_MEMORY_PER_TASK"
MAINTENANCE = "MAINTENANCE"

# Ray Cluster Configuration
RAY_KUBERAY_NAMESPACE = "RAY_KUBERAY_NAMESPACE"
RAY_CLUSTER_MODE_LOCAL = "RAY_CLUSTER_MODE_LOCAL"
RAY_CLUSTER_MODE_LOCAL_HOST = "RAY_CLUSTER_MODE_LOCAL_HOST"
RAY_NODE_IMAGE = "RAY_NODE_IMAGE"
RAY_CLUSTER_WORKER_REPLICAS = "RAY_CLUSTER_WORKER_REPLICAS"
RAY_CLUSTER_WORKER_REPLICAS_MAX = "RAY_CLUSTER_WORKER_REPLICAS_MAX"
RAY_CLUSTER_WORKER_MIN_REPLICAS = "RAY_CLUSTER_WORKER_MIN_REPLICAS"
RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX = "RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX"
RAY_CLUSTER_WORKER_MAX_REPLICAS = "RAY_CLUSTER_WORKER_MAX_REPLICAS"
RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX = "RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX"
RAY_CLUSTER_WORKER_AUTO_SCALING = "RAY_CLUSTER_WORKER_AUTO_SCALING"
RAY_CLUSTER_MAX_READINESS_TIME = "RAY_CLUSTER_MAX_READINESS_TIME"
RAY_SETUP_MAX_RETRIES = "RAY_SETUP_MAX_RETRIES"
RAY_CLUSTER_NO_DELETE_ON_COMPLETE = "RAY_CLUSTER_NO_DELETE_ON_COMPLETE"
RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL = "RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL"
RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL = "RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL"

# Program Configuration
PROGRAM_TIMEOUT = "PROGRAM_TIMEOUT"
GATEWAY_ALLOWLIST_CONFIG = "GATEWAY_ALLOWLIST_CONFIG"
GATEWAY_GPU_JOBS_CONFIG = "GATEWAY_GPU_JOBS_CONFIG"
GATEWAY_DYNAMIC_DEPENDENCIES = "GATEWAY_DYNAMIC_DEPENDENCIES"

# IBM Cloud and Qiskit
QISKIT_IBM_URL = "QISKIT_IBM_URL"
IQP_QCON_API_BASE_URL = "IQP_QCON_API_BASE_URL"
IAM_IBM_CLOUD_BASE_URL = "IAM_IBM_CLOUD_BASE_URL"
RESOURCE_CONTROLLER_IBM_CLOUD_BASE_URL = "RESOURCE_CONTROLLER_IBM_CLOUD_BASE_URL"
RESOURCE_PLANS_ID_ALLOWED = "RESOURCE_PLANS_ID_ALLOWED"

# Custom Image
CUSTOM_IMAGE_PACKAGE_NAME = "CUSTOM_IMAGE_PACKAGE_NAME"
CUSTOM_IMAGE_PACKAGE_PATH = "CUSTOM_IMAGE_PACKAGE_PATH"

# Functions
FUNCTIONS_LOGS_SIZE_LIMIT = "FUNCTIONS_LOGS_SIZE_LIMIT"

# OpenTelemetry
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT = "OTEL_EXPORTER_OTLP_TRACES_ENDPOINT"
OTEL_EXPORTER_OTLP_TRACES_INSECURE = "OTEL_EXPORTER_OTLP_TRACES_INSECURE"
OTEL_ENABLED = "OTEL_ENABLED"

# Default values
VERSION_DEFAULT = "UNKNOWN"
DEBUG_DEFAULT = "1"
DJANGO_SECRET_KEY_DEFAULT = (
"django-insecure-&)i3b5aue*#-i6k9i-03qm(d!0h&662lbhj12on_*gimn3x8p7"
)
ALLOWED_HOSTS_DEFAULT = "*"
CSRF_TRUSTED_ORIGINS_DEFAULT = "http://localhost"
CORS_ALLOWED_ORIGIN_REGEXES_DEFAULT = "http://localhost"
DATABASE_NAME_DEFAULT = "serverlessdb"
DATABASE_USER_DEFAULT = "serverlessuser"
DATABASE_PASSWORD_DEFAULT = "serverlesspassword"
DATABASE_HOST_DEFAULT = "localhost"
DATABASE_PORT_DEFAULT = "5432"
SETTINGS_AUTH_MECHANISM_DEFAULT = "default"
SETTINGS_AUTH_MOCK_TOKEN_DEFAULT = "awesome_token"
SITE_HOST_DEFAULT = "http://localhost:8000"
LIMITS_JOBS_PER_USER_DEFAULT = "2"
LIMITS_MAX_CLUSTERS_DEFAULT = "6"
LIMITS_MAX_GPU_CLUSTERS_DEFAULT = "1"
LIMITS_CPU_PER_TASK_DEFAULT = "4"
LIMITS_GPU_PER_TASK_DEFAULT = "1"
LIMITS_MEMORY_PER_TASK_DEFAULT = "8"
RAY_KUBERAY_NAMESPACE_DEFAULT = "qiskit-serverless"
RAY_CLUSTER_MODE_LOCAL_DEFAULT = "0"
RAY_CLUSTER_MODE_LOCAL_HOST_DEFAULT = "http://localhost:8265"
RAY_NODE_IMAGE_DEFAULT = "icr.io/quantum-public/qiskit-serverless/ray-node:0.27.1"
RAY_CLUSTER_WORKER_REPLICAS_DEFAULT = "1"
RAY_CLUSTER_WORKER_REPLICAS_MAX_DEFAULT = "5"
RAY_CLUSTER_WORKER_MIN_REPLICAS_DEFAULT = "1"
RAY_CLUSTER_WORKER_MIN_REPLICAS_MAX_DEFAULT = "2"
RAY_CLUSTER_WORKER_MAX_REPLICAS_DEFAULT = "4"
RAY_CLUSTER_WORKER_MAX_REPLICAS_MAX_DEFAULT = "10"
RAY_CLUSTER_MAX_READINESS_TIME_DEFAULT = "120"
RAY_SETUP_MAX_RETRIES_DEFAULT = "30"
RAY_CLUSTER_CPU_NODE_SELECTOR_LABEL_DEFAULT = (
"ibm-cloud.kubernetes.io/worker-pool-name: default"
)
RAY_CLUSTER_GPU_NODE_SELECTOR_LABEL_DEFAULT = (
"ibm-cloud.kubernetes.io/worker-pool-name: gpu-workers"
)
PROGRAM_TIMEOUT_DEFAULT = "14"
GATEWAY_ALLOWLIST_CONFIG_DEFAULT = "api/v1/allowlist.json"
GATEWAY_GPU_JOBS_CONFIG_DEFAULT = "api/v1/gpu-jobs.json"
GATEWAY_DYNAMIC_DEPENDENCIES_DEFAULT = "requirements-dynamic-dependencies.txt"
QISKIT_IBM_URL_DEFAULT = "https://cloud.ibm.com"
CUSTOM_IMAGE_PACKAGE_NAME_DEFAULT = "runner"
CUSTOM_IMAGE_PACKAGE_PATH_DEFAULT = "/runner"
FUNCTIONS_LOGS_SIZE_LIMIT_DEFAULT = "50"
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT_DEFAULT = "http://otel-collector:4317"
OTEL_EXPORTER_OTLP_TRACES_INSECURE_DEFAULT = "0"
OTEL_ENABLED_DEFAULT = "0"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same approach with the settings.py class, why do we create a Config class when we only use it once during bootstrap to assign its values to a bunch of constants that need to be imported? I would remove the settings.py and only use the new Config class, which should be the de facto source of truth for the config/settings (config = settings, right?).

@Tansito
Copy link
Member

Tansito commented Dec 3, 2025

In fact, if I remember correctly the proposal was done by @korgan00 but only for the client. I think Django is just managing this correctly. I wouldn't change the gateway.

@korgan00
Copy link
Contributor

korgan00 commented Dec 3, 2025

I proposed this for client but the reasons also apply for gateway I think. The main reason is not access to envars anywhere in the code having a default value in each call and unify everything in one class or somewhere, I dont know if there is a django way to improve this.

@Tansito
Copy link
Member

Tansito commented Dec 3, 2025

But you access to the env_vars only in the settings.py. Through the code you use:

from django.conf import settings
....
settings.LIMITS_JOBS_PER_USER

I don't think there is nothing wrong with this approach. Or I don't think so at least.

This is what we were trying to fix in the client: https://github.com/Qiskit/qiskit-serverless/pull/1790/files#diff-fdc3aef5e1a595990db1b71f1ca195cbdfc589291d1f23c213c5fe735c8b0611L127

@avilches
Copy link
Contributor

avilches commented Dec 3, 2025

But you access to the env_vars only in the settings.py. Through the code you use:

from django.conf import settings
....
settings.LIMITS_JOBS_PER_USER

I don't think there is nothing wrong with this approach. Or I don't think so at least.

This is what we were trying to fix in the client: https://github.com/Qiskit/qiskit-serverless/pull/1790/files#diff-fdc3aef5e1a595990db1b71f1ca195cbdfc589291d1f23c213c5fe735c8b0611L127

The main goal of the issue is to define a single source of truth (settings, Config, or whatever) instead of reading environment variables scattered throughout the codebase. To achieve this, I'm fine with having a Config class with methods, or just a bunch of constants in the settings.py. But we can't have it both at the same time...

settings.py

CUSTOM_IMAGE_PACKAGE_NAME = Config.custom_image_package_name()

which calls to config.py:

def custom_image_package_name(cls) -> str:
        """Get custom image package name."""
        return os.environ.get(
            CUSTOM_IMAGE_PACKAGE_NAME, CUSTOM_IMAGE_PACKAGE_NAME_DEFAULT
        )

which requires constants.py

CUSTOM_IMAGE_PACKAGE_NAME = "CUSTOM_IMAGE_PACKAGE_NAME"
CUSTOM_IMAGE_PACKAGE_NAME_DEFAULT = "CUSTOM_IMAGE_PACKAGE_NAME_DEFAULT"

I suggest having only settings, only Config, but no both. And remove the constants. That will make easier for us: just one single place to use and one single place to add/update variables.

Regarding constants in settings vs class Config, I think class is superior because:

  • It requires importing the Class, not every constant needed in your class.
  • The Config class has methods that are executed every time they are needed, not only in the bootstrap. We can play with this: read from different sources (database, LaunchDarkly, AppConfig), cache them or do whatever we need.

@Tansito
Copy link
Member

Tansito commented Dec 3, 2025

For the purpose of this PR as it was created focusing on the client my proposal is to create an issue for the gateway and have the final discussion there. WDYT @avilches , @korgan00 , @paaragon . I think everyone agrees at least that this PR should be simplified and contains only the changes in the client.

@paaragon
Copy link
Contributor Author

paaragon commented Dec 4, 2025

Hi @Tansito @avilches @korgan00

I have removed the changes in the gateway

@korgan00
Copy link
Contributor

korgan00 commented Dec 5, 2025

Agree with @avilches . We can just remove the constants file now and use literals in the Config file.

@paaragon
Copy link
Contributor Author

paaragon commented Dec 5, 2025

Agree with @avilches . We can just remove the constants file now and use literals in the Config file.

Ok, this is what I did: I have changed the config file to use literals instead of constants. Also, I have removed from the constants.py file all the variables that weren't being used

…t-serverless into fix-env-config-to-variables
@classmethod
def gateway_token(cls) -> Optional[str]:
"""Get gateway provider token."""
return os.environ.get("ENV_GATEWAY_PROVIDER_TOKEN", None)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why was the "provider" part removed from the gateway host, token and version? I mean, why not gateway_provider_token, gateway_provider_version and gateway_provider_host instead... is the "provider" word redundant in the gateway?

Comment on lines +57 to +64
def gateway_version(cls) -> str:
"""Get gateway provider version."""
return os.environ.get("ENV_GATEWAY_PROVIDER_VERSION", "v1")

@classmethod
def gateway_provider_version(cls) -> str:
"""Get gateway provider version (alias for gateway_version)."""
return cls.gateway_version()
Copy link
Contributor

@avilches avilches Dec 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why have two methods (where one calls the other) instead of just one?

Comment on lines 3 to 20
# telemetry
OT_PROGRAM_NAME = "OT_PROGRAM_NAME"
OT_PROGRAM_NAME_DEFAULT = "unnamed_execution"
OT_JAEGER_HOST = "OT_JAEGER_HOST"
OT_JAEGER_HOST_KEY = "OT_JAEGER_HOST_KEY"
OT_JAEGER_PORT_KEY = "OT_JAEGER_PORT_KEY"
OT_TRACEPARENT_ID_KEY = "OT_TRACEPARENT_ID_KEY"
OT_INSECURE = "OT_INSECURE"
OT_ENABLED = "OT_ENABLED"
OT_RAY_TRACER = "OT_RAY_TRACER"
OT_SPAN_DEFAULT_NAME = "entrypoint"
OT_ATTRIBUTE_PREFIX = "qs"
OT_LABEL_CALL_LOCATION = "qs.location"

# request timeout
REQUESTS_TIMEOUT_DEFAULT: int = 30
REQUESTS_TIMEOUT_OVERRIDE = "REQUESTS_TIMEOUT_OVERRIDE"
REQUESTS_STREAMING_TIMEOUT_DEFAULT: int = 60
REQUESTS_STREAMING_TIMEOUT_OVERRIDE = "REQUESTS_TIMEOUT_OVERRIDE"

# gateway
ENV_GATEWAY_PROVIDER_HOST = "ENV_GATEWAY_PROVIDER_HOST"
ENV_GATEWAY_PROVIDER_VERSION = "ENV_GATEWAY_PROVIDER_VERSION"
ENV_GATEWAY_PROVIDER_TOKEN = "ENV_GATEWAY_PROVIDER_TOKEN"
GATEWAY_PROVIDER_VERSION_DEFAULT = "v1"

# auth
ENV_JOB_GATEWAY_TOKEN = "ENV_JOB_GATEWAY_TOKEN"
ENV_JOB_GATEWAY_INSTANCE = "ENV_JOB_GATEWAY_INSTANCE"
ENV_JOB_GATEWAY_HOST = "ENV_JOB_GATEWAY_HOST"
ENV_JOB_ID_GATEWAY = "ENV_JOB_ID_GATEWAY"
ENV_JOB_ARGUMENTS = "ENV_JOB_ARGUMENTS"
QISKIT_IBM_CHANNEL = "QISKIT_IBM_CHANNEL"

DATA_PATH = "DATA_PATH"

# job
ENV_ACCESS_TRIAL = "ENV_ACCESS_TRIAL"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think these variables should be removed too. If the codebase is still using them, then their usage should be done through the new Config class.

@classmethod
def requests_streaming_timeout(cls) -> int:
"""Get streaming request timeout in seconds."""
return int(os.environ.get("REQUESTS_TIMEOUT_OVERRIDE", "60"))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These two config values have the same environment variable REQUESTS_TIMEOUT_OVERRIDE


# IBM Serverless Configuration
@classmethod
def ibm_serverless_host_url(cls) -> str:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should be ibm_serverless_host_url_override

file using the default account name.
Args:
host: host of gateway. Optional. It uses IBM_SERVERLESS_HOST_URL env var or IBM host
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
host: host of gateway. Optional. It uses IBM_SERVERLESS_HOST_URL_OVERRIDE env var or IBM host

Wrong environment variable, my bad... 0294630#diff-fdc3aef5e1a595990db1b71f1ca195cbdfc589291d1f23c213c5fe735c8b0611R112

Copy link
Contributor

@avilches avilches left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check comments

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants