diff --git a/README.md b/README.md index c761f985d898..f7bb86043d2d 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,6 @@ The simplest way to run OpenShift Origin is in a Docker container: Once the container is started, you can jump into a console inside the container and run the CLI. $ docker exec -it openshift-origin bash - $ export KUBECONFIG=/var/lib/openshift/openshift.local.certificates/admin/.kubeconfig $ osc --help diff --git a/examples/sample-app/README.md b/examples/sample-app/README.md index 2323da0a067e..a74f6fb7fcaf 100644 --- a/examples/sample-app/README.md +++ b/examples/sample-app/README.md @@ -36,17 +36,17 @@ At this stage of OpenShift 3 development, there are a few things that you will n ### Docker Changes ### -First, you'll need to configure the docker daemon on your host to trust the docker registry service you'll be starting. +First, you'll need to configure the Docker daemon on your host to trust the Docker registry service you'll be starting. -To do this, you need to add "--insecure-registry 172.30.17.0/24" to the docker daemon invocation, eg: +To do this, you need to add "--insecure-registry 172.30.17.0/24" to the Docker daemon invocation, eg: $ docker -d --insecure-registry 172.30.17.0/24 Note that you need to have installed Docker 1.3.2 or higher in order to use the `--insecure-registry` flag. -If you are running docker as a service via `systemd`, you can add this argument to the options value in `/etc/sysconfig/docker` +If you are running Docker as a service via `systemd`, you can add this argument to the options value in `/etc/sysconfig/docker` -This will instruct the docker daemon to trust any docker registry on the 172.30.17.0/24 subnet, +This will instruct the Docker daemon to trust any Docker registry on the 172.30.17.0/24 subnet, rather than requiring the registry to have a verifiable certificate. These instructions assume you have not changed the kubernetes/openshift service subnet configuration from the default value of 172.30.17.0/24. @@ -73,7 +73,7 @@ This section covers how to perform all the steps of building, deploying, and upd NOTE: All commands assume the `osc` binary/symlink is in your path and the present working directory is the same directory as this README. -1. *Optional*: Pre-pull the docker images used in this sample. This is +1. *Optional*: Pre-pull the Docker images used in this sample. This is not strictly necessary as OpenShift will pull the images as it needs them, but by doing it up front it will prevent lengthy operations during build and deployment which might otherwise lead you to believe the process @@ -104,52 +104,49 @@ the present working directory is the same directory as this README. $ export CURL_CA_BUNDLE=`pwd`/openshift.local.certificates/admin/root.crt $ sudo chmod +r "$KUBECONFIG" -4. Deploy a private docker registry within OpenShift with the certs necessary for access to master: +4. Deploy a private Docker registry within OpenShift with the certs necessary for access to master: $ sudo chmod +r ./openshift.local.certificates/openshift-client/key.key - $ pushd ../.. - $ CERT_DIR=examples/sample-app/openshift.local.certificates/openshift-client hack/install-registry.sh - $ popd + $ openshift ex registry --create --credentials="${KUBECONFIG}" + docker-registry # the service + docker-registry # the deployment config - Note that the private docker registry is using ephemeral storage, + Note that the private Docker registry is using ephemeral storage, so when it is stopped, the image will be lost. An external volume could be used for persistent storage, but that is beyond the scope of this tutorial. 5. Confirm the registry is started (this can take a few minutes): - $ osc get pods + $ osc describe service docker-registry You should see: - Name Image(s) Host Labels Status - ---------- ---------- ---------- ---------- ---------- - 94679170-54dc-11e4-88cc-3c970e3bf0b7 openshift/docker-registry localhost.localdomain/ deployment=registry-config,name=registrypod,replicationController=946583f6-54dc-11e4-88cc-3c970e3bf0b7 Running + Name: docker-registry + Labels: docker-registry=default + Selector: docker-registry=default + Port: 5000 + Endpoints: 172.17.0.60:5000 + No events. -6. Confirm the registry service is running. Note that the actual IP address may vary. + If "Endpoints" is listed as , your registry hasn't started yet. You can run `osc get pods` to + see the registry pod and if there are any issues. Once the pod has started, the IP of the pod will + be added to the docker-registry service list so that it's reachable from other places. - $ osc get services +6. Confirm the registry is accessible (you may need to run this more than once): - You should see: - - Name Labels Selector IP Port - ---------- ---------- ---------- ---------- ---------- - docker-registry name=registrypod 172.30.17.3 5001 - -7. Confirm the registry is accessible (you may need to run this more than once): - - $ curl `osc get services docker-registry -o template --template="{{ .portalIP}}:{{ .port }}"` + $ curl `osc get service docker-registry --template="{{ .portalIP}}:{{ .port }}"` You should see: "docker-registry server (dev) (v0.9.0)" -8. Create a new project in OpenShift. This creates a namespace `test` to contain the builds and app that we will generate below. +7. Create a new project in OpenShift. This creates a namespace `test` to contain the builds and app that we will generate below. $ osc create -f project.json -9. *Optional:* View the OpenShift web console in your browser by browsing to `https://:8444` +8. *Optional:* View the OpenShift web console in your browser by browsing to `https://:8444` * You will need to have the browser accept the certificate at `https://:8443` before the console can consult the OpenShift @@ -159,7 +156,7 @@ the present working directory is the same directory as this README. you'll see the page update as you deploy objects into the project and run builds. -10. *Optional:* Fork the [ruby sample repository](https://github.com/openshift/ruby-hello-world) +9. *Optional:* Fork the [ruby sample repository](https://github.com/openshift/ruby-hello-world) to an OpenShift-visible git account that you control, preferably somewhere that can also reach your OpenShift server with a webhook. A github.com account is an obvious place for this, but an in-house @@ -172,7 +169,7 @@ the present working directory is the same directory as this README. Without your own fork, you can still run the initial build from OpenShift's public repository, just not a changed build. -11. *Optional:* Add the following webhook under the settings in your new GitHub repository: +10. *Optional:* Add the following webhook under the settings in your new GitHub repository: $ https://:8443/osapi/v1beta1/buildConfigHooks/ruby-sample-build/secret101/github?namespace=test @@ -181,12 +178,12 @@ the present working directory is the same directory as this README. will almost certainly need to "Disable SSL Verification" for your test instance as the certificate chain generated is not publicly verified. -12. Edit application-template-stibuild.json which will define the sample application +11. Edit application-template-stibuild.json which will define the sample application * Update the BuildConfig's sourceURI (git://github.com/openshift/ruby-hello-world.git) to point to your forked repository. *Note:* You can skip this step if you did not create a forked repository. -13. Submit the application template for processing (generating shared parameters requested in the template) +12. Submit the application template for processing (generating shared parameters requested in the template) and then request creation of the processed template: $ osc process -n test -f application-template-stibuild.json | osc create -n test -f - @@ -205,13 +202,13 @@ the present working directory is the same directory as this README. Note that no build has actually occurred yet, so at this time there is no image to deploy and no application to visit. -14. Trigger an initial build of your application - * If you setup the GitHub webhook, push a change to app.rb in your ruby sample repository from step 10. +13. Trigger an initial build of your application + * If you setup the GitHub webhook, push a change to app.rb in your ruby sample repository. * Otherwise you can request a new build by running: $ osc start-build -n test ruby-sample-build -15. Monitor the builds and wait for the status to go to "complete" (this can take a few minutes): +14. Monitor the builds and wait for the status to go to "complete" (this can take a few minutes): $ osc get -n test builds @@ -241,7 +238,7 @@ the present working directory is the same directory as this README. automatically trigger a deployment of the application, creating a pod each for the frontend (your Ruby code) and backend. -16. Wait for the application's frontend pod and database pods to be started (this can take a few minutes): +15. Wait for the application's frontend pod and database pods to be started (this can take a few minutes): $ osc get -n test pods @@ -252,7 +249,7 @@ the present working directory is the same directory as this README. 1b978f62-605f-11e4-b0db-3c970e3bf0b7 mysql localhost.localdomain/ deploymentConfig=,deploymentID=database,name=database,replicationController=1b960e56-605f-11e4-b0db-3c970e3bf0b7,template=ruby-helloworld-sample Running 4a792f55-605f-11e4-b0db-3c970e3bf0b7 172.30.17.3:5001/openshift/origin-ruby-sample:9477bdb99a409b9c747e699361ae7934fd83bb4092627e2ee35f9f0b0869885b localhost.localdomain/ deploymentConfig=frontend,deploymentID=frontend-1,name=frontend,replicationController=4a749831-605f-11e4-b0db-3c970e3bf0b7,template=ruby-helloworld-sample Running -17. Determine the IP for the frontend service: +16. Determine the IP for the frontend service: $ osc get -n test services @@ -266,20 +263,20 @@ the present working directory is the same directory as this README. In this case, the IP for frontend is 172.30.17.4 and it is on port 5432. - *Note:* you can also get this information from the web console if you launched it in step 9. + *Note:* you can also get this information from the web console. -18. Confirm the application is now accessible via the frontend service on port 5432. Go to http://172.30.17.4:5432 (or whatever IP address was reported above) in your browser if you're running this locally; otherwise you can use curl to see the HTML, or port forward the address to your local workstation to visit it. +17. Confirm the application is now accessible via the frontend service on port 5432. Go to http://172.30.17.4:5432 (or whatever IP address was reported above) in your browser if you're running this locally; otherwise you can use curl to see the HTML, or port forward the address to your local workstation to visit it. You should see a welcome page and a form that allows you to query and update key/value pairs. The keys are stored in the database container running in the database pod. -19. Make a change to your ruby sample main.html file, commit, and push it via git. +18. Make a change to your ruby sample main.html file, commit, and push it via git. * If you do not have the webhook enabled, you'll have to manually trigger another build: $ osc start-build -n test ruby-sample-build -20. Repeat step 15 (waiting for the build to complete). Once the build is complete, refreshing your browser should show your changes. +19. Repeat step 14 (waiting for the build to complete). Once the build is complete, refreshing your browser should show your changes. Congratulations, you've successfully deployed and updated an application on OpenShift. diff --git a/examples/sample-app/container-setup.md b/examples/sample-app/container-setup.md index 5d7567794984..adae83833c80 100644 --- a/examples/sample-app/container-setup.md +++ b/examples/sample-app/container-setup.md @@ -60,15 +60,10 @@ bits that are used in the sample app. $ wget \ https://raw.githubusercontent.com/openshift/origin/master/examples/sample-app/project.json \ -O examples/sample-app/project.json - $ wget \ - https://raw.githubusercontent.com/openshift/origin/master/hack/install-registry.sh - $ chmod a+x install-registry.sh ## Configure client security - $ export KUBECONFIG=`pwd`/openshift.local.certificates/admin/.kubeconfig $ export CURL_CA_BUNDLE=`pwd`/openshift.local.certificates/admin/root.crt - $ chmod +r "$KUBECONFIG" For more information on this step, see [Application Build, Deploy, and Update Flow](https://github.com/openshift/origin/blob/master/examples/sample-app/README.md#application-build-deploy-and-update-flow), @@ -76,8 +71,7 @@ step #3. ## Deploy the private docker registry - $ chmod +r ./openshift.local.certificates/openshift-client/key.key - $ CERT_DIR=openshift.local.certificates/openshift-client ./install-registry.sh + $ openshift ex registry --create --credentials="${KUBECONFIG}" $ cd examples/sample-app For more information on this step, see [Application Build, Deploy, and Update diff --git a/examples/sample-app/updateregistry.sh b/examples/sample-app/updateregistry.sh deleted file mode 100755 index 6808fa936b7a..000000000000 --- a/examples/sample-app/updateregistry.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -# This script will update the application-template-stibuild.json with the correct -# registry service ip+port. You must have started openshift and deployed -# the docker-registry service before running this. -# The new template file produced is template.json. -REGISTRY_IP=$(osc get services docker-registry -o template --template="{{ .portalIP}}:{{ .port }}") -sed s/172\.30\.17\.3:5001/$REGISTRY_IP/g application-template-stibuild.json > template.json diff --git a/hack/install-registry.sh b/hack/install-registry.sh deleted file mode 100755 index 39d6feb794c8..000000000000 --- a/hack/install-registry.sh +++ /dev/null @@ -1,50 +0,0 @@ -#!/bin/sh - -# This uses osc to bootstrap a Docker registry image as a pod under a running OpenShift. -# It uses the key/certs in the directory specified by CERT_DIR to configure the registry -# for connecting securely to the OpenShift master's. -# -# To use key/certs generated automatically by "openshift start", look for the -# openshift.local.certificates/openshift-client/ directory underneath where it was started. -# For instance, if the openshift home directory is /var/lib/openshift, then run: -# CERT_DIR=/var/lib/openshift/openshift.local.certificates/openshift-client hack/install-registry.sh -# -# You may also need to set KUBERNETES_MASTER if the master is not listening at https://localhost:8443/ - -if [ -z "${CERT_DIR}" ]; then - echo "You have to set the CERT_DIR environment variable to point into master certificate" - echo "Example:" - echo "$ CERT_DIR='/var/lib/openshift/openshift.local.certificates/openshift-client' hack/install-registry.sh" - exit 1 -fi - -set -o errexit -set -o nounset -set -o pipefail - -API_PORT="${API_PORT:-8443}" -API_SCHEME="${API_SCHEME:-https}" -API_HOST="${API_HOST:-localhost}" - -# use the docker bridge ip address until there is a good way to get the auto-selected address from master -# this address is considered stable -# Used by the docker-registry and the router pods to call back to the API -CONTAINER_ACCESSIBLE_API_HOST="${CONTAINER_ACCESSIBLE_API_HOST:-172.17.42.1}" - -# Set KUBERNETES_MASTER for osc -KUBERNETES_MASTER="${KUBERNETES_MASTER:-${API_SCHEME}://${API_HOST}:${API_PORT}}" -if [[ "${API_SCHEME}" == "https" ]]; then - # Read client cert data in to send to containerized components - OPENSHIFT_CA_DATA="$(cat "${CERT_DIR}/root.crt")" - OPENSHIFT_CERT_DATA="$(cat "${CERT_DIR}/cert.crt")" - OPENSHIFT_KEY_DATA="$(cat "${CERT_DIR}/key.key")" -else - OPENSHIFT_CA_DATA="" - OPENSHIFT_CERT_DATA="" - OPENSHIFT_KEY_DATA="" -fi -export KUBERNETES_MASTER - -# Deploy private docker registry -echo "[INFO] Submitting docker-registry template file for processing" -osc process -f examples/sample-app/docker-registry-template.json -v "OPENSHIFT_MASTER=$API_SCHEME://${CONTAINER_ACCESSIBLE_API_HOST}:${API_PORT},OPENSHIFT_CA_DATA=${OPENSHIFT_CA_DATA},OPENSHIFT_CERT_DATA=${OPENSHIFT_CERT_DATA},OPENSHIFT_KEY_DATA=${OPENSHIFT_KEY_DATA}" | osc create -f - diff --git a/hack/test-cmd.sh b/hack/test-cmd.sh index 4035762090bf..6487f54874c9 100755 --- a/hack/test-cmd.sh +++ b/hack/test-cmd.sh @@ -264,4 +264,10 @@ openshift ex router --create --credentials="${KUBECONFIG}" [ "$(openshift ex router | grep 'service exists')" ] echo "ex router: ok" +[ ! "$(openshift ex registry | grep 'does not exist')"] +[ "$(openshift ex registry -o yaml --credentials="${KUBECONFIG}" | grep 'openshift/origin-docker-registry')" ] +openshift ex registry --create --credentials="${KUBECONFIG}" +[ "$(openshift ex registry | grep 'service exists')" ] +echo "ex registry: ok" + osc get minions,pods diff --git a/hack/test-end-to-end.sh b/hack/test-end-to-end.sh index 3a9e3ff2ccc0..13cf33e02d71 100755 --- a/hack/test-end-to-end.sh +++ b/hack/test-end-to-end.sh @@ -83,6 +83,7 @@ function cleanup() fi echo + set +e echo "[INFO] Dumping container logs to ${LOG_DIR}" for container in $(docker ps -aq); do docker logs "$container" >&"${LOG_DIR}/container-$container.log" @@ -90,7 +91,6 @@ function cleanup() echo "[INFO] Dumping build log to ${LOG_DIR}" - set +e osc get -n test builds -o template -t '{{ range .items }}{{.metadata.name}}{{ "\n" }}{{end}}' | xargs -r -l osc build-logs -n test >"${LOG_DIR}/stibuild.log" osc get -n docker builds -o template -t '{{ range .items }}{{.metadata.name}}{{ "\n" }}{{end}}' | xargs -r -l osc build-logs -n docker >"${LOG_DIR}/dockerbuild.log" osc get -n custom builds -o template -t '{{ range .items }}{{.metadata.name}}{{ "\n" }}{{end}}' | xargs -r -l osc build-logs -n custom >"${LOG_DIR}/custombuild.log" @@ -213,28 +213,29 @@ echo "Log in as 'e2e-user' to see the 'test' project." echo "[INFO] Installing the router" openshift ex router --create --credentials="${KUBECONFIG}" --images="${USE_IMAGES}" -# install the registry +# install the registry. The --mount-host option is provided to reuse local storage. echo "[INFO] Installing the registry" -CERT_DIR="${CERT_DIR}/openshift-client" hack/install-registry.sh +# TODO: add --images="${USE_IMAGES}" when the Docker registry is built alongside OpenShift +openshift ex registry --create --credentials="${KUBECONFIG}" --mount-host="/tmp/openshift.local.registry" --images='openshift/origin-${component}:latest' -echo "[INFO] Waiting for Docker registry pod to start" -wait_for_command "osc get pods | grep registrypod | grep -i Running" $((5*TIME_MIN)) +echo "[INFO] Pre-pulling and pushing centos7" +docker pull centos:centos7 +# TODO: remove after this becomes part of the build +docker pull openshift/origin-docker-registry +echo "[INFO] Pulled centos7" -echo "[INFO] Waiting for Docker registry service to start" -wait_for_command "osc get services | grep registrypod" +echo "[INFO] Waiting for Docker registry pod to start" +# TODO: simplify when #4702 is fixed upstream +wait_for_command '[[ "$(osc get endpoints docker-registry -t "{{ if .endpoints }}{{ len .endpoints }}{{ else }}0{{ end }}" || echo "0")" != "0" ]]' $((5*TIME_MIN)) # services can end up on any IP. Make sure we get the IP we need for the docker registry -DOCKER_REGISTRY_IP=$(osc get -o template --output-version=v1beta1 --template="{{ .portalIP }}" service docker-registry) - -echo "[INFO] Probing the docker-registry" -wait_for_url_timed "http://${DOCKER_REGISTRY_IP}:5001" "[INFO] Docker registry says: " $((2*TIME_MIN)) +DOCKER_REGISTRY=$(osc get --output-version=v1beta1 --template="{{ .portalIP }}:{{ .port }}" service docker-registry) -echo "[INFO] Pre-pulling and pushing centos7" -docker pull centos:centos7 -echo "[INFO] Pulled centos7" +echo "[INFO] Verifying the docker-registry is up at ${DOCKER_REGISTRY}" +wait_for_url_timed "http://${DOCKER_REGISTRY}" "[INFO] Docker registry says: " $((2*TIME_MIN)) -docker tag -f centos:centos7 ${DOCKER_REGISTRY_IP}:5001/cached/centos:centos7 -docker push ${DOCKER_REGISTRY_IP}:5001/cached/centos:centos7 +docker tag -f centos:centos7 ${DOCKER_REGISTRY}/cached/centos:centos7 +docker push ${DOCKER_REGISTRY}/cached/centos:centos7 echo "[INFO] Pushed centos7" # Process template and create @@ -267,7 +268,8 @@ wait_for_app "test" #wait_for_app "custom" # ensure the router is started -wait_for_command "osc get pods | grep router-1 | grep -i Running" $((5*TIME_MIN)) +# TODO: simplify when #4702 is fixed upstream +wait_for_command '[[ "$(osc get endpoints router -t "{{ if .endpoints }}{{ len .endpoints }}{{ else }}0{{ end }}" || echo "0")" != "0" ]]' $((5*TIME_MIN)) echo "[INFO] Validating routed app response..." validate_response "-s -k --resolve www.example.com:443:${CONTAINER_ACCESSIBLE_API_HOST} https://www.example.com" "Hello from OpenShift" 0.2 50 diff --git a/images/origin/Dockerfile b/images/origin/Dockerfile index e3e5b4ec326a..1d199c0f7a68 100644 --- a/images/origin/Dockerfile +++ b/images/origin/Dockerfile @@ -16,5 +16,6 @@ RUN ln -s /usr/bin/openshift /usr/bin/osc && \ ln -s /usr/bin/openshift /usr/bin/openshift-router ENV HOME /root +ENV KUBECONFIG /var/lib/openshift/openshift.local.certificates/admin/.kubeconfig WORKDIR /var/lib/openshift ENTRYPOINT ["/usr/bin/openshift"] diff --git a/pkg/cmd/experimental/registry/registry.go b/pkg/cmd/experimental/registry/registry.go new file mode 100644 index 000000000000..43c543938ef3 --- /dev/null +++ b/pkg/cmd/experimental/registry/registry.go @@ -0,0 +1,277 @@ +package registry + +import ( + "fmt" + "io" + "os" + "strings" + + kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + kclient "github.com/GoogleCloudPlatform/kubernetes/pkg/client" + kclientcmd "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" + "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" + "github.com/golang/glog" + "github.com/spf13/cobra" + + "github.com/openshift/origin/pkg/cmd/util/clientcmd" + "github.com/openshift/origin/pkg/cmd/util/variable" + configcmd "github.com/openshift/origin/pkg/config/cmd" + dapi "github.com/openshift/origin/pkg/deploy/api" + "github.com/openshift/origin/pkg/generate/app" +) + +const longDesc = ` +Install or configure a Docker registry for OpenShift + +This command sets up a Docker registry integrated with OpenShift to provide notifications when +images are pushed. With no arguments, the command will check for the existing registry service +called 'docker-registry' and perform some diagnostics to ensure the registry is properly +configured and functioning. + +If a registry service does not exist, the --create flag can be passed to +create a deployment configuration and service that will run the registry. + +To run a highly available registry, you should be using a remote storage mechanism like an +object store (several are supported by the Docker registry). The default Docker registry image +is configured to accept configuration as environment variables - refer to the config file in +that image for more on setting up alternative storage. Once you've made those changes, you can +pass --replicas=2 or higher to ensure you have failover protection. The default registry setup +uses a local volume and the data will be lost if you delete the running pod. + +Examples: + Check the default Docker registry ("docker-registry"): + + $ %[1]s %[2]s + + See what the registry would look like if created: + + $ %[1]s %[2]s -o json + + Create a registry if it does not exist with two replicas: + + $ %[1]s %[2]s --create --replicas=2 + + Use a different registry image and see the registry configuration: + + $ %[1]s %[2]s -o yaml --images=myrepo/docker-registry:mytag + +ALPHA: This command is currently being actively developed. It is intended to simplify + the tasks of setting up a Docker registry in a new installation. Some configuration + beyond this command is still required to make your registry permanent. +` + +type config struct { + Type string + ImageTemplate variable.ImageTemplate + Ports string + Replicas int + Labels string + Volume string + HostMount string + Create bool + Credentials string + + // TODO: accept environment values. +} + +const defaultLabel = "docker-registry=default" + +func NewCmdRegistry(f *clientcmd.Factory, parentName, name string, out io.Writer) *cobra.Command { + cfg := &config{ + ImageTemplate: variable.NewDefaultImageTemplate(), + + Labels: defaultLabel, + Ports: "5000", + Volume: "/registry", + Replicas: 1, + } + + cmd := &cobra.Command{ + Use: name, + Short: "Install and check OpenShift Docker registry", + Long: fmt.Sprintf(longDesc, parentName, name), + + Run: func(cmd *cobra.Command, args []string) { + var name string + switch len(args) { + case 0: + name = "docker-registry" + default: + glog.Fatalf("No arguments are allowed to this command") + } + + ports, err := app.ContainerPortsFromString(cfg.Ports) + if err != nil { + glog.Fatal(err) + } + + label := map[string]string{ + "docker-registry": "default", + } + if cfg.Labels != defaultLabel { + valid, remove, err := app.LabelsFromSpec(strings.Split(cfg.Labels, ",")) + if err != nil { + glog.Fatal(err) + } + if len(remove) > 0 { + glog.Fatalf("You may not pass negative labels in %q", cfg.Labels) + } + label = valid + } + + image := cfg.ImageTemplate.ExpandOrDie(cfg.Type) + + namespace, err := f.OpenShiftClientConfig.Namespace() + if err != nil { + glog.Fatalf("Error getting client: %v", err) + } + _, kClient, err := f.Clients(cmd) + if err != nil { + glog.Fatalf("Error getting client: %v", err) + } + + p, output, err := cmdutil.PrinterForCommand(cmd) + if err != nil { + glog.Fatalf("Unable to configure printer: %v", err) + } + + generate := output + if !generate { + _, err = kClient.Services(namespace).Get(name) + if err != nil { + if !errors.IsNotFound(err) { + glog.Fatalf("Can't check for existing docker-registry %q: %v", name, err) + } + generate = true + } + } + + if generate { + if !cfg.Create && !output { + glog.Fatalf("Docker-registry %q does not exist (no service). Pass --create to install.", name) + } + + // create new registry + if len(cfg.Credentials) == 0 { + glog.Fatalf("You must specify a .kubeconfig file path containing credentials for connecting the registry to the master with --credentials") + } + credentials, err := (&kclientcmd.ClientConfigLoadingRules{CommandLinePath: cfg.Credentials}).Load() + if err != nil { + glog.Fatalf("The provided credentials %q could not be loaded: %v", cfg.Credentials, err) + } + config, err := kclientcmd.NewDefaultClientConfig(*credentials, &kclientcmd.ConfigOverrides{}).ClientConfig() + if err != nil { + glog.Fatalf("The provided credentials %q could not be used: %v", cfg.Credentials, err) + } + if err := kclient.LoadTLSFiles(config); err != nil { + glog.Fatalf("The provided credentials %q could not load certificate info: %v", cfg.Credentials, err) + } + insecure := "false" + if config.Insecure { + insecure = "true" + } + env := app.Environment{ + "OPENSHIFT_MASTER": config.Host, + "OPENSHIFT_CA_DATA": string(config.CAData), + "OPENSHIFT_KEY_DATA": string(config.KeyData), + "OPENSHIFT_CERT_DATA": string(config.CertData), + "OPENSHIFT_INSECURE": insecure, + } + + mountHost := len(cfg.HostMount) > 0 + podTemplate := &kapi.PodTemplateSpec{ + ObjectMeta: kapi.ObjectMeta{Labels: label}, + Spec: kapi.PodSpec{ + Containers: []kapi.Container{ + { + Name: "registry", + Image: image, + Ports: ports, + Env: env.List(), + VolumeMounts: []kapi.VolumeMount{ + { + Name: "registry-storage", + MountPath: cfg.Volume, + }, + }, + Privileged: mountHost, + }, + }, + Volumes: []kapi.Volume{ + { + Name: "registry-storage", + Source: kapi.VolumeSource{}, + }, + }, + }, + } + if mountHost { + podTemplate.Spec.Volumes[0].Source.HostPath = &kapi.HostPath{Path: cfg.HostMount} + } else { + podTemplate.Spec.Volumes[0].Source.EmptyDir = &kapi.EmptyDir{} + } + + objects := []runtime.Object{ + &dapi.DeploymentConfig{ + ObjectMeta: kapi.ObjectMeta{ + Name: name, + Labels: label, + }, + Triggers: []dapi.DeploymentTriggerPolicy{ + {Type: dapi.DeploymentTriggerOnConfigChange}, + }, + Template: dapi.DeploymentTemplate{ + Strategy: dapi.DeploymentStrategy{ + Type: dapi.DeploymentStrategyTypeRecreate, + }, + ControllerTemplate: kapi.ReplicationControllerSpec{ + Replicas: cfg.Replicas, + Selector: label, + Template: podTemplate, + }, + }, + }, + } + objects = app.AddServices(objects) + // TODO: label all created objects with the same label + list := &kapi.List{Items: objects} + + if output { + if err := p.PrintObj(list, out); err != nil { + glog.Fatalf("Unable to print object: %v", err) + } + return + } + + bulk := configcmd.Bulk{ + Factory: f.Factory, + Command: cmd, + After: configcmd.NewPrintNameOrErrorAfter(out, os.Stderr), + } + if errs := bulk.Create(list, namespace); len(errs) != 0 { + os.Exit(1) + } + return + } + + fmt.Fprintf(out, "Docker registry %q service exists", name) + }, + } + + cmd.Flags().StringVar(&cfg.Type, "type", "docker-registry", "The registry image to use - if you specify --images this flag may be ignored.") + cmd.Flags().StringVar(&cfg.ImageTemplate.Format, "images", cfg.ImageTemplate.Format, "The image to base this registry on - ${component} will be replaced with --type") + cmd.Flags().BoolVar(&cfg.ImageTemplate.Latest, "latest-images", cfg.ImageTemplate.Latest, "If true, attempt to use the latest image for the registry instead of the latest release.") + cmd.Flags().StringVar(&cfg.Ports, "ports", cfg.Ports, "A comma delimited list of ports or port pairs to expose on the registry pod. The default is set for 5000.") + cmd.Flags().IntVar(&cfg.Replicas, "replicas", cfg.Replicas, "The replication factor of the registry; commonly 2 when high availability is desired.") + cmd.Flags().StringVar(&cfg.Labels, "labels", cfg.Labels, "A set of labels to uniquely identify the registry and its components.") + cmd.Flags().StringVar(&cfg.Volume, "volume", cfg.Volume, "The volume path to use for registry storage; defaults to /registry which is the default for origin-docker-registry.") + cmd.Flags().StringVar(&cfg.HostMount, "mount-host", cfg.HostMount, "If set, the registry volume will be created as a host-mount at this path.") + cmd.Flags().BoolVar(&cfg.Create, "create", cfg.Create, "Create the registry if it does not exist.") + cmd.Flags().StringVar(&cfg.Credentials, "credentials", "", "Path to a .kubeconfig file that will contain the credentials the registry should use to contact the master.") + + cmdutil.AddPrinterFlags(cmd) + + return cmd +} diff --git a/pkg/cmd/openshift/openshift.go b/pkg/cmd/openshift/openshift.go index c1f50545cb01..57a9d1f533c2 100644 --- a/pkg/cmd/openshift/openshift.go +++ b/pkg/cmd/openshift/openshift.go @@ -13,6 +13,7 @@ import ( "github.com/openshift/origin/pkg/cmd/experimental/login" "github.com/openshift/origin/pkg/cmd/experimental/policy" "github.com/openshift/origin/pkg/cmd/experimental/project" + exregistry "github.com/openshift/origin/pkg/cmd/experimental/registry" exrouter "github.com/openshift/origin/pkg/cmd/experimental/router" "github.com/openshift/origin/pkg/cmd/experimental/tokens" "github.com/openshift/origin/pkg/cmd/flagtypes" @@ -123,6 +124,7 @@ func newExperimentalCommand(parentName, name string) *cobra.Command { experimental.AddCommand(generate.NewCmdGenerate(f, subName, "generate")) experimental.AddCommand(login.NewCmdLogin(f, subName, "login")) experimental.AddCommand(exrouter.NewCmdRouter(f, subName, "router", os.Stdout)) + experimental.AddCommand(exregistry.NewCmdRegistry(f, subName, "registry", os.Stdout)) return experimental }