├── .circleci └── config.yml ├── .dockerignore ├── .gitbook.yaml ├── .github ├── ISSUE_TEMPLATE │ ├── bug-report.md │ ├── feature-request.md │ └── question.md └── pull_request_template.md ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── Makefile ├── README.md ├── build ├── amend-image.sh ├── amend-images.sh ├── build-image.sh ├── build-images.sh ├── cli.sh ├── generate_ami_mapping.go ├── images.sh ├── lint-docs.sh ├── lint.sh ├── push-image.sh ├── push-images.sh └── test.sh ├── cli ├── cluster │ ├── delete.go │ ├── deploy.go │ ├── errors.go │ ├── get.go │ ├── info.go │ ├── lib_http_client.go │ ├── logs.go │ └── refresh.go ├── cmd │ ├── cluster.go │ ├── completion.go │ ├── const.go │ ├── delete.go │ ├── deploy.go │ ├── describe.go │ ├── env.go │ ├── errors.go │ ├── get.go │ ├── lib_apis.go │ ├── lib_async_apis.go │ ├── lib_aws_creds.go │ ├── lib_batch_apis.go │ ├── lib_cli_config.go │ ├── lib_client_id.go │ ├── lib_cluster_config.go │ ├── lib_manager.go │ ├── lib_realtime_apis.go │ ├── lib_task_apis.go │ ├── lib_traffic_splitters.go │ ├── lib_watch.go │ ├── logs.go │ ├── refresh.go │ ├── root.go │ └── version.go ├── lib │ └── routines │ │ └── routines.go ├── main.go └── types │ ├── cliconfig │ ├── cli_config.go │ ├── config_key.go │ ├── environment.go │ └── errors.go │ └── flags │ ├── errors.go │ └── output_type.go ├── cmd ├── activator │ └── main.go ├── async-gateway │ └── main.go ├── autoscaler │ └── main.go ├── dequeuer │ └── main.go ├── enqueuer │ └── main.go ├── operator │ └── main.go └── proxy │ └── main.go ├── dev ├── build_cli.sh ├── create_user.py ├── delete_ecr_repos.py ├── export_images.sh ├── find_missing_docs_links.py ├── format.sh ├── generate_cli_md.sh ├── generate_python_client_md.sh ├── get_operator_url.py ├── load.go ├── minimum_aws_policy.json ├── operator_local.sh ├── prometheus.md ├── registry.sh ├── update_cli_config.py ├── util.sh └── versions.md ├── docs ├── README.md ├── clients │ ├── cli.md │ ├── install.md │ ├── python.md │ └── uninstall.md ├── clusters │ ├── advanced │ │ ├── kubectl.md │ │ ├── registry.md │ │ └── self-hosted-images.md │ ├── instances │ │ ├── multi.md │ │ └── spot.md │ ├── management │ │ ├── auth.md │ │ ├── create.md │ │ ├── delete.md │ │ ├── environments.md │ │ ├── production.md │ │ └── update.md │ ├── networking │ │ ├── api-gateway.md │ │ ├── custom-domain.md │ │ ├── https.md │ │ ├── load-balancers.md │ │ └── vpc-peering.md │ └── observability │ │ ├── alerting.md │ │ ├── logging.md │ │ └── metrics.md ├── overview.md ├── start.md ├── summary.md └── workloads │ ├── async │ ├── async.md │ ├── autoscaling.md │ ├── configuration.md │ ├── containers.md │ ├── example.md │ └── statuses.md │ ├── batch │ ├── batch.md │ ├── configuration.md │ ├── containers.md │ ├── example.md │ ├── jobs.md │ └── statuses.md │ ├── realtime │ ├── autoscaling.md │ ├── configuration.md │ ├── containers.md │ ├── example.md │ ├── metrics.md │ ├── realtime.md │ ├── statuses.md │ ├── traffic-splitter.md │ └── troubleshooting.md │ └── task │ ├── configuration.md │ ├── containers.md │ ├── example.md │ ├── jobs.md │ ├── statuses.md │ └── task.md ├── get-cli.sh ├── go.mod ├── go.sum ├── images ├── activator │ └── Dockerfile ├── async-gateway │ └── Dockerfile ├── autoscaler │ └── Dockerfile ├── cluster-autoscaler │ └── Dockerfile ├── controller-manager │ └── Dockerfile ├── dequeuer │ └── Dockerfile ├── enqueuer │ └── Dockerfile ├── event-exporter │ └── Dockerfile ├── fluent-bit │ └── Dockerfile ├── grafana │ └── Dockerfile ├── istio-pilot │ └── Dockerfile ├── istio-proxy │ └── Dockerfile ├── kube-rbac-proxy │ └── Dockerfile ├── kubexit │ └── Dockerfile ├── manager │ └── Dockerfile ├── metrics-server │ └── Dockerfile ├── neuron-device-plugin │ └── Dockerfile ├── neuron-scheduler │ └── Dockerfile ├── nvidia-device-plugin │ └── Dockerfile ├── operator │ └── Dockerfile ├── prometheus-config-reloader │ └── Dockerfile ├── prometheus-dcgm-exporter │ └── Dockerfile ├── prometheus-kube-state-metrics │ └── Dockerfile ├── prometheus-node-exporter │ └── Dockerfile ├── prometheus-operator │ └── Dockerfile ├── prometheus-statsd-exporter │ └── Dockerfile ├── prometheus │ └── Dockerfile └── proxy │ └── Dockerfile ├── manager ├── check_cortex_version.sh ├── cluster_config_env.py ├── debug.sh ├── generate_eks.py ├── get_api_load_balancer_state.py ├── get_operator_load_balancer_state.py ├── get_operator_target_group_status.py ├── helpers.py ├── install.sh ├── manifests │ ├── activator.yaml.j2 │ ├── ami.json │ ├── apis.yaml.j2 │ ├── async-gateway.yaml.j2 │ ├── autoscaler.yaml.j2 │ ├── cluster-autoscaler.yaml.j2 │ ├── default_cortex_cli_config.yaml │ ├── event-exporter.yaml │ ├── fluent-bit.yaml.j2 │ ├── grafana │ │ ├── grafana-dashboard-async.yaml │ │ ├── grafana-dashboard-batch.yaml │ │ ├── grafana-dashboard-cluster.yaml │ │ ├── grafana-dashboard-control-plane.yaml │ │ ├── grafana-dashboard-nodes.yaml │ │ ├── grafana-dashboard-realtime.yaml │ │ ├── grafana-dashboard-task.yaml │ │ └── grafana.yaml.j2 │ ├── inferentia.yaml │ ├── istio.yaml.j2 │ ├── kube-proxy.patch.yaml │ ├── metrics-server.yaml │ ├── namespaces.yaml │ ├── nvidia.yaml │ ├── operator.yaml.j2 │ ├── prometheus-additional-scrape-configs.yaml.j2 │ ├── prometheus-dcgm-exporter.yaml │ ├── prometheus-kube-state-metrics.yaml │ ├── prometheus-kubelet-exporter.yaml │ ├── prometheus-monitoring.yaml │ ├── prometheus-node-exporter.yaml │ ├── prometheus-operator.yaml │ └── prometheus-statsd-exporter.yaml ├── refresh.sh ├── render_template.py ├── requirements.txt ├── uninstall.sh └── upgrade_kube_proxy_mode.py ├── pkg ├── activator │ ├── activator.go │ ├── activator_test.go │ ├── api_activator.go │ ├── api_activator_test.go │ ├── handler.go │ ├── handler_test.go │ ├── helpers.go │ └── request_stats.go ├── async-gateway │ ├── endpoint.go │ ├── queue.go │ ├── service.go │ ├── storage.go │ └── types.go ├── autoscaler │ ├── async_scaler.go │ ├── autoscaler.go │ ├── autoscaler_test.go │ ├── client.go │ ├── handler.go │ ├── realtime_scaler.go │ ├── recommendations.go │ └── scaler_func.go ├── config │ └── config.go ├── consts │ └── consts.go ├── crds │ ├── Makefile │ ├── PROJECT │ ├── apis │ │ └── batch │ │ │ └── v1alpha1 │ │ │ ├── batchjob_metrics.go │ │ │ ├── batchjob_types.go │ │ │ ├── groupversion_info.go │ │ │ └── zz_generated.deepcopy.go │ ├── config │ │ ├── crd │ │ │ ├── bases │ │ │ │ └── batch.cortex.dev_batchjobs.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── kustomizeconfig.yaml │ │ │ └── patches │ │ │ │ ├── cainjection_in_batchjobs.yaml │ │ │ │ └── webhook_in_batchjobs.yaml │ │ ├── default │ │ │ ├── kustomization.yaml │ │ │ ├── manager_auth_proxy_patch.yaml │ │ │ └── manager_config_patch.yaml │ │ ├── manager │ │ │ ├── controller_manager_config.yaml │ │ │ ├── kustomization.yaml │ │ │ └── manager.yaml │ │ ├── prometheus │ │ │ ├── kustomization.yaml │ │ │ └── monitor.yaml │ │ ├── rbac │ │ │ ├── auth_proxy_client_clusterrole.yaml │ │ │ ├── auth_proxy_role.yaml │ │ │ ├── auth_proxy_role_binding.yaml │ │ │ ├── auth_proxy_service.yaml │ │ │ ├── batchjob_editor_role.yaml │ │ │ ├── batchjob_viewer_role.yaml │ │ │ ├── kustomization.yaml │ │ │ ├── leader_election_role.yaml │ │ │ ├── leader_election_role_binding.yaml │ │ │ ├── role.yaml │ │ │ ├── role_binding.yaml │ │ │ └── service_account.yaml │ │ └── samples │ │ │ └── batch_v1alpha1_batchjob.yaml │ ├── controllers │ │ ├── batch │ │ │ ├── batchjob_controller.go │ │ │ ├── batchjob_controller_config.go │ │ │ ├── batchjob_controller_helpers.go │ │ │ ├── batchjob_controller_test.go │ │ │ └── suite_test.go │ │ └── errors.go │ ├── hack │ │ ├── boilerplate.go.txt │ │ └── run_manager.sh │ └── main.go ├── dequeuer │ ├── async_handler.go │ ├── async_handler_test.go │ ├── async_stats.go │ ├── async_stats_test.go │ ├── batch_handler.go │ ├── batch_handler_test.go │ ├── dequeuer.go │ ├── dequeuer_test.go │ ├── errors.go │ ├── http_handler.go │ ├── message_handler.go │ ├── probes.go │ ├── probes_test.go │ ├── queue_attributes.go │ └── request_stats.go ├── enqueuer │ ├── enqueuer.go │ ├── errors.go │ ├── helpers.go │ └── uploader.go ├── health │ └── health.go ├── lib │ ├── archive │ │ ├── archive_test.go │ │ ├── archiver.go │ │ ├── errors.go │ │ ├── input.go │ │ ├── tar.go │ │ ├── tgz.go │ │ └── zip.go │ ├── aws │ │ ├── acm.go │ │ ├── apigateway.go │ │ ├── autoscaling.go │ │ ├── aws.go │ │ ├── clients.go │ │ ├── cloudformation.go │ │ ├── cloudwatch.go │ │ ├── credentials.go │ │ ├── ec2.go │ │ ├── ec2_test.go │ │ ├── ecr.go │ │ ├── eks.go │ │ ├── elb.go │ │ ├── elbv2.go │ │ ├── errors.go │ │ ├── gen_resource_metadata.py │ │ ├── iam.go │ │ ├── resource_metadata.go │ │ ├── s3.go │ │ ├── servicequotas.go │ │ ├── sqs.go │ │ └── sts.go │ ├── cast │ │ ├── interface.go │ │ └── interface_test.go │ ├── configreader │ │ ├── bool.go │ │ ├── bool_list.go │ │ ├── bool_ptr.go │ │ ├── errors.go │ │ ├── float32.go │ │ ├── float32_list.go │ │ ├── float32_ptr.go │ │ ├── float64.go │ │ ├── float64_list.go │ │ ├── float64_ptr.go │ │ ├── int.go │ │ ├── int32.go │ │ ├── int32_list.go │ │ ├── int32_ptr.go │ │ ├── int64.go │ │ ├── int64_list.go │ │ ├── int64_ptr.go │ │ ├── int_list.go │ │ ├── int_ptr.go │ │ ├── interface.go │ │ ├── interface_map.go │ │ ├── interface_map_list.go │ │ ├── interface_test.go │ │ ├── reader.go │ │ ├── reader_test.go │ │ ├── string.go │ │ ├── string_list.go │ │ ├── string_map.go │ │ ├── string_ptr.go │ │ ├── types.go │ │ └── validators.go │ ├── console │ │ └── format.go │ ├── cron │ │ └── cron.go │ ├── debug │ │ └── debug.go │ ├── docker │ │ ├── docker.go │ │ └── errors.go │ ├── errors │ │ ├── error.go │ │ ├── errors.go │ │ ├── message.go │ │ ├── multi.go │ │ └── stack.go │ ├── exit │ │ └── exit.go │ ├── files │ │ ├── errors.go │ │ ├── files.go │ │ └── files_test.go │ ├── hash │ │ └── hash.go │ ├── json │ │ ├── errors.go │ │ └── json.go │ ├── k8s │ │ ├── configmap.go │ │ ├── deployment.go │ │ ├── errors.go │ │ ├── hpa.go │ │ ├── ingress.go │ │ ├── job.go │ │ ├── k8s.go │ │ ├── node.go │ │ ├── parsers.go │ │ ├── pod.go │ │ ├── quantity.go │ │ ├── secret.go │ │ ├── service.go │ │ ├── virtual_service.go │ │ └── volume.go │ ├── logging │ │ ├── errors.go │ │ └── logging.go │ ├── maps │ │ ├── interface.go │ │ └── string.go │ ├── math │ │ ├── float32.go │ │ ├── float64.go │ │ ├── int.go │ │ ├── int32.go │ │ └── int64.go │ ├── msgpack │ │ ├── errors.go │ │ └── msgpack.go │ ├── parallel │ │ ├── parallel.go │ │ └── parallel_test.go │ ├── pointer │ │ ├── equal.go │ │ ├── pointer.go │ │ └── pointer_test.go │ ├── print │ │ └── print.go │ ├── prompt │ │ ├── errors.go │ │ └── prompt.go │ ├── random │ │ └── random.go │ ├── regex │ │ ├── regex.go │ │ └── regex_test.go │ ├── requests │ │ ├── errors.go │ │ └── requests.go │ ├── sets │ │ └── strset │ │ │ ├── strset.go │ │ │ ├── strset_test.go │ │ │ └── threadsafe │ │ │ ├── strset.go │ │ │ └── strset_test.go │ ├── slices │ │ ├── bool.go │ │ ├── errors.go │ │ ├── float32.go │ │ ├── float64.go │ │ ├── float64_ptr.go │ │ ├── float64_ptr_test.go │ │ ├── int.go │ │ ├── int32.go │ │ ├── int64.go │ │ ├── sort.go │ │ ├── string.go │ │ └── string_test.go │ ├── strings │ │ ├── operations.go │ │ ├── operations_test.go │ │ ├── parse.go │ │ ├── stringify.go │ │ └── stringify_test.go │ ├── structs │ │ ├── deepcopy.go │ │ └── deepcopy_test.go │ ├── table │ │ ├── errors.go │ │ ├── key_value.go │ │ └── table.go │ ├── telemetry │ │ ├── error_cache.go │ │ ├── errors.go │ │ └── telemetry.go │ ├── time │ │ └── time.go │ └── urls │ │ ├── errors.go │ │ └── urls.go ├── operator │ ├── endpoints │ │ ├── delete.go │ │ ├── deploy.go │ │ ├── describe.go │ │ ├── errors.go │ │ ├── get.go │ │ ├── get_batch_job.go │ │ ├── get_task_job.go │ │ ├── info.go │ │ ├── logs.go │ │ ├── logs_job.go │ │ ├── middleware.go │ │ ├── params.go │ │ ├── refresh.go │ │ ├── respond.go │ │ ├── stop_batch_job.go │ │ ├── stop_task_job.go │ │ ├── submit_batch.go │ │ ├── submit_task.go │ │ └── verify_cortex.go │ ├── lib │ │ ├── exit │ │ │ └── exit.go │ │ └── routines │ │ │ └── routines.go │ ├── operator │ │ ├── cron.go │ │ ├── deployed_resource.go │ │ ├── errors.go │ │ ├── k8s.go │ │ ├── logging.go │ │ ├── memory_capacity.go │ │ ├── storage.go │ │ └── workload_logging.go │ ├── resources │ │ ├── asyncapi │ │ │ ├── api.go │ │ │ ├── errors.go │ │ │ ├── k8s_specs.go │ │ │ ├── queue.go │ │ │ ├── queue_metrics.go │ │ │ └── status.go │ │ ├── errors.go │ │ ├── job │ │ │ ├── batchapi │ │ │ │ ├── api.go │ │ │ │ ├── errors.go │ │ │ │ ├── job.go │ │ │ │ ├── job_status.go │ │ │ │ ├── k8s_specs.go │ │ │ │ ├── queue.go │ │ │ │ ├── s3_iterator.go │ │ │ │ └── validations.go │ │ │ ├── cache.go │ │ │ ├── consts.go │ │ │ ├── errors.go │ │ │ ├── state.go │ │ │ ├── taskapi │ │ │ │ ├── api.go │ │ │ │ ├── cron.go │ │ │ │ ├── job.go │ │ │ │ ├── job_status.go │ │ │ │ ├── k8s_specs.go │ │ │ │ ├── metrics.go │ │ │ │ └── validations.go │ │ │ └── worker_stats.go │ │ ├── realtimeapi │ │ │ ├── api.go │ │ │ ├── errors.go │ │ │ ├── k8s_specs.go │ │ │ └── status.go │ │ ├── resources.go │ │ ├── trafficsplitter │ │ │ ├── api.go │ │ │ └── k8s_specs.go │ │ └── validations.go │ └── schema │ │ ├── config_key.go │ │ ├── job_submission.go │ │ └── schema.go ├── probe │ ├── handler.go │ ├── handler_test.go │ ├── probe.go │ └── probe_test.go ├── proxy │ ├── breaker.go │ ├── breaker_test.go │ ├── handler.go │ ├── handler_test.go │ ├── proxy.go │ ├── proxy_test.go │ └── request_stats.go ├── types │ ├── async │ │ ├── s3_paths.go │ │ └── status.go │ ├── clusterconfig │ │ ├── availability_zones.go │ │ ├── aws_policy.go │ │ ├── cluster_config.go │ │ ├── config_key.go │ │ ├── errors.go │ │ ├── load_balancer_scheme.go │ │ ├── load_balancer_type.go │ │ ├── nat_gateway_type.go │ │ ├── network_validations.go │ │ ├── subnet_visibility.go │ │ └── volume_types.go │ ├── clusterstate │ │ ├── clusterstate.go │ │ ├── errors.go │ │ └── state.go │ ├── metrics │ │ ├── batch_metrics.go │ │ ├── metrics_test.go │ │ └── queue_metrics.go │ ├── spec │ │ ├── api.go │ │ ├── errors.go │ │ ├── id_gen.go │ │ ├── job.go │ │ ├── utils.go │ │ └── validations.go │ ├── status │ │ ├── job_code.go │ │ ├── job_status.go │ │ └── status.go │ └── userconfig │ │ ├── api.go │ │ ├── config_key.go │ │ ├── kind.go │ │ ├── log_level.go │ │ └── resource.go └── workloads │ ├── configmap.go │ ├── helpers.go │ ├── init.go │ └── k8s.go ├── python └── client │ ├── README.md │ ├── cortex │ ├── __init__.py │ ├── binary │ │ └── __init__.py │ ├── client.py │ ├── consts.py │ ├── exceptions.py │ ├── telemetry.py │ └── util.py │ └── setup.py └── test ├── README.md ├── apis ├── async │ ├── hello-world │ │ ├── app │ │ │ ├── main.py │ │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ └── cpu.Dockerfile │ └── text-generator │ │ ├── app │ │ ├── main.py │ │ ├── requirements-cpu.txt │ │ └── requirements-gpu.txt │ │ ├── build-cpu.sh │ │ ├── build-gpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cortex_gpu.yaml │ │ ├── cpu.Dockerfile │ │ ├── expectations.yaml │ │ ├── gpu.Dockerfile │ │ └── sample.json ├── batch │ ├── image-classifier-alexnet │ │ ├── app │ │ │ ├── main.py │ │ │ ├── requirements-cpu.txt │ │ │ └── requirements-gpu.txt │ │ ├── build-cpu.sh │ │ ├── build-gpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cortex_gpu.yaml │ │ ├── cpu.Dockerfile │ │ ├── gpu.Dockerfile │ │ ├── sample.json │ │ └── submit.py │ └── sum │ │ ├── app │ │ ├── main.py │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cpu.Dockerfile │ │ ├── sample.json │ │ ├── sample_generator.py │ │ └── submit.py ├── realtime │ ├── hello-world │ │ ├── app │ │ │ ├── main.py │ │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cortex_cpu_arm64.yaml │ │ ├── cortex_scale_to_zero.yaml │ │ ├── cpu.Dockerfile │ │ └── sample.json │ ├── image-classifier-resnet50 │ │ ├── README.md │ │ ├── build-cpu.sh │ │ ├── build-gpu.sh │ │ ├── build-neuron-rtd.sh │ │ ├── build-neuron-tf-serving.sh │ │ ├── client.py │ │ ├── client_inf.py │ │ ├── cortex_cpu.yaml │ │ ├── cortex_gpu.yaml │ │ ├── cortex_inf.yaml │ │ ├── cortex_inf_rtd.yaml │ │ ├── cpu.Dockerfile │ │ ├── gpu.Dockerfile │ │ ├── neuron-rtd.Dockerfile │ │ ├── neuron-tf-serving.Dockerfile │ │ └── sample.json │ ├── multi-container │ │ ├── app │ │ │ ├── main.py │ │ │ └── requirements.txt │ │ ├── build-tfs-cpu.sh │ │ ├── build-web-cpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── sample.json │ │ ├── tfs-cpu.Dockerfile │ │ └── web-cpu.Dockerfile │ ├── prime-generator │ │ ├── app │ │ │ ├── main.py │ │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cpu.Dockerfile │ │ └── sample.json │ ├── sleep │ │ ├── app │ │ │ ├── main.py │ │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ └── cpu.Dockerfile │ └── text-generator │ │ ├── app │ │ ├── main.py │ │ ├── requirements-cpu.txt │ │ └── requirements-gpu.txt │ │ ├── build-cpu.sh │ │ ├── build-gpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cortex_gpu.yaml │ │ ├── cpu.Dockerfile │ │ ├── gpu.Dockerfile │ │ └── sample.json ├── task │ └── iris-classifier-trainer │ │ ├── app │ │ ├── main.py │ │ └── requirements.txt │ │ ├── build-cpu.sh │ │ ├── cortex_cpu.yaml │ │ ├── cpu.Dockerfile │ │ └── submit.py └── trafficsplitter │ └── hello-world │ ├── .dockerignore │ ├── cortex_cpu.yaml │ └── sample.json ├── e2e ├── README.md ├── e2e │ ├── __init__.py │ ├── cluster.py │ ├── exceptions.py │ ├── expectations.py │ ├── generator.py │ ├── tests.py │ └── utils.py ├── pytest.ini ├── setup.py └── tests │ ├── __init__.py │ ├── aws │ ├── __init__.py │ ├── conftest.py │ ├── test_async.py │ ├── test_autoscaling.py │ ├── test_batch.py │ ├── test_load.py │ ├── test_long_running.py │ ├── test_realtime.py │ ├── test_scale_to_zero.py │ └── test_task.py │ └── conftest.py └── utils ├── README.md ├── build-all.sh ├── build.sh └── throughput_test.py /.dockerignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /bin/ 3 | /testbin/ 4 | /dev/ 5 | /docs/ 6 | /test/ 7 | 8 | **/.* 9 | **/*.md 10 | **/*.zip 11 | 12 | **/*.pyc 13 | **/*.pyo 14 | **/*.pyd 15 | **/__pycache__/ 16 | 17 | **/hack/ 18 | **/PROJECT 19 | **/Makefile 20 | -------------------------------------------------------------------------------- /.gitbook.yaml: -------------------------------------------------------------------------------- 1 | root: ./docs/ 2 | 3 | structure: 4 | readme: ./start.md 5 | summary: summary.md 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug-report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Report a bug 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Version 11 | 12 | (use `cortex version` to determine your version) 13 | 14 | ### Description 15 | 16 | (describe the bug) 17 | 18 | ### Configuration 19 | 20 | (paste relevant `cortex.yaml` or `cluster.yaml` configuration) 21 | 22 | ### Steps to reproduce 23 | 24 | 1. ... 25 | 2. ... 26 | 3. ... 27 | 28 | ### Expected behavior 29 | 30 | (describe the behavior you expected) 31 | 32 | ### Actual behavior 33 | 34 | (describe the behavior you experienced) 35 | 36 | ### Screenshots 37 | 38 | (optional) 39 | 40 | ### Stack traces 41 | 42 | (error output from CloudWatch Insights or from a random pod `cortex logs `) 43 | 44 | ```text 45 | 46 | ``` 47 | 48 | ### Additional context 49 | 50 | (optional) 51 | 52 | ### Suggested solution 53 | 54 | (optional) 55 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature-request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Request a feature 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Description 11 | 12 | (describe the feature) 13 | 14 | ### Motivation 15 | 16 | (how this will improve the product / what problem will this solve / what is the use case) 17 | 18 | ### Additional context 19 | 20 | (optional) 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/question.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Question 3 | about: Ask a question 4 | title: '' 5 | labels: question 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | closes # 2 | 3 | --- 4 | 5 | checklist: 6 | 7 | - [ ] run `make test` and `make lint` 8 | - [ ] test manually (i.e. build/push all images, restart operator, and re-deploy APIs) 9 | - [ ] update examples 10 | - [ ] update docs and add any new files to `summary.md` (view in [gitbook](https://cortex-labs.gitbook.io/staging/-MOmCGMADSRNQahK3Kox/) after merging) 11 | - [ ] cherry-pick into release branches if applicable 12 | - [ ] alert the dev team if the dev environment changed 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /vendor/ 2 | /bin/ 3 | /testbin/ 4 | /dev/config/ 5 | 6 | # PYTHON 7 | __pycache__/ 8 | *.py[cod] 9 | *$py.class 10 | .python-version 11 | .env 12 | .venv 13 | *.egg-info 14 | *.pytest_cache 15 | 16 | # OSX 17 | .DS_Store 18 | ._* 19 | 20 | # MISC 21 | *.zip 22 | .unison* 23 | .vscode/ 24 | 25 | # Binaries for programs and plugins 26 | *.exe 27 | *.exe~ 28 | *.dll 29 | *.so 30 | *.dylib 31 | 32 | # Test binary, build with `go test -c` 33 | *.test 34 | 35 | # Kubernetes Generated files - skip generated files, except for vendored files 36 | 37 | !vendor/**/zz_generated.* 38 | 39 | # editor and IDE paraphernalia 40 | .idea 41 | *.swp 42 | *.swo 43 | *~ 44 | -------------------------------------------------------------------------------- /build/amend-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | CORTEX_VERSION=master 21 | 22 | host_primary=$1 23 | host_backup=$2 24 | image=$3 25 | 26 | hosts=( 27 | "$host_primary" 28 | "$host_backup" 29 | ) 30 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 31 | 32 | for host in "${hosts[@]}"; do 33 | docker manifest create $host/cortexlabs/${image}:${CORTEX_VERSION} \ 34 | -a $host/cortexlabs/${image}:manifest-${CORTEX_VERSION}-amd64 \ 35 | -a $host/cortexlabs/${image}:manifest-${CORTEX_VERSION}-arm64 36 | docker manifest push $host/cortexlabs/${image}:${CORTEX_VERSION} 37 | done 38 | -------------------------------------------------------------------------------- /build/amend-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | source $ROOT/build/images.sh 23 | source $ROOT/dev/util.sh 24 | 25 | host_primary=$1 26 | host_backup=$2 27 | 28 | for image in "${multi_arch_images[@]}"; do 29 | $ROOT/build/amend-image.sh $host_primary $host_backup $image 30 | done 31 | -------------------------------------------------------------------------------- /build/build-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | CORTEX_VERSION=master 23 | 24 | host_primary=$1 25 | host_backup=$2 26 | image=$3 27 | is_multi_arch=$4 28 | arch=$5 29 | 30 | if [ "$is_multi_arch" = "true" ]; then 31 | tag="manifest-${CORTEX_VERSION}-$arch" 32 | else 33 | tag="${CORTEX_VERSION}" 34 | fi 35 | 36 | docker build $ROOT \ 37 | --build-arg TARGETOS=linux \ 38 | --build-arg TARGETARCH=$arch \ 39 | -f $ROOT/images/$image/Dockerfile \ 40 | -t $host_primary/cortexlabs/${image}:${tag} \ 41 | -t $host_backup/cortexlabs/${image}:${tag} 42 | -------------------------------------------------------------------------------- /build/build-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | source $ROOT/build/images.sh 23 | source $ROOT/dev/util.sh 24 | 25 | arch=$1 26 | host_primary=$2 27 | host_backup=$3 28 | 29 | for image in "${all_images[@]}"; do 30 | is_multi_arch="false" 31 | if [[ " ${multi_arch_images[*]} " =~ " $image " ]]; then 32 | is_multi_arch="true" 33 | $ROOT/build/build-image.sh $host_primary $host_backup $image $is_multi_arch $arch 34 | elif [ "$arch" = "amd64" ]; then 35 | $ROOT/build/build-image.sh $host_primary $host_backup $image $is_multi_arch $arch 36 | fi 37 | done 38 | -------------------------------------------------------------------------------- /build/push-image.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | CORTEX_VERSION=master 23 | 24 | host_primary=$1 25 | host_backup=$2 26 | image=$3 27 | is_multi_arch=$4 28 | arch=$5 29 | 30 | echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin 31 | if [ "$is_multi_arch" = "true" ]; then 32 | tag="manifest-${CORTEX_VERSION}-$arch" 33 | else 34 | tag="${CORTEX_VERSION}" 35 | fi 36 | 37 | docker push $host_primary/cortexlabs/${image}:${tag} 38 | docker push $host_backup/cortexlabs/${image}:${tag} 39 | -------------------------------------------------------------------------------- /build/push-images.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | source $ROOT/build/images.sh 23 | source $ROOT/dev/util.sh 24 | 25 | arch=$1 26 | host_primary=$2 27 | host_backup=$3 28 | 29 | for image in "${all_images[@]}"; do 30 | is_multi_arch="false" 31 | if [[ " ${multi_arch_images[*]} " =~ " $image " ]]; then 32 | is_multi_arch="true" 33 | $ROOT/build/push-image.sh $host_primary $host_backup $image $is_multi_arch $arch 34 | elif [ "$arch" = "amd64" ]; then 35 | $ROOT/build/push-image.sh $host_primary $host_backup $image $is_multi_arch $arch 36 | fi 37 | done 38 | -------------------------------------------------------------------------------- /cli/cluster/info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cluster 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | "github.com/cortexlabs/cortex/pkg/lib/json" 22 | "github.com/cortexlabs/cortex/pkg/operator/schema" 23 | ) 24 | 25 | func Info(operatorConfig OperatorConfig) (*schema.InfoResponse, error) { 26 | httpResponse, err := HTTPGet(operatorConfig, "/info") 27 | if err != nil { 28 | return nil, errors.Wrap(err, "unable to connect to operator", "/info") 29 | } 30 | 31 | var infoResponse schema.InfoResponse 32 | err = json.Unmarshal(httpResponse, &infoResponse) 33 | if err != nil { 34 | return nil, errors.Wrap(err, "/info", string(httpResponse)) 35 | } 36 | 37 | return &infoResponse, nil 38 | } 39 | -------------------------------------------------------------------------------- /cli/cluster/refresh.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cluster 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | "github.com/cortexlabs/cortex/pkg/lib/json" 22 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 23 | "github.com/cortexlabs/cortex/pkg/operator/schema" 24 | ) 25 | 26 | func Refresh(operatorConfig OperatorConfig, apiName string, force bool) (schema.RefreshResponse, error) { 27 | params := map[string]string{ 28 | "force": s.Bool(force), 29 | } 30 | 31 | httpRes, err := HTTPPostNoBody(operatorConfig, "/refresh/"+apiName, params) 32 | if err != nil { 33 | return schema.RefreshResponse{}, err 34 | } 35 | 36 | var refreshRes schema.RefreshResponse 37 | err = json.Unmarshal(httpRes, &refreshRes) 38 | if err != nil { 39 | return schema.RefreshResponse{}, errors.Wrap(err, "/refresh", string(httpRes)) 40 | } 41 | 42 | return refreshRes, nil 43 | } 44 | -------------------------------------------------------------------------------- /cli/cmd/const.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd 18 | 19 | const ( 20 | _timeFormat = "02 Jan 06 15:04:05 MST" 21 | ) 22 | -------------------------------------------------------------------------------- /cli/cmd/lib_client_id.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cmd 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/files" 21 | "github.com/google/uuid" 22 | ) 23 | 24 | var _cachedClientID string 25 | 26 | func clientID() string { 27 | if _cachedClientID != "" { 28 | return _cachedClientID 29 | } 30 | 31 | var err error 32 | _cachedClientID, err = files.ReadFile(_clientIDPath) 33 | if err != nil || _cachedClientID == "" { 34 | _cachedClientID = uuid.New().String() 35 | files.WriteFile([]byte(_cachedClientID), _clientIDPath) 36 | } 37 | 38 | return _cachedClientID 39 | } 40 | -------------------------------------------------------------------------------- /cli/lib/routines/routines.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package routines 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | "github.com/cortexlabs/cortex/pkg/lib/exit" 22 | "github.com/cortexlabs/cortex/pkg/lib/telemetry" 23 | ) 24 | 25 | func RunWithPanicHandler(f func(), exitOnPanic bool) { 26 | go func() { 27 | defer func() { 28 | if r := recover(); r != nil { 29 | err := errors.CastRecoverError(r) 30 | errors.PrintStacktrace(err) 31 | if exitOnPanic { 32 | exit.Error(err) 33 | } 34 | telemetry.Error(err) 35 | } 36 | }() 37 | f() 38 | }() 39 | } 40 | -------------------------------------------------------------------------------- /cli/main.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package main 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/cli/cmd" 21 | ) 22 | 23 | func main() { 24 | cmd.Execute() 25 | } 26 | -------------------------------------------------------------------------------- /cli/types/cliconfig/config_key.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package cliconfig 18 | 19 | const ( 20 | EnvironmentsKey = "environments" 21 | DefaultEnvironmentKey = "default_environment" 22 | NameKey = "name" 23 | OperatorEndpointKey = "operator_endpoint" 24 | ) 25 | -------------------------------------------------------------------------------- /cli/types/flags/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package flags 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 24 | ) 25 | 26 | const ( 27 | ErrInvalidOutputType = "flags.invalid_output_type" 28 | ) 29 | 30 | func ErrorInvalidOutputType(invalidOutputType string) error { 31 | return errors.WithStack(&errors.Error{ 32 | Kind: ErrInvalidOutputType, 33 | Message: fmt.Sprintf("invalid value \"%s\" specified for -o/--output; valid values are %s", invalidOutputType, s.StrsAnd(OutputTypeStrings())), 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /dev/build_cli.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | set -euo pipefail 19 | 20 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/.. >/dev/null && pwd)" 21 | 22 | $ROOT/build/cli.sh upload 23 | -------------------------------------------------------------------------------- /dev/delete_ecr_repos.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import boto3 16 | 17 | ecr = boto3.client("ecr") 18 | 19 | response = ecr.describe_repositories(maxResults=1000) 20 | 21 | for repo in response["repositories"]: 22 | ecr.delete_repository( 23 | registryId=repo["registryId"], 24 | repositoryName=repo["repositoryName"], 25 | force=True, 26 | ) 27 | print(f"deleted{repo['repositoryName']}") 28 | 29 | print("done") 30 | -------------------------------------------------------------------------------- /dev/util.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | 18 | function blue_echo() { 19 | echo -e "\033[1;34m$1\033[0m" 20 | } 21 | 22 | function green_echo() { 23 | echo -e "\033[1;32m$1\033[0m" 24 | } 25 | 26 | function error_echo() { 27 | echo -e "\033[1;31mERROR: \033[0m$1" 28 | } 29 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | **Please read our documentation at [docs.cortexlabs.com](https://docs.cortexlabs.com)** 2 | -------------------------------------------------------------------------------- /docs/clients/install.md: -------------------------------------------------------------------------------- 1 | # Install 2 | 3 | ## Install the CLI 4 | 5 | 6 | ```bash 7 | # download CLI version 0.42.1 (Note the "v"): 8 | bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/v0.42.1/get-cli.sh)" 9 | ``` 10 | 11 | By default, the Cortex CLI is installed at `/usr/local/bin/cortex`. To install the executable elsewhere, export the `CORTEX_INSTALL_PATH` environment variable to your desired location before running the command above. 12 | 13 | ## Install the CLI and Python client via pip 14 | 15 | To install the latest version: 16 | 17 | ```bash 18 | pip install cortex 19 | ``` 20 | 21 | 22 | To install or upgrade to a specific version (e.g. v0.42.1): 23 | 24 | ```bash 25 | pip install cortex==0.42.1 26 | ``` 27 | 28 | To upgrade to the latest version: 29 | 30 | ```bash 31 | pip install --upgrade cortex 32 | ``` 33 | 34 | ## Changing the CLI/client configuration directory 35 | 36 | By default, the CLI/client creates a directory at `~/.cortex/` and uses it to store environment configuration. To use a different directory, export the `CORTEX_CLI_CONFIG_DIR` environment variable before running any `cortex` commands. 37 | -------------------------------------------------------------------------------- /docs/clients/uninstall.md: -------------------------------------------------------------------------------- 1 | # Uninstall 2 | 3 | ## Uninstall (if installed with pip) 4 | 5 | ```bash 6 | pip uninstall cortex 7 | rm -rf ~/.cortex 8 | ``` 9 | 10 | ## Uninstall (if installed without pip) 11 | 12 | ```bash 13 | rm /usr/local/bin/cortex 14 | rm -rf ~/.cortex 15 | ``` 16 | -------------------------------------------------------------------------------- /docs/clusters/advanced/kubectl.md: -------------------------------------------------------------------------------- 1 | # Setting up `kubectl` 2 | 3 | ## Install `kubectl` 4 | 5 | Follow these [instructions](https://kubernetes.io/docs/tasks/tools/install-kubectl). 6 | 7 | ## Install the AWS CLI 8 | 9 | Follow these [instructions](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html). 10 | 11 | ## Configure the AWS CLI 12 | 13 | ```bash 14 | aws --version # should be >= 1.16 15 | 16 | aws configure 17 | ``` 18 | 19 | ## Update `kubeconfig` 20 | 21 | ```bash 22 | aws eks update-kubeconfig --name= --region= 23 | ``` 24 | 25 | ## Test `kubectl` 26 | 27 | ```bash 28 | kubectl get pods 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/clusters/advanced/registry.md: -------------------------------------------------------------------------------- 1 | # Private Docker registry 2 | 3 | ## Configuring `kubectl` 4 | 5 | Follow the instructions [here](kubectl.md). 6 | 7 | ## Setting credentials 8 | 9 | ```bash 10 | DOCKER_USERNAME=*** 11 | DOCKER_PASSWORD=*** 12 | 13 | kubectl create secret docker-registry registry-credentials \ 14 | --namespace default \ 15 | --docker-username=$DOCKER_USERNAME \ 16 | --docker-password=$DOCKER_PASSWORD 17 | 18 | kubectl patch serviceaccount default --namespace default \ 19 | -p "{\"imagePullSecrets\": [{\"name\": \"registry-credentials\"}]}" 20 | ``` 21 | 22 | ## Deleting credentials 23 | 24 | ```bash 25 | kubectl delete secret --namespace default registry-credentials 26 | 27 | kubectl patch serviceaccount default --namespace default \ 28 | -p "{\"imagePullSecrets\": []}" 29 | ``` 30 | -------------------------------------------------------------------------------- /docs/start.md: -------------------------------------------------------------------------------- 1 | # Get started 2 | 3 | ## Create a cluster on your AWS account 4 | 5 | 6 | ```bash 7 | # install the CLI 8 | bash -c "$(curl -sS https://raw.githubusercontent.com/cortexlabs/cortex/v0.42.1/get-cli.sh)" 9 | 10 | # create a cluster 11 | cortex cluster up cluster.yaml 12 | ``` 13 | 14 | * [Client installation](clients/install.md) - customize your client installation. 15 | * [Cluster configuration](clusters/management/create.md) - optimize your cluster for your workloads. 16 | * [Environments](clusters/management/environments.md) - manage multiple clusters. 17 | 18 | ## Build scalable APIs 19 | 20 | ```bash 21 | # deploy APIs 22 | cortex deploy apis.yaml 23 | ``` 24 | 25 | * [Realtime](workloads/realtime/example.md) - create APIs that respond to requests in real-time. 26 | * [Async](workloads/async/example.md) - create APIs that respond to requests asynchronously. 27 | * [Batch](workloads/batch/example.md) - create APIs that run distributed batch jobs. 28 | * [Task](workloads/task/example.md) - create APIs that run jobs on-demand. 29 | -------------------------------------------------------------------------------- /docs/workloads/batch/statuses.md: -------------------------------------------------------------------------------- 1 | # Job statuses 2 | 3 | | Status | Meaning | 4 | | :--- | :--- | 5 | | enqueuing | Job is being split into batches and placed into a queue | 6 | | running | Workers are retrieving batches from the queue and running inference | 7 | | succeeded | Workers completed all items in the queue without any failures | 8 | | failed while enqueuing | Failure occurred while enqueuing; check job logs for more details | 9 | | completed with failures | Workers completed all items in the queue but some of the batches weren't processed successfully and raised exceptions; check job logs for more details | 10 | | worker error | One or more workers experienced an irrecoverable error, causing the job to fail; check job logs for more details | 11 | | out of memory | One or more workers ran out of memory, causing the job to fail; check job logs for more details | 12 | | timed out | Job was terminated after the specified timeout has elapsed | 13 | | stopped | Job was stopped by the user or the Batch API was deleted | 14 | -------------------------------------------------------------------------------- /docs/workloads/realtime/realtime.md: -------------------------------------------------------------------------------- 1 | # Realtime 2 | 3 | Realtime APIs respond to requests synchronously and autoscale based on in-flight request volumes. 4 | 5 | Realtime APIs are a good fit for users who want to run stateless containers as a scalable microservice (for example, deploying machine learning models as APIs). 6 | 7 | **Key features** 8 | 9 | * respond to requests synchronously 10 | * autoscale based on request volume 11 | * avoid cold starts 12 | * scale to zero 13 | * perform rolling updates 14 | * automatically recover from failures and spot instance termination 15 | * perform A/B tests and canary deployments 16 | 17 | ## How it works 18 | 19 | When you deploy a Realtime API, Cortex initializes a pool of worker pods and attaches a proxy sidecar to each of the pods. 20 | 21 | The proxy is responsible for receiving incoming requests, queueing them (if necessary), and forwarding them to your pod when it is ready. Autoscaling is based on aggregate in-flight request volume, which is published by the proxy sidecars. 22 | 23 | ![](https://user-images.githubusercontent.com/808475/146854245-ed0fc153-d083-47d8-a7e2-ac5beb114ee6.png) 24 | -------------------------------------------------------------------------------- /docs/workloads/realtime/statuses.md: -------------------------------------------------------------------------------- 1 | # Replica states 2 | 3 | The replica states of an API can be inspected by running `cortex describe `. Here are the possible states for each replica in an API: 4 | 5 | | State | Meaning | 6 | |:---|:---| 7 | | Ready | Replica is running and it has passed the readiness checks | 8 | | ReadyOutOfDate | Replica is running and it has passed the readiness checks (for an out-of-date replica) | 9 | | NotReady | Replica is running but it's not passing the readiness checks; make sure the server is listening on the designed port of the API | 10 | | Pending | Replica is in a pending state (waiting to get scheduled onto a node) | 11 | | Creating | Replica is in the process of having its containers created | 12 | | ErrImagePull | Replica was not created because one of the specified Docker images was inaccessible at runtime; check that your API's docker images exist and are accessible via your cluster's AWS credentials | 13 | | Failed | Replica couldn't start due to an error; run `cortex logs ` to view the logs | 14 | | Killed | Replica has had one of its containers killed | 15 | | KilledOOM | Replica was terminated due to excessive memory usage; try allocating more memory to the API and re-deploy | 16 | | Stalled | Replica has been in a pending state for more than 15 minutes; see [troubleshooting](../realtime/troubleshooting.md) | 17 | | Terminating | Replica is currently in the process of being terminated | 18 | | Unknown | Replica is in an unknown state | 19 | -------------------------------------------------------------------------------- /docs/workloads/task/statuses.md: -------------------------------------------------------------------------------- 1 | # Job statuses 2 | 3 | | Status | Meaning | 4 | | :--- | :--- | 5 | | running | Task is running | 6 | | succeeded | Task has finished without errors | 7 | | worker error | The task has experienced an irrecoverable error, causing the job to fail; check job logs for more details | 8 | | out of memory | The task has ran out of memory, causing the job to fail; check job logs for more details | 9 | | timed out | Job was terminated after the specified timeout has elapsed | 10 | | stopped | Job was stopped by the user or the Task API was deleted | 11 | -------------------------------------------------------------------------------- /docs/workloads/task/task.md: -------------------------------------------------------------------------------- 1 | # Task 2 | 3 | Task APIs provide a lambda-style execution of containers. They are useful for running your containers on demand. 4 | 5 | Task APIs are a good fit when you need to trigger container execution via an HTTP request. They can be used to run tasks (e.g. training models), and can be configured as task runners for orchestrators (such as airflow). 6 | 7 | **Key Features** 8 | 9 | * run containers on-demand 10 | * scale to 0 (when there are no tasks) 11 | * automatically recover from failures and spot instance termination 12 | 13 | ## How it works 14 | 15 | When you deploy a Task API, an endpoint is created to receive task submissions. Upon submitting a Task, Cortex will respond with a Task ID and will asynchronously trigger the execution of a Task. 16 | 17 | Cortex will initialize a worker pod based on your API specification. After the worker pod runs to completion, the Task is marked as completed and the pod is terminated. 18 | 19 | You can make GET requests to the Task API endpoint to retrieve the status of the Task. 20 | 21 | ![](https://user-images.githubusercontent.com/808475/146854267-3785e8ee-4233-4473-a0db-37a5c5438fb4.png) 22 | -------------------------------------------------------------------------------- /images/activator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM golang:1.17.3 as builder 16 | 17 | WORKDIR /workspace 18 | COPY go.mod go.mod 19 | COPY go.sum go.sum 20 | RUN go mod download 21 | 22 | COPY pkg pkg 23 | COPY cmd/activator cmd/activator 24 | WORKDIR /workspace/cmd/activator 25 | 26 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o /workspace/bin/activator main.go 27 | 28 | FROM gcr.io/distroless/static:nonroot 29 | WORKDIR / 30 | COPY --from=builder /workspace/bin/activator . 31 | USER 65532:65532 32 | 33 | ENTRYPOINT ["/activator"] 34 | -------------------------------------------------------------------------------- /images/async-gateway/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ARG TARGETARCH, TARGETOS 16 | 17 | FROM golang:1.17.3 as builder 18 | 19 | COPY go.mod go.sum /workspace/ 20 | WORKDIR /workspace 21 | RUN go mod download 22 | 23 | COPY pkg/consts pkg/consts 24 | COPY pkg/lib pkg/lib 25 | COPY pkg/async-gateway pkg/async-gateway 26 | COPY pkg/types pkg/types 27 | COPY cmd/async-gateway cmd/async-gateway 28 | 29 | RUN GO111MODULE=on CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -installsuffix cgo -o async-gateway ./cmd/async-gateway 30 | 31 | FROM alpine:3.15 32 | 33 | RUN apk update && apk add ca-certificates 34 | 35 | COPY --from=builder /workspace/async-gateway /root/ 36 | RUN chmod +x /root/async-gateway 37 | 38 | ENTRYPOINT ["/root/async-gateway"] 39 | -------------------------------------------------------------------------------- /images/autoscaler/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM golang:1.17.3 as builder 16 | 17 | WORKDIR /workspace 18 | COPY go.mod go.mod 19 | COPY go.sum go.sum 20 | RUN go mod download 21 | 22 | COPY pkg pkg 23 | COPY cmd/autoscaler cmd/autoscaler 24 | WORKDIR /workspace/cmd/autoscaler 25 | 26 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o /workspace/bin/autoscaler main.go 27 | 28 | FROM gcr.io/distroless/static:nonroot 29 | WORKDIR / 30 | COPY --from=builder /workspace/bin/autoscaler . 31 | USER 65532:65532 32 | 33 | ENTRYPOINT ["/autoscaler"] 34 | -------------------------------------------------------------------------------- /images/cluster-autoscaler/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ARG TARGETARCH, TARGETOS 16 | 17 | FROM golang:1.17.5 AS builder 18 | RUN git clone -b cluster-autoscaler-1.22.2-cortex --depth 1 https://github.com/cortexlabs/autoscaler /k8s.io/autoscaler 19 | WORKDIR /k8s.io/autoscaler/cluster-autoscaler 20 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build --installsuffix cgo -o cluster-autoscaler k8s.io/autoscaler/cluster-autoscaler \ 21 | && cp cluster-autoscaler /usr/local/bin 22 | 23 | FROM alpine:3.8 24 | RUN apk add -U --no-cache ca-certificates && rm -rf /var/cache/apk/* 25 | COPY --from=builder /usr/local/bin/cluster-autoscaler . 26 | -------------------------------------------------------------------------------- /images/controller-manager/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM golang:1.17.3 as builder 16 | 17 | WORKDIR /workspace 18 | COPY go.mod go.mod 19 | COPY go.sum go.sum 20 | RUN go mod download 21 | 22 | COPY pkg/config pkg/config 23 | COPY pkg/consts pkg/consts 24 | COPY pkg/crds pkg/crds 25 | COPY pkg/lib pkg/lib 26 | COPY pkg/types pkg/types 27 | COPY pkg/workloads pkg/workloads 28 | 29 | WORKDIR /workspace/pkg/crds 30 | 31 | RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GO111MODULE=on go build -a -o /workspace/bin/manager main.go 32 | 33 | FROM gcr.io/distroless/static:nonroot 34 | WORKDIR / 35 | COPY --from=builder /workspace/bin/manager . 36 | USER 65532:65532 37 | 38 | ENTRYPOINT ["/manager"] 39 | -------------------------------------------------------------------------------- /images/dequeuer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ARG TARGETARCH, TARGETOS 16 | 17 | FROM golang:1.17.3 as builder 18 | 19 | COPY go.mod go.sum /workspace/ 20 | WORKDIR /workspace 21 | RUN go mod download 22 | 23 | COPY pkg/config pkg/config 24 | COPY pkg/consts pkg/consts 25 | COPY pkg/lib pkg/lib 26 | COPY pkg/dequeuer pkg/dequeuer 27 | COPY pkg/probe pkg/probe 28 | COPY pkg/types pkg/types 29 | COPY pkg/crds pkg/crds 30 | COPY pkg/workloads pkg/workloads 31 | COPY cmd/dequeuer cmd/dequeuer 32 | 33 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} GO111MODULE=on go build -o dequeuer ./cmd/dequeuer 34 | 35 | FROM gcr.io/distroless/static:nonroot 36 | WORKDIR / 37 | COPY --from=builder /workspace/dequeuer . 38 | USER nonroot:nonroot 39 | 40 | ENTRYPOINT ["/dequeuer"] 41 | -------------------------------------------------------------------------------- /images/enqueuer/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ARG TARGETARCH, TARGETOS 16 | 17 | FROM golang:1.17.3 as builder 18 | 19 | COPY go.mod go.sum /workspace/ 20 | WORKDIR /workspace 21 | RUN go mod download 22 | 23 | COPY pkg/config pkg/config 24 | COPY pkg/consts pkg/consts 25 | COPY pkg/lib pkg/lib 26 | COPY pkg/enqueuer pkg/enqueuer 27 | COPY pkg/types pkg/types 28 | COPY pkg/crds pkg/crds 29 | COPY pkg/workloads pkg/workloads 30 | COPY cmd/enqueuer cmd/enqueuer 31 | 32 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} GO111MODULE=on go build -o enqueuer ./cmd/enqueuer 33 | 34 | FROM gcr.io/distroless/static:nonroot 35 | WORKDIR / 36 | COPY --from=builder /workspace/enqueuer . 37 | USER nonroot:nonroot 38 | 39 | ENTRYPOINT ["/enqueuer"] 40 | -------------------------------------------------------------------------------- /images/event-exporter/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM ghcr.io/opsgenie/kubernetes-event-exporter:v0.11 16 | -------------------------------------------------------------------------------- /images/fluent-bit/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM amazon/aws-for-fluent-bit:2.23.3 16 | -------------------------------------------------------------------------------- /images/grafana/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM grafana/grafana:8.0.4 16 | -------------------------------------------------------------------------------- /images/istio-pilot/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM docker.io/istio/pilot:1.11.8 16 | -------------------------------------------------------------------------------- /images/istio-proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM docker.io/istio/proxyv2:1.11.8 16 | -------------------------------------------------------------------------------- /images/kube-rbac-proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Kube RBAC Proxy Authors rights reserved. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # Modifications Copyright 2022 Cortex Labs, Inc. 16 | 17 | ARG TARGETARCH, TARGETOS 18 | 19 | FROM golang:1.18 AS builder 20 | RUN git clone -b v0.13.0 --depth 1 https://github.com/brancz/kube-rbac-proxy /go/src/github.com/brancz/kube-rbac-proxy 21 | WORKDIR /go/src/github.com/brancz/kube-rbac-proxy 22 | RUN GO111MODULE=on CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build --installsuffix cgo -o kube-rbac-proxy github.com/brancz/kube-rbac-proxy \ 23 | && cp kube-rbac-proxy /usr/local/bin 24 | 25 | FROM alpine:3.8 26 | RUN apk add -U --no-cache ca-certificates && rm -rf /var/cache/apk/* 27 | COPY --from=builder /usr/local/bin/kube-rbac-proxy . 28 | ENTRYPOINT ["./kube-rbac-proxy"] 29 | EXPOSE 8080 30 | -------------------------------------------------------------------------------- /images/kubexit/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Karl Isenberg (https://github.com/karlkfi/kubexit) 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # Modifications Copyright 2022 Cortex Labs, Inc. 16 | 17 | ARG TARGETARCH, TARGETOS 18 | 19 | FROM golang:1.14 AS builder 20 | 21 | RUN mkdir /tmp/kubexit 22 | RUN git clone -b v0.1.0-cortex --depth 1 https://github.com/cortexlabs/kubexit.git /tmp/kubexit 23 | 24 | WORKDIR /tmp/kubexit 25 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o kubexit ./cmd/kubexit 26 | 27 | FROM alpine:3.11 28 | RUN apk --no-cache add ca-certificates tzdata 29 | COPY --from=builder /tmp/kubexit/kubexit /bin/ 30 | ENTRYPOINT ["kubexit"] 31 | -------------------------------------------------------------------------------- /images/metrics-server/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM k8s.gcr.io/metrics-server/metrics-server:v0.6.1 16 | -------------------------------------------------------------------------------- /images/neuron-device-plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM public.ecr.aws/neuron/neuron-device-plugin:1.8.2.0 16 | -------------------------------------------------------------------------------- /images/neuron-scheduler/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM public.ecr.aws/neuron/neuron-scheduler:1.8.2.0 16 | -------------------------------------------------------------------------------- /images/nvidia-device-plugin/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM nvidia/k8s-device-plugin:v0.11.0 16 | -------------------------------------------------------------------------------- /images/prometheus-config-reloader/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM quay.io/prometheus-operator/prometheus-config-reloader:v0.48.1 16 | -------------------------------------------------------------------------------- /images/prometheus-dcgm-exporter/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM nvcr.io/nvidia/k8s/dcgm-exporter:2.1.4-2.3.1-ubuntu18.04 16 | 17 | # uncomment DCGM_FI_DEV_GPU_UTIL metric 18 | RUN sed -i '/DCGM_FI_DEV_GPU_UTIL/s/^# //g' /etc/dcgm-exporter/default-counters.csv 19 | -------------------------------------------------------------------------------- /images/prometheus-kube-state-metrics/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM k8s.gcr.io/kube-state-metrics/kube-state-metrics:v2.1.0 16 | -------------------------------------------------------------------------------- /images/prometheus-node-exporter/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM quay.io/prometheus/node-exporter:v1.3.1 16 | -------------------------------------------------------------------------------- /images/prometheus-operator/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM quay.io/prometheus-operator/prometheus-operator:v0.48.1 16 | -------------------------------------------------------------------------------- /images/prometheus-statsd-exporter/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM prom/statsd-exporter:v0.22.4 16 | -------------------------------------------------------------------------------- /images/prometheus/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | FROM quay.io/prometheus/prometheus:v2.28.0 16 | -------------------------------------------------------------------------------- /images/proxy/Dockerfile: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | ARG TARGETARCH, TARGETOS 16 | 17 | FROM golang:1.17.3 as builder 18 | 19 | WORKDIR /workspace 20 | COPY go.mod go.mod 21 | COPY go.sum go.sum 22 | RUN go mod download 23 | 24 | COPY pkg pkg 25 | COPY cmd/proxy cmd/proxy 26 | WORKDIR /workspace/cmd/proxy 27 | 28 | RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} GO111MODULE=on go build -a -o /workspace/bin/proxy main.go 29 | 30 | FROM gcr.io/distroless/static:nonroot 31 | WORKDIR / 32 | COPY --from=builder /workspace/bin/proxy . 33 | USER 65532:65532 34 | 35 | ENTRYPOINT ["/proxy"] 36 | -------------------------------------------------------------------------------- /manager/check_cortex_version.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | CORTEX_VERSION=master 20 | 21 | if [ "$CORTEX_VERSION" != "$CORTEX_CLI_VERSION" ]; then 22 | echo "error: your CLI version ($CORTEX_CLI_VERSION) doesn't match your Cortex manager image version ($CORTEX_VERSION); please update your CLI (pip install cortex==$CORTEX_VERSION) to match the version of your Cortex manager image" 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /manager/get_operator_load_balancer_state.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import boto3 16 | import os 17 | 18 | from helpers import get_operator_load_balancer_v2 19 | 20 | 21 | def get_operator_load_balancer_state(): 22 | cluster_name = os.environ["CORTEX_CLUSTER_NAME"] 23 | region = os.environ["CORTEX_REGION"] 24 | 25 | client_elbv2 = boto3.client("elbv2", region_name=region) 26 | 27 | load_balancer = get_operator_load_balancer_v2(cluster_name, client_elbv2) 28 | return load_balancer["State"]["Code"] 29 | 30 | 31 | if __name__ == "__main__": 32 | print(get_operator_load_balancer_state(), end="") 33 | -------------------------------------------------------------------------------- /manager/manifests/apis.yaml.j2: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: networking.istio.io/v1beta1 16 | kind: Gateway 17 | metadata: 18 | name: apis-gateway 19 | namespace: default 20 | spec: 21 | selector: 22 | istio: ingressgateway-apis 23 | servers: 24 | - port: 25 | number: 80 26 | name: http 27 | protocol: HTTP 28 | hosts: 29 | - "*" 30 | {% if config.get('ssl_certificate_arn', '') == '' %} 31 | - port: 32 | number: 443 33 | name: https 34 | protocol: HTTPS 35 | hosts: 36 | - "*" 37 | tls: 38 | mode: SIMPLE 39 | serverCertificate: /etc/istio/customgateway-certs/tls.crt 40 | privateKey: /etc/istio/customgateway-certs/tls.key 41 | {% else %} 42 | - port: 43 | number: 443 44 | name: https 45 | protocol: HTTP 46 | hosts: 47 | - "*" 48 | {% endif %} 49 | -------------------------------------------------------------------------------- /manager/manifests/default_cortex_cli_config.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | default_environment: default 16 | environments: 17 | - name: default 18 | operator_endpoint: http://operator.default.svc.cluster.local:8888 19 | -------------------------------------------------------------------------------- /manager/manifests/kube-proxy.patch.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # This is a patch that needs to be applied onto the daemonset that's added by eksctl. 16 | 17 | apiVersion: apps/v1 18 | kind: DaemonSet 19 | metadata: 20 | name: kube-proxy 21 | namespace: kube-system 22 | spec: 23 | selector: 24 | matchLabels: 25 | k8s-app: kube-proxy 26 | template: 27 | spec: 28 | containers: 29 | - name: kube-proxy 30 | command: 31 | - kube-proxy 32 | - --v=2 33 | - --proxy-mode=ipvs 34 | - --ipvs-scheduler=rr 35 | - --config=/var/lib/kube-proxy/config 36 | env: 37 | - name: KUBE_PROXY_MODE 38 | value: ipvs 39 | updateStrategy: 40 | rollingUpdate: 41 | maxUnavailable: 20% 42 | type: RollingUpdate 43 | -------------------------------------------------------------------------------- /manager/manifests/namespaces.yaml: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | apiVersion: v1 16 | kind: Namespace 17 | metadata: 18 | name: istio-system 19 | --- 20 | 21 | apiVersion: v1 22 | kind: Namespace 23 | metadata: 24 | name: logging 25 | --- 26 | 27 | apiVersion: v1 28 | kind: Namespace 29 | metadata: 30 | name: prometheus 31 | --- 32 | -------------------------------------------------------------------------------- /manager/requirements.txt: -------------------------------------------------------------------------------- 1 | boto3 2 | jinja2 3 | pyyaml 4 | yq 5 | click==8.0.4 6 | -------------------------------------------------------------------------------- /manager/uninstall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | set -e 18 | 19 | EKSCTL_TIMEOUT=45m 20 | 21 | function main() { 22 | echo 23 | aws eks --region $CORTEX_REGION update-kubeconfig --name $CORTEX_CLUSTER_NAME >/dev/null 24 | eksctl delete cluster --wait --name=$CORTEX_CLUSTER_NAME --region=$CORTEX_REGION --disable-nodegroup-eviction --timeout=$EKSCTL_TIMEOUT 25 | echo -e "\n✓ done spinning down the cluster" 26 | } 27 | 28 | main 29 | -------------------------------------------------------------------------------- /manager/upgrade_kube_proxy_mode.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | # Usage: python create_user.py $KUBE_PROXY_CONFIG.yaml 16 | 17 | import yaml 18 | import sys 19 | 20 | 21 | def main(): 22 | kube_proxy_config_file = sys.argv[1] 23 | with open(kube_proxy_config_file, "r") as f: 24 | kube_proxy_config = yaml.safe_load(f) 25 | 26 | kube_proxy_config["mode"] = "ipvs" # IP Virtual Server 27 | kube_proxy_config["ipvs"]["scheduler"] = "rr" # round robin 28 | 29 | print(yaml.dump(kube_proxy_config, indent=2)) 30 | 31 | 32 | if __name__ == "__main__": 33 | main() 34 | -------------------------------------------------------------------------------- /pkg/activator/api_activator_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Knative Authors 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Modifications Copyright 2022 Cortex Labs, Inc. 17 | */ 18 | 19 | package activator 20 | 21 | import ( 22 | "context" 23 | "testing" 24 | 25 | "github.com/cortexlabs/cortex/pkg/proxy" 26 | "github.com/pkg/errors" 27 | "github.com/stretchr/testify/require" 28 | ) 29 | 30 | func TestApiActivator_Try(t *testing.T) { 31 | t.Parallel() 32 | 33 | act := newAPIActivator(1, 1) 34 | 35 | errCh := make(chan error) 36 | waitCh := make(chan struct{}) 37 | 38 | for i := 0; i < 3; i++ { 39 | 40 | go func() { 41 | errCh <- act.try(context.Background(), func() error { 42 | <-waitCh 43 | return nil 44 | }, &readinessTracker{ready: true}) 45 | }() 46 | } 47 | 48 | err := <-errCh 49 | require.Error(t, err) 50 | require.True(t, errors.Is(err, proxy.ErrRequestQueueFull)) 51 | 52 | for i := 0; i < 2; i++ { 53 | waitCh <- struct{}{} 54 | require.NoError(t, <-errCh) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /pkg/async-gateway/types.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package gateway 18 | 19 | import ( 20 | "time" 21 | 22 | "github.com/cortexlabs/cortex/pkg/types/async" 23 | ) 24 | 25 | // UserResponse represents the user's API response, which has to be JSON serializable 26 | type UserResponse = map[string]interface{} 27 | 28 | //CreateWorkloadResponse represents the response returned to the user on workload creation 29 | type CreateWorkloadResponse struct { 30 | ID string `json:"id"` 31 | } 32 | 33 | // GetWorkloadResponse represents the workload response that is returned to the user 34 | type GetWorkloadResponse struct { 35 | ID string `json:"id"` 36 | Status async.Status `json:"status"` 37 | Result *UserResponse `json:"result,omitempty"` 38 | Timestamp *time.Time `json:"timestamp,omitempty"` 39 | } 40 | -------------------------------------------------------------------------------- /pkg/crds/PROJECT: -------------------------------------------------------------------------------- 1 | domain: cortex.dev 2 | layout: 3 | - go.kubebuilder.io/v3 4 | multigroup: true 5 | projectName: operator 6 | repo: github.com/cortexlabs/cortex 7 | resources: 8 | - api: 9 | crdVersion: v1 10 | namespaced: true 11 | controller: true 12 | domain: cortex.dev 13 | group: batch 14 | kind: BatchJob 15 | path: github.com/cortexlabs/cortex/pkg/crds/apis/batch/v1alpha1 16 | version: v1alpha1 17 | version: "3" 18 | -------------------------------------------------------------------------------- /pkg/crds/apis/batch/v1alpha1/groupversion_info.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | // Package v1alpha1 contains API Schema definitions for the batch v1alpha1 API group 18 | // +kubebuilder:object:generate=true 19 | // +groupName=batch.cortex.dev 20 | package v1alpha1 21 | 22 | import ( 23 | "k8s.io/apimachinery/pkg/runtime/schema" 24 | "sigs.k8s.io/controller-runtime/pkg/scheme" 25 | ) 26 | 27 | var ( 28 | // GroupVersion is group version used to register these objects 29 | GroupVersion = schema.GroupVersion{Group: "batch.cortex.dev", Version: "v1alpha1"} 30 | 31 | // SchemeBuilder is used to add go types to the GroupVersionKind scheme 32 | SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} 33 | 34 | // AddToScheme adds the types in this group-version to the given scheme. 35 | AddToScheme = SchemeBuilder.AddToScheme 36 | ) 37 | -------------------------------------------------------------------------------- /pkg/crds/config/crd/kustomization.yaml: -------------------------------------------------------------------------------- 1 | # This kustomization.yaml is not intended to be run by itself, 2 | # since it depends on service name and namespace that are out of this kustomize package. 3 | # It should be run by config/default 4 | resources: 5 | - bases/batch.cortex.dev_batchjobs.yaml 6 | #+kubebuilder:scaffold:crdkustomizeresource 7 | 8 | patchesStrategicMerge: 9 | # [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix. 10 | # patches here are for enabling the conversion webhook for each CRD 11 | #- patches/webhook_in_batchjobs.yaml 12 | #+kubebuilder:scaffold:crdkustomizewebhookpatch 13 | 14 | # [CERTMANAGER] To enable webhook, uncomment all the sections with [CERTMANAGER] prefix. 15 | # patches here are for enabling the CA injection for each CRD 16 | #- patches/cainjection_in_batchjobs.yaml 17 | #+kubebuilder:scaffold:crdkustomizecainjectionpatch 18 | 19 | # the following config is for teaching kustomize how to do kustomization for CRDs. 20 | configurations: 21 | - kustomizeconfig.yaml 22 | -------------------------------------------------------------------------------- /pkg/crds/config/crd/kustomizeconfig.yaml: -------------------------------------------------------------------------------- 1 | # This file is for teaching kustomize how to substitute name and namespace reference in CRD 2 | nameReference: 3 | - kind: Service 4 | version: v1 5 | fieldSpecs: 6 | - kind: CustomResourceDefinition 7 | version: v1 8 | group: apiextensions.k8s.io 9 | path: spec/conversion/webhook/clientConfig/service/name 10 | 11 | namespace: 12 | - kind: CustomResourceDefinition 13 | version: v1 14 | group: apiextensions.k8s.io 15 | path: spec/conversion/webhook/clientConfig/service/namespace 16 | create: false 17 | 18 | varReference: 19 | - path: metadata/annotations 20 | -------------------------------------------------------------------------------- /pkg/crds/config/crd/patches/cainjection_in_batchjobs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch adds a directive for certmanager to inject CA into the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | annotations: 6 | cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME) 7 | name: batchjobs.batch.cortex.dev 8 | -------------------------------------------------------------------------------- /pkg/crds/config/crd/patches/webhook_in_batchjobs.yaml: -------------------------------------------------------------------------------- 1 | # The following patch enables a conversion webhook for the CRD 2 | apiVersion: apiextensions.k8s.io/v1 3 | kind: CustomResourceDefinition 4 | metadata: 5 | name: batchjobs.batch.cortex.dev 6 | spec: 7 | conversion: 8 | strategy: Webhook 9 | webhook: 10 | clientConfig: 11 | service: 12 | namespace: system 13 | name: webhook-service 14 | path: /convert 15 | -------------------------------------------------------------------------------- /pkg/crds/config/default/manager_auth_proxy_patch.yaml: -------------------------------------------------------------------------------- 1 | # This patch inject a sidecar container which is a HTTP proxy for the 2 | # controller manager, it performs RBAC authorization against the Kubernetes API using SubjectAccessReviews. 3 | apiVersion: apps/v1 4 | kind: Deployment 5 | metadata: 6 | name: controller-manager 7 | namespace: system 8 | spec: 9 | template: 10 | spec: 11 | containers: 12 | - name: kube-rbac-proxy 13 | image: gcr.io/kubebuilder/kube-rbac-proxy:v0.8.0 14 | args: 15 | - "--secure-listen-address=0.0.0.0:8443" 16 | - "--upstream=http://127.0.0.1:8080/" 17 | - "--logtostderr=true" 18 | - "--v=10" 19 | ports: 20 | - containerPort: 8443 21 | name: https 22 | - name: manager 23 | args: 24 | - "--health-probe-bind-address=:8081" 25 | - "--metrics-bind-address=127.0.0.1:8080" 26 | - "--leader-elect" 27 | -------------------------------------------------------------------------------- /pkg/crds/config/default/manager_config_patch.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | spec: 7 | template: 8 | spec: 9 | containers: 10 | - name: manager 11 | args: 12 | - "--config=controller_manager_config.yaml" 13 | volumeMounts: 14 | - name: manager-config 15 | mountPath: /controller_manager_config.yaml 16 | subPath: controller_manager_config.yaml 17 | volumes: 18 | - name: manager-config 19 | configMap: 20 | name: manager-config 21 | -------------------------------------------------------------------------------- /pkg/crds/config/manager/controller_manager_config.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: controller-runtime.sigs.k8s.io/v1alpha1 2 | kind: ControllerManagerConfig 3 | health: 4 | healthProbeBindAddress: :8081 5 | metrics: 6 | bindAddress: 127.0.0.1:8080 7 | webhook: 8 | port: 9443 9 | leaderElection: 10 | leaderElect: true 11 | resourceName: 7cc92962.cortex.dev 12 | -------------------------------------------------------------------------------- /pkg/crds/config/manager/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - manager.yaml 3 | 4 | generatorOptions: 5 | disableNameSuffixHash: true 6 | 7 | configMapGenerator: 8 | - files: 9 | - controller_manager_config.yaml 10 | name: manager-config 11 | apiVersion: kustomize.config.k8s.io/v1beta1 12 | kind: Kustomization 13 | -------------------------------------------------------------------------------- /pkg/crds/config/prometheus/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | - monitor.yaml 3 | -------------------------------------------------------------------------------- /pkg/crds/config/prometheus/monitor.yaml: -------------------------------------------------------------------------------- 1 | # Prometheus Monitor Service (Metrics) 2 | apiVersion: monitoring.coreos.com/v1 3 | kind: ServiceMonitor 4 | metadata: 5 | labels: 6 | control-plane: controller-manager 7 | name: controller-manager-metrics-monitor 8 | namespace: system 9 | spec: 10 | endpoints: 11 | - path: /metrics 12 | port: https 13 | scheme: https 14 | bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token 15 | tlsConfig: 16 | insecureSkipVerify: true 17 | selector: 18 | matchLabels: 19 | control-plane: controller-manager 20 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/auth_proxy_client_clusterrole.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: metrics-reader 5 | rules: 6 | - nonResourceURLs: 7 | - "/metrics" 8 | verbs: 9 | - get 10 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/auth_proxy_role.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRole 3 | metadata: 4 | name: proxy-role 5 | rules: 6 | - apiGroups: 7 | - authentication.k8s.io 8 | resources: 9 | - tokenreviews 10 | verbs: 11 | - create 12 | - apiGroups: 13 | - authorization.k8s.io 14 | resources: 15 | - subjectaccessreviews 16 | verbs: 17 | - create 18 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/auth_proxy_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: proxy-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: proxy-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/auth_proxy_service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | labels: 5 | control-plane: controller-manager 6 | name: controller-manager-metrics-service 7 | namespace: system 8 | spec: 9 | ports: 10 | - name: https 11 | port: 8443 12 | targetPort: https 13 | selector: 14 | control-plane: controller-manager 15 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/batchjob_editor_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to edit batchjobs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: batchjob-editor-role 6 | rules: 7 | - apiGroups: 8 | - batch.cortex.dev 9 | resources: 10 | - batchjobs 11 | verbs: 12 | - create 13 | - delete 14 | - get 15 | - list 16 | - patch 17 | - update 18 | - watch 19 | - apiGroups: 20 | - batch.cortex.dev 21 | resources: 22 | - batchjobs/status 23 | verbs: 24 | - get 25 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/batchjob_viewer_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions for end users to view batchjobs. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | name: batchjob-viewer-role 6 | rules: 7 | - apiGroups: 8 | - batch.cortex.dev 9 | resources: 10 | - batchjobs 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - apiGroups: 16 | - batch.cortex.dev 17 | resources: 18 | - batchjobs/status 19 | verbs: 20 | - get 21 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/kustomization.yaml: -------------------------------------------------------------------------------- 1 | resources: 2 | # All RBAC will be applied under this service account in 3 | # the deployment namespace. You may comment out this resource 4 | # if your manager will use a service account that exists at 5 | # runtime. Be sure to update RoleBinding and ClusterRoleBinding 6 | # subjects if changing service account names. 7 | - service_account.yaml 8 | - role.yaml 9 | - role_binding.yaml 10 | - leader_election_role.yaml 11 | - leader_election_role_binding.yaml 12 | # Comment the following 4 lines if you want to disable 13 | # the auth proxy (https://github.com/brancz/kube-rbac-proxy) 14 | # which protects your /metrics endpoint. 15 | - auth_proxy_service.yaml 16 | - auth_proxy_role.yaml 17 | - auth_proxy_role_binding.yaml 18 | - auth_proxy_client_clusterrole.yaml 19 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/leader_election_role.yaml: -------------------------------------------------------------------------------- 1 | # permissions to do leader election. 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: Role 4 | metadata: 5 | name: leader-election-role 6 | rules: 7 | - apiGroups: 8 | - "" 9 | resources: 10 | - configmaps 11 | verbs: 12 | - get 13 | - list 14 | - watch 15 | - create 16 | - update 17 | - patch 18 | - delete 19 | - apiGroups: 20 | - coordination.k8s.io 21 | resources: 22 | - leases 23 | verbs: 24 | - get 25 | - list 26 | - watch 27 | - create 28 | - update 29 | - patch 30 | - delete 31 | - apiGroups: 32 | - "" 33 | resources: 34 | - events 35 | verbs: 36 | - create 37 | - patch 38 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/leader_election_role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: RoleBinding 3 | metadata: 4 | name: leader-election-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: Role 8 | name: leader-election-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/role.yaml: -------------------------------------------------------------------------------- 1 | --- 2 | apiVersion: rbac.authorization.k8s.io/v1 3 | kind: ClusterRole 4 | metadata: 5 | creationTimestamp: null 6 | name: manager-role 7 | rules: 8 | - apiGroups: 9 | - "" 10 | resources: 11 | - configmaps 12 | verbs: 13 | - create 14 | - get 15 | - list 16 | - watch 17 | - apiGroups: 18 | - "" 19 | resources: 20 | - pods 21 | verbs: 22 | - get 23 | - list 24 | - watch 25 | - apiGroups: 26 | - batch 27 | resources: 28 | - jobs 29 | verbs: 30 | - create 31 | - get 32 | - list 33 | - patch 34 | - update 35 | - watch 36 | - apiGroups: 37 | - batch.cortex.dev 38 | resources: 39 | - batchjobs 40 | verbs: 41 | - create 42 | - delete 43 | - get 44 | - list 45 | - patch 46 | - update 47 | - watch 48 | - apiGroups: 49 | - batch.cortex.dev 50 | resources: 51 | - batchjobs/finalizers 52 | verbs: 53 | - update 54 | - apiGroups: 55 | - batch.cortex.dev 56 | resources: 57 | - batchjobs/status 58 | verbs: 59 | - get 60 | - patch 61 | - update 62 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/role_binding.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: rbac.authorization.k8s.io/v1 2 | kind: ClusterRoleBinding 3 | metadata: 4 | name: manager-rolebinding 5 | roleRef: 6 | apiGroup: rbac.authorization.k8s.io 7 | kind: ClusterRole 8 | name: manager-role 9 | subjects: 10 | - kind: ServiceAccount 11 | name: controller-manager 12 | namespace: system 13 | -------------------------------------------------------------------------------- /pkg/crds/config/rbac/service_account.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ServiceAccount 3 | metadata: 4 | name: controller-manager 5 | namespace: system 6 | -------------------------------------------------------------------------------- /pkg/crds/config/samples/batch_v1alpha1_batchjob.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: batch.cortex.dev/v1alpha1 2 | kind: BatchJob 3 | metadata: 4 | name: "123456" 5 | spec: 6 | api_name: "image-classifier" 7 | api_id: "123456" 8 | workers: 1 9 | config: | 10 | dest_s3_dir: s3://abc/123 11 | ttl: "10s" 12 | -------------------------------------------------------------------------------- /pkg/crds/controllers/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package controllers 18 | 19 | import ( 20 | "strings" 21 | 22 | kerrors "k8s.io/apimachinery/pkg/api/errors" 23 | ) 24 | 25 | const ( 26 | _optimisticLockErrorMessage = "the object has been modified; please apply your changes to the latest version and try again" 27 | ) 28 | 29 | // IsOptimisticLockError checks if an error is an optimistic lock error 30 | func IsOptimisticLockError(err error) bool { 31 | return kerrors.IsConflict(err) && strings.Contains(err.Error(), _optimisticLockErrorMessage) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/crds/hack/boilerplate.go.txt: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | -------------------------------------------------------------------------------- /pkg/crds/hack/run_manager.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # This is a subset of lint.sh, and is only meant to be run on master 18 | 19 | CLUSTER_CONFIG=$1 20 | 21 | port_forward_cmd="kubectl port-forward -n prometheus prometheus-prometheus-0 9090" 22 | kill $(pgrep -f "${port_forward_cmd}") >/dev/null 2>&1 || true 23 | 24 | echo "Port-forwarding Prometheus to localhost:9090" 25 | eval "${port_forward_cmd}" >/dev/null 2>&1 & 26 | 27 | CORTEX_DISABLE_JSON_LOGGING="true" \ 28 | CORTEX_PROMETHEUS_URL="http://localhost:9090" \ 29 | go run ./main.go -config "${CLUSTER_CONFIG}" 30 | -------------------------------------------------------------------------------- /pkg/dequeuer/http_handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package dequeuer 18 | 19 | import "net/http" 20 | 21 | func HealthcheckHandler(isHealthy func() bool) http.HandlerFunc { 22 | return func(w http.ResponseWriter, r *http.Request) { 23 | if !isHealthy() { 24 | w.WriteHeader(http.StatusInternalServerError) 25 | _, _ = w.Write([]byte("unhealthy")) 26 | return 27 | } 28 | 29 | w.WriteHeader(http.StatusOK) 30 | _, _ = w.Write([]byte("healthy")) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /pkg/dequeuer/message_handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package dequeuer 18 | 19 | import "github.com/aws/aws-sdk-go/service/sqs" 20 | 21 | type MessageHandler interface { 22 | Handle(*sqs.Message) error 23 | } 24 | 25 | func NewMessageHandlerFunc(handleFunc func(*sqs.Message) error) MessageHandler { 26 | return &messageHandlerFunc{HandleFunc: handleFunc} 27 | } 28 | 29 | type messageHandlerFunc struct { 30 | HandleFunc func(message *sqs.Message) error 31 | } 32 | 33 | func (h *messageHandlerFunc) Handle(msg *sqs.Message) error { 34 | return h.HandleFunc(msg) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/dequeuer/request_stats.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package dequeuer 18 | 19 | import "time" 20 | 21 | type RequestEvent struct { 22 | StatusCode int 23 | Duration time.Duration 24 | } 25 | 26 | type RequestEventHandler interface { 27 | HandleEvent(event RequestEvent) 28 | } 29 | 30 | type requestEventHandlerFunc struct { 31 | HandleFunc func(event RequestEvent) 32 | } 33 | 34 | func (h *requestEventHandlerFunc) HandleEvent(event RequestEvent) { 35 | h.HandleFunc(event) 36 | } 37 | 38 | func NewRequestEventHandlerFunc(handleFunc func(event RequestEvent)) RequestEventHandler { 39 | return &requestEventHandlerFunc{ 40 | HandleFunc: handleFunc, 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pkg/enqueuer/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package enqueuer 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | ) 24 | 25 | const ( 26 | ErrFailedToEnqueueMessages = "batchapi.failed_to_enqueue_messages" 27 | ErrMessageExceedsMaxSize = "batchapi.message_exceeds_max_size" 28 | ) 29 | 30 | func ErrorFailedToEnqueueMessages(message string) error { 31 | return errors.WithStack(&errors.Error{ 32 | Kind: ErrFailedToEnqueueMessages, 33 | Message: message, 34 | }) 35 | } 36 | 37 | func ErrorMessageExceedsMaxSize(messageSize int, messageLimit int) error { 38 | return errors.WithStack(&errors.Error{ 39 | Kind: ErrMessageExceedsMaxSize, 40 | Message: fmt.Sprintf("cannot enqueue message because its size of %d bytes exceeds the %d bytes limit; use a smaller batch size or reduce the size of each of item in the batch", messageSize, messageLimit), 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/lib/archive/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package archive 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 24 | ) 25 | 26 | const ( 27 | _errStrCreateArchive = "unable to create archive" 28 | _errStrCreateZip = "unable to create zip file" 29 | _errStrCreateTar = "unable to create tar file" 30 | _errStrUnzip = "unable to unzip file" 31 | _errStrUntar = "unable to extract tar file" 32 | ) 33 | 34 | const ( 35 | ErrDuplicatePath = "archive.duplicate_path" 36 | ) 37 | 38 | func ErrorDuplicatePath(path string) error { 39 | return errors.WithStack(&errors.Error{ 40 | Kind: ErrDuplicatePath, 41 | Message: fmt.Sprintf("duplicate path was provided (%s)", s.UserStr(path)), 42 | }) 43 | } 44 | -------------------------------------------------------------------------------- /pkg/lib/aws/acm.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package aws 18 | 19 | import ( 20 | "github.com/aws/aws-sdk-go/aws" 21 | "github.com/aws/aws-sdk-go/service/acm" 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | ) 24 | 25 | func (c *Client) DoesCertificateExist(sslCertificateARN string) (bool, error) { 26 | _, err := c.ACM().DescribeCertificate(&acm.DescribeCertificateInput{ 27 | CertificateArn: aws.String(sslCertificateARN), 28 | }) 29 | 30 | if err != nil { 31 | if IsErrCode(err, "ResourceNotFoundException") { 32 | return false, nil 33 | } 34 | return false, errors.Wrap(err, sslCertificateARN) 35 | } 36 | 37 | return true, nil 38 | } 39 | -------------------------------------------------------------------------------- /pkg/lib/aws/eks.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package aws 18 | 19 | import ( 20 | "github.com/aws/aws-sdk-go/service/eks" 21 | "github.com/cortexlabs/cortex/pkg/lib/errors" 22 | "github.com/cortexlabs/cortex/pkg/lib/sets/strset" 23 | ) 24 | 25 | var EKSSupportedRegions strset.Set 26 | 27 | func init() { 28 | EKSSupportedRegions = strset.New() 29 | for region := range InstanceMetadatas { 30 | EKSSupportedRegions.Add(region) 31 | } 32 | } 33 | 34 | // Returns info for the cluster, or nil of no cluster exists with the provided name 35 | func (c *Client) EKSClusterOrNil(clusterName string) (*eks.Cluster, error) { 36 | clusterInfo, err := c.EKS().DescribeCluster(&eks.DescribeClusterInput{Name: &clusterName}) 37 | if err != nil { 38 | if IsErrCode(err, eks.ErrCodeResourceNotFoundException) { 39 | return nil, nil 40 | } 41 | return nil, errors.WithStack(err) 42 | } 43 | 44 | return clusterInfo.Cluster, nil 45 | } 46 | -------------------------------------------------------------------------------- /pkg/lib/console/format.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package console 18 | 19 | import ( 20 | "github.com/fatih/color" 21 | ) 22 | 23 | var _bold = color.New(color.Bold).SprintFunc() 24 | 25 | // Bold returns a string formatted in bold 26 | func Bold(a ...interface{}) string { 27 | return _bold(a...) 28 | } 29 | 30 | // BoolColor converts a boolean into a colored string (green: true, red: false) 31 | func BoolColor(b bool) string { 32 | if b { 33 | return color.GreenString("%t", b) 34 | } 35 | return color.RedString("%t", b) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/lib/errors/stack.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package errors 18 | 19 | import ( 20 | "fmt" 21 | "runtime" 22 | 23 | pkgerrors "github.com/pkg/errors" 24 | ) 25 | 26 | type stack []uintptr 27 | 28 | func callers() *stack { 29 | const depth = 32 30 | var pcs [depth]uintptr 31 | n := runtime.Callers(3, pcs[:]) 32 | var st stack = pcs[0:n] 33 | return &st 34 | } 35 | 36 | func (s *stack) Format(st fmt.State, verb rune) { 37 | switch verb { 38 | case 'v': 39 | switch { 40 | case st.Flag('+'): 41 | for _, pc := range *s { 42 | f := pkgerrors.Frame(pc) 43 | fmt.Fprintf(st, "\n%+v", f) 44 | } 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /pkg/lib/hash/hash.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package hash 18 | 19 | import ( 20 | "crypto/sha256" 21 | "encoding/hex" 22 | "strings" 23 | 24 | "github.com/cortexlabs/cortex/pkg/lib/files" 25 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 26 | ) 27 | 28 | // Bytes will trim to 63 characters because e.g. K8s labels must be < 64 29 | func Bytes(bytes []byte) string { 30 | hash := sha256.New() 31 | hash.Write(bytes) 32 | str := hex.EncodeToString(hash.Sum(nil)) 33 | return str[:63] 34 | } 35 | 36 | func String(str string) string { 37 | return Bytes([]byte(str)) 38 | } 39 | 40 | func Strings(strs ...string) string { 41 | return String(strings.Join(strs, ",")) 42 | } 43 | 44 | func Any(obj interface{}) string { 45 | return String(s.Obj(obj)) 46 | } 47 | 48 | func File(path string) (string, error) { 49 | fileBytes, err := files.ReadFileBytes(path) 50 | if err != nil { 51 | return "", err 52 | } 53 | return Bytes(fileBytes), nil 54 | } 55 | -------------------------------------------------------------------------------- /pkg/lib/json/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package json 18 | 19 | const ( 20 | errStrMarshalJSON = "invalid json" 21 | errStrUnmarshalJSON = "invalid json cannot be serialized" 22 | ) 23 | -------------------------------------------------------------------------------- /pkg/lib/k8s/volume.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package k8s 18 | 19 | import ( 20 | kcore "k8s.io/api/core/v1" 21 | ) 22 | 23 | func EmptyDirVolume(volumeName string) kcore.Volume { 24 | return kcore.Volume{ 25 | Name: volumeName, 26 | VolumeSource: kcore.VolumeSource{ 27 | EmptyDir: &kcore.EmptyDirVolumeSource{}, 28 | }, 29 | } 30 | } 31 | 32 | func EmptyDirVolumeMount(volumeName string, mountPath string) kcore.VolumeMount { 33 | return kcore.VolumeMount{ 34 | Name: volumeName, 35 | MountPath: mountPath, 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /pkg/lib/logging/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package logging 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 24 | ) 25 | 26 | const ( 27 | ErrInvalidLogLevel = "logging.invalid_log_level" 28 | ) 29 | 30 | func ErrorInvalidLogLevel(provided string, loglevels []string) error { 31 | return errors.WithStack(&errors.Error{ 32 | Kind: ErrInvalidLogLevel, 33 | Message: fmt.Sprintf("invalid log level %s; must be one of %s", provided, s.StrsOr(loglevels)), 34 | }) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/lib/math/float32.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package math 18 | 19 | func MinFloat32(val float32, vals ...float32) float32 { 20 | min := val 21 | for _, v := range vals { 22 | if v < min { 23 | min = v 24 | } 25 | } 26 | return min 27 | } 28 | 29 | func MaxFloat32(val float32, vals ...float32) float32 { 30 | max := val 31 | for _, v := range vals { 32 | if v > max { 33 | max = v 34 | } 35 | } 36 | return max 37 | } 38 | -------------------------------------------------------------------------------- /pkg/lib/math/float64.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package math 18 | 19 | func MinFloat64(val float64, vals ...float64) float64 { 20 | min := val 21 | for _, v := range vals { 22 | if v < min { 23 | min = v 24 | } 25 | } 26 | return min 27 | } 28 | 29 | func MaxFloat64(val float64, vals ...float64) float64 { 30 | max := val 31 | for _, v := range vals { 32 | if v > max { 33 | max = v 34 | } 35 | } 36 | return max 37 | } 38 | -------------------------------------------------------------------------------- /pkg/lib/msgpack/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package msgpack 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | ) 22 | 23 | const ( 24 | ErrUnmarshalMsgpack = "msgpack.unmarshal_msgpack" 25 | ErrMarshalMsgpack = "msgpack.marshal_msgpack" 26 | ) 27 | 28 | func ErrorUnmarshalMsgpack() error { 29 | return errors.WithStack(&errors.Error{ 30 | Kind: ErrUnmarshalMsgpack, 31 | Message: "invalid messagepack", 32 | }) 33 | } 34 | 35 | func ErrorMarshalMsgpack() error { 36 | return errors.WithStack(&errors.Error{ 37 | Kind: ErrMarshalMsgpack, 38 | Message: "invalid messagepack cannot be serialized", 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/lib/pointer/pointer_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package pointer 18 | 19 | import ( 20 | "testing" 21 | ) 22 | 23 | func TestIndirectSafe(t *testing.T) { 24 | IndirectSafe(nil) 25 | IndirectSafe("") 26 | IndirectSafe([]string{}) 27 | var s []string 28 | IndirectSafe(s) 29 | } 30 | -------------------------------------------------------------------------------- /pkg/lib/prompt/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package prompt 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | ) 22 | 23 | const ( 24 | ErrUserNoContinue = "prompt.user_no_continue" 25 | ErrUserCtrlC = "prompt.user_ctrl_c" 26 | ) 27 | 28 | func ErrorUserNoContinue() error { 29 | return errors.WithStack(&errors.Error{ 30 | Kind: ErrUserNoContinue, 31 | NoPrint: true, 32 | NoTelemetry: true, 33 | }) 34 | } 35 | 36 | func ErrorUserCtrlC() error { 37 | return errors.WithStack(&errors.Error{ 38 | Kind: ErrUserCtrlC, 39 | NoPrint: true, 40 | NoTelemetry: true, 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/lib/requests/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package requests 18 | 19 | import ( 20 | "fmt" 21 | "net/url" 22 | "strings" 23 | 24 | "github.com/cortexlabs/cortex/pkg/lib/errors" 25 | "github.com/cortexlabs/cortex/pkg/lib/urls" 26 | ) 27 | 28 | const ( 29 | _errStrCantMakeRequest = "unable to make request" 30 | _errStrRead = "unable to read" 31 | ) 32 | 33 | func errStrFailedToConnect(u url.URL) string { 34 | return "failed to connect to " + urls.TrimQueryParamsURL(u) 35 | } 36 | 37 | const ( 38 | ErrResponseUnknown = "requests.response_unknown" 39 | ) 40 | 41 | func ErrorResponseUnknown(body string, statusCode int) error { 42 | msg := body 43 | if strings.TrimSpace(body) == "" { 44 | msg = fmt.Sprintf("empty response (status code %d)", statusCode) 45 | } 46 | 47 | return errors.WithStack(&errors.Error{ 48 | Kind: ErrResponseUnknown, 49 | Message: msg, 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /pkg/lib/slices/bool.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | func HasTrue(list []bool) bool { 20 | for _, elem := range list { 21 | if elem { 22 | return true 23 | } 24 | } 25 | return false 26 | } 27 | -------------------------------------------------------------------------------- /pkg/lib/slices/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | ) 22 | 23 | const ( 24 | ErrLenValuesWeightsMismatch = "slices.len_values_weights_mismatch" 25 | ) 26 | 27 | func ErrorLenValuesWeightsMismatch() error { 28 | return errors.WithStack(&errors.Error{ 29 | Kind: ErrLenValuesWeightsMismatch, 30 | Message: "length of values is not equal to length of weights", 31 | }) 32 | } 33 | -------------------------------------------------------------------------------- /pkg/lib/slices/float32.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 21 | ) 22 | 23 | func HasFloat32(list []float32, query float32) bool { 24 | for _, elem := range list { 25 | if elem == query { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func CopyFloat32s(vals []float32) []float32 { 33 | return append(vals[:0:0], vals...) 34 | } 35 | 36 | func Float32ToString(vals []float32) []string { 37 | stringSlice := []string{} 38 | for _, elem := range vals { 39 | stringSlice = append(stringSlice, s.Float32(elem)) 40 | } 41 | return stringSlice 42 | } 43 | -------------------------------------------------------------------------------- /pkg/lib/slices/float64.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 21 | ) 22 | 23 | func HasFloat64(list []float64, query float64) bool { 24 | for _, elem := range list { 25 | if elem == query { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func CopyFloat64s(vals []float64) []float64 { 33 | return append(vals[:0:0], vals...) 34 | } 35 | 36 | func Float64ToString(vals []float64) []string { 37 | stringSlice := []string{} 38 | for _, elem := range vals { 39 | stringSlice = append(stringSlice, s.Float64(elem)) 40 | } 41 | return stringSlice 42 | } 43 | -------------------------------------------------------------------------------- /pkg/lib/slices/int.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 21 | ) 22 | 23 | func HasInt(list []int, query int) bool { 24 | for _, elem := range list { 25 | if elem == query { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func CopyInts(vals []int) []int { 33 | return append(vals[:0:0], vals...) 34 | } 35 | 36 | func AreNGreaterThanZero(minCount int, val int, vals ...int) bool { 37 | count := 0 38 | allVals := append(vals, val) 39 | for _, val := range allVals { 40 | if val > 0 { 41 | count++ 42 | if count >= minCount { 43 | return true 44 | } 45 | } 46 | } 47 | return false 48 | } 49 | 50 | func IntToString(vals []int) []string { 51 | stringSlice := []string{} 52 | for _, elem := range vals { 53 | stringSlice = append(stringSlice, s.Int(elem)) 54 | } 55 | return stringSlice 56 | } 57 | -------------------------------------------------------------------------------- /pkg/lib/slices/int32.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 21 | ) 22 | 23 | func HasInt32(list []int32, query int32) bool { 24 | for _, elem := range list { 25 | if elem == query { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func CopyInt32s(vals []int32) []int32 { 33 | return append(vals[:0:0], vals...) 34 | } 35 | 36 | func Int32ToString(vals []int32) []string { 37 | stringSlice := []string{} 38 | for _, elem := range vals { 39 | stringSlice = append(stringSlice, s.Int32(elem)) 40 | } 41 | return stringSlice 42 | } 43 | -------------------------------------------------------------------------------- /pkg/lib/slices/int64.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package slices 18 | 19 | import ( 20 | s "github.com/cortexlabs/cortex/pkg/lib/strings" 21 | ) 22 | 23 | func HasInt64(list []int64, query int64) bool { 24 | for _, elem := range list { 25 | if elem == query { 26 | return true 27 | } 28 | } 29 | return false 30 | } 31 | 32 | func CopyInt64s(vals []int64) []int64 { 33 | return append(vals[:0:0], vals...) 34 | } 35 | 36 | func UniqueInt64(vals []int64) []int64 { 37 | keys := make(map[int64]bool) 38 | list := []int64{} 39 | for _, entry := range vals { 40 | if _, value := keys[entry]; !value { 41 | keys[entry] = true 42 | list = append(list, entry) 43 | } 44 | } 45 | return list 46 | } 47 | 48 | func Int64ToString(vals []int64) []string { 49 | stringSlice := []string{} 50 | for _, elem := range vals { 51 | stringSlice = append(stringSlice, s.Int64(elem)) 52 | } 53 | return stringSlice 54 | } 55 | -------------------------------------------------------------------------------- /pkg/lib/structs/deepcopy.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package structs 18 | 19 | import ( 20 | "bytes" 21 | "encoding/gob" 22 | ) 23 | 24 | func DeepCopy(dst, src interface{}) error { 25 | var buf bytes.Buffer 26 | if err := gob.NewEncoder(&buf).Encode(src); err != nil { 27 | return err 28 | } 29 | return gob.NewDecoder(bytes.NewBuffer(buf.Bytes())).Decode(dst) 30 | } 31 | -------------------------------------------------------------------------------- /pkg/lib/telemetry/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package telemetry 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | ) 22 | 23 | const ( 24 | ErrUserIDNotSpecified = "telemetry.user_id_not_specified" 25 | ErrSentryFlushTimeoutExceeded = "telemetry.sentry_flush_timeout_exceeded" 26 | ) 27 | 28 | func ErrorUserIDNotSpecified() error { 29 | return errors.WithStack(&errors.Error{ 30 | Kind: ErrUserIDNotSpecified, 31 | Message: "user ID must be specified to enable telemetry", 32 | }) 33 | } 34 | 35 | func ErrorSentryFlushTimeoutExceeded() error { 36 | return errors.WithStack(&errors.Error{ 37 | Kind: ErrSentryFlushTimeoutExceeded, 38 | Message: "sentry flush timout exceeded", 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /pkg/operator/endpoints/delete.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package endpoints 18 | 19 | import ( 20 | "net/http" 21 | 22 | "github.com/cortexlabs/cortex/pkg/operator/resources" 23 | "github.com/gorilla/mux" 24 | ) 25 | 26 | func Delete(w http.ResponseWriter, r *http.Request) { 27 | apiName := mux.Vars(r)["apiName"] 28 | keepCache := getOptionalBoolQParam("keepCache", false, r) 29 | 30 | response, err := resources.DeleteAPI(apiName, keepCache) 31 | if err != nil { 32 | respondError(w, r, err) 33 | return 34 | } 35 | respondJSON(w, r, response) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/operator/endpoints/describe.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package endpoints 18 | 19 | import ( 20 | "net/http" 21 | 22 | "github.com/cortexlabs/cortex/pkg/operator/resources" 23 | "github.com/gorilla/mux" 24 | ) 25 | 26 | func DescribeAPI(w http.ResponseWriter, r *http.Request) { 27 | apiName := mux.Vars(r)["apiName"] 28 | 29 | response, err := resources.DescribeAPI(apiName) 30 | if err != nil { 31 | respondError(w, r, err) 32 | return 33 | } 34 | 35 | respondJSON(w, r, response) 36 | } 37 | -------------------------------------------------------------------------------- /pkg/operator/endpoints/refresh.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package endpoints 18 | 19 | import ( 20 | "net/http" 21 | 22 | "github.com/cortexlabs/cortex/pkg/operator/resources" 23 | "github.com/cortexlabs/cortex/pkg/operator/schema" 24 | "github.com/gorilla/mux" 25 | ) 26 | 27 | func Refresh(w http.ResponseWriter, r *http.Request) { 28 | apiName := mux.Vars(r)["apiName"] 29 | force := getOptionalBoolQParam("force", false, r) 30 | 31 | msg, err := resources.RefreshAPI(apiName, force) 32 | if err != nil { 33 | respondError(w, r, err) 34 | return 35 | } 36 | 37 | response := schema.RefreshResponse{ 38 | Message: msg, 39 | } 40 | respondJSON(w, r, response) 41 | } 42 | -------------------------------------------------------------------------------- /pkg/operator/endpoints/verify_cortex.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package endpoints 18 | 19 | import ( 20 | "net/http" 21 | 22 | "github.com/cortexlabs/cortex/pkg/operator/schema" 23 | ) 24 | 25 | func VerifyCortex(w http.ResponseWriter, r *http.Request) { 26 | respondJSON(w, r, schema.VerifyCortexResponse{}) 27 | } 28 | -------------------------------------------------------------------------------- /pkg/operator/lib/routines/routines.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package routines 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/lib/errors" 21 | "github.com/cortexlabs/cortex/pkg/lib/logging" 22 | "github.com/cortexlabs/cortex/pkg/lib/telemetry" 23 | ) 24 | 25 | var operatorLogger = logging.GetLogger() 26 | 27 | func RunWithPanicHandler(f func()) { 28 | go func() { 29 | defer func() { 30 | if r := recover(); r != nil { 31 | err := errors.CastRecoverError(r) 32 | operatorLogger.Error(err) 33 | telemetry.Error(err) 34 | } 35 | }() 36 | f() 37 | }() 38 | } 39 | -------------------------------------------------------------------------------- /pkg/operator/operator/deployed_resource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package operator 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/types/userconfig" 21 | istioclientnetworking "istio.io/client-go/pkg/apis/networking/v1beta1" 22 | ) 23 | 24 | type DeployedResource struct { 25 | userconfig.Resource 26 | VirtualService *istioclientnetworking.VirtualService 27 | } 28 | 29 | func (deployedResourced *DeployedResource) ID() string { 30 | return deployedResourced.VirtualService.Labels["apiID"] 31 | } 32 | -------------------------------------------------------------------------------- /pkg/operator/resources/asyncapi/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package asyncapi 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | ) 24 | 25 | const ( 26 | ErrAPIUpdating = "asyncapi.api_updating" 27 | ) 28 | 29 | func ErrorAPIUpdating(apiName string) error { 30 | return errors.WithStack(&errors.Error{ 31 | Kind: ErrAPIUpdating, 32 | Message: fmt.Sprintf("%s is updating (override with --force)", apiName), 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/operator/resources/job/batchapi/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package batchapi 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | ) 24 | 25 | const ( 26 | ErrNoS3FilesFound = "batchapi.no_s3_files_found" 27 | ErrBatchItemSizeExceedsLimit = "batchapi.item_size_exceeds_limit" 28 | ) 29 | 30 | func ErrorNoS3FilesFound() error { 31 | return errors.WithStack(&errors.Error{ 32 | Kind: ErrNoS3FilesFound, 33 | Message: "no s3 files match search criteria", 34 | }) 35 | } 36 | 37 | func ErrorItemSizeExceedsLimit(index int, size int, limit int) error { 38 | return errors.WithStack(&errors.Error{ 39 | Kind: ErrBatchItemSizeExceedsLimit, 40 | Message: fmt.Sprintf("item %d has size %d bytes which exceeds the limit (%d bytes)", index, size, limit), 41 | }) 42 | } 43 | -------------------------------------------------------------------------------- /pkg/operator/resources/job/consts.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package job 18 | 19 | import "github.com/cortexlabs/cortex/pkg/types/userconfig" 20 | 21 | const ( 22 | _jobsPrefix = "jobs" 23 | _inProgressFilePrefix = "in_progress" 24 | _enqueuingLivenessFile = "enqueuing_liveness" 25 | ) 26 | 27 | var _jobKinds = map[userconfig.Kind]bool{ 28 | userconfig.TaskAPIKind: true, 29 | userconfig.BatchAPIKind: true, 30 | } 31 | 32 | func LivenessFile() string { 33 | return _enqueuingLivenessFile 34 | } 35 | -------------------------------------------------------------------------------- /pkg/operator/resources/job/taskapi/validations.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package taskapi 18 | 19 | import ( 20 | cr "github.com/cortexlabs/cortex/pkg/lib/configreader" 21 | "github.com/cortexlabs/cortex/pkg/lib/errors" 22 | "github.com/cortexlabs/cortex/pkg/operator/schema" 23 | ) 24 | 25 | func validateJobSubmission(submission *schema.TaskJobSubmission) error { 26 | if submission.Workers != 1 { 27 | return errors.Wrap(cr.ErrorInvalidInt(submission.Workers, 1), schema.WorkersKey) 28 | } 29 | 30 | return nil 31 | } 32 | -------------------------------------------------------------------------------- /pkg/operator/resources/realtimeapi/errors.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package realtimeapi 18 | 19 | import ( 20 | "fmt" 21 | 22 | "github.com/cortexlabs/cortex/pkg/lib/errors" 23 | ) 24 | 25 | const ( 26 | ErrAPIUpdating = "realtimeapi.api_updating" 27 | ) 28 | 29 | func ErrorAPIUpdating(apiName string) error { 30 | return errors.WithStack(&errors.Error{ 31 | Kind: ErrAPIUpdating, 32 | Message: fmt.Sprintf("%s is updating (override with --force)", apiName), 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /pkg/operator/schema/config_key.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package schema 18 | 19 | const ( 20 | // Job Submission 21 | BatchSizeKey = "batch_size" 22 | ItemsKey = "items" 23 | ItemListKey = "item_list" 24 | FilePathListerKey = "file_path_lister" 25 | DelimitedFilesKey = "delimited_files" 26 | S3PathsKey = "s3_paths" 27 | IncludesKey = "includes" 28 | ExcludesKey = "excludes" 29 | WorkersKey = "workers" 30 | TimeoutKey = "timeout" 31 | MaxReceiveCountKey = "max_receive_count" 32 | ARNKey = "arn" 33 | SQSDeadLetterQueueKey = "sqs_dead_letter_queue" 34 | ) 35 | -------------------------------------------------------------------------------- /pkg/probe/handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package probe 18 | 19 | import ( 20 | "net/http" 21 | "strings" 22 | 23 | "github.com/cortexlabs/cortex/pkg/consts" 24 | ) 25 | 26 | func IsRequestKubeletProbe(r *http.Request) bool { 27 | return strings.HasPrefix(r.Header.Get(consts.UserAgentKey), consts.KubeProbeUserAgentPrefix) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/proxy/handler.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Knative Authors 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Modifications Copyright 2022 Cortex Labs, Inc. 17 | */ 18 | 19 | package proxy 20 | 21 | import ( 22 | "context" 23 | "errors" 24 | "net/http" 25 | 26 | "github.com/cortexlabs/cortex/pkg/lib/telemetry" 27 | "github.com/cortexlabs/cortex/pkg/probe" 28 | ) 29 | 30 | func Handler(breaker *Breaker, next http.Handler) http.HandlerFunc { 31 | return func(w http.ResponseWriter, r *http.Request) { 32 | if probe.IsRequestKubeletProbe(r) || breaker == nil { 33 | next.ServeHTTP(w, r) 34 | return 35 | } 36 | 37 | if err := breaker.Maybe(r.Context(), func() { 38 | next.ServeHTTP(w, r) 39 | }); err != nil { 40 | if errors.Is(err, context.DeadlineExceeded) || errors.Is(err, ErrRequestQueueFull) { 41 | http.Error(w, err.Error(), http.StatusServiceUnavailable) 42 | } else { 43 | w.WriteHeader(http.StatusInternalServerError) 44 | telemetry.Error(err) 45 | } 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /pkg/proxy/proxy_test.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2018 The Knative Authors 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | 16 | Modifications Copyright 2022 Cortex Labs, Inc. 17 | */ 18 | 19 | package proxy_test 20 | 21 | import ( 22 | "net/http" 23 | "net/http/httptest" 24 | "testing" 25 | 26 | "github.com/cortexlabs/cortex/pkg/proxy" 27 | "github.com/stretchr/testify/require" 28 | ) 29 | 30 | func TestNewReverseProxy(t *testing.T) { 31 | var isHandlerCalled bool 32 | var handler http.HandlerFunc = func(w http.ResponseWriter, r *http.Request) { 33 | isHandlerCalled = true 34 | } 35 | 36 | server := httptest.NewServer(handler) 37 | httpProxy := proxy.NewReverseProxy(server.URL, 1000, 1000) 38 | 39 | resp := httptest.NewRecorder() 40 | req := httptest.NewRequest(http.MethodPost, "http://user-container.cortex.dev", nil) 41 | httpProxy.ServeHTTP(resp, req) 42 | 43 | require.True(t, isHandlerCalled) 44 | } 45 | -------------------------------------------------------------------------------- /pkg/types/async/status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package async 18 | 19 | // Status is an enum type for workload status 20 | type Status string 21 | 22 | // Different possible workload status 23 | const ( 24 | StatusNotFound Status = "not_found" 25 | StatusFailed Status = "failed" 26 | StatusInProgress Status = "in_progress" 27 | StatusInQueue Status = "in_queue" 28 | StatusCompleted Status = "completed" 29 | ) 30 | 31 | func (status Status) String() string { 32 | return string(status) 33 | } 34 | 35 | func (status Status) Valid() bool { 36 | switch status { 37 | case StatusNotFound, StatusFailed, StatusInProgress, StatusInQueue, StatusCompleted: 38 | return true 39 | default: 40 | return false 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /pkg/types/clusterstate/state.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package clusterstate 18 | 19 | type State string 20 | 21 | const ( 22 | StateClusterExists State = "cluster_exists" 23 | StateClusterDoesntExist State = "cluster_doesnt_exist" 24 | StateClusterInUnexpectedState State = "cluster_in_unexpected_state" 25 | ) 26 | -------------------------------------------------------------------------------- /pkg/types/metrics/queue_metrics.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package metrics 18 | 19 | // There could be Cortex specific messages in queue 20 | type QueueMetrics struct { 21 | Visible int `json:"visible"` 22 | NotVisible int `json:"not_visible"` 23 | } 24 | 25 | func (q QueueMetrics) IsEmpty() bool { 26 | return q.TotalInQueue() == 0 27 | } 28 | 29 | func (q QueueMetrics) TotalInQueue() int { 30 | return q.Visible + q.NotVisible 31 | } 32 | 33 | func (q QueueMetrics) TotalUserMessages() int { 34 | total := q.TotalInQueue() 35 | if total == 0 { 36 | return 0 37 | } 38 | 39 | return total - 1 // An extra message is added 40 | } 41 | -------------------------------------------------------------------------------- /pkg/types/spec/id_gen.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package spec 18 | 19 | import ( 20 | "fmt" 21 | "math" 22 | "sync" 23 | "time" 24 | ) 25 | 26 | var idGenMutex = sync.Mutex{} 27 | 28 | // ID creation optimized for listing the most recently created jobs in S3. S3 objects are listed in ascending UTF-8 binary order. This should work until the year 2262. 29 | func MonotonicallyDecreasingID() string { 30 | idGenMutex.Lock() 31 | defer idGenMutex.Unlock() 32 | 33 | i := math.MaxInt64 - time.Now().UnixNano() 34 | return fmt.Sprintf("%x", i) 35 | } 36 | -------------------------------------------------------------------------------- /pkg/types/status/job_status.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package status 18 | 19 | import ( 20 | "time" 21 | 22 | "github.com/cortexlabs/cortex/pkg/types/spec" 23 | ) 24 | 25 | type BatchJobStatus struct { 26 | spec.BatchJob 27 | Status JobCode `json:"status" yaml:"status"` 28 | EndTime *time.Time `json:"end_time,omitempty" yaml:"end_time,omitempty"` 29 | BatchesInQueue int `json:"batches_in_queue" yaml:"batches_in_queue"` 30 | WorkerCounts *WorkerCounts `json:"worker_counts,omitempty" yaml:"worker_counts,omitempty"` 31 | } 32 | 33 | type TaskJobStatus struct { 34 | spec.TaskJob 35 | EndTime *time.Time `json:"end_time,omitempty" yaml:"end_time,omitempty"` 36 | Status JobCode `json:"status" yaml:"status"` 37 | WorkerCounts *WorkerCounts `json:"worker_counts,omitempty" yaml:"worker_counts,omitempty"` 38 | } 39 | -------------------------------------------------------------------------------- /pkg/types/userconfig/resource.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package userconfig 18 | 19 | import "fmt" 20 | 21 | type Resource struct { 22 | Name string `json:"name" yaml:"name"` 23 | Kind Kind `json:"kind" yaml:"kind"` 24 | } 25 | 26 | func (r Resource) UserString() string { 27 | return fmt.Sprintf("%s (%s)", r.Name, r.Kind.String()) 28 | } 29 | -------------------------------------------------------------------------------- /pkg/workloads/init.go: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2022 Cortex Labs, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package workloads 18 | 19 | import ( 20 | "github.com/cortexlabs/cortex/pkg/config" 21 | kcore "k8s.io/api/core/v1" 22 | ) 23 | 24 | const ( 25 | _kubexitInitContainerName = "kubexit" 26 | ) 27 | 28 | func KubexitInitContainer() kcore.Container { 29 | return kcore.Container{ 30 | Name: _kubexitInitContainerName, 31 | Image: config.ClusterConfig.ImageKubexit, 32 | ImagePullPolicy: kcore.PullAlways, 33 | Command: []string{"cp", "/bin/kubexit", "/cortex/kubexit"}, 34 | VolumeMounts: []kcore.VolumeMount{ 35 | CortexMount(), 36 | }, 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /python/client/README.md: -------------------------------------------------------------------------------- 1 | Cost-effective serverless computing - [docs.cortexlabs.com](https://www.docs.cortexlabs.com) 2 | -------------------------------------------------------------------------------- /python/client/cortex/consts.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | CORTEX_VERSION = "master" # CORTEX_VERSION 17 | CORTEX_TELEMETRY_SENTRY_DSN = "https://5cea3d2d67194d028f7191fcc6ebca14@sentry.io/1825326" 18 | CORTEX_TELEMETRY_SENTRY_ENVIRONMENT = "client" 19 | -------------------------------------------------------------------------------- /python/client/cortex/exceptions.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | 16 | class CortexException(Exception): 17 | """ 18 | Base class for all Cortex's errors. Each custom exception should be derived from this class. 19 | """ 20 | 21 | pass 22 | 23 | 24 | class CortexBinaryException(CortexException): 25 | """ 26 | Raise when binary execution returns an unexpected non-zero return code. 27 | """ 28 | 29 | pass 30 | 31 | 32 | class NotFound(CortexException): 33 | """ 34 | Raise when the specified resource or name is not found. 35 | """ 36 | 37 | pass 38 | -------------------------------------------------------------------------------- /test/README.md: -------------------------------------------------------------------------------- 1 | # Cortex Tests 2 | 3 | - [Example APIs](apis) 4 | - [End-to-end Tests](e2e) 5 | - [Testing Utilities](utils) 6 | -------------------------------------------------------------------------------- /test/apis/async/hello-world/app/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fastapi import FastAPI 4 | from fastapi.responses import PlainTextResponse 5 | 6 | app = FastAPI() 7 | app.response_str = os.getenv("RESPONSE", "hello world") 8 | 9 | 10 | @app.get("/healthz") 11 | def healthz(): 12 | return PlainTextResponse("ok") 13 | 14 | 15 | @app.post("/") 16 | def handler(): 17 | return {"message": app.response_str} 18 | -------------------------------------------------------------------------------- /test/apis/async/hello-world/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | -------------------------------------------------------------------------------- /test/apis/async/hello-world/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="async-hello-world-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/async/hello-world/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: hello-world 2 | kind: AsyncAPI 3 | pod: 4 | port: 8080 5 | containers: 6 | - name: api 7 | image: quay.io/cortexlabs-test/async-hello-world-cpu:latest 8 | readiness_probe: 9 | http_get: 10 | path: "/healthz" 11 | port: 8080 12 | compute: 13 | cpu: 200m 14 | mem: 128Mi 15 | -------------------------------------------------------------------------------- /test/apis/async/hello-world/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/app/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fastapi import FastAPI, status 4 | from fastapi.responses import PlainTextResponse 5 | from pydantic import BaseModel 6 | from transformers import GPT2Tokenizer, GPT2LMHeadModel 7 | 8 | app = FastAPI() 9 | app.device = os.getenv("TARGET_DEVICE", "cpu") 10 | app.ready = False 11 | 12 | 13 | @app.on_event("startup") 14 | def startup(): 15 | app.tokenizer = GPT2Tokenizer.from_pretrained("gpt2") 16 | app.model = GPT2LMHeadModel.from_pretrained("gpt2").to(app.device) 17 | app.ready = True 18 | 19 | 20 | @app.get("/healthz") 21 | def healthz(): 22 | if app.ready: 23 | return PlainTextResponse("ok") 24 | return PlainTextResponse("service unavailable", status_code=status.HTTP_503_SERVICE_UNAVAILABLE) 25 | 26 | 27 | class Body(BaseModel): 28 | text: str 29 | 30 | 31 | @app.post("/") 32 | def text_generator(body: Body): 33 | input_length = len(body.text.split()) 34 | tokens = app.tokenizer.encode(body.text, return_tensors="pt").to(app.device) 35 | prediction = app.model.generate(tokens, max_length=input_length + 20, do_sample=True) 36 | return {"text": app.tokenizer.decode(prediction[0])} 37 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/app/requirements-cpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | transformers==3.0.* 4 | -f https://download.pytorch.org/whl/torch_stable.html 5 | torch==1.7.1+cpu 6 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/app/requirements-gpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard]==0.16.0 2 | sentencepiece==0.1.94 3 | fastapi 4 | transformers==3.0.* 5 | torch==1.10.2 6 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="async-text-generator-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/build-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-gpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="async-text-generator-gpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: text-generator 2 | kind: AsyncAPI 3 | pod: 4 | port: 8080 5 | containers: 6 | - name: api 7 | image: quay.io/cortexlabs-test/async-text-generator-cpu:latest 8 | readiness_probe: 9 | http_get: 10 | path: "/healthz" 11 | port: 8080 12 | compute: 13 | cpu: 1 14 | mem: 2.5Gi 15 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/cortex_gpu.yaml: -------------------------------------------------------------------------------- 1 | - name: text-generator 2 | kind: AsyncAPI 3 | pod: 4 | port: 8080 5 | containers: 6 | - name: api 7 | image: quay.io/cortexlabs-test/async-text-generator-gpu:latest 8 | env: 9 | TARGET_DEVICE: "cuda" 10 | readiness_probe: 11 | http_get: 12 | path: "/healthz" 13 | port: 8080 14 | compute: 15 | cpu: 1 16 | gpu: 1 17 | mem: 512Mi 18 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements-cpu.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/expectations.yaml: -------------------------------------------------------------------------------- 1 | response: 2 | content_type: "json" 3 | json_schema: 4 | type: "object" 5 | properties: 6 | text: 7 | type: "string" 8 | required: 9 | - "text" 10 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/gpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu18.04 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y \ 5 | python3 \ 6 | python3-pip \ 7 | pkg-config \ 8 | build-essential \ 9 | git \ 10 | cmake \ 11 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 12 | 13 | ENV LC_ALL=C.UTF-8 LANG=C.UTF-8 14 | ENV PYTHONUNBUFFERED TRUE 15 | 16 | COPY app/requirements-gpu.txt /app/requirements.txt 17 | RUN pip3 install \ 18 | --no-cache-dir \ 19 | --extra-index-url https://download.pytorch.org/whl/cu113 \ 20 | -r /app/requirements.txt 21 | 22 | COPY app /app 23 | WORKDIR /app/ 24 | ENV PYTHONPATH=/app 25 | 26 | ENV CORTEX_PORT=8080 27 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 28 | -------------------------------------------------------------------------------- /test/apis/async/text-generator/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "machine learning is" 3 | } 4 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/app/requirements-cpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | requests 4 | boto3==1.17.* 5 | -f https://download.pytorch.org/whl/torch_stable.html 6 | torch==1.7.1+cpu 7 | torchvision==0.8.2+cpu 8 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/app/requirements-gpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard]==0.16.0 2 | sentencepiece==0.1.94 3 | fastapi 4 | requests 5 | boto3==1.17.* 6 | torch==1.10.2 7 | torchvision==0.8.* 8 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="batch-image-classifier-alexnet-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/build-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-gpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="batch-image-classifier-alexnet-gpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-alexnet 2 | kind: BatchAPI 3 | pod: 4 | containers: 5 | - name: api 6 | image: quay.io/cortexlabs-test/batch-image-classifier-alexnet-cpu:latest 7 | command: ["uvicorn", "--workers", "1", "--host", "0.0.0.0", "--port", "$(CORTEX_PORT)", "main:app"] 8 | readiness_probe: 9 | http_get: 10 | path: "/healthz" 11 | port: 8080 12 | compute: 13 | cpu: 1 14 | mem: 2Gi 15 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/cortex_gpu.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-alexnet 2 | kind: BatchAPI 3 | pod: 4 | containers: 5 | - name: api 6 | image: quay.io/cortexlabs-test/batch-image-classifier-alexnet-gpu:latest 7 | command: ["uvicorn", "--workers", "1", "--host", "0.0.0.0", "--port", "$(CORTEX_PORT)", "main:app"] 8 | env: 9 | TARGET_DEVICE: "cuda" 10 | readiness_probe: 11 | http_get: 12 | path: "/healthz" 13 | port: 8080 14 | compute: 15 | cpu: 200m 16 | gpu: 1 17 | mem: 512Mi 18 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements-cpu.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/gpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu18.04 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y \ 5 | python3 \ 6 | python3-pip \ 7 | pkg-config \ 8 | build-essential \ 9 | git \ 10 | cmake \ 11 | libjpeg8-dev \ 12 | zlib1g-dev \ 13 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 14 | 15 | ENV LC_ALL=C.UTF-8 LANG=C.UTF-8 16 | ENV PYTHONUNBUFFERED TRUE 17 | 18 | COPY app/requirements-gpu.txt /app/requirements.txt 19 | RUN pip3 install \ 20 | --no-cache-dir \ 21 | --extra-index-url https://download.pytorch.org/whl/cu113 \ 22 | -r /app/requirements.txt 23 | 24 | COPY app /app 25 | WORKDIR /app/ 26 | ENV PYTHONPATH=/app 27 | 28 | ENV CORTEX_PORT=8080 29 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 30 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/sample.json: -------------------------------------------------------------------------------- 1 | [ 2 | "https://i.imgur.com/PzXprwl.jpg", 3 | "https://i.imgur.com/a5djbnv.jpeg", 4 | "https://i.imgur.com/jDimNTZ.jpg", 5 | "https://i.imgur.com/WqeovVj.jpg" 6 | ] 7 | -------------------------------------------------------------------------------- /test/apis/batch/image-classifier-alexnet/submit.py: -------------------------------------------------------------------------------- 1 | """ 2 | Typical usage example: 3 | 4 | python submit.py 5 | """ 6 | 7 | from typing import List 8 | 9 | import sys 10 | import json 11 | import requests 12 | import cortex 13 | 14 | 15 | def main(): 16 | # parse args 17 | if len(sys.argv) != 3: 18 | print("usage: python submit.py ") 19 | sys.exit(1) 20 | env_name = sys.argv[1] 21 | dest_s3_dir = sys.argv[2] 22 | 23 | # read sample file 24 | with open("sample.json") as f: 25 | sample_items: List[str] = json.load(f) 26 | 27 | # get batch endpoint 28 | cx = cortex.client(env_name) 29 | batch_endpoint = cx.get_api("image-classifier-alexnet")["endpoint"] 30 | 31 | # submit job 32 | job_spec = { 33 | "workers": 1, 34 | "item_list": {"items": sample_items, "batch_size": 1}, 35 | "config": {"dest_s3_dir": dest_s3_dir}, 36 | } 37 | response = requests.post(batch_endpoint, json=job_spec) 38 | print(json.dumps(response.json(), indent=2)) 39 | 40 | 41 | if __name__ == "__main__": 42 | main() 43 | -------------------------------------------------------------------------------- /test/apis/batch/sum/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | boto3==1.17.* 4 | -------------------------------------------------------------------------------- /test/apis/batch/sum/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="batch-sum-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/batch/sum/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | # this API is only meant to run with 1-worker jobs 2 | 3 | - name: sum 4 | kind: BatchAPI 5 | pod: 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/batch-sum-cpu:latest 9 | command: ["uvicorn", "--workers", "1", "--host", "0.0.0.0", "--port", "$(CORTEX_PORT)", "main:app"] 10 | readiness_probe: 11 | http_get: 12 | path: "/healthz" 13 | port: 8080 14 | compute: 15 | cpu: 200m 16 | mem: 256Mi 17 | -------------------------------------------------------------------------------- /test/apis/batch/sum/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/batch/sum/sample.json: -------------------------------------------------------------------------------- 1 | [ 2 | [1, 2, 67, -2, 43], 3 | [9, 0, 1, 0, 0, -1] 4 | ] 5 | -------------------------------------------------------------------------------- /test/apis/batch/sum/sample_generator.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | from random import sample 3 | 4 | RANGE = 10 ** 12 5 | LENGTH = 5 6 | 7 | 8 | def generate_sample() -> List[int]: 9 | return sample(range(RANGE), LENGTH) 10 | -------------------------------------------------------------------------------- /test/apis/batch/sum/submit.py: -------------------------------------------------------------------------------- 1 | """ 2 | Typical usage example: 3 | 4 | python submit.py 5 | """ 6 | 7 | from typing import List 8 | 9 | import sys 10 | import json 11 | import requests 12 | import cortex 13 | 14 | 15 | def main(): 16 | # parse args 17 | if len(sys.argv) != 3: 18 | print("usage: python submit.py ") 19 | sys.exit(1) 20 | env_name = sys.argv[1] 21 | dest_s3_dir = sys.argv[2] 22 | 23 | # read sample file 24 | with open("sample.json") as f: 25 | sample_items: List[str] = json.load(f) 26 | 27 | # get batch endpoint 28 | cx = cortex.client(env_name) 29 | batch_endpoint = cx.get_api("sum")["endpoint"] 30 | 31 | # submit job 32 | job_spec = { 33 | "workers": 1, 34 | "item_list": {"items": sample_items, "batch_size": 1}, 35 | "config": {"dest_s3_dir": dest_s3_dir}, 36 | } 37 | response = requests.post(batch_endpoint, json=job_spec) 38 | print(json.dumps(response.json(), indent=2)) 39 | 40 | 41 | if __name__ == "__main__": 42 | main() 43 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/app/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fastapi import FastAPI 4 | from fastapi.responses import PlainTextResponse 5 | 6 | app = FastAPI() 7 | app.response_str = os.getenv("RESPONSE", "hello world") 8 | 9 | 10 | @app.get("/healthz") 11 | def healthz(): 12 | return PlainTextResponse("ok") 13 | 14 | 15 | @app.post("/") 16 | def post_handler(): 17 | return PlainTextResponse(app.response_str) 18 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-hello-world-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: hello-world 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-hello-world-cpu:latest 9 | readiness_probe: 10 | http_get: 11 | path: "/healthz" 12 | port: 8080 13 | compute: 14 | cpu: 200m 15 | mem: 128Mi 16 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/cortex_cpu_arm64.yaml: -------------------------------------------------------------------------------- 1 | - name: hello-world 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | containers: 7 | - name: api 8 | image: infrastructureascode/hello-world 9 | readiness_probe: 10 | http_get: 11 | path: "/health" 12 | port: 8080 13 | compute: 14 | cpu: 200m 15 | mem: 128Mi 16 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/cortex_scale_to_zero.yaml: -------------------------------------------------------------------------------- 1 | - name: hello-world 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | max_queue_length: 999 7 | containers: 8 | - name: api 9 | image: quay.io/cortexlabs-test/realtime-hello-world-cpu:latest 10 | readiness_probe: 11 | http_get: 12 | path: "/healthz" 13 | port: 8080 14 | timeout_seconds: 3 15 | compute: 16 | cpu: 200m 17 | mem: 128Mi 18 | autoscaling: 19 | min_replicas: 0 20 | max_replicas: 1 21 | downscale_stabilization_period: 30s 22 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/realtime/hello-world/sample.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-image-classifier-resnet50-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/build-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-gpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-image-classifier-resnet50-gpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/build-neuron-rtd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-neuron-rtd.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="neuron-rtd" 7 | 8 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 790709498068.dkr.ecr.us-east-1.amazonaws.com 9 | 10 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 11 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/build-neuron-tf-serving.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-neuron-tf-serving.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="neuron-tf-serving" 7 | 8 | aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 763104351884.dkr.ecr.us-east-1.amazonaws.com 9 | 10 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 11 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-resnet50 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8501 5 | max_concurrency: 8 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-image-classifier-resnet50-cpu:latest 9 | readiness_probe: 10 | exec: 11 | command: ["tfs_model_status_probe", "-addr", "localhost:8500", "-model-name", "resnet50"] 12 | compute: 13 | cpu: 1 14 | mem: 2Gi 15 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/cortex_gpu.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-resnet50 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8501 5 | max_concurrency: 8 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-image-classifier-resnet50-gpu:latest 9 | readiness_probe: 10 | exec: 11 | command: ["tfs_model_status_probe", "-addr", "localhost:8500", "-model-name", "resnet50"] 12 | compute: 13 | cpu: 200m 14 | gpu: 1 15 | mem: 512Mi 16 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/cortex_inf.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-resnet50 2 | kind: RealtimeAPI 3 | pod: 4 | port: 9000 5 | max_concurrency: 8 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/neuron-tf-serving:latest 9 | command: ["/usr/local/bin/entrypoint.sh"] 10 | args: 11 | - --port=8500 12 | - --rest_api_port=9000 13 | - --model_name=resnet50_neuron 14 | - --model_base_path=s3://cortex-examples/resnet50_neuron/ 15 | env: 16 | AWS_REGION: us-west-2 17 | S3_USE_HTTPS: "1" 18 | S3_VERIFY_SSL: "0" 19 | S3_ENDPOINT: s3.us-west-2.amazonaws.com 20 | AWS_LOG_LEVEL: "3" 21 | compute: 22 | inf: 1 23 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/cortex_inf_rtd.yaml: -------------------------------------------------------------------------------- 1 | - name: image-classifier-resnet50 2 | kind: RealtimeAPI 3 | pod: 4 | port: 9000 5 | max_concurrency: 8 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/neuron-tf-serving:latest 9 | command: ["/usr/local/bin/tensorflow_model_server_neuron"] 10 | args: 11 | - --port=8500 12 | - --rest_api_port=9000 13 | - --model_name=resnet50_neuron 14 | - --model_base_path=s3://cortex-examples/resnet50_neuron/ 15 | env: 16 | AWS_REGION: us-west-2 17 | S3_USE_HTTPS: "1" 18 | S3_VERIFY_SSL: "0" 19 | S3_ENDPOINT: s3.us-west-2.amazonaws.com 20 | AWS_LOG_LEVEL: "3" 21 | NEURON_RTD_ADDRESS: unix:/mnt/neuron.sock 22 | - name: rtd 23 | image: quay.io/cortexlabs-test/neuron-rtd:latest 24 | command: ["neuron-rtd", "-g", "$(NEURON_RTD_ADDRESS)", "--log-console"] 25 | compute: 26 | inf: 1 27 | env: 28 | NEURON_RTD_ADDRESS: unix:/mnt/neuron.sock 29 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tensorflow/serving:2.3.0 2 | 3 | RUN apt-get update -qq && apt-get install -y --no-install-recommends -q \ 4 | wget \ 5 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 6 | 7 | RUN TFS_PROBE_VERSION=1.0.1 \ 8 | && wget -qO /bin/tfs_model_status_probe https://github.com/codycollier/tfs-model-status-probe/releases/download/v${TFS_PROBE_VERSION}/tfs_model_status_probe_${TFS_PROBE_VERSION}_linux_amd64 \ 9 | && chmod +x /bin/tfs_model_status_probe 10 | 11 | RUN mkdir -p /model/resnet50/ \ 12 | && wget -qO- http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NHWC_jpg.tar.gz | \ 13 | tar --strip-components=2 -C /model/resnet50 -xvz 14 | 15 | ENV CORTEX_PORT 8501 16 | 17 | ENTRYPOINT tensorflow_model_server --rest_api_port=$CORTEX_PORT --rest_api_num_threads=8 --model_name="resnet50" --model_base_path="/model/resnet50" 18 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/gpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tensorflow/serving:2.8.2-gpu 2 | 3 | RUN apt-get update -qq && apt-get install -y --no-install-recommends -q \ 4 | wget \ 5 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 6 | 7 | RUN TFS_PROBE_VERSION=1.0.1 \ 8 | && wget -qO /bin/tfs_model_status_probe https://github.com/codycollier/tfs-model-status-probe/releases/download/v${TFS_PROBE_VERSION}/tfs_model_status_probe_${TFS_PROBE_VERSION}_linux_amd64 \ 9 | && chmod +x /bin/tfs_model_status_probe 10 | 11 | RUN mkdir -p /model/resnet50/ \ 12 | && wget -qO- http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NHWC_jpg.tar.gz | \ 13 | tar --strip-components=2 -C /model/resnet50 -xvz 14 | 15 | ENV CORTEX_PORT 8501 16 | 17 | ENTRYPOINT tensorflow_model_server --rest_api_port=$CORTEX_PORT --rest_api_num_threads=8 --model_name="resnet50" --model_base_path="/model/resnet50" 18 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/neuron-rtd.Dockerfile: -------------------------------------------------------------------------------- 1 | # LIST VERSIONS: aws ecr list-images --region us-east-1 --registry-id 790709498068 --repository-name neuron-rtd 2 | 3 | FROM 790709498068.dkr.ecr.us-east-1.amazonaws.com/neuron-rtd:1.5.0.0 4 | -------------------------------------------------------------------------------- /test/apis/realtime/image-classifier-resnet50/neuron-tf-serving.Dockerfile: -------------------------------------------------------------------------------- 1 | # LIST VERSIONS: aws ecr list-images --region us-east-1 --registry-id 763104351884 --repository-name tensorflow-inference-neuron 2 | 3 | FROM 763104351884.dkr.ecr.us-east-1.amazonaws.com/tensorflow-inference-neuron:1.15.5-neuron-py37-ubuntu18.04-v1.3 4 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/app/main.py: -------------------------------------------------------------------------------- 1 | import base64 2 | import requests 3 | 4 | from fastapi import FastAPI 5 | from pydantic import BaseModel 6 | 7 | 8 | class Request(BaseModel): 9 | image_url: str 10 | 11 | 12 | app = FastAPI() 13 | app.server_url = "http://localhost:8501/v1/models/resnet50:predict" 14 | app.labels = requests.get( 15 | "https://storage.googleapis.com/download.tensorflow.org/data/ImageNetLabels.txt" 16 | ).text.split("\n")[1:] 17 | 18 | 19 | @app.get("/healthz") 20 | def healthz(): 21 | return "ok" 22 | 23 | 24 | @app.post("/") 25 | def text_generator(request: Request): 26 | # download the image 27 | dl_request = requests.get(request.image_url, stream=True) 28 | dl_request.raise_for_status() 29 | 30 | # compose a JSON Predict request (send JPEG image in base64). 31 | jpeg_bytes = base64.b64encode(dl_request.content).decode("utf-8") 32 | predict_request = '{"instances" : [{"b64": "%s"}]}' % jpeg_bytes 33 | 34 | # make prediction 35 | response = requests.post(app.server_url, data=predict_request) 36 | response.raise_for_status() 37 | label_id = response.json()["predictions"][0]["classes"] 38 | return {"image_prediction": app.labels[label_id]} 39 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | requests 4 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/build-tfs-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-multi-container-tfs-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/build-web-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-multi-container-web-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: multi-container 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | containers: 6 | - name: web-server 7 | image: quay.io/cortexlabs-test/realtime-multi-container-web-cpu:latest 8 | readiness_probe: 9 | http_get: 10 | path: "/healthz" 11 | port: 8080 12 | - name: tfs-server 13 | image: quay.io/cortexlabs-test/realtime-multi-container-tfs-cpu:latest 14 | readiness_probe: 15 | exec: 16 | command: ["tfs_model_status_probe", "-addr", "localhost:8500", "-model-name", "resnet50"] 17 | compute: 18 | cpu: 1 19 | mem: 2G 20 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "image_url": "https://tensorflow.org/images/blogs/serving/cat.jpg" 3 | } 4 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/tfs-cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM tensorflow/serving:2.3.0 2 | 3 | RUN apt-get update -qq && apt-get install -y --no-install-recommends -q \ 4 | wget \ 5 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 6 | 7 | RUN TFS_PROBE_VERSION=1.0.1 \ 8 | && wget -qO /bin/tfs_model_status_probe https://github.com/codycollier/tfs-model-status-probe/releases/download/v${TFS_PROBE_VERSION}/tfs_model_status_probe_${TFS_PROBE_VERSION}_linux_amd64 \ 9 | && chmod +x /bin/tfs_model_status_probe 10 | 11 | RUN mkdir -p /model/resnet50/ \ 12 | && wget -qO- http://download.tensorflow.org/models/official/20181001_resnet/savedmodels/resnet_v2_fp32_savedmodel_NHWC_jpg.tar.gz | \ 13 | tar --strip-components=2 -C /model/resnet50 -xvz 14 | 15 | ENTRYPOINT tensorflow_model_server --rest_api_port=8501 --rest_api_num_threads=8 --model_name="resnet50" --model_base_path="/model/resnet50" 16 | -------------------------------------------------------------------------------- /test/apis/realtime/multi-container/web-cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/app/main.py: -------------------------------------------------------------------------------- 1 | from typing import DefaultDict 2 | from fastapi import FastAPI 3 | from pydantic import BaseModel 4 | 5 | app = FastAPI() 6 | 7 | 8 | def generate_primes(limit=None): 9 | """Sieve of Eratosthenes""" 10 | not_prime = DefaultDict(list) 11 | num = 2 12 | while limit is None or num <= limit: 13 | if num in not_prime: 14 | for prime in not_prime[num]: 15 | not_prime[prime + num].append(prime) 16 | del not_prime[num] 17 | else: 18 | yield num 19 | not_prime[num * num] = [num] 20 | num += 1 21 | 22 | 23 | @app.get("/healthz") 24 | def healthz(): 25 | return "ok" 26 | 27 | 28 | class Body(BaseModel): 29 | primes_to_generate: float 30 | 31 | 32 | @app.post("/") 33 | def prime_numbers(body: Body): 34 | return {"prime_numbers": list(generate_primes(body.primes_to_generate))} 35 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-prime-generator-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: prime-generator 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-prime-generator-cpu:latest 9 | readiness_probe: 10 | http_get: 11 | path: "/healthz" 12 | port: 8080 13 | compute: 14 | cpu: 200m 15 | mem: 128Mi 16 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/realtime/prime-generator/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "primes_to_generate": 100 3 | } 4 | -------------------------------------------------------------------------------- /test/apis/realtime/sleep/app/main.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | from fastapi import FastAPI 4 | from fastapi.responses import PlainTextResponse 5 | 6 | app = FastAPI() 7 | 8 | 9 | @app.get("/healthz") 10 | def healthz(): 11 | return PlainTextResponse("ok") 12 | 13 | 14 | @app.post("/") 15 | def sleep(sleep: float = 0): 16 | time.sleep(sleep) 17 | return PlainTextResponse("ok") 18 | -------------------------------------------------------------------------------- /test/apis/realtime/sleep/app/requirements.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | -------------------------------------------------------------------------------- /test/apis/realtime/sleep/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-sleep-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/sleep/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: sleep 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | max_queue_length: 128 7 | containers: 8 | - name: api 9 | image: quay.io/cortexlabs-test/realtime-sleep-cpu:latest 10 | readiness_probe: 11 | http_get: 12 | path: "/healthz" 13 | port: 8080 14 | compute: 15 | cpu: 200m 16 | mem: 128Mi 17 | autoscaling: 18 | target_in_flight: 1 19 | -------------------------------------------------------------------------------- /test/apis/realtime/sleep/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/app/main.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from fastapi import FastAPI, status 4 | from fastapi.responses import PlainTextResponse 5 | from pydantic import BaseModel 6 | from transformers import GPT2Tokenizer, GPT2LMHeadModel 7 | 8 | app = FastAPI() 9 | app.device = os.getenv("TARGET_DEVICE", "cpu") 10 | app.ready = False 11 | 12 | 13 | @app.on_event("startup") 14 | def startup(): 15 | app.tokenizer = GPT2Tokenizer.from_pretrained("gpt2") 16 | app.model = GPT2LMHeadModel.from_pretrained("gpt2").to(app.device) 17 | app.ready = True 18 | 19 | 20 | @app.get("/healthz") 21 | def healthz(): 22 | if app.ready: 23 | return PlainTextResponse("ok") 24 | return PlainTextResponse("service unavailable", status_code=status.HTTP_503_SERVICE_UNAVAILABLE) 25 | 26 | 27 | class Body(BaseModel): 28 | text: str 29 | 30 | 31 | @app.post("/") 32 | def text_generator(body: Body): 33 | input_length = len(body.text.split()) 34 | tokens = app.tokenizer.encode(body.text, return_tensors="pt").to(app.device) 35 | prediction = app.model.generate(tokens, max_length=input_length + 20, do_sample=True) 36 | return {"text": app.tokenizer.decode(prediction[0])} 37 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/app/requirements-cpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard] 2 | fastapi 3 | transformers==3.0.* 4 | -f https://download.pytorch.org/whl/torch_stable.html 5 | torch==1.7.1+cpu 6 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/app/requirements-gpu.txt: -------------------------------------------------------------------------------- 1 | uvicorn[standard]==0.16.0 2 | sentencepiece==0.1.94 3 | fastapi 4 | transformers==3.0.* 5 | torch==1.10.2 6 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-text-generator-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/build-gpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-gpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="realtime-text-generator-gpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: text-generator 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-text-generator-cpu:latest 9 | readiness_probe: 10 | http_get: 11 | path: "/healthz" 12 | port: 8080 13 | compute: 14 | cpu: 1 15 | mem: 2.5Gi 16 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/cortex_gpu.yaml: -------------------------------------------------------------------------------- 1 | - name: text-generator 2 | kind: RealtimeAPI 3 | pod: 4 | port: 8080 5 | max_concurrency: 1 6 | containers: 7 | - name: api 8 | image: quay.io/cortexlabs-test/realtime-text-generator-gpu:latest 9 | env: 10 | TARGET_DEVICE: "cuda" 11 | readiness_probe: 12 | http_get: 13 | path: "/healthz" 14 | port: 8080 15 | compute: 16 | cpu: 1 17 | gpu: 1 18 | mem: 512Mi 19 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.8-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements-cpu.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | ENV PYTHONPATH=/app 11 | 12 | ENV CORTEX_PORT=8080 13 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 14 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/gpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM nvidia/cuda:11.3.1-cudnn8-runtime-ubuntu18.04 2 | 3 | RUN apt-get update \ 4 | && apt-get install -y \ 5 | python3 \ 6 | python3-pip \ 7 | pkg-config \ 8 | build-essential \ 9 | git \ 10 | cmake \ 11 | && apt-get clean -qq && rm -rf /var/lib/apt/lists/* 12 | 13 | ENV LC_ALL=C.UTF-8 LANG=C.UTF-8 14 | ENV PYTHONUNBUFFERED TRUE 15 | 16 | COPY app/requirements-gpu.txt /app/requirements.txt 17 | RUN pip3 install \ 18 | --no-cache-dir \ 19 | --extra-index-url https://download.pytorch.org/whl/cu113 \ 20 | -r /app/requirements.txt 21 | 22 | COPY app /app 23 | WORKDIR /app/ 24 | ENV PYTHONPATH=/app 25 | 26 | ENV CORTEX_PORT=8080 27 | CMD uvicorn --workers 1 --host 0.0.0.0 --port $CORTEX_PORT main:app 28 | -------------------------------------------------------------------------------- /test/apis/realtime/text-generator/sample.json: -------------------------------------------------------------------------------- 1 | { 2 | "text": "machine learning is" 3 | } 4 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/app/main.py: -------------------------------------------------------------------------------- 1 | import json 2 | import pickle 3 | import re 4 | import os 5 | import boto3 6 | 7 | from sklearn.datasets import load_iris 8 | from sklearn.model_selection import train_test_split 9 | from sklearn.linear_model import LogisticRegression 10 | 11 | 12 | def main(): 13 | with open("/cortex/spec/job.json", "r") as f: 14 | job_spec = json.load(f) 15 | print(json.dumps(job_spec, indent=2)) 16 | 17 | # get metadata 18 | config = job_spec["config"] 19 | job_id = job_spec["job_id"] 20 | s3_path = None 21 | if config is not None and "dest_s3_dir" in config: 22 | s3_path = config["dest_s3_dir"] 23 | 24 | # Train the model 25 | iris = load_iris() 26 | data, labels = iris.data, iris.target 27 | training_data, test_data, training_labels, test_labels = train_test_split(data, labels) 28 | 29 | model = LogisticRegression(solver="lbfgs", multi_class="multinomial", max_iter=1000) 30 | model.fit(training_data, training_labels) 31 | accuracy = model.score(test_data, test_labels) 32 | print("accuracy: {:.2f}".format(accuracy)) 33 | 34 | # Upload the model 35 | if s3_path: 36 | pickle.dump(model, open("model.pkl", "wb")) 37 | bucket, key = re.match("s3://(.+?)/(.+)", s3_path).groups() 38 | s3 = boto3.client("s3") 39 | s3.upload_file("model.pkl", bucket, os.path.join(key, job_id, "model.pkl")) 40 | else: 41 | print("not uploading the model to the s3 bucket") 42 | 43 | 44 | if __name__ == "__main__": 45 | main() 46 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/app/requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.18.* 2 | scikit-learn==0.21.* 3 | boto3==1.17.* 4 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/build-cpu.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # usage: build-cpu.sh [REGISTRY] [--skip-push] 4 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 5 | 6 | image_name="task-iris-classifier-trainer-cpu" 7 | 8 | "$(dirname "${BASH_SOURCE[0]}")"/../../../utils/build.sh $(realpath "${BASH_SOURCE[0]}") "$image_name" "$@" 9 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/cortex_cpu.yaml: -------------------------------------------------------------------------------- 1 | - name: iris-classifier-trainer 2 | kind: TaskAPI 3 | pod: 4 | containers: 5 | - name: trainer 6 | image: quay.io/cortexlabs-test/task-iris-classifier-trainer-cpu:latest 7 | command: 8 | - python 9 | - main.py 10 | compute: 11 | cpu: 200m 12 | mem: 256Mi 13 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/cpu.Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.7-slim 2 | 3 | ENV PYTHONUNBUFFERED TRUE 4 | 5 | COPY app/requirements.txt /app/requirements.txt 6 | RUN pip install --no-cache-dir -r /app/requirements.txt 7 | 8 | COPY app /app 9 | WORKDIR /app/ 10 | 11 | CMD exec python app/main.py 12 | -------------------------------------------------------------------------------- /test/apis/task/iris-classifier-trainer/submit.py: -------------------------------------------------------------------------------- 1 | """ 2 | Typical usage example: 3 | 4 | python submit.py 5 | """ 6 | 7 | import sys 8 | import json 9 | import requests 10 | import cortex 11 | 12 | 13 | def main(): 14 | # parse args 15 | if len(sys.argv) != 3: 16 | print("usage: python submit.py ") 17 | sys.exit(1) 18 | env_name = sys.argv[1] 19 | dest_s3_dir = sys.argv[2] 20 | 21 | # get task endpoint 22 | cx = cortex.client(env_name) 23 | task_endpoint = cx.get_api("iris-classifier-trainer")["endpoint"] 24 | 25 | # submit job 26 | job_spec = {"config": {"dest_s3_dir": dest_s3_dir}} 27 | response = requests.post(task_endpoint, json=job_spec) 28 | print(json.dumps(response.json(), indent=2)) 29 | 30 | 31 | if __name__ == "__main__": 32 | main() 33 | -------------------------------------------------------------------------------- /test/apis/trafficsplitter/hello-world/.dockerignore: -------------------------------------------------------------------------------- 1 | *.dockerfile 2 | README.md 3 | sample.json 4 | *.pyc 5 | *.pyo 6 | *.pyd 7 | __pycache__ 8 | .pytest_cache 9 | -------------------------------------------------------------------------------- /test/apis/trafficsplitter/hello-world/sample.json: -------------------------------------------------------------------------------- 1 | {} 2 | -------------------------------------------------------------------------------- /test/e2e/e2e/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from .cluster import create_cluster, delete_cluster 16 | 17 | __all__ = ["create_cluster", "delete_cluster"] 18 | -------------------------------------------------------------------------------- /test/e2e/e2e/exceptions.py: -------------------------------------------------------------------------------- 1 | class ClusterCreationException(Exception): 2 | pass 3 | 4 | 5 | class ClusterDeletionException(Exception): 6 | pass 7 | 8 | 9 | class ExpectationsValidationException(Exception): 10 | pass 11 | 12 | 13 | class GeneratorValidationException(Exception): 14 | pass 15 | -------------------------------------------------------------------------------- /test/e2e/pytest.ini: -------------------------------------------------------------------------------- 1 | # pytest.ini 2 | [pytest] 3 | minversion = 6.0 4 | addopts = -s -v -r sxf 5 | -------------------------------------------------------------------------------- /test/e2e/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/e2e/tests/aws/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | -------------------------------------------------------------------------------- /test/e2e/tests/aws/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import cortex as cx 16 | import pytest 17 | 18 | import e2e 19 | from e2e.utils import client_from_config 20 | 21 | 22 | @pytest.fixture 23 | def client(config): 24 | env_name = config["aws"]["env"] 25 | if env_name: 26 | return cx.client(env_name) 27 | 28 | config_path = config["aws"]["config"] 29 | if config_path is not None: 30 | return client_from_config(config_path) 31 | 32 | pytest.skip("--env or --config must be passed to run tests") 33 | 34 | 35 | def pytest_configure(config): 36 | cluster_config = config.getoption("--config") 37 | if cluster_config: 38 | e2e.create_cluster(cluster_config) 39 | 40 | 41 | def pytest_unconfigure(config): 42 | cluster_config = config.getoption("--config") 43 | if cluster_config: 44 | e2e.delete_cluster(cluster_config) 45 | -------------------------------------------------------------------------------- /test/e2e/tests/aws/test_long_running.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import Callable, Dict 16 | 17 | import cortex as cx 18 | import pytest 19 | 20 | import e2e.tests 21 | 22 | TEST_APIS = ["realtime/text-generator"] 23 | 24 | 25 | @pytest.mark.usefixtures("client") 26 | @pytest.mark.parametrize("api", TEST_APIS) 27 | def test_long_running_realtime(printer: Callable, config: Dict, client: cx.Client, api: str): 28 | skip_load_test = config["global"].get("skip_long_running", False) 29 | if skip_load_test: 30 | pytest.skip("--skip-long-running flag detected, skipping long-running test") 31 | 32 | e2e.tests.test_long_running_realtime( 33 | printer, 34 | client, 35 | api, 36 | long_running_config=config["global"]["long_running_test_config"], 37 | deploy_timeout=config["global"]["realtime_deploy_timeout"], 38 | node_groups=config["aws"]["x86_nodegroups"], 39 | ) 40 | -------------------------------------------------------------------------------- /test/e2e/tests/aws/test_scale_to_zero.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import Dict 16 | 17 | import pytest 18 | 19 | import cortex as cx 20 | import e2e.tests 21 | 22 | TEST_APIS = [{"api": "realtime/hello-world", "config": "cortex_scale_to_zero.yaml"}] 23 | 24 | 25 | @pytest.mark.parametrize("api", TEST_APIS, ids=[api["api"] for api in TEST_APIS]) 26 | @pytest.mark.usefixtures("client") 27 | def test_scale_to_zero_realtime(config: Dict, client: cx.Client, api: Dict[str, str]): 28 | e2e.tests.test_realtime_scale_to_zero( 29 | client=client, 30 | api=api["api"], 31 | timeout=config["global"]["realtime_deploy_timeout"], 32 | api_config_name=api["config"], 33 | ) 34 | -------------------------------------------------------------------------------- /test/e2e/tests/aws/test_task.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Cortex Labs, Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from typing import Callable, Dict 16 | 17 | import cortex as cx 18 | import pytest 19 | 20 | import e2e.tests 21 | 22 | TEST_APIS = ["task/iris-classifier-trainer"] 23 | 24 | 25 | @pytest.mark.usefixtures("client") 26 | @pytest.mark.parametrize("api", TEST_APIS) 27 | def test_task_api(printer: Callable, config: Dict, client: cx.Client, api: str): 28 | e2e.tests.test_task_api( 29 | printer, 30 | client, 31 | api, 32 | retry_attempts=5, 33 | deploy_timeout=config["global"]["task_deploy_timeout"], 34 | job_timeout=config["global"]["task_job_timeout"], 35 | node_groups=config["aws"]["x86_nodegroups"], 36 | local_operator=config["global"]["local_operator"], 37 | ) 38 | -------------------------------------------------------------------------------- /test/utils/build-all.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2022 Cortex Labs, Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # usage: ./build-all.sh [REGISTRY] [--skip-push] 18 | # REGISTRY defaults to $CORTEX_DEV_DEFAULT_IMAGE_REGISTRY; e.g. 764403040460.dkr.ecr.us-west-2.amazonaws.com/cortexlabs or quay.io/cortexlabs-test 19 | 20 | set -eo pipefail 21 | 22 | ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")"/../.. >/dev/null && pwd)" 23 | 24 | for f in $(find $ROOT/test/apis -type f -name 'build-*.sh'); do 25 | "$f" "$@" 26 | done 27 | --------------------------------------------------------------------------------