From 0cba36d79fc11174e3eb588c611c0465a67c9e7f Mon Sep 17 00:00:00 2001 From: stonezdj Date: Fri, 22 Feb 2019 16:34:26 +0800 Subject: [PATCH] Remove everything of adminserver Signed-off-by: stonezdj --- .gitignore | 1 + Makefile | 30 +- docs/installation_guide.md | 3 - docs/migration_guide.md | 4 +- docs/use_make.md | 3 +- .../{adminserver/env => core/config_env} | 0 make/common/templates/core/env | 1 - make/docker-compose.tpl | 2 +- make/photon/Makefile | 19 +- make/photon/adminserver/Dockerfile | 15 - make/photon/adminserver/start.sh | 7 - make/prepare | 14 +- src/adminserver/api/base.go | 48 -- src/adminserver/api/base_test.go | 78 --- src/adminserver/api/cfg.go | 75 --- src/adminserver/api/cfg_test.go | 168 ------ src/adminserver/api/monitor.go | 14 - src/adminserver/api/monitor_test.go | 17 - src/adminserver/auth/auth.go | 54 -- src/adminserver/auth/auth_test.go | 53 -- src/adminserver/client/client.go | 105 ---- src/adminserver/client/client_test.go | 71 --- src/adminserver/handlers/handler.go | 88 ---- src/adminserver/handlers/handlers_test.go | 84 --- src/adminserver/handlers/router.go | 31 -- src/adminserver/main.go | 60 --- src/adminserver/systemcfg/encrypt/encrypt.go | 60 --- .../systemcfg/encrypt/encrypt_test.go | 92 ---- .../systemcfg/store/database/driver_db.go | 151 ------ .../store/database/driver_db_test.go | 75 --- src/adminserver/systemcfg/store/driver.go | 26 - .../systemcfg/store/encrypt/driver.go | 97 ---- .../systemcfg/store/encrypt/driver_test.go | 81 --- .../systemcfg/store/json/driver_json.go | 119 ----- .../systemcfg/store/json/driver_json_test.go | 51 -- src/adminserver/systemcfg/systemcfg.go | 483 ------------------ src/adminserver/systemcfg/systemcfg_test.go | 290 ----------- src/common/config/config.go | 112 ---- src/common/config/config_test.go | 17 - src/common/config/manager.go | 12 +- src/common/const.go | 48 -- src/common/token/htoken_test.go | 18 +- .../utils/test/{adminserver.go => config.go} | 55 +- src/jobservice/README.md | 5 +- src/jobservice/config/config.go | 16 - src/jobservice/config/config_test.go | 5 - tests/configharbor.py | 1 - tests/testprepare.sh | 4 - tests/travis/ut_install.sh | 1 - 49 files changed, 32 insertions(+), 2832 deletions(-) rename make/common/templates/{adminserver/env => core/config_env} (100%) delete mode 100644 make/photon/adminserver/Dockerfile delete mode 100644 make/photon/adminserver/start.sh delete mode 100644 src/adminserver/api/base.go delete mode 100644 src/adminserver/api/base_test.go delete mode 100644 src/adminserver/api/cfg.go delete mode 100644 src/adminserver/api/cfg_test.go delete mode 100644 src/adminserver/api/monitor.go delete mode 100644 src/adminserver/api/monitor_test.go delete mode 100644 src/adminserver/auth/auth.go delete mode 100644 src/adminserver/auth/auth_test.go delete mode 100644 src/adminserver/client/client.go delete mode 100644 src/adminserver/client/client_test.go delete mode 100644 src/adminserver/handlers/handler.go delete mode 100644 src/adminserver/handlers/handlers_test.go delete mode 100644 src/adminserver/handlers/router.go delete mode 100644 src/adminserver/main.go delete mode 100644 src/adminserver/systemcfg/encrypt/encrypt.go delete mode 100644 src/adminserver/systemcfg/encrypt/encrypt_test.go delete mode 100644 src/adminserver/systemcfg/store/database/driver_db.go delete mode 100644 src/adminserver/systemcfg/store/database/driver_db_test.go delete mode 100644 src/adminserver/systemcfg/store/driver.go delete mode 100644 src/adminserver/systemcfg/store/encrypt/driver.go delete mode 100644 src/adminserver/systemcfg/store/encrypt/driver_test.go delete mode 100644 src/adminserver/systemcfg/store/json/driver_json.go delete mode 100644 src/adminserver/systemcfg/store/json/driver_json_test.go delete mode 100644 src/adminserver/systemcfg/systemcfg.go delete mode 100644 src/adminserver/systemcfg/systemcfg_test.go delete mode 100644 src/common/config/config.go delete mode 100644 src/common/config/config_test.go rename src/common/utils/test/{adminserver.go => config.go} (75%) diff --git a/.gitignore b/.gitignore index f5ee13e22..86f776f21 100644 --- a/.gitignore +++ b/.gitignore @@ -41,3 +41,4 @@ src/portal/src/**/*.js.map **/aot **/dist **/.bin +src/core/conf/app.conf diff --git a/Makefile b/Makefile index 4543814af..621f6e422 100644 --- a/Makefile +++ b/Makefile @@ -4,13 +4,13 @@ # # all: prepare env, compile binaries, build images and install images # prepare: prepare env -# compile: compile adminserver, ui and jobservice code +# compile: compile core and jobservice code # # compile_golangimage: # compile from golang image # for example: make compile_golangimage -e GOBUILDIMAGE= \ # golang:1.11.2 -# compile_adminserver, compile_core, compile_jobservice: compile specific binary +# compile_core, compile_jobservice: compile specific binary # # build: build Harbor docker images from photon baseimage # @@ -43,7 +43,7 @@ # # clean: remove binary, Harbor images, specific version docker-compose \ # file, specific version tag and online/offline install package -# cleanbinary: remove adminserver, ui and jobservice binary +# cleanbinary: remove core and jobservice binary # cleanimage: remove Harbor images # cleandockercomposefile: # remove specific version docker-compose @@ -129,21 +129,17 @@ GOBUILDIMAGE=golang:1.11.2 GOBUILDPATH=$(GOBASEPATH)/harbor GOIMAGEBUILDCMD=/usr/local/go/bin/go GOIMAGEBUILD=$(GOIMAGEBUILDCMD) build -GOBUILDPATH_ADMINSERVER=$(GOBUILDPATH)/src/adminserver GOBUILDPATH_CORE=$(GOBUILDPATH)/src/core GOBUILDPATH_JOBSERVICE=$(GOBUILDPATH)/src/jobservice GOBUILDPATH_REGISTRYCTL=$(GOBUILDPATH)/src/registryctl GOBUILDPATH_MIGRATEPATCH=$(GOBUILDPATH)/src/cmd/migrate-patch GOBUILDMAKEPATH=$(GOBUILDPATH)/make -GOBUILDMAKEPATH_ADMINSERVER=$(GOBUILDMAKEPATH)/photon/adminserver GOBUILDMAKEPATH_CORE=$(GOBUILDMAKEPATH)/photon/core GOBUILDMAKEPATH_JOBSERVICE=$(GOBUILDMAKEPATH)/photon/jobservice GOBUILDMAKEPATH_REGISTRYCTL=$(GOBUILDMAKEPATH)/photon/registryctl GOBUILDMAKEPATH_NOTARY=$(GOBUILDMAKEPATH)/photon/notary # binary -ADMINSERVERBINARYPATH=$(MAKEDEVPATH)/adminserver -ADMINSERVERBINARYNAME=harbor_adminserver CORE_BINARYPATH=$(MAKEDEVPATH)/core CORE_BINARYNAME=harbor_core JOBSERVICEBINARYPATH=$(MAKEDEVPATH)/jobservice @@ -178,7 +174,6 @@ MAKEFILEPATH_PHOTON=$(MAKEPATH)/photon DOCKERFILEPATH_COMMON=$(MAKEPATH)/common # docker image name -DOCKERIMAGENAME_ADMINSERVER=goharbor/harbor-adminserver DOCKERIMAGENAME_PORTAL=goharbor/harbor-portal DOCKERIMAGENAME_CORE=goharbor/harbor-core DOCKERIMAGENAME_JOBSERVICE=goharbor/harbor-jobservice @@ -213,8 +208,7 @@ REGISTRYUSER=user REGISTRYPASSWORD=default # cmds -DOCKERSAVE_PARA=$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) \ - $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) \ +DOCKERSAVE_PARA= $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) \ $(DOCKERIMAGENAME_CORE):$(VERSIONTAG) \ $(DOCKERIMAGENAME_LOG):$(VERSIONTAG) \ $(DOCKERIMAGENAME_DB):$(VERSIONTAG) \ @@ -268,13 +262,6 @@ ui_version: check_environment: @$(MAKEPATH)/$(CHECKENVCMD) -compile_adminserver: - @echo "compiling binary for adminserver (golang image)..." - @echo $(GOBASEPATH) - @echo $(GOBUILDPATH) - $(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_ADMINSERVER) $(GOBUILDIMAGE) $(GOIMAGEBUILD) -o $(GOBUILDMAKEPATH_ADMINSERVER)/$(ADMINSERVERBINARYNAME) - @echo "Done." - compile_core: @echo "compiling binary for core (golang image)..." @echo $(GOBASEPATH) @@ -297,7 +284,7 @@ compile_notary_migrate_patch: @$(DOCKERCMD) run --rm -v $(BUILDPATH):$(GOBUILDPATH) -w $(GOBUILDPATH_MIGRATEPATCH) $(GOBUILDIMAGE) $(GOIMAGEBUILD) -o $(GOBUILDMAKEPATH_NOTARY)/$(MIGRATEPATCHBINARYNAME) @echo "Done." -compile:check_environment compile_adminserver compile_core compile_jobservice compile_registryctl compile_notary_migrate_patch +compile:check_environment compile_core compile_jobservice compile_registryctl compile_notary_migrate_patch prepare: @echo "preparing..." @@ -417,11 +404,6 @@ govet: pushimage: @echo "pushing harbor images ..." - @$(DOCKERTAG) $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) - @$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) \ - $(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER) - @$(DOCKERRMIMAGE) $(REGISTRYSERVER)$(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) - @$(DOCKERTAG) $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) $(REGISTRYSERVER)$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) @$(PUSHSCRIPTPATH)/$(PUSHSCRIPTNAME) $(REGISTRYSERVER)$(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) \ $(REGISTRYUSER) $(REGISTRYPASSWORD) $(REGISTRYSERVER) @@ -474,13 +456,11 @@ swagger_client: cleanbinary: @echo "cleaning binary..." - @if [ -f $(ADMINSERVERBINARYPATH)/$(ADMINSERVERBINARYNAME) ] ; then rm $(ADMINSERVERBINARYPATH)/$(ADMINSERVERBINARYNAME) ; fi @if [ -f $(CORE_BINARYPATH)/$(CORE_BINARYNAME) ] ; then rm $(CORE_BINARYPATH)/$(CORE_BINARYNAME) ; fi @if [ -f $(JOBSERVICEBINARYPATH)/$(JOBSERVICEBINARYNAME) ] ; then rm $(JOBSERVICEBINARYPATH)/$(JOBSERVICEBINARYNAME) ; fi cleanimage: @echo "cleaning image for photon..." - - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_CORE):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_DB):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) diff --git a/docs/installation_guide.md b/docs/installation_guide.md index 886184b09..0b96f6a48 100644 --- a/docs/installation_guide.md +++ b/docs/installation_guide.md @@ -210,7 +210,6 @@ Stopping registry ... done Stopping redis ... done Stopping registryctl ... done Stopping harbor-db ... done -Stopping harbor-adminserver ... done Stopping harbor-log ... done ``` Restarting Harbor after stopping: @@ -220,7 +219,6 @@ Starting log ... done Starting registry ... done Starting registryctl ... done Starting postgresql ... done -Starting adminserver ... done Starting core ... done Starting portal ... done Starting redis ... done @@ -390,7 +388,6 @@ By default, Harbor limits the CPU usage of Clair container to 150000 and avoids $ sudo docker-compose ps Name Command State Ports ----------------------------------------------------------------------------------------------------------------------------- - harbor-adminserver /harbor/start.sh Up harbor-core /harbor/start.sh Up harbor-db /entrypoint.sh postgres Up 5432/tcp harbor-jobservice /harbor/start.sh Up diff --git a/docs/migration_guide.md b/docs/migration_guide.md index 61d38259a..ea4eefd6e 100644 --- a/docs/migration_guide.md +++ b/docs/migration_guide.md @@ -47,8 +47,8 @@ or above it's not necessary to call the migrator tool to migrate the schema. ``` docker run -it --rm -v ${harbor_cfg}:/harbor-migration/harbor-cfg/harbor.cfg goharbor/harbor-migrator:[tag] --cfg up ``` - **NOTE:** The schema upgrade and data migration of Database is performed by adminserver when Harbor starts, if the migration fails, - please check the log of adminserver to debug. + **NOTE:** The schema upgrade and data migration of Database is performed by core when Harbor starts, if the migration fails, + please check the log of core to debug. 6. Under the directory `./harbor`, run the `./install.sh` script to install the new Harbor instance. If you choose to install Harbor with components like Notary, Clair, and chartmuseum, refer to [Installation & Configuration Guide](../docs/installation_guide.md) for more information. diff --git a/docs/use_make.md b/docs/use_make.md index 7fc98888d..c18da1ad6 100644 --- a/docs/use_make.md +++ b/docs/use_make.md @@ -15,9 +15,8 @@ all | prepare env, compile binaries, build images and install im prepare | prepare env compile | compile ui and jobservice code compile_portal | compile portal code -compile_ui | compile ui binary +compile_core | compile core binary compile_jobservice | compile jobservice binary -compile_adminserver | compile admin server binary build | build Harbor docker images (default: using build_photon) build_photon | build Harbor docker images from Photon OS base image install | compile binaries, build images, prepare specific version of compose file and startup Harbor instance diff --git a/make/common/templates/adminserver/env b/make/common/templates/core/config_env similarity index 100% rename from make/common/templates/adminserver/env rename to make/common/templates/core/config_env diff --git a/make/common/templates/core/env b/make/common/templates/core/env index 8cc74521f..f855fd148 100644 --- a/make/common/templates/core/env +++ b/make/common/templates/core/env @@ -2,7 +2,6 @@ LOG_LEVEL=info CONFIG_PATH=/etc/core/app.conf CORE_SECRET=$core_secret JOBSERVICE_SECRET=$jobservice_secret -ADMINSERVER_URL=$adminserver_url UAA_CA_ROOT=/etc/core/certificates/uaa_ca.pem _REDIS_URL=$redis_host:$redis_port,100,$redis_password SYNC_REGISTRY=false diff --git a/make/docker-compose.tpl b/make/docker-compose.tpl index 315c311fe..22144d29b 100644 --- a/make/docker-compose.tpl +++ b/make/docker-compose.tpl @@ -99,7 +99,7 @@ services: container_name: harbor-core env_file: - ./common/config/core/env - - ./common/config/adminserver/env + - ./common/config/core/config_env restart: always cap_drop: - ALL diff --git a/make/photon/Makefile b/make/photon/Makefile index 074c8fcb1..c70209963 100644 --- a/make/photon/Makefile +++ b/make/photon/Makefile @@ -3,7 +3,7 @@ # Targets: # # build: build harbor photon images -# clean: clean adminserver, ui and jobservice harbor images +# clean: clean core and jobservice harbor images # common SHELL := /bin/bash @@ -21,10 +21,7 @@ DOCKERBUILD=$(DOCKERCMD) build --pull DOCKERRMIMAGE=$(DOCKERCMD) rmi DOCKERIMASES=$(DOCKERCMD) images -# binary -ADMINSERVERSOURCECODE=$(SRCPATH)/adminserver -ADMINSERVERBINARYPATH=$(MAKEDEVPATH)/adminserver -ADMINSERVERBINARYNAME=harbor_adminserver +# binary CORE_SOURCECODE=$(SRCPATH)/core CORE_BINARYPATH=$(MAKEDEVPATH)/core CORE_BINARYNAME=harbor_core @@ -35,10 +32,6 @@ JOBSERVICEBINARYNAME=harbor_jobservice # photon dockerfile DOCKERFILEPATH=$(MAKEPATH)/photon -DOCKERFILEPATH_ADMINSERVER=$(DOCKERFILEPATH)/adminserver -DOCKERFILENAME_ADMINSERVER=Dockerfile -DOCKERIMAGENAME_ADMINSERVER=goharbor/harbor-adminserver - DOCKERFILEPATH_PORTAL=$(DOCKERFILEPATH)/portal DOCKERFILENAME_PORTAL=Dockerfile DOCKERIMAGENAME_PORTAL=goharbor/harbor-portal @@ -105,11 +98,6 @@ _build_db: @$(DOCKERBUILD) -f $(DOCKERFILEPATH_DB)/$(DOCKERFILENAME_DB) -t $(DOCKERIMAGENAME_DB):$(VERSIONTAG) . @echo "Done." -_build_adminserver: - @echo "building adminserver container for photon..." - @$(DOCKERBUILD) -f $(DOCKERFILEPATH_ADMINSERVER)/$(DOCKERFILENAME_ADMINSERVER) -t $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) . - @echo "Done." - _build_portal: @echo "building portal container for photon..." $(DOCKERBUILD) -f $(DOCKERFILEPATH_PORTAL)/$(DOCKERFILENAME_PORTAL) -t $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) . @@ -212,11 +200,10 @@ define _get_binary $(WGET) --timeout 30 --no-check-certificate $1 -O $2 endef -build: _build_db _build_adminserver _build_portal _build_core _build_jobservice _build_log _build_nginx _build_registry _build_registryctl _build_notary _build_clair _build_redis _build_migrator _build_chart_server +build: _build_db _build_portal _build_core _build_jobservice _build_log _build_nginx _build_registry _build_registryctl _build_notary _build_clair _build_redis _build_migrator _build_chart_server cleanimage: @echo "cleaning image for photon..." - - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_ADMINSERVER):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_PORTAL):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_CORE):$(VERSIONTAG) - $(DOCKERRMIMAGE) -f $(DOCKERIMAGENAME_JOBSERVICE):$(VERSIONTAG) diff --git a/make/photon/adminserver/Dockerfile b/make/photon/adminserver/Dockerfile deleted file mode 100644 index f0ec24883..000000000 --- a/make/photon/adminserver/Dockerfile +++ /dev/null @@ -1,15 +0,0 @@ -FROM photon:2.0 - -RUN tdnf install -y sudo >> /dev/null \ - && tdnf clean all \ - && groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor \ - && mkdir /harbor/ -COPY ./make/photon/adminserver/harbor_adminserver ./make/photon/adminserver/start.sh /harbor/ -#As UI will be blocked until adminserver is ready, let adminserver do the initialise work for DB -COPY ./make/migrations /harbor/migrations - -HEALTHCHECK CMD curl --fail -s http://127.0.0.1:8080/api/ping || exit 1 - -RUN chmod u+x /harbor/harbor_adminserver /harbor/start.sh -WORKDIR /harbor/ -ENTRYPOINT ["/harbor/start.sh"] diff --git a/make/photon/adminserver/start.sh b/make/photon/adminserver/start.sh deleted file mode 100644 index cc7f4a2ec..000000000 --- a/make/photon/adminserver/start.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -#In the case when the config store is set to filesystem, the directory has to be writable. -if [ -d /etc/adminserver/config ]; then - chown -R 10000:10000 /etc/adminserver/config -fi -sudo -E -u \#10000 "/harbor/harbor_adminserver" diff --git a/make/prepare b/make/prepare index bcb2d0eb9..0af25e4c8 100755 --- a/make/prepare +++ b/make/prepare @@ -253,10 +253,6 @@ registry_custom_ca_bundle_path = rcp.get("configuration", "registry_custom_ca_bu core_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16)) jobservice_secret = ''.join(random.choice(string.ascii_letters+string.digits) for i in range(16)) -adminserver_config_dir = os.path.join(config_dir,"adminserver") -if not os.path.exists(adminserver_config_dir): - os.makedirs(os.path.join(config_dir, "adminserver")) - core_config_dir = prep_conf_dir(config_dir,"core") core_certificates_dir = prep_conf_dir(core_config_dir,"certificates") db_config_dir = prep_conf_dir(config_dir, "db") @@ -267,7 +263,7 @@ nginx_config_dir = prep_conf_dir (config_dir, "nginx") nginx_conf_d = prep_conf_dir(nginx_config_dir, "conf.d") log_config_dir = prep_conf_dir (config_dir, "log") -adminserver_conf_env = os.path.join(config_dir, "adminserver", "env") +conf_env = os.path.join(config_dir, "core", "config_env") core_conf_env = os.path.join(config_dir, "core", "env") core_conf = os.path.join(config_dir, "core", "app.conf") core_cert_dir = os.path.join(config_dir, "core", "certificates") @@ -279,8 +275,7 @@ db_conf_env = os.path.join(config_dir, "db", "env") job_conf_env = os.path.join(config_dir, "jobservice", "env") nginx_conf = os.path.join(config_dir, "nginx", "nginx.conf") cert_dir = os.path.join(config_dir, "nginx", "cert") -log_rotate_config = os.path.join(config_dir, "log", "logrotate.conf") -adminserver_url = "http://adminserver:8080" +log_rotate_config = os.path.join(config_dir, "log", "logrotate.conf") registry_url = "http://registry:5000" registry_controller_url = "http://registryctl:8080" core_url = "http://core:8080" @@ -338,8 +333,8 @@ reload_key = ''.join(random.choice(string.ascii_uppercase + string.digits) for _ ldap_group_admin_dn = rcp.get("configuration", "ldap_group_admin_dn") if rcp.has_option("configuration", "ldap_group_admin_dn") else "" -render(os.path.join(templates_dir, "adminserver", "env"), - adminserver_conf_env, +render(os.path.join(templates_dir, "core", "config_env"), + conf_env, reload_config=reload_config, public_url=public_url, core_url=core_url, @@ -415,7 +410,6 @@ render(os.path.join(templates_dir, "core", "env"), redis_host=redis_host, redis_port=redis_port, redis_password=redis_password, - adminserver_url = adminserver_url, chart_cache_driver = chart_cache_driver, redis_url_reg = redis_url_reg) diff --git a/src/adminserver/api/base.go b/src/adminserver/api/base.go deleted file mode 100644 index 94722a701..000000000 --- a/src/adminserver/api/base.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package api - -import ( - "encoding/json" - "net/http" -) - -func handleInternalServerError(w http.ResponseWriter) { - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) -} - -func handleBadRequestError(w http.ResponseWriter, error string) { - http.Error(w, error, http.StatusBadRequest) -} - -func handleUnauthorized(w http.ResponseWriter) { - http.Error(w, http.StatusText(http.StatusUnauthorized), - http.StatusUnauthorized) -} - -// response status code will be written automatically if there is an error -func writeJSON(w http.ResponseWriter, v interface{}) error { - b, err := json.Marshal(v) - if err != nil { - handleInternalServerError(w) - return err - } - - if _, err = w.Write(b); err != nil { - return err - } - return nil -} diff --git a/src/adminserver/api/base_test.go b/src/adminserver/api/base_test.go deleted file mode 100644 index 626684d97..000000000 --- a/src/adminserver/api/base_test.go +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package api - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestHandleInternalServerError(t *testing.T) { - w := httptest.NewRecorder() - handleInternalServerError(w) - - if w.Code != http.StatusInternalServerError { - t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusInternalServerError) - } -} - -func TestHandleBadRequestError(t *testing.T) { - w := httptest.NewRecorder() - err := "error message" - handleBadRequestError(w, err) - - if w.Code != http.StatusBadRequest { - t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusBadRequest) - } -} - -func TestHandleUnauthorized(t *testing.T) { - w := httptest.NewRecorder() - handleUnauthorized(w) - - if w.Code != http.StatusUnauthorized { - t.Errorf("unexpected status code: %d != %d", w.Code, http.StatusUnauthorized) - } -} - -func TestWriteJSONNilInterface(t *testing.T) { - w := httptest.NewRecorder() - - if err := writeJSON(w, nil); err != nil { - t.Errorf("Expected nil error, received: %v", err) - } -} - -func TestWriteJSONMarshallErr(t *testing.T) { - // Tests capture json.Marshall error - x := map[string]interface{}{ - "foo": make(chan int), - } - - w := httptest.NewRecorder() - - if err := writeJSON(w, x); err == nil { - t.Errorf("Expected %v error received: no no error", err) - } -} - -func TestWriteJSON(t *testing.T) { - w := httptest.NewRecorder() - - if err := writeJSON(w, "Pong"); err != nil { - t.Errorf("Expected nil error, received: %v", err) - } -} diff --git a/src/adminserver/api/cfg.go b/src/adminserver/api/cfg.go deleted file mode 100644 index b267c1ff4..000000000 --- a/src/adminserver/api/cfg.go +++ /dev/null @@ -1,75 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package api - -import ( - "encoding/json" - "io/ioutil" - "net/http" - - "github.com/goharbor/harbor/src/adminserver/systemcfg" - "github.com/goharbor/harbor/src/common/utils/log" -) - -// ListCfgs lists configurations -func ListCfgs(w http.ResponseWriter, r *http.Request) { - cfg, err := systemcfg.CfgStore.Read() - if err != nil { - log.Errorf("failed to get system configurations: %v", err) - handleInternalServerError(w) - return - } - systemcfg.AddMissedKey(cfg) - if err = writeJSON(w, cfg); err != nil { - log.Errorf("failed to write response: %v", err) - return - } -} - -// UpdateCfgs updates configurations -func UpdateCfgs(w http.ResponseWriter, r *http.Request) { - b, err := ioutil.ReadAll(r.Body) - if err != nil { - log.Errorf("failed to read request body: %v", err) - handleInternalServerError(w) - return - } - - m := map[string]interface{}{} - if err = json.Unmarshal(b, &m); err != nil { - handleBadRequestError(w, err.Error()) - return - } - if err = systemcfg.CfgStore.Write(m); err != nil { - log.Errorf("failed to update system configurations: %v", err) - handleInternalServerError(w) - return - } -} - -// ResetCfgs resets configurations from environment variables -func ResetCfgs(w http.ResponseWriter, r *http.Request) { - cfgs := map[string]interface{}{} - if err := systemcfg.LoadFromEnv(cfgs, true); err != nil { - log.Errorf("failed to reset system configurations: %v", err) - handleInternalServerError(w) - return - } - if err := systemcfg.CfgStore.Write(cfgs); err != nil { - log.Errorf("failed to write system configurations to storage: %v", err) - handleInternalServerError(w) - return - } -} diff --git a/src/adminserver/api/cfg_test.go b/src/adminserver/api/cfg_test.go deleted file mode 100644 index 7ad70a7aa..000000000 --- a/src/adminserver/api/cfg_test.go +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package api - -import ( - "bytes" - "encoding/json" - "errors" - "fmt" - "io" - "io/ioutil" - "net/http" - "net/http/httptest" - "os" - "testing" - - "github.com/goharbor/harbor/src/adminserver/systemcfg" - "github.com/goharbor/harbor/src/common" - "github.com/stretchr/testify/assert" -) - -type fakeCfgStore struct { - cfgs map[string]interface{} - err error -} - -func (f *fakeCfgStore) Name() string { - return "fake" -} - -func (f *fakeCfgStore) Read() (map[string]interface{}, error) { - return f.cfgs, f.err -} - -func (f *fakeCfgStore) Write(cfgs map[string]interface{}) error { - f.cfgs = cfgs - return f.err -} - -func TestListCfgs(t *testing.T) { - // 500 - systemcfg.CfgStore = &fakeCfgStore{ - cfgs: nil, - err: errors.New("error"), - } - - w := httptest.NewRecorder() - ListCfgs(w, nil) - assert.Equal(t, http.StatusInternalServerError, w.Code) - - // 200 - key := "key" - value := "value" - cfgs := map[string]interface{}{ - key: value, - } - systemcfg.CfgStore = &fakeCfgStore{ - cfgs: cfgs, - err: nil, - } - w = httptest.NewRecorder() - ListCfgs(w, nil) - assert.Equal(t, http.StatusOK, w.Code) - result, err := parse(w.Body) - if err != nil { - t.Fatalf("failed to parse response body: %v", err) - } - assert.Equal(t, value, result[key]) -} - -func TestUpdateCfgs(t *testing.T) { - // 400 - w := httptest.NewRecorder() - r, err := http.NewRequest("", "", bytes.NewReader([]byte{'a'})) - if err != nil { - t.Fatalf("failed to create request: %v", err) - } - - UpdateCfgs(w, r) - assert.Equal(t, http.StatusBadRequest, w.Code) - - // 500 - systemcfg.CfgStore = &fakeCfgStore{ - cfgs: nil, - err: errors.New("error"), - } - w = httptest.NewRecorder() - r, err = http.NewRequest("", "", bytes.NewBufferString("{}")) - if err != nil { - t.Fatalf("failed to create request: %v", err) - } - - UpdateCfgs(w, r) - assert.Equal(t, http.StatusInternalServerError, w.Code) - - // 200 - key := "key" - value := "value" - systemcfg.CfgStore = &fakeCfgStore{ - cfgs: nil, - err: nil, - } - w = httptest.NewRecorder() - r, err = http.NewRequest("", "", - bytes.NewBufferString(fmt.Sprintf(`{"%s":"%s"}`, key, value))) - if err != nil { - t.Fatalf("failed to create request: %v", err) - } - - UpdateCfgs(w, r) - assert.Equal(t, http.StatusOK, w.Code) - -} - -func TestResetCfgs(t *testing.T) { - // 500 - systemcfg.CfgStore = &fakeCfgStore{ - cfgs: nil, - err: errors.New("error"), - } - w := httptest.NewRecorder() - - ResetCfgs(w, nil) - assert.Equal(t, http.StatusInternalServerError, w.Code) - - // 200 - os.Clearenv() - key := "LDAP_URL" - value := "ldap://ldap.com" - if err := os.Setenv(key, value); err != nil { - t.Fatalf("failed to set env: %v", err) - } - store := &fakeCfgStore{ - cfgs: nil, - err: nil, - } - systemcfg.CfgStore = store - w = httptest.NewRecorder() - - ResetCfgs(w, nil) - assert.Equal(t, http.StatusOK, w.Code) - assert.Equal(t, value, store.cfgs[common.LDAPURL]) -} - -func parse(reader io.Reader) (map[string]interface{}, error) { - b, err := ioutil.ReadAll(reader) - if err != nil { - return nil, err - } - - m := map[string]interface{}{} - if err := json.Unmarshal(b, &m); err != nil { - return nil, err - } - return m, nil -} diff --git a/src/adminserver/api/monitor.go b/src/adminserver/api/monitor.go deleted file mode 100644 index 1555c2964..000000000 --- a/src/adminserver/api/monitor.go +++ /dev/null @@ -1,14 +0,0 @@ -package api - -import ( - "github.com/goharbor/harbor/src/common/utils/log" - "net/http" -) - -// Ping monitor the server status -func Ping(w http.ResponseWriter, r *http.Request) { - if err := writeJSON(w, "Pong"); err != nil { - log.Errorf("Failed to write response: %v", err) - return - } -} diff --git a/src/adminserver/api/monitor_test.go b/src/adminserver/api/monitor_test.go deleted file mode 100644 index 578fab9f5..000000000 --- a/src/adminserver/api/monitor_test.go +++ /dev/null @@ -1,17 +0,0 @@ -package api - -import ( - "github.com/stretchr/testify/assert" - "io/ioutil" - "net/http" - "net/http/httptest" - "testing" -) - -func TestPing(t *testing.T) { - w := httptest.NewRecorder() - Ping(w, nil) - assert.Equal(t, http.StatusOK, w.Code) - result, _ := ioutil.ReadAll(w.Body) - assert.Equal(t, "\"Pong\"", string(result)) -} diff --git a/src/adminserver/auth/auth.go b/src/adminserver/auth/auth.go deleted file mode 100644 index 11beb9b2d..000000000 --- a/src/adminserver/auth/auth.go +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package auth - -import ( - "github.com/goharbor/harbor/src/common/secret" - "net/http" -) - -// Authenticator defines Authenticate function to authenticate requests -type Authenticator interface { - // Authenticate the request, if there is no error, the bool value - // determines whether the request is authenticated or not - Authenticate(req *http.Request) (bool, error) -} - -type secretAuthenticator struct { - secrets map[string]string -} - -// NewSecretAuthenticator returns an instance of secretAuthenticator -func NewSecretAuthenticator(secrets map[string]string) Authenticator { - return &secretAuthenticator{ - secrets: secrets, - } -} - -// Authenticate the request according the secret -func (s *secretAuthenticator) Authenticate(req *http.Request) (bool, error) { - if len(s.secrets) == 0 { - return true, nil - } - reqSecret := secret.FromRequest(req) - - for _, v := range s.secrets { - if reqSecret == v { - return true, nil - } - } - - return false, nil -} diff --git a/src/adminserver/auth/auth_test.go b/src/adminserver/auth/auth_test.go deleted file mode 100644 index bbbc8cf3d..000000000 --- a/src/adminserver/auth/auth_test.go +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package auth - -import ( - "net/http" - "testing" - - commonsecret "github.com/goharbor/harbor/src/common/secret" - "github.com/stretchr/testify/assert" -) - -func TestAuthenticate(t *testing.T) { - secret := "correct" - req1, err := http.NewRequest("", "", nil) - if err != nil { - t.Fatalf("failed to create request: %v", err) - } - - req2, err := http.NewRequest("", "", nil) - if err != nil { - t.Fatalf("failed to create request: %v", err) - } - _ = commonsecret.AddToRequest(req2, secret) - cases := []struct { - secrets map[string]string - req *http.Request - result bool - }{ - {nil, req1, true}, - {map[string]string{"secret1": "incorrect"}, req2, false}, - {map[string]string{"secret1": "incorrect", "secret2": secret}, req2, true}, - } - - for _, c := range cases { - authenticator := NewSecretAuthenticator(c.secrets) - authenticated, err := authenticator.Authenticate(c.req) - assert.Nil(t, err, "unexpected error") - assert.Equal(t, c.result, authenticated, "unexpected result") - } -} diff --git a/src/adminserver/client/client.go b/src/adminserver/client/client.go deleted file mode 100644 index 0f486e693..000000000 --- a/src/adminserver/client/client.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package client - -import ( - "strings" - - "github.com/goharbor/harbor/src/common/http" - "github.com/goharbor/harbor/src/common/http/modifier/auth" - "github.com/goharbor/harbor/src/common/utils" - "github.com/goharbor/harbor/src/core/systeminfo/imagestorage" -) - -// Client defines methods that an Adminserver client should implement -type Client interface { - // Ping tests the connection with server - Ping() error - // GetCfgs returns system configurations - GetCfgs() (map[string]interface{}, error) - // UpdateCfgs updates system configurations - UpdateCfgs(map[string]interface{}) error - // ResetCfgs resets system configuratoins form environment variables - ResetCfgs() error - // Capacity returns the capacity of image storage - Capacity() (*imagestorage.Capacity, error) -} - -// NewClient return an instance of Adminserver client -func NewClient(baseURL string, cfg *Config) Client { - baseURL = strings.TrimRight(baseURL, "/") - if !strings.Contains(baseURL, "://") { - baseURL = "http://" + baseURL - } - client := &client{ - baseURL: baseURL, - } - if cfg != nil { - authorizer := auth.NewSecretAuthorizer(cfg.Secret) - client.client = http.NewClient(nil, authorizer) - } - return client -} - -type client struct { - baseURL string - client *http.Client -} - -// Config contains configurations needed for client -type Config struct { - Secret string -} - -func (c *client) Ping() error { - addr := strings.Split(c.baseURL, "://")[1] - if !strings.Contains(addr, ":") { - addr = addr + ":80" - } - - return utils.TestTCPConn(addr, 60, 2) -} - -// GetCfgs ... -func (c *client) GetCfgs() (map[string]interface{}, error) { - url := c.baseURL + "/api/configs" - cfgs := map[string]interface{}{} - if err := c.client.Get(url, &cfgs); err != nil { - return nil, err - } - return cfgs, nil -} - -// UpdateCfgs ... -func (c *client) UpdateCfgs(cfgs map[string]interface{}) error { - url := c.baseURL + "/api/configurations" - return c.client.Put(url, cfgs) -} - -// ResetCfgs ... -func (c *client) ResetCfgs() error { - url := c.baseURL + "/api/configurations/reset" - return c.client.Post(url) -} - -// Capacity ... -func (c *client) Capacity() (*imagestorage.Capacity, error) { - url := c.baseURL + "/api/systeminfo/capacity" - capacity := &imagestorage.Capacity{} - if err := c.client.Get(url, capacity); err != nil { - return nil, err - } - return capacity, nil -} diff --git a/src/adminserver/client/client_test.go b/src/adminserver/client/client_test.go deleted file mode 100644 index c11aaf312..000000000 --- a/src/adminserver/client/client_test.go +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package client - -import ( - "fmt" - "os" - "testing" - - "github.com/goharbor/harbor/src/common" - "github.com/goharbor/harbor/src/common/utils/test" - "github.com/stretchr/testify/assert" -) - -var c Client - -func TestMain(m *testing.M) { - - server, err := test.NewAdminserver(nil) - if err != nil { - fmt.Printf("failed to create adminserver: %v", err) - os.Exit(1) - } - - c = NewClient(server.URL, &Config{}) - - os.Exit(m.Run()) -} - -func TestPing(t *testing.T) { - err := c.Ping() - assert.Nil(t, err, "unexpected error") -} - -func TestGetCfgs(t *testing.T) { - cfgs, err := c.GetCfgs() - if !assert.Nil(t, err, "unexpected error") { - return - } - - assert.Equal(t, common.DBAuth, cfgs[common.AUTHMode], "unexpected configuration") -} - -func TestUpdateCfgs(t *testing.T) { - cfgs := map[string]interface{}{ - common.AUTHMode: common.LDAPAuth, - } - err := c.UpdateCfgs(cfgs) - if !assert.Nil(t, err, "unexpected error") { - return - } -} - -func TestResetCfgs(t *testing.T) { - err := c.ResetCfgs() - if !assert.Nil(t, err, "unexpected error") { - return - } -} diff --git a/src/adminserver/handlers/handler.go b/src/adminserver/handlers/handler.go deleted file mode 100644 index 55bf6157a..000000000 --- a/src/adminserver/handlers/handler.go +++ /dev/null @@ -1,88 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package handlers - -import ( - "net/http" - "os" - - "github.com/goharbor/harbor/src/adminserver/auth" - "github.com/goharbor/harbor/src/common/utils/log" - gorilla_handlers "github.com/gorilla/handlers" -) - -// NewHandler returns a gorilla router which is wrapped by authenticate handler -// and logging handler -func NewHandler() http.Handler { - h := newRouter() - secrets := map[string]string{ - "uiSecret": os.Getenv("CORE_SECRET"), - "jobserviceSecret": os.Getenv("JOBSERVICE_SECRET"), - } - insecureAPIs := map[string]bool{ - "/api/ping": true, - } - h = newAuthHandler(auth.NewSecretAuthenticator(secrets), h, insecureAPIs) - h = gorilla_handlers.LoggingHandler(os.Stdout, h) - return h -} - -type authHandler struct { - authenticator auth.Authenticator - handler http.Handler - insecureAPIs map[string]bool -} - -func newAuthHandler(authenticator auth.Authenticator, handler http.Handler, insecureAPIs map[string]bool) http.Handler { - return &authHandler{ - authenticator: authenticator, - handler: handler, - insecureAPIs: insecureAPIs, - } -} - -func (a *authHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - if a.authenticator == nil { - if a.handler != nil { - a.handler.ServeHTTP(w, r) - } - return - } - - if a.insecureAPIs != nil && a.insecureAPIs[r.URL.Path] { - if a.handler != nil { - a.handler.ServeHTTP(w, r) - } - return - } - valid, err := a.authenticator.Authenticate(r) - if err != nil { - log.Errorf("failed to authenticate request: %v", err) - http.Error(w, http.StatusText(http.StatusInternalServerError), - http.StatusInternalServerError) - return - } - - if !valid { - http.Error(w, http.StatusText(http.StatusUnauthorized), - http.StatusUnauthorized) - return - } - - if a.handler != nil { - a.handler.ServeHTTP(w, r) - } - return -} diff --git a/src/adminserver/handlers/handlers_test.go b/src/adminserver/handlers/handlers_test.go deleted file mode 100644 index 97bfa9edc..000000000 --- a/src/adminserver/handlers/handlers_test.go +++ /dev/null @@ -1,84 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package handlers - -import ( - "errors" - "net/http" - "net/http/httptest" - "testing" - - "github.com/goharbor/harbor/src/adminserver/auth" - "github.com/stretchr/testify/assert" -) - -type fakeAuthenticator struct { - authenticated bool - err error -} - -func (f *fakeAuthenticator) Authenticate(req *http.Request) (bool, error) { - return f.authenticated, f.err -} - -type fakeHandler struct { - responseCode int -} - -func (f *fakeHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(f.responseCode) -} - -func TestNewAuthHandler(t *testing.T) { - cases := []struct { - authenticator auth.Authenticator - handler http.Handler - insecureAPIs map[string]bool - responseCode int - requestURL string - }{ - - {nil, nil, nil, http.StatusOK, "http://localhost/good"}, - {&fakeAuthenticator{ - authenticated: false, - err: nil, - }, nil, nil, http.StatusUnauthorized, "http://localhost/hello"}, - {&fakeAuthenticator{ - authenticated: false, - err: errors.New("error"), - }, nil, nil, http.StatusInternalServerError, "http://localhost/hello"}, - {&fakeAuthenticator{ - authenticated: true, - err: nil, - }, &fakeHandler{http.StatusNotFound}, nil, http.StatusNotFound, "http://localhost/notexsit"}, - {&fakeAuthenticator{ - authenticated: false, - err: nil, - }, &fakeHandler{http.StatusOK}, map[string]bool{"/api/ping": true}, http.StatusOK, "http://localhost/api/ping"}, - } - - for _, c := range cases { - handler := newAuthHandler(c.authenticator, c.handler, c.insecureAPIs) - w := httptest.NewRecorder() - r := httptest.NewRequest("GET", c.requestURL, nil) - handler.ServeHTTP(w, r) - assert.Equal(t, c.responseCode, w.Code, "unexpected response code") - } - handler := NewHandler() - w := httptest.NewRecorder() - r := httptest.NewRequest("GET", "http://localhost/api/ping", nil) - handler.ServeHTTP(w, r) - -} diff --git a/src/adminserver/handlers/router.go b/src/adminserver/handlers/router.go deleted file mode 100644 index 24ad5dd93..000000000 --- a/src/adminserver/handlers/router.go +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package handlers - -import ( - "net/http" - - "github.com/goharbor/harbor/src/adminserver/api" - "github.com/gorilla/mux" -) - -func newRouter() http.Handler { - r := mux.NewRouter() - r.HandleFunc("/api/configurations", api.UpdateCfgs).Methods("PUT") - r.HandleFunc("/api/configs", api.ListCfgs).Methods("GET") - r.HandleFunc("/api/configurations/reset", api.ResetCfgs).Methods("POST") - r.HandleFunc("/api/ping", api.Ping).Methods("GET") - return r -} diff --git a/src/adminserver/main.go b/src/adminserver/main.go deleted file mode 100644 index 93b47b5b5..000000000 --- a/src/adminserver/main.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "net/http" - "os" - - "github.com/goharbor/harbor/src/adminserver/handlers" - syscfg "github.com/goharbor/harbor/src/adminserver/systemcfg" - "github.com/goharbor/harbor/src/common/utils/log" -) - -// Server for admin component -type Server struct { - Port string - Handler http.Handler -} - -// Serve the API -func (s *Server) Serve() error { - server := &http.Server{ - Addr: ":" + s.Port, - Handler: s.Handler, - } - - return server.ListenAndServe() -} - -func main() { - log.Info("initializing system configurations...") - if err := syscfg.Init(); err != nil { - log.Fatalf("failed to initialize the system: %v", err) - } - log.Info("system initialization completed") - - port := os.Getenv("PORT") - if len(port) == 0 { - port = "80" - } - server := &Server{ - Port: port, - Handler: handlers.NewHandler(), - } - if err := server.Serve(); err != nil { - log.Fatal(err) - } -} diff --git a/src/adminserver/systemcfg/encrypt/encrypt.go b/src/adminserver/systemcfg/encrypt/encrypt.go deleted file mode 100644 index 8861e7862..000000000 --- a/src/adminserver/systemcfg/encrypt/encrypt.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package encrypt - -import ( - comcfg "github.com/goharbor/harbor/src/common/config" - "github.com/goharbor/harbor/src/common/utils" -) - -// Encryptor encrypts or decrypts a strings -type Encryptor interface { - // Encrypt encrypts plaintext - Encrypt(string) (string, error) - // Decrypt decrypts ciphertext - Decrypt(string) (string, error) -} - -// AESEncryptor uses AES to encrypt or decrypt string -type AESEncryptor struct { - keyProvider comcfg.KeyProvider - keyParams map[string]interface{} -} - -// NewAESEncryptor returns an instance of an AESEncryptor -func NewAESEncryptor(keyProvider comcfg.KeyProvider, - keyParams map[string]interface{}) Encryptor { - return &AESEncryptor{ - keyProvider: keyProvider, - } -} - -// Encrypt ... -func (a *AESEncryptor) Encrypt(plaintext string) (string, error) { - key, err := a.keyProvider.Get(a.keyParams) - if err != nil { - return "", err - } - return utils.ReversibleEncrypt(plaintext, key) -} - -// Decrypt ... -func (a *AESEncryptor) Decrypt(ciphertext string) (string, error) { - key, err := a.keyProvider.Get(a.keyParams) - if err != nil { - return "", err - } - return utils.ReversibleDecrypt(ciphertext, key) -} diff --git a/src/adminserver/systemcfg/encrypt/encrypt_test.go b/src/adminserver/systemcfg/encrypt/encrypt_test.go deleted file mode 100644 index 01f67d183..000000000 --- a/src/adminserver/systemcfg/encrypt/encrypt_test.go +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package encrypt - -import ( - "errors" - "testing" - - comcfg "github.com/goharbor/harbor/src/common/config" - "github.com/stretchr/testify/assert" -) - -type fakeKeyProvider struct { - key string - err error -} - -func (f *fakeKeyProvider) Get(params map[string]interface{}) ( - string, error) { - return f.key, f.err -} - -func TestEncrypt(t *testing.T) { - cases := []struct { - plaintext string - keyProvider comcfg.KeyProvider - err bool - }{ - {"", &fakeKeyProvider{"", errors.New("error")}, true}, - {"text", &fakeKeyProvider{"1234567890123456", nil}, false}, - } - - for _, c := range cases { - encrptor := NewAESEncryptor(c.keyProvider, nil) - ciphertext, err := encrptor.Encrypt(c.plaintext) - if c.err { - assert.NotNil(t, err) - } else { - assert.Nil(t, err) - str, err := encrptor.Decrypt(ciphertext) - assert.Nil(t, err) - assert.Equal(t, c.plaintext, str) - } - } -} - -func TestDecrypt(t *testing.T) { - plaintext := "text" - key := "1234567890123456" - - encrptor := NewAESEncryptor(&fakeKeyProvider{ - key: key, - err: nil, - }, nil) - - ciphertext, err := encrptor.Encrypt(plaintext) - if err != nil { - t.Fatalf("failed to encrpt %s: %v", plaintext, err) - } - - cases := []struct { - ciphertext string - keyProvider comcfg.KeyProvider - err bool - }{ - {"", &fakeKeyProvider{"", errors.New("error")}, true}, - {ciphertext, &fakeKeyProvider{key, nil}, false}, - } - - for _, c := range cases { - encrptor := NewAESEncryptor(c.keyProvider, nil) - str, err := encrptor.Decrypt(c.ciphertext) - if c.err { - assert.NotNil(t, err) - } else { - assert.Nil(t, err) - assert.Equal(t, plaintext, str) - } - } -} diff --git a/src/adminserver/systemcfg/store/database/driver_db.go b/src/adminserver/systemcfg/store/database/driver_db.go deleted file mode 100644 index fb3a79ee0..000000000 --- a/src/adminserver/systemcfg/store/database/driver_db.go +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package database - -import ( - "encoding/json" - "fmt" - "strconv" - - "github.com/goharbor/harbor/src/adminserver/systemcfg/store" - "github.com/goharbor/harbor/src/common" - "github.com/goharbor/harbor/src/common/dao" - "github.com/goharbor/harbor/src/common/models" -) - -const ( - name = "database" -) - -var ( - numKeys = map[string]bool{ - common.EmailPort: true, - common.LDAPScope: true, - common.LDAPGroupSearchScope: true, - common.LDAPTimeout: true, - common.TokenExpiration: true, - common.MaxJobWorkers: true, - common.CfgExpiration: true, - common.ClairDBPort: true, - common.PostGreSQLPort: true, - } - boolKeys = map[string]bool{ - common.WithClair: true, - common.WithNotary: true, - common.SelfRegistration: true, - common.EmailSSL: true, - common.EmailInsecure: true, - common.LDAPVerifyCert: true, - common.UAAVerifyCert: true, - common.ReadOnly: true, - common.WithChartMuseum: true, - } - mapKeys = map[string]bool{ - common.ScanAllPolicy: true, - } -) - -type cfgStore struct { - name string -} - -// Name The name of the driver -func (c *cfgStore) Name() string { - return name -} - -// NewCfgStore New a cfg store for database driver -func NewCfgStore() (store.Driver, error) { - return &cfgStore{ - name: name, - }, nil -} - -// Read configuration from database -func (c *cfgStore) Read() (map[string]interface{}, error) { - configEntries, err := dao.GetConfigEntries() - if err != nil { - return nil, err - } - return WrapperConfig(configEntries) -} - -// WrapperConfig Wrapper the configuration -func WrapperConfig(configEntries []*models.ConfigEntry) (map[string]interface{}, error) { - config := make(map[string]interface{}) - for _, entry := range configEntries { - if numKeys[entry.Key] { - strvalue, err := strconv.Atoi(entry.Value) - if err != nil { - return nil, err - } - config[entry.Key] = float64(strvalue) - } else if boolKeys[entry.Key] { - strvalue, err := strconv.ParseBool(entry.Value) - if err != nil { - return nil, err - } - config[entry.Key] = strvalue - } else if mapKeys[entry.Key] { - m := map[string]interface{}{} - if err := json.Unmarshal([]byte(entry.Value), &m); err != nil { - return nil, err - } - config[entry.Key] = m - } else { - config[entry.Key] = entry.Value - } - - } - return config, nil -} - -// Write save configuration to database -func (c *cfgStore) Write(config map[string]interface{}) error { - configEntries, err := TranslateConfig(config) - if err != nil { - return err - } - return dao.SaveConfigEntries(configEntries) -} - -// TranslateConfig Translate configuration from int, bool, float64 to string -func TranslateConfig(config map[string]interface{}) ([]models.ConfigEntry, error) { - var configEntries []models.ConfigEntry - for k, v := range config { - var entry = new(models.ConfigEntry) - entry.Key = k - switch v.(type) { - case string: - entry.Value = v.(string) - case int: - entry.Value = strconv.Itoa(v.(int)) - case bool: - entry.Value = strconv.FormatBool(v.(bool)) - case float64: - entry.Value = strconv.Itoa(int(v.(float64))) - case map[string]interface{}: - data, err := json.Marshal(v) - if err != nil { - return nil, err - } - entry.Value = string(data) - default: - return nil, fmt.Errorf("unknown type %v", v) - } - configEntries = append(configEntries, *entry) - } - return configEntries, nil -} diff --git a/src/adminserver/systemcfg/store/database/driver_db_test.go b/src/adminserver/systemcfg/store/database/driver_db_test.go deleted file mode 100644 index 00970e5ac..000000000 --- a/src/adminserver/systemcfg/store/database/driver_db_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package database - -import ( - "testing" - - "github.com/goharbor/harbor/src/common" - "github.com/goharbor/harbor/src/common/models" - "github.com/stretchr/testify/assert" -) - -func TestCfgStore_Name(t *testing.T) { - driver, err := NewCfgStore() - if err != nil { - t.Fatalf("Failed to create db configuration store %v", err) - } - assert.Equal(t, name, driver.Name()) -} - -func TestWrapperConfig(t *testing.T) { - cfg := []*models.ConfigEntry{ - { - Key: common.CfgExpiration, - Value: "500", - }, - { - Key: common.WithNotary, - Value: "true", - }, - { - Key: common.PostGreSQLHOST, - Value: "192.168.1.210", - }, - } - result, err := WrapperConfig(cfg) - if err != nil { - t.Fatalf("Failed to wrapper config %v", err) - } - withNotary, _ := result[common.WithNotary].(bool) - assert.Equal(t, true, withNotary) - - postgresqlhost, ok := result[common.PostGreSQLHOST].(string) - assert.True(t, ok) - assert.Equal(t, "192.168.1.210", postgresqlhost) - - expiration, ok := result[common.CfgExpiration].(float64) - - assert.True(t, ok) - assert.Equal(t, float64(500), expiration) -} - -func TestTranslateConfig(t *testing.T) { - config := map[string]interface{}{} - config[common.PostGreSQLHOST] = "192.168.1.210" - - entries, err := TranslateConfig(config) - if err != nil { - t.Fatalf("Failed to translate configuration %v", err) - } - assert.Equal(t, "192.168.1.210", entries[0].Value) - config = make(map[string]interface{}) - config[common.WithNotary] = true - entries, err = TranslateConfig(config) - if err != nil { - t.Fatalf("Failed to translate configuration %v", err) - } - assert.Equal(t, "true", entries[0].Value) - - config = make(map[string]interface{}) - config[common.CfgExpiration] = float64(500) - entries, err = TranslateConfig(config) - if err != nil { - t.Fatalf("Failed to translate configuration %v", err) - } - assert.Equal(t, "500", entries[0].Value) -} diff --git a/src/adminserver/systemcfg/store/driver.go b/src/adminserver/systemcfg/store/driver.go deleted file mode 100644 index 6241effd7..000000000 --- a/src/adminserver/systemcfg/store/driver.go +++ /dev/null @@ -1,26 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package store - -// Driver defines methods that a configuration store driver must implement -type Driver interface { - // Name returns a human-readable name of the driver - Name() string - // Read reads all the configurations from store - Read() (map[string]interface{}, error) - // Write writes the configurations to store, the configurations can be - // part of all - Write(map[string]interface{}) error -} diff --git a/src/adminserver/systemcfg/store/encrypt/driver.go b/src/adminserver/systemcfg/store/encrypt/driver.go deleted file mode 100644 index 67262a383..000000000 --- a/src/adminserver/systemcfg/store/encrypt/driver.go +++ /dev/null @@ -1,97 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package encrypt - -import ( - "github.com/goharbor/harbor/src/adminserver/systemcfg/encrypt" - "github.com/goharbor/harbor/src/adminserver/systemcfg/store" - "github.com/goharbor/harbor/src/common/utils/log" -) - -const ( - name = "encrypt" -) - -// cfgStore wraps a store.Driver with an encryptor -type cfgStore struct { - // attrs need to be encrypted and decrypted - keys []string - encryptor encrypt.Encryptor - store store.Driver -} - -// NewCfgStore returns an instance of cfgStore -// keys are the attrs need to be encrypted or decrypted -func NewCfgStore(encryptor encrypt.Encryptor, - keys []string, store store.Driver) store.Driver { - return &cfgStore{ - keys: keys, - encryptor: encryptor, - store: store, - } -} - -func (c *cfgStore) Name() string { - return name -} - -func (c *cfgStore) Read() (map[string]interface{}, error) { - m, err := c.store.Read() - if err != nil { - return nil, err - } - - for _, key := range c.keys { - v, ok := m[key] - if !ok { - continue - } - - str, ok := v.(string) - if !ok { - log.Warningf("the value of %s is not string, skip decrypt", key) - continue - } - - text, err := c.encryptor.Decrypt(str) - if err != nil { - return nil, err - } - m[key] = text - } - return m, nil -} - -func (c *cfgStore) Write(m map[string]interface{}) error { - for _, key := range c.keys { - v, ok := m[key] - if !ok { - continue - } - - str, ok := v.(string) - if !ok { - log.Warningf("%v is not string, skip encrypt", v) - continue - } - - ciphertext, err := c.encryptor.Encrypt(str) - if err != nil { - return err - } - m[key] = ciphertext - } - return c.store.Write(m) -} diff --git a/src/adminserver/systemcfg/store/encrypt/driver_test.go b/src/adminserver/systemcfg/store/encrypt/driver_test.go deleted file mode 100644 index e06749332..000000000 --- a/src/adminserver/systemcfg/store/encrypt/driver_test.go +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package encrypt - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -type fakeCfgStore struct { - cfgs map[string]interface{} -} - -func (f *fakeCfgStore) Name() string { - return "fake" -} - -func (f *fakeCfgStore) Read() (map[string]interface{}, error) { - return f.cfgs, nil -} - -func (f *fakeCfgStore) Write(cfgs map[string]interface{}) error { - f.cfgs = cfgs - return nil -} - -type fakeEncryptor struct { -} - -func (f *fakeEncryptor) Encrypt(plaintext string) (string, error) { - return "encrypted" + plaintext, nil -} - -func (f *fakeEncryptor) Decrypt(ciphertext string) (string, error) { - return "decrypted" + ciphertext, nil -} - -func TestName(t *testing.T) { - driver := NewCfgStore(nil, nil, nil) - assert.Equal(t, name, driver.Name()) -} - -func TestRead(t *testing.T) { - keys := []string{"key"} - driver := NewCfgStore(&fakeEncryptor{}, keys, &fakeCfgStore{ - cfgs: map[string]interface{}{"key": "value"}, - }) - - cfgs, err := driver.Read() - assert.Nil(t, err) - assert.Equal(t, "decryptedvalue", cfgs["key"]) -} - -func TestWrite(t *testing.T) { - keys := []string{"key"} - store := &fakeCfgStore{ - cfgs: map[string]interface{}{}, - } - driver := NewCfgStore(&fakeEncryptor{}, keys, store) - - cfgs := map[string]interface{}{ - "key": "value", - } - - err := driver.Write(cfgs) - assert.Nil(t, err) - assert.Equal(t, "encryptedvalue", store.cfgs["key"]) -} diff --git a/src/adminserver/systemcfg/store/json/driver_json.go b/src/adminserver/systemcfg/store/json/driver_json.go deleted file mode 100644 index 36689d184..000000000 --- a/src/adminserver/systemcfg/store/json/driver_json.go +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package json - -import ( - "encoding/json" - "io/ioutil" - "os" - "path/filepath" - "sync" - - "github.com/goharbor/harbor/src/adminserver/systemcfg/store" - "github.com/goharbor/harbor/src/common/utils/log" -) - -const ( - // the default path of configuration file - defaultPath = "/etc/harbor/config.json" -) - -type cfgStore struct { - path string // the path of cfg file - sync.RWMutex -} - -// NewCfgStore returns an instance of cfgStore that stores the configurations -// in a json file. The file will be created if it does not exist. -func NewCfgStore(path ...string) (store.Driver, error) { - p := defaultPath - if len(path) > 0 && len(path[0]) > 0 { - p = path[0] - } - - log.Debugf("path of configuration file: %s", p) - - if _, err := os.Stat(p); os.IsNotExist(err) { - log.Infof("the configuration file %s does not exist, creating it...", p) - if err = os.MkdirAll(filepath.Dir(p), 0600); err != nil { - return nil, err - } - if err = ioutil.WriteFile(p, []byte{}, 0600); err != nil { - return nil, err - } - } - - return &cfgStore{ - path: p, - }, nil -} - -// Name ... -func (c *cfgStore) Name() string { - return "JSON" -} - -// Read ... -func (c *cfgStore) Read() (map[string]interface{}, error) { - c.RLock() - defer c.RUnlock() - - return read(c.path) -} - -func read(path string) (map[string]interface{}, error) { - b, err := ioutil.ReadFile(path) - if err != nil { - return nil, err - } - - // empty file - if len(b) == 0 { - return nil, nil - } - - config := map[string]interface{}{} - if err = json.Unmarshal(b, &config); err != nil { - return nil, err - } - - return config, nil -} - -// Write ... -func (c *cfgStore) Write(config map[string]interface{}) error { - c.Lock() - defer c.Unlock() - - cfg, err := read(c.path) - if err != nil { - return err - } - - if cfg == nil { - cfg = config - } else { - for k, v := range config { - cfg[k] = v - } - } - - b, err := json.MarshalIndent(cfg, "", " ") - if err != nil { - return err - } - - return ioutil.WriteFile(c.path, b, 0600) -} diff --git a/src/adminserver/systemcfg/store/json/driver_json_test.go b/src/adminserver/systemcfg/store/json/driver_json_test.go deleted file mode 100644 index cedd188a3..000000000 --- a/src/adminserver/systemcfg/store/json/driver_json_test.go +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package json - -import ( - "os" - "testing" -) - -func TestReadWrite(t *testing.T) { - path := "/tmp/config.json" - store, err := NewCfgStore(path) - if err != nil { - t.Fatalf("failed to create json cfg store: %v", err) - } - defer func() { - if err := os.Remove(path); err != nil { - t.Fatalf("failed to remove the json file %s: %v", path, err) - } - }() - - if store.Name() != "JSON" { - t.Errorf("unexpected name: %s != %s", store.Name(), "JSON") - return - } - - config := map[string]interface{}{ - "key": "value", - } - if err := store.Write(config); err != nil { - t.Errorf("failed to write configurations to json file: %v", err) - return - } - - if _, err = store.Read(); err != nil { - t.Errorf("failed to read configurations from json file: %v", err) - return - } -} diff --git a/src/adminserver/systemcfg/systemcfg.go b/src/adminserver/systemcfg/systemcfg.go deleted file mode 100644 index 88be64f71..000000000 --- a/src/adminserver/systemcfg/systemcfg.go +++ /dev/null @@ -1,483 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package systemcfg - -import ( - "fmt" - "os" - "regexp" - "strconv" - "strings" - - enpt "github.com/goharbor/harbor/src/adminserver/systemcfg/encrypt" - "github.com/goharbor/harbor/src/adminserver/systemcfg/store" - "github.com/goharbor/harbor/src/adminserver/systemcfg/store/database" - "github.com/goharbor/harbor/src/adminserver/systemcfg/store/encrypt" - "github.com/goharbor/harbor/src/adminserver/systemcfg/store/json" - "github.com/goharbor/harbor/src/common" - comcfg "github.com/goharbor/harbor/src/common/config" - "github.com/goharbor/harbor/src/common/dao" - "github.com/goharbor/harbor/src/common/models" - "github.com/goharbor/harbor/src/common/utils" - "github.com/goharbor/harbor/src/common/utils/log" -) - -const ( - defaultJSONCfgStorePath string = "/etc/adminserver/config/config.json" - defaultKeyPath string = "/etc/adminserver/key" - ldapScopeKey string = "ldap_scope" -) - -var ( - // CfgStore is a storage driver that configurations - // can be read from and wrote to - CfgStore store.Driver - - // attrs need to be encrypted or decrypted - attrs = []string{ - common.EmailPassword, - common.LDAPSearchPwd, - common.PostGreSQLPassword, - common.AdminInitialPassword, - common.ClairDBPassword, - common.UAAClientSecret, - } - - // all configurations need read from environment variables - allEnvs = map[string]interface{}{ - common.ExtEndpoint: "EXT_ENDPOINT", - common.AUTHMode: "AUTH_MODE", - common.SelfRegistration: &parser{ - env: "SELF_REGISTRATION", - parse: parseStringToBool, - }, - common.DatabaseType: "DATABASE_TYPE", - common.PostGreSQLHOST: "POSTGRESQL_HOST", - common.PostGreSQLPort: &parser{ - env: "POSTGRESQL_PORT", - parse: parseStringToInt, - }, - common.PostGreSQLUsername: "POSTGRESQL_USERNAME", - common.PostGreSQLPassword: "POSTGRESQL_PASSWORD", - common.PostGreSQLDatabase: "POSTGRESQL_DATABASE", - common.PostGreSQLSSLMode: "POSTGRESQL_SSLMODE", - common.LDAPURL: "LDAP_URL", - common.LDAPSearchDN: "LDAP_SEARCH_DN", - common.LDAPSearchPwd: "LDAP_SEARCH_PWD", - common.LDAPBaseDN: "LDAP_BASE_DN", - common.LDAPFilter: "LDAP_FILTER", - common.LDAPUID: "LDAP_UID", - common.LDAPScope: &parser{ - env: "LDAP_SCOPE", - parse: parseStringToInt, - }, - common.LDAPTimeout: &parser{ - env: "LDAP_TIMEOUT", - parse: parseStringToInt, - }, - common.LDAPVerifyCert: &parser{ - env: "LDAP_VERIFY_CERT", - parse: parseStringToBool, - }, - common.LDAPGroupBaseDN: "LDAP_GROUP_BASEDN", - common.LDAPGroupSearchFilter: "LDAP_GROUP_FILTER", - common.LDAPGroupAttributeName: "LDAP_GROUP_GID", - common.LDAPGroupSearchScope: &parser{ - env: "LDAP_GROUP_SCOPE", - parse: parseStringToInt, - }, - common.EmailHost: "EMAIL_HOST", - common.EmailPort: &parser{ - env: "EMAIL_PORT", - parse: parseStringToInt, - }, - common.EmailUsername: "EMAIL_USR", - common.EmailPassword: "EMAIL_PWD", - common.EmailSSL: &parser{ - env: "EMAIL_SSL", - parse: parseStringToBool, - }, - common.EmailInsecure: &parser{ - env: "EMAIL_INSECURE", - parse: parseStringToBool, - }, - common.EmailFrom: "EMAIL_FROM", - common.EmailIdentity: "EMAIL_IDENTITY", - common.RegistryURL: "REGISTRY_URL", - common.TokenExpiration: &parser{ - env: "TOKEN_EXPIRATION", - parse: parseStringToInt, - }, - common.CfgExpiration: &parser{ - env: "CFG_EXPIRATION", - parse: parseStringToInt, - }, - common.MaxJobWorkers: &parser{ - env: "MAX_JOB_WORKERS", - parse: parseStringToInt, - }, - common.ProjectCreationRestriction: "PROJECT_CREATION_RESTRICTION", - common.AdminInitialPassword: "HARBOR_ADMIN_PASSWORD", - common.AdmiralEndpoint: "ADMIRAL_URL", - common.WithNotary: &parser{ - env: "WITH_NOTARY", - parse: parseStringToBool, - }, - common.WithClair: &parser{ - env: "WITH_CLAIR", - parse: parseStringToBool, - }, - common.ClairDBPassword: "CLAIR_DB_PASSWORD", - common.ClairDB: "CLAIR_DB", - common.ClairDBUsername: "CLAIR_DB_USERNAME", - common.ClairDBHost: "CLAIR_DB_HOST", - common.ClairDBPort: &parser{ - env: "CLAIR_DB_PORT", - parse: parseStringToInt, - }, - common.ClairDBSSLMode: "CLAIR_DB_SSLMODE", - common.UAAEndpoint: "UAA_ENDPOINT", - common.UAAClientID: "UAA_CLIENTID", - common.UAAClientSecret: "UAA_CLIENTSECRET", - common.UAAVerifyCert: &parser{ - env: "UAA_VERIFY_CERT", - parse: parseStringToBool, - }, - common.CoreURL: "CORE_URL", - common.JobServiceURL: "JOBSERVICE_URL", - common.TokenServiceURL: "TOKEN_SERVICE_URL", - common.ClairURL: "CLAIR_URL", - common.NotaryURL: "NOTARY_URL", - common.RegistryStorageProviderName: "REGISTRY_STORAGE_PROVIDER_NAME", - common.ReadOnly: &parser{ - env: "READ_ONLY", - parse: parseStringToBool, - }, - common.ReloadKey: "RELOAD_KEY", - common.LdapGroupAdminDn: "LDAP_GROUP_ADMIN_DN", - common.ChartRepoURL: "CHART_REPOSITORY_URL", - common.WithChartMuseum: &parser{ - env: "WITH_CHARTMUSEUM", - parse: parseStringToBool, - }, - } - - // configurations need read from environment variables - // every time the system startup - repeatLoadEnvs = map[string]interface{}{ - common.ExtEndpoint: "EXT_ENDPOINT", - common.PostGreSQLHOST: "POSTGRESQL_HOST", - common.PostGreSQLPort: &parser{ - env: "POSTGRESQL_PORT", - parse: parseStringToInt, - }, - common.PostGreSQLUsername: "POSTGRESQL_USERNAME", - common.PostGreSQLPassword: "POSTGRESQL_PASSWORD", - common.PostGreSQLDatabase: "POSTGRESQL_DATABASE", - common.PostGreSQLSSLMode: "POSTGRESQL_SSLMODE", - common.MaxJobWorkers: &parser{ - env: "MAX_JOB_WORKERS", - parse: parseStringToInt, - }, - common.CfgExpiration: &parser{ - env: "CFG_EXPIRATION", - parse: parseStringToInt, - }, - common.AdmiralEndpoint: "ADMIRAL_URL", - common.WithNotary: &parser{ - env: "WITH_NOTARY", - parse: parseStringToBool, - }, - common.WithClair: &parser{ - env: "WITH_CLAIR", - parse: parseStringToBool, - }, - common.ClairDBPassword: "CLAIR_DB_PASSWORD", - common.ClairDBHost: "CLAIR_DB_HOST", - common.ClairDBUsername: "CLAIR_DB_USERNAME", - common.ClairDBPort: &parser{ - env: "CLAIR_DB_PORT", - parse: parseStringToInt, - }, - common.ClairDBSSLMode: "CLAIR_DB_SSLMODE", - common.UAAEndpoint: "UAA_ENDPOINT", - common.UAAClientID: "UAA_CLIENTID", - common.UAAClientSecret: "UAA_CLIENTSECRET", - common.UAAVerifyCert: &parser{ - env: "UAA_VERIFY_CERT", - parse: parseStringToBool, - }, - common.RegistryStorageProviderName: "REGISTRY_STORAGE_PROVIDER_NAME", - common.CoreURL: "CORE_URL", - common.JobServiceURL: "JOBSERVICE_URL", - common.RegistryURL: "REGISTRY_URL", - common.TokenServiceURL: "TOKEN_SERVICE_URL", - common.ClairURL: "CLAIR_URL", - common.NotaryURL: "NOTARY_URL", - common.DatabaseType: "DATABASE_TYPE", - common.ChartRepoURL: "CHART_REPOSITORY_URL", - common.WithChartMuseum: &parser{ - env: "WITH_CHARTMUSEUM", - parse: parseStringToBool, - }, - } -) - -type parser struct { - // the name of env - env string - // parse the value of env, e.g. parse string to int or - // parse string to bool - parse func(string) (interface{}, error) -} - -func parseStringToInt(str string) (interface{}, error) { - if len(str) == 0 { - return 0, nil - } - return strconv.Atoi(str) -} - -func parseStringToBool(str string) (interface{}, error) { - return strings.ToLower(str) == "true" || - strings.ToLower(str) == "on", nil -} - -// Init system configurations. If env RESET is set or configurations -// read from storage driver is null, load all configurations from env -func Init() (err error) { - // init database - envCfgs := map[string]interface{}{} - if err := LoadFromEnv(envCfgs, true); err != nil { - return err - } - db := GetDatabaseFromCfg(envCfgs) - if err := dao.InitDatabase(db); err != nil { - return err - } - if err := dao.UpgradeSchema(db); err != nil { - return err - } - if err := dao.CheckSchemaVersion(); err != nil { - return err - } - - if err := initCfgStore(); err != nil { - return err - } - - // Use reload key to avoid reset customed setting after restart - curCfgs, err := CfgStore.Read() - if err != nil { - return err - } - loadAll := isLoadAll(curCfgs) - if curCfgs == nil { - curCfgs = map[string]interface{}{} - } - // restart: only repeatload envs will be load - // reload_config: all envs will be reload except the skiped envs - if err = LoadFromEnv(curCfgs, loadAll); err != nil { - return err - } - AddMissedKey(curCfgs) - return CfgStore.Write(curCfgs) -} - -func isLoadAll(cfg map[string]interface{}) bool { - return cfg == nil || strings.EqualFold(os.Getenv("RESET"), "true") && os.Getenv("RELOAD_KEY") != cfg[common.ReloadKey] -} - -func initCfgStore() (err error) { - - drivertype := os.Getenv("CFG_DRIVER") - if len(drivertype) == 0 { - drivertype = common.CfgDriverDB - } - path := os.Getenv("JSON_CFG_STORE_PATH") - if len(path) == 0 { - path = defaultJSONCfgStorePath - } - log.Infof("the path of json configuration storage: %s", path) - - if drivertype == common.CfgDriverDB { - CfgStore, err = database.NewCfgStore() - if err != nil { - return err - } - // migration check: if no data in the db , then will try to load from path - m, err := CfgStore.Read() - if err != nil { - return err - } - if m == nil || len(m) == 0 { - if _, err := os.Stat(path); err == nil { - jsondriver, err := json.NewCfgStore(path) - if err != nil { - log.Errorf("Failed to migrate configuration from %s", path) - return err - } - jsonconfig, err := jsondriver.Read() - if err != nil { - log.Errorf("Failed to read old configuration from %s", path) - return err - } - // Update LDAP Scope for migration - // only used when migrating harbor release before v1.3 - // after v1.3 there is always a db configuration before migrate. - validLdapScope(jsonconfig, true) - err = CfgStore.Write(jsonconfig) - if err != nil { - log.Error("Failed to update old configuration to database") - return err - } - } - } - } else { - CfgStore, err = json.NewCfgStore(path) - if err != nil { - return err - } - } - kp := os.Getenv("KEY_PATH") - if len(kp) == 0 { - kp = defaultKeyPath - } - log.Infof("the path of key used by key provider: %s", kp) - - encryptor := enpt.NewAESEncryptor( - comcfg.NewFileKeyProvider(kp), nil) - - CfgStore = encrypt.NewCfgStore(encryptor, attrs, CfgStore) - return nil -} - -// LoadFromEnv loads the configurations from allEnvs, if all is false, it just loads -// the repeatLoadEnvs and the env which is absent in cfgs -func LoadFromEnv(cfgs map[string]interface{}, all bool) error { - var envs map[string]interface{} - - if all { - envs = allEnvs - } else { - envs = make(map[string]interface{}) - for k, v := range repeatLoadEnvs { - envs[k] = v - } - for k, v := range allEnvs { - if _, exist := cfgs[k]; !exist { - envs[k] = v - } - } - } - - reloadCfg := os.Getenv("RESET") - skipPattern := os.Getenv("SKIP_RELOAD_ENV_PATTERN") - skipPattern = strings.TrimSpace(skipPattern) - if len(skipPattern) == 0 { - skipPattern = "$^" // doesn't match any string by default - } - skipMatcher, err := regexp.Compile(skipPattern) - if err != nil { - log.Errorf("Regular express parse error, skipPattern:%v", skipPattern) - skipMatcher = regexp.MustCompile("$^") - } - - for k, v := range envs { - if str, ok := v.(string); ok { - if skipMatcher.MatchString(str) && strings.EqualFold(reloadCfg, "true") { - continue - } - cfgs[k] = os.Getenv(str) - continue - } - - if parser, ok := v.(*parser); ok { - if skipMatcher.MatchString(parser.env) && strings.EqualFold(reloadCfg, "true") { - continue - } - i, err := parser.parse(os.Getenv(parser.env)) - if err != nil { - return err - } - cfgs[k] = i - continue - } - - return fmt.Errorf("%v is not string or parse type", v) - } - validLdapScope(cfgs, false) - return nil -} - -// GetDatabaseFromCfg Create database object from config -func GetDatabaseFromCfg(cfg map[string]interface{}) *models.Database { - database := &models.Database{} - database.Type = cfg[common.DatabaseType].(string) - postgresql := &models.PostGreSQL{} - postgresql.Host = utils.SafeCastString(cfg[common.PostGreSQLHOST]) - postgresql.Port = int(utils.SafeCastInt(cfg[common.PostGreSQLPort])) - postgresql.Username = utils.SafeCastString(cfg[common.PostGreSQLUsername]) - postgresql.Password = utils.SafeCastString(cfg[common.PostGreSQLPassword]) - postgresql.Database = utils.SafeCastString(cfg[common.PostGreSQLDatabase]) - postgresql.SSLMode = utils.SafeCastString(cfg[common.PostGreSQLSSLMode]) - database.PostGreSQL = postgresql - return database -} - -// Valid LDAP Scope -func validLdapScope(cfg map[string]interface{}, isMigrate bool) { - ldapScope, ok := cfg[ldapScopeKey].(int) - if !ok { - ldapScopeFloat, ok := cfg[ldapScopeKey].(float64) - if ok { - ldapScope = int(ldapScopeFloat) - } - } - if isMigrate && ldapScope > 0 && ldapScope < 3 { - ldapScope = ldapScope - 1 - } - if ldapScope >= 3 { - ldapScope = 2 - } - if ldapScope < 0 { - ldapScope = 0 - } - cfg[ldapScopeKey] = ldapScope - -} - -// AddMissedKey ... If the configure key is missing in the cfg map, add default value to it -func AddMissedKey(cfg map[string]interface{}) { - - for k, v := range common.HarborStringKeysMap { - if _, exist := cfg[k]; !exist { - cfg[k] = v - } - } - - for k, v := range common.HarborNumKeysMap { - if _, exist := cfg[k]; !exist { - cfg[k] = v - } - } - - for k, v := range common.HarborBoolKeysMap { - if _, exist := cfg[k]; !exist { - cfg[k] = v - } - } - -} diff --git a/src/adminserver/systemcfg/systemcfg_test.go b/src/adminserver/systemcfg/systemcfg_test.go deleted file mode 100644 index 60a3333f7..000000000 --- a/src/adminserver/systemcfg/systemcfg_test.go +++ /dev/null @@ -1,290 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package systemcfg - -import ( - "os" - "testing" - - "github.com/goharbor/harbor/src/common" - "github.com/stretchr/testify/assert" -) - -func TestParseStringToInt(t *testing.T) { - cases := []struct { - input string - result int - }{ - {"1", 1}, - {"-1", -1}, - {"0", 0}, - {"", 0}, - } - - for _, c := range cases { - i, err := parseStringToInt(c.input) - assert.Nil(t, err) - assert.Equal(t, c.result, i) - } -} - -func TestParseStringToBool(t *testing.T) { - cases := []struct { - input string - result bool - }{ - {"true", true}, - {"on", true}, - {"TRUE", true}, - {"ON", true}, - {"other", false}, - {"", false}, - } - - for _, c := range cases { - b, _ := parseStringToBool(c.input) - assert.Equal(t, c.result, b) - } -} - -func TestInitCfgStore(t *testing.T) { - os.Clearenv() - path := "/tmp/config.json" - if err := os.Setenv("CFG_DRIVER", "json"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("JSON_CFG_STORE_PATH", path); err != nil { - t.Fatalf("failed to set env: %v", err) - } - defer os.RemoveAll(path) - err := initCfgStore() - assert.Nil(t, err) -} - -func TestLoadFromEnv(t *testing.T) { - os.Clearenv() - ldapURL := "ldap://ldap.com" - extEndpoint := "http://harbor.com" - if err := os.Setenv("LDAP_URL", ldapURL); err != nil { - t.Fatalf("failed to set env: %v", err) - } - cfgs := map[string]interface{}{} - err := LoadFromEnv(cfgs, true) - assert.Nil(t, err) - assert.Equal(t, ldapURL, cfgs[common.LDAPURL]) - - os.Clearenv() - if err := os.Setenv("LDAP_URL", ldapURL); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("EXT_ENDPOINT", extEndpoint); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - if err := os.Setenv("LDAP_VERIFY_CERT", "false"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - cfgs = map[string]interface{}{} - err = LoadFromEnv(cfgs, false) - assert.Nil(t, err) - assert.Equal(t, extEndpoint, cfgs[common.ExtEndpoint]) - assert.Equal(t, ldapURL, cfgs[common.LDAPURL]) - assert.Equal(t, false, cfgs[common.LDAPVerifyCert]) - - os.Clearenv() - if err := os.Setenv("LDAP_URL", ldapURL); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("EXT_ENDPOINT", extEndpoint); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - if err := os.Setenv("LDAP_VERIFY_CERT", "true"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - cfgs = map[string]interface{}{ - common.LDAPURL: "ldap_url", - } - err = LoadFromEnv(cfgs, false) - assert.Nil(t, err) - assert.Equal(t, extEndpoint, cfgs[common.ExtEndpoint]) - assert.Equal(t, "ldap_url", cfgs[common.LDAPURL]) - assert.Equal(t, true, cfgs[common.LDAPVerifyCert]) - -} - -func TestIsLoadAll(t *testing.T) { - os.Clearenv() - if err := os.Setenv("RELOAD_KEY", "123456"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("RESET", "True"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - cfg1 := map[string]interface{}{common.ReloadKey: "123456"} - cfg2 := map[string]interface{}{common.ReloadKey: "654321"} - assert.False(t, isLoadAll(cfg1)) - assert.True(t, isLoadAll(cfg2)) -} - -func TestLoadFromEnvWithReloadConfigInvalidSkipPattern(t *testing.T) { - os.Clearenv() - ldapURL := "ldap://ldap.com" - extEndpoint := "http://harbor.com" - cfgsReload := map[string]interface{}{ - common.LDAPURL: "ldap_url", - } - if err := os.Setenv("LDAP_URL", ldapURL); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("EXT_ENDPOINT", extEndpoint); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - if err := os.Setenv("LDAP_VERIFY_CERT", "false"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - if err := os.Setenv("SKIP_RELOAD_ENV_PATTERN", "a(b"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - err := LoadFromEnv(cfgsReload, true) - if err != nil { - t.Fatalf("failed to load From env: %v", err) - } - assert.Equal(t, ldapURL, cfgsReload[common.LDAPURL]) - - os.Clearenv() - -} - -func TestLoadFromEnvWithReloadConfigSkipPattern(t *testing.T) { - os.Clearenv() - ldapURL := "ldap://ldap.com" - extEndpoint := "http://harbor.com" - cfgsReload := map[string]interface{}{ - common.LDAPURL: "ldap_url", - } - if err := os.Setenv("LDAP_URL", ldapURL); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("EXT_ENDPOINT", extEndpoint); err != nil { - t.Fatalf("failed to set env: %v", err) - } - - if err := os.Setenv("LDAP_VERIFY_CERT", "false"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("SKIP_RELOAD_ENV_PATTERN", "^LDAP.*"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - if err := os.Setenv("RESET", "true"); err != nil { - t.Fatalf("failed to set env: %v", err) - } - err := LoadFromEnv(cfgsReload, false) - if err != nil { - t.Fatalf("failed to load From env: %v", err) - } - assert.Equal(t, "ldap_url", cfgsReload[common.LDAPURL]) // env value ignored - - os.Clearenv() - -} -func TestGetDatabaseFromCfg(t *testing.T) { - cfg := map[string]interface{}{ - common.DatabaseType: "postgresql", - common.PostGreSQLDatabase: "registry", - common.PostGreSQLHOST: "127.0.0.1", - common.PostGreSQLPort: 5432, - common.PostGreSQLPassword: "root123", - common.PostGreSQLUsername: "postgres", - } - - database := GetDatabaseFromCfg(cfg) - - assert.Equal(t, "postgresql", database.Type) -} - -func TestValidLdapScope(t *testing.T) { - var dbValue float64 - dbValue = 2 - ldapScopeKey := "ldap_scope" - testCfgs := []struct { - config map[string]interface{} - migrate bool - ldapScopeResult int - }{ - {map[string]interface{}{ - ldapScopeKey: 1, - }, true, 0}, - {map[string]interface{}{ - ldapScopeKey: 2, - }, true, 1}, - {map[string]interface{}{ - ldapScopeKey: 3, - }, true, 2}, - {map[string]interface{}{ - ldapScopeKey: -1, - }, true, 0}, - {map[string]interface{}{ - ldapScopeKey: 100, - }, false, 2}, - {map[string]interface{}{ - ldapScopeKey: -100, - }, false, 0}, - {map[string]interface{}{ - ldapScopeKey: dbValue, - }, false, 2}, - } - - for i, item := range testCfgs { - validLdapScope(item.config, item.migrate) - if item.config[ldapScopeKey].(int) != item.ldapScopeResult { - t.Fatalf("Failed to update ldapScope expected %v, actual %v at index %v", item.ldapScopeResult, item.config[ldapScopeKey], i) - } - - } - -} -func Test_AddMissingKey(t *testing.T) { - - cfg := map[string]interface{}{ - common.LDAPURL: "sampleurl", - common.EmailPort: 555, - common.LDAPVerifyCert: true, - } - - type args struct { - cfg map[string]interface{} - } - tests := []struct { - name string - args args - }{ - {"Add default value", args{cfg}}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - AddMissedKey(tt.args.cfg) - }) - } - - if _, ok := cfg[common.LDAPBaseDN]; !ok { - t.Errorf("Can not found default value for %v", common.LDAPBaseDN) - } - -} diff --git a/src/common/config/config.go b/src/common/config/config.go deleted file mode 100644 index 90ad2c80f..000000000 --- a/src/common/config/config.go +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package config provide methods to get the configurations reqruied by code in src/common -package config - -import ( - "fmt" - "time" - - "github.com/astaxie/beego/cache" - "github.com/goharbor/harbor/src/adminserver/client" - "github.com/goharbor/harbor/src/common" -) - -// Manager manages configurations -type Manager struct { - client client.Client - Cache bool - cache cache.Cache - key string -} - -// NewManager returns an instance of Manager -func NewManager(client client.Client, enableCache bool) *Manager { - m := &Manager{ - client: client, - } - - if enableCache { - m.Cache = true - m.cache = cache.NewMemoryCache() - m.key = "cfg" - } - - return m -} - -// Load configurations, if cache is enabled, cache the configurations -func (m *Manager) Load() (map[string]interface{}, error) { - c, err := m.client.GetCfgs() - if err != nil { - return nil, err - } - - if m.Cache { - expi, err := getCfgExpiration(c) - if err != nil { - return nil, err - } - - // copy the configuration map so that later modification to the - // map does not effect the cached value - cachedCfgs := map[string]interface{}{} - for k, v := range c { - cachedCfgs[k] = v - } - - if err = m.cache.Put(m.key, cachedCfgs, - time.Duration(expi)*time.Second); err != nil { - return nil, err - } - } - - return c, nil -} - -// Reset configurations -func (m *Manager) Reset() error { - return m.client.ResetCfgs() -} - -func getCfgExpiration(m map[string]interface{}) (int, error) { - if m == nil { - return 0, fmt.Errorf("can not get cfg expiration as configurations are null") - } - - expi, ok := m[common.CfgExpiration] - if !ok { - return 0, fmt.Errorf("cfg expiration is not set") - } - - return int(expi.(float64)), nil -} - -// Get : if cache is enabled, read configurations from cache, -// if cache is null or cache is disabled it loads configurations directly -func (m *Manager) Get() (map[string]interface{}, error) { - if m.Cache { - c := m.cache.Get(m.key) - if c != nil { - return c.(map[string]interface{}), nil - } - } - return m.Load() -} - -// Upload configurations -func (m *Manager) Upload(cfgs map[string]interface{}) error { - return m.client.UpdateCfgs(cfgs) -} diff --git a/src/common/config/config_test.go b/src/common/config/config_test.go deleted file mode 100644 index 4fe7e29ec..000000000 --- a/src/common/config/config_test.go +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright Project Harbor Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -package config - -// the functions in common/config/config.go have been tested -// by cases in UI and Jobservice diff --git a/src/common/config/manager.go b/src/common/config/manager.go index 22831df25..eecd64726 100644 --- a/src/common/config/manager.go +++ b/src/common/config/manager.go @@ -125,8 +125,10 @@ func (c *CfgManager) GetAll() map[string]interface{} { metaDataList := metadata.Instance().GetAll() for _, item := range metaDataList { cfgValue, err := c.store.GetAnyType(item.Name) - if err != metadata.ErrValueNotSet && err != nil { - log.Errorf("Failed to get value of key %v, error %v", item.Name, err) + if err != nil { + if err != metadata.ErrValueNotSet { + log.Errorf("Failed to get value of key %v, error %v", item.Name, err) + } continue } resultMap[item.Name] = cfgValue @@ -145,8 +147,10 @@ func (c *CfgManager) GetUserCfgs() map[string]interface{} { for _, item := range metaDataList { if item.Scope == metadata.UserScope { cfgValue, err := c.store.GetAnyType(item.Name) - if err != metadata.ErrValueNotSet && err != nil { - log.Errorf("Failed to get value of key %v, error %v", item.Name, err) + if err != nil { + if err != metadata.ErrValueNotSet { + log.Errorf("Failed to get value of key %v, error %v", item.Name, err) + } continue } resultMap[item.Name] = cfgValue diff --git a/src/common/const.go b/src/common/const.go index c79c4795a..f6ae886ad 100644 --- a/src/common/const.go +++ b/src/common/const.go @@ -80,7 +80,6 @@ const ( MaxJobWorkers = "max_job_workers" TokenExpiration = "token_expiration" CfgExpiration = "cfg_expiration" - JobLogDir = "job_log_dir" AdminInitialPassword = "admin_initial_password" AdmiralEndpoint = "admiral_url" WithNotary = "with_notary" @@ -98,7 +97,6 @@ const ( UAAVerifyCert = "uaa_verify_cert" DefaultClairEndpoint = "http://clair:6060" CfgDriverDB = "db" - CfgDriverJSON = "json" NewHarborAdminName = "admin@harbor.local" RegistryStorageProviderName = "registry_storage_provider_name" UserMember = "u" @@ -106,7 +104,6 @@ const ( ReadOnly = "read_only" ClairURL = "clair_url" NotaryURL = "notary_url" - DefaultAdminserverEndpoint = "http://adminserver:8080" DefaultCoreEndpoint = "http://core:8080" DefaultNotaryEndpoint = "http://notary-server:4443" LdapGroupType = 1 @@ -123,48 +120,3 @@ const ( RobotPrefix = "robot$" CoreConfigPath = "/api/internal/configurations" ) - -// TODO remove with adminserver -// Shared variable, not allowed to modify -var ( - - // value is default value - HarborStringKeysMap = map[string]string{ - AUTHMode: "db_auth", - LDAPURL: "", - LDAPSearchDN: "", - LDAPSearchPwd: "", - LDAPBaseDN: "", - LDAPUID: "", - LDAPFilter: "", - LDAPGroupAttributeName: "", - LDAPGroupBaseDN: "", - LdapGroupAdminDn: "", - LDAPGroupSearchFilter: "", - EmailHost: "smtp.mydomain.com", - EmailUsername: "sample_admin@mydomain.com", - EmailPassword: "abc", - EmailFrom: "admin ", - EmailIdentity: "", - ProjectCreationRestriction: ProCrtRestrEveryone, - UAAClientID: "", - UAAEndpoint: "", - } - - HarborNumKeysMap = map[string]int{ - EmailPort: 25, - LDAPScope: 2, - LDAPTimeout: 5, - LDAPGroupSearchScope: 2, - TokenExpiration: 30, - } - - HarborBoolKeysMap = map[string]bool{ - EmailSSL: false, - EmailInsecure: false, - SelfRegistration: true, - LDAPVerifyCert: true, - UAAVerifyCert: true, - ReadOnly: false, - } -) diff --git a/src/common/token/htoken_test.go b/src/common/token/htoken_test.go index 58a853d94..e2d81b10c 100644 --- a/src/common/token/htoken_test.go +++ b/src/common/token/htoken_test.go @@ -1,25 +1,15 @@ package token import ( - "github.com/goharbor/harbor/src/common/rbac" - "github.com/goharbor/harbor/src/common/utils/test" - "github.com/goharbor/harbor/src/core/config" - "github.com/stretchr/testify/assert" "os" "testing" + + "github.com/goharbor/harbor/src/common/rbac" + "github.com/goharbor/harbor/src/core/config" + "github.com/stretchr/testify/assert" ) func TestMain(m *testing.M) { - server, err := test.NewAdminserver(nil) - if err != nil { - panic(err) - } - defer server.Close() - - if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil { - panic(err) - } - if err := config.Init(); err != nil { panic(err) } diff --git a/src/common/utils/test/adminserver.go b/src/common/utils/test/config.go similarity index 75% rename from src/common/utils/test/adminserver.go rename to src/common/utils/test/config.go index 283727225..b57111e4a 100644 --- a/src/common/utils/test/adminserver.go +++ b/src/common/utils/test/config.go @@ -15,14 +15,10 @@ package test import ( - "encoding/json" - "net/http" - "net/http/httptest" - "github.com/goharbor/harbor/src/common" ) -var adminServerDefaultConfig = map[string]interface{}{ +var defaultConfig = map[string]interface{}{ common.ExtEndpoint: "https://host01.com", common.AUTHMode: common.DBAuth, common.DatabaseType: "postgresql", @@ -77,54 +73,7 @@ var adminServerDefaultConfig = map[string]interface{}{ common.NotaryURL: "http://notary-server:4443", } -// NewAdminserver returns a mock admin server -func NewAdminserver(config map[string]interface{}) (*httptest.Server, error) { - m := []*RequestHandlerMapping{} - if config == nil { - config = adminServerDefaultConfig - } else { - for k, v := range adminServerDefaultConfig { - if _, ok := config[k]; !ok { - config[k] = v - } - } - } - b, err := json.Marshal(config) - if err != nil { - return nil, err - } - - resp := &Response{ - StatusCode: http.StatusOK, - Body: b, - } - - m = append(m, &RequestHandlerMapping{ - Method: "GET", - Pattern: "/api/configs", - Handler: Handler(resp), - }) - - m = append(m, &RequestHandlerMapping{ - Method: "PUT", - Pattern: "/api/configurations", - Handler: Handler(&Response{ - StatusCode: http.StatusOK, - }), - }) - - m = append(m, &RequestHandlerMapping{ - Method: "POST", - Pattern: "/api/configurations/reset", - Handler: Handler(&Response{ - StatusCode: http.StatusOK, - }), - }) - - return NewServer(m...), nil -} - // GetDefaultConfigMap returns the defailt config map for easier modification. func GetDefaultConfigMap() map[string]interface{} { - return adminServerDefaultConfig + return defaultConfig } diff --git a/src/jobservice/README.md b/src/jobservice/README.md index b707dd942..a7c8e4e94 100644 --- a/src/jobservice/README.md +++ b/src/jobservice/README.md @@ -382,7 +382,7 @@ The following configuration options are supported: | worker_pool.redis_pool.namespace | The namespace used in redis| JOB_SERVICE_POOL_REDIS_NAMESPACE | | loggers | Loggers for job service itself. Refer to [Configure loggers](#configure-loggers)| | | job_loggers | Loggers for the running jobs. Refer to [Configure loggers](#configure-loggers) | | -| admin_server | The harbor admin server endpoint which used to retrieve Harbor configures| ADMINSERVER_URL | +| core_server | The harbor core server endpoint which used to retrieve Harbor configures| CORE_URL | ### Sample @@ -428,9 +428,6 @@ job_loggers: loggers: - name: "STD_OUTPUT" # Same with above level: "DEBUG" - -#Admin server endpoint -admin_server: "http://adminserver:9010/" ``` ## API diff --git a/src/jobservice/config/config.go b/src/jobservice/config/config.go index 34be52e5a..5e128cdd3 100644 --- a/src/jobservice/config/config.go +++ b/src/jobservice/config/config.go @@ -65,8 +65,6 @@ type Configuration struct { // Server listening port Port uint `yaml:"port"` - AdminServer string `yaml:"admin_server"` - // Additional config when using https HTTPSConfig *HTTPSConfig `yaml:"https_config,omitempty"` @@ -171,11 +169,6 @@ func GetUIAuthSecret() string { return utils.ReadEnv(uiAuthSecret) } -// GetAdminServerEndpoint return the admin server endpoint -func GetAdminServerEndpoint() string { - return DefaultConfig.AdminServer -} - // Load env variables func (c *Configuration) loadEnvs() { prot := utils.ReadEnv(jobServiceProtocol) @@ -251,11 +244,6 @@ func (c *Configuration) loadEnvs() { } } - // admin server - if coreServer := utils.ReadEnv(jobServiceCoreServerEndpoint); !utils.IsEmptyStr(coreServer) { - c.AdminServer = coreServer - } - } // Check if the configurations are valid settings. @@ -325,9 +313,5 @@ func (c *Configuration) validate() error { return errors.New("missing logger config of job") } - if _, err := url.Parse(c.AdminServer); err != nil { - return fmt.Errorf("invalid admin server endpoint: %s", err) - } - return nil // valid } diff --git a/src/jobservice/config/config_test.go b/src/jobservice/config/config_test.go index 687f1d8ab..6b925d5d1 100644 --- a/src/jobservice/config/config_test.go +++ b/src/jobservice/config/config_test.go @@ -69,11 +69,6 @@ func TestDefaultConfig(t *testing.T) { if err := DefaultConfig.Load("../config_test.yml", true); err != nil { t.Fatalf("Load config from yaml file, expect nil error but got error '%s'\n", err) } - - if endpoint := GetAdminServerEndpoint(); endpoint != "http://127.0.0.1:8888" { - t.Errorf("expect default admin server endpoint 'http://127.0.0.1:8888' but got '%s'\n", endpoint) - } - redisURL := DefaultConfig.PoolConfig.RedisPoolCfg.RedisURL if redisURL != "redis://localhost:6379" { t.Errorf("expect redisURL '%s' but got '%s'\n", "redis://localhost:6379", redisURL) diff --git a/tests/configharbor.py b/tests/configharbor.py index f355faaac..19955ff57 100644 --- a/tests/configharbor.py +++ b/tests/configharbor.py @@ -46,4 +46,3 @@ if response.status_code == 200 : else: print("Failed with http return code:"+ str(response.status_code)) sys.exit(1) - diff --git a/tests/testprepare.sh b/tests/testprepare.sh index 384e0da24..66e43af3c 100755 --- a/tests/testprepare.sh +++ b/tests/testprepare.sh @@ -14,8 +14,4 @@ else fi echo "server ip is "$IP -sed -i -r "s/POSTGRESQL_HOST=postgresql/POSTGRESQL_HOST=$IP/" make/common/config/adminserver/env -sed -i -r "s|REGISTRY_URL=http://registry:5000|REGISTRY_URL=http://$IP:5000|" make/common/config/adminserver/env -sed -i -r "s/CORE_SECRET=.*/CORE_SECRET=$CORE_SECRET/" make/common/config/adminserver/env - chmod 777 /data/ diff --git a/tests/travis/ut_install.sh b/tests/travis/ut_install.sh index 1bf39d275..da9c17ff5 100644 --- a/tests/travis/ut_install.sh +++ b/tests/travis/ut_install.sh @@ -32,7 +32,6 @@ sudo mkdir -p /harbor && sudo mv ./VERSION /harbor/UIVERSION sudo ./tests/testprepare.sh cd tests && sudo ./ldapprepare.sh && sudo ./admiral.sh && cd .. -sudo make compile_adminserver sudo make -f make/photon/Makefile _build_db _build_registry -e VERSIONTAG=dev -e CLAIRDBVERSION=dev -e REGISTRYVERSION=${REG_VERSION} sudo sed -i 's/__reg_version__/${REG_VERSION}-dev/g' ./make/docker-compose.test.yml sudo sed -i 's/__version__/dev/g' ./make/docker-compose.test.yml