Merge branch 'master' of https://github.com/vmware/harbor
@ -19,7 +19,7 @@ env:
|
||||
MYSQL_PWD: root123
|
||||
MYSQL_DATABASE: registry
|
||||
SQLITE_FILE: /tmp/registry.db
|
||||
ADMIN_SERVER_URL: http://127.0.0.1:8888
|
||||
ADMINSERVER_URL: http://127.0.0.1:8888
|
||||
DOCKER_COMPOSE_VERSION: 1.7.1
|
||||
HARBOR_ADMIN: admin
|
||||
HARBOR_ADMIN_PASSWD: Harbor12345
|
||||
|
Before Width: | Height: | Size: 163 KiB After Width: | Height: | Size: 68 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 105 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 73 KiB After Width: | Height: | Size: 94 KiB |
BIN
docs/img/log_search_advanced.png
Normal file
After Width: | Height: | Size: 74 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 78 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 63 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 85 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 112 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 69 KiB After Width: | Height: | Size: 84 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 61 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 67 KiB After Width: | Height: | Size: 90 KiB |
Before Width: | Height: | Size: 52 KiB After Width: | Height: | Size: 60 KiB |
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 66 KiB |
BIN
docs/img/project_configuration.png
Normal file
After Width: | Height: | Size: 107 KiB |
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 61 KiB |
Before Width: | Height: | Size: 76 KiB After Width: | Height: | Size: 65 KiB |
Before Width: | Height: | Size: 79 KiB After Width: | Height: | Size: 66 KiB |
@ -70,14 +70,28 @@ You can create a project after you signed in. Check on the "Access Level" checkb
|
||||
|
||||
![create project](img/new_create_project.png)
|
||||
|
||||
After the project is created, you can browse repositories, users and logs using the navigation tab.
|
||||
After the project is created, you can browse repositories, members, logs, replication and configuration using the navigation tab.
|
||||
|
||||
![browse project](img/new_browse_project.png)
|
||||
|
||||
All logs can be listed by clicking "Logs". You can apply a filter by username, or operations and dates under "Advanced Search".
|
||||
|
||||
![browse project](img/log_search_advanced.png)
|
||||
|
||||
![browse project](img/new_project_log.png)
|
||||
|
||||
Project properties can be changed by clicking "Configuration".
|
||||
|
||||
* To make all repositories under the project accessible to everyone, select the `Public` checkbox.
|
||||
|
||||
* To prevent un-signed images under the project from being pulled, select the `Enable content trust` checkbox.
|
||||
|
||||
* To prevent vulnerable images under the project from being pulled, select the `Prevent vulnerable images from running` checkbox and change the severity level of vulnerabilities. Images cannot be pulled if their level equals to or higher than the currently selected level.
|
||||
|
||||
* To activate an immediate vulnerability scan on new images that are pushed to the project, select the `Automatically scan images on push` checkbox.
|
||||
|
||||
![browse project](img/project_configuration.png)
|
||||
|
||||
## Managing members of a project
|
||||
### Adding members
|
||||
You can add members with different roles to an existing project.
|
||||
@ -98,7 +112,7 @@ There may be a bit of delay during replication according to the situation of the
|
||||
|
||||
**Note:** The replication feature is incompatible between Harbor instance before version 0.3.5(included) and after version 0.3.5.
|
||||
|
||||
Start replication by creating a rule. Click "Add Replication Rule" on the "Replication" tab, fill in the necessary fields, if there is no endpoint in the list, you need to create one, and then click "OK", a rule for this project will be created. If "Enable" is chosen, the project will be replicated to the remote immediately.
|
||||
Replication can be configured by creating a rule. Click "Add Replication Rule" on the "Replication" tab and fill in the necessary fields. If there is no endpoint available in the list, you need to create one. Uncheck "Verify Remote Cert" if the remote registry uses a self-signed or an untrusted certificate. Click "OK" to create a replication rule for this project. If "Enable" is chosen, the project will be replicated to the remote registry immediately.
|
||||
|
||||
![browse project](img/new_create_rule.png)
|
||||
|
||||
@ -145,10 +159,6 @@ Use the **Project Creation** drop-down menu to set which users can create projec
|
||||
You can manage whether a user can sign up for a new account. This option is not available if you use LDAP authentication.
|
||||
![browse project](img/new_self_reg.png)
|
||||
|
||||
### Managing verification of remote certificate
|
||||
You can choose whether to verify remote endpoint's certification. You may need to disable certificate verification if the remote registry uses a self-signed or an untrusted certificate.
|
||||
![browse project](img/new_remote_cert.png)
|
||||
|
||||
### Managing email settings
|
||||
You can change Harbor's email settings, the mail server is used to send out responses to users who request to reset their password.
|
||||
![browse project](img/new_config_email.png)
|
||||
|
@ -2,7 +2,7 @@ FROM vmware/photon:1.0
|
||||
|
||||
#The Docker Daemon has to be running with storage backend btrfs when building the image
|
||||
|
||||
RUN tdnf distro-sync -y || echo \
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf install -y sed shadow procps-ng gawk gzip sudo net-tools \
|
||||
&& groupadd -r -g 10000 mysql && useradd --no-log-init -r -g 10000 -u 10000 mysql \
|
||||
&& tdnf install -y mariadb-server mariadb \
|
||||
|
@ -1,13 +1,13 @@
|
||||
FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y || echo \
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf install -y nginx \
|
||||
&& ln -sf /dev/stdout /var/log/nginx/access.log \
|
||||
&& ln -sf /dev/stderr /var/log/nginx/error.log \
|
||||
&& mkdir -p /var/run \
|
||||
&& tdnf clean all
|
||||
|
||||
EXPOSE 80
|
||||
VOLUME /var/cache/nginx /var/log/nginx /run
|
||||
STOPSIGNAL SIGQUIT
|
||||
|
||||
CMD ["nginx", "-g", "daemon off;"]
|
||||
|
@ -3,7 +3,7 @@ FROM vmware/photon:1.0
|
||||
ENV PGDATA /var/lib/postgresql/data
|
||||
|
||||
RUN touch /etc/localtime.bak \
|
||||
&& tdnf distro-sync -y || echo \
|
||||
&& tdnf distro-sync -y \
|
||||
&& tdnf install -y sed shadow gzip postgresql\
|
||||
&& groupadd -r postgres --gid=999 \
|
||||
&& useradd -r -g postgres --uid=999 postgres \
|
||||
|
@ -1,3 +1,4 @@
|
||||
PORT=8080
|
||||
LOG_LEVEL=debug
|
||||
EXT_ENDPOINT=$ui_url
|
||||
AUTH_MODE=$auth_mode
|
||||
@ -42,5 +43,5 @@ RESET=false
|
||||
UAA_ENDPOINT=$uaa_endpoint
|
||||
UAA_CLIENTID=$uaa_clientid
|
||||
UAA_CLIENTSECRET=$uaa_clientsecret
|
||||
UI_URL=http://ui
|
||||
JOBSERVICE_URL=http://jobservice
|
||||
UI_URL=http://ui:8080
|
||||
JOBSERVICE_URL=http://jobservice:8080
|
||||
|
@ -22,4 +22,4 @@ clair:
|
||||
attempts: 3
|
||||
renotifyinterval: 2h
|
||||
http:
|
||||
endpoint: http://ui/service/notifications/clair
|
||||
endpoint: http://ui:8080/service/notifications/clair
|
||||
|
@ -2,4 +2,4 @@ appname = jobservice
|
||||
runmode = dev
|
||||
|
||||
[dev]
|
||||
httpport = 80
|
||||
httpport = 8080
|
||||
|
@ -2,4 +2,5 @@ LOG_LEVEL=debug
|
||||
CONFIG_PATH=/etc/jobservice/app.conf
|
||||
UI_SECRET=$ui_secret
|
||||
JOBSERVICE_SECRET=$jobservice_secret
|
||||
ADMINSERVER_URL=http://adminserver:8080
|
||||
GODEBUG=netdns=cgo
|
||||
|
@ -18,7 +18,7 @@ http {
|
||||
}
|
||||
|
||||
upstream ui {
|
||||
server ui:80;
|
||||
server ui:8080;
|
||||
}
|
||||
|
||||
log_format timed_combined '$$remote_addr - '
|
||||
|
@ -18,7 +18,7 @@ http {
|
||||
}
|
||||
|
||||
upstream ui {
|
||||
server ui:80;
|
||||
server ui:8080;
|
||||
}
|
||||
|
||||
log_format timed_combined '$$remote_addr - '
|
||||
|
@ -29,7 +29,7 @@ notifications:
|
||||
endpoints:
|
||||
- name: harbor
|
||||
disabled: false
|
||||
url: http://ui/service/notifications
|
||||
url: http://ui:8080/service/notifications
|
||||
timeout: 3000ms
|
||||
threshold: 5
|
||||
backoff: 1s
|
||||
|
@ -3,4 +3,4 @@ runmode = dev
|
||||
enablegzip = true
|
||||
|
||||
[dev]
|
||||
httpport = 80
|
||||
httpport = 8080
|
||||
|
@ -3,4 +3,5 @@ CONFIG_PATH=/etc/ui/app.conf
|
||||
UI_SECRET=$ui_secret
|
||||
JOBSERVICE_SECRET=$jobservice_secret
|
||||
GODEBUG=netdns=cgo
|
||||
ADMINSERVER_URL=http://adminserver:8080
|
||||
UAA_CA_ROOT=/etc/ui/certificates/uaa_ca.pem
|
||||
|
@ -16,8 +16,6 @@ services:
|
||||
- harbor-notary
|
||||
volumes:
|
||||
- ./common/config/notary:/config
|
||||
entrypoint: /usr/bin/env sh
|
||||
command: -c "/migrations/migrate.sh && notary-server -config=/config/server-config.json -logf=logfmt"
|
||||
depends_on:
|
||||
- notary-db
|
||||
- notary-signer
|
||||
@ -39,8 +37,6 @@ services:
|
||||
- ./common/config/notary:/config
|
||||
env_file:
|
||||
- ./common/config/notary/signer_env
|
||||
entrypoint: /usr/bin/env sh
|
||||
command: -c "/migrations/migrate.sh && notary-signer -config=/config/signer-config.json -logf=logfmt"
|
||||
depends_on:
|
||||
- notary-db
|
||||
logging:
|
||||
|
@ -1,11 +1,14 @@
|
||||
FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf erase vim -y \
|
||||
&& tdnf distro-sync -y || echo \
|
||||
&& tdnf distro-sync -y \
|
||||
&& tdnf install -y sudo \
|
||||
&& tdnf clean all \
|
||||
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor \
|
||||
&& mkdir /harbor/
|
||||
COPY ./make/dev/adminserver/harbor_adminserver /harbor/
|
||||
COPY ./make/dev/adminserver/harbor_adminserver ./make/photon/adminserver/start.sh /harbor/
|
||||
HEALTHCHECK CMD curl -s -o /dev/null -w "%{http_code}" 127.0.0.1:8080/api/configurations|grep 401
|
||||
|
||||
RUN chmod u+x /harbor/harbor_adminserver
|
||||
RUN chmod u+x /harbor/harbor_adminserver /harbor/start.sh
|
||||
WORKDIR /harbor/
|
||||
ENTRYPOINT ["/harbor/harbor_adminserver"]
|
||||
ENTRYPOINT ["/harbor/start.sh"]
|
||||
|
5
make/photon/adminserver/start.sh
Normal file
@ -0,0 +1,5 @@
|
||||
#!/bin/sh
|
||||
if [ -d /etc/adminserver ]; then
|
||||
chown -R 10000:10000 /etc/adminserver
|
||||
fi
|
||||
sudo -E -u \#10000 "/harbor/harbor_adminserver"
|
@ -1,5 +1,6 @@
|
||||
FROM vmware/photon:1.0
|
||||
|
||||
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf erase vim -y \
|
||||
&& tdnf install -y git shadow sudo bzr rpm xz python-xml \
|
||||
@ -9,11 +10,20 @@ RUN tdnf distro-sync -y \
|
||||
&& useradd --no-log-init -m -r -g 10000 -u 10000 clair
|
||||
COPY clair /clair2.0.1/
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
COPY dumb-init /dumb-init
|
||||
|
||||
VOLUME /config
|
||||
|
||||
EXPOSE 6060 6061
|
||||
|
||||
RUN chown -R 10000:10000 /clair2.0.1 \
|
||||
&& chmod u+x /clair2.0.1/clair \
|
||||
&& chmod u+x /docker-entrypoint.sh
|
||||
&& chmod u+x /docker-entrypoint.sh \
|
||||
&& chmod +x /dumb-init
|
||||
|
||||
|
||||
HEALTHCHECK --interval=30s --timeout=10s --retries=3 CMD curl -sS 127.0.0.1:6061/health || exit 1
|
||||
|
||||
USER clair
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
/clair2.0.1/clair -config /config/config.yaml
|
||||
/dumb-init -- /clair2.0.1/clair -config /config/config.yaml
|
||||
set +e
|
||||
|
BIN
make/photon/clair/dumb-init
Executable file
@ -1,10 +1,14 @@
|
||||
FROM vmware/photon:1.0
|
||||
|
||||
RUN mkdir /harbor/ \
|
||||
&& tdnf distro-sync -y || echo \
|
||||
&& tdnf clean all
|
||||
COPY ./make/dev/jobservice/harbor_jobservice /harbor/
|
||||
&& tdnf distro-sync -y \
|
||||
&& tdnf install sudo -y \
|
||||
&& tdnf clean all \
|
||||
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor
|
||||
HEALTHCHECK CMD curl -s -o /dev/null -w "%{http_code}" http://127.0.0.1:8080/api/jobs/replication/1/log|grep 401
|
||||
|
||||
RUN chmod u+x /harbor/harbor_jobservice
|
||||
COPY ./make/photon/jobservice/start.sh ./make/dev/jobservice/harbor_jobservice /harbor/
|
||||
|
||||
RUN chmod u+x /harbor/harbor_jobservice /harbor/start.sh
|
||||
WORKDIR /harbor/
|
||||
ENTRYPOINT ["/harbor/harbor_jobservice"]
|
||||
ENTRYPOINT ["/harbor/start.sh"]
|
||||
|
9
make/photon/jobservice/start.sh
Normal file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
if [ -d /etc/jobservice/ ]; then
|
||||
chown -R 10000:10000 /etc/jobservice/
|
||||
fi
|
||||
if [ -d /var/log/jobs ]; then
|
||||
chown -R 10000:10000 /var/log/jobs/
|
||||
fi
|
||||
sudo -E -u \#10000 "/harbor/harbor_jobservice"
|
||||
|
@ -1,6 +1,6 @@
|
||||
FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y || echo \
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf install -y cronie rsyslog logrotate shadow tar gzip sudo net-tools\
|
||||
&& mkdir /etc/rsyslog.d/ \
|
||||
&& mkdir /var/spool/rsyslog \
|
||||
@ -17,7 +17,7 @@ RUN mv /etc/cron.daily/logrotate /etc/cron.hourly/logrotate
|
||||
|
||||
COPY start.sh /usr/local/bin/
|
||||
RUN chmod +x /usr/local/bin/start.sh && \
|
||||
chown -R 10000:10000 /run
|
||||
chown -R 10000:10000 /etc/rsyslog.conf /etc/rsyslog.d/ /run
|
||||
|
||||
HEALTHCHECK CMD netstat -ltu|grep 10514
|
||||
|
||||
|
@ -35,7 +35,7 @@ cur=$PWD
|
||||
|
||||
# the temp folder to store notary source code...
|
||||
TEMP=`mktemp -d /$TMPDIR/notary.XXXXXX`
|
||||
git clone -b $VERSION https://github.com/docker/notary.git $TEMP
|
||||
git clone -b $VERSION https://github.com/theupdateframework/notary.git $TEMP
|
||||
|
||||
echo 'build the notary binary bases on the golang:1.7.3...'
|
||||
cp binary.Dockerfile $TEMP
|
||||
@ -56,4 +56,4 @@ docker build -f server.Dockerfile -t $SERVER_PHOTONIMAGE .
|
||||
docker build -f signer.Dockerfile -t $SIGNER_PHOTONIMAGE .
|
||||
|
||||
echo 'Push image to docker hub.'
|
||||
../../pushimage.sh $PHOTONIMAGE $USERNAME $PASSWORD
|
||||
../../pushimage.sh $PHOTONIMAGE $USERNAME $PASSWORD
|
||||
|
3
make/photon/notary/server-start.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
chown 10000:10000 -R /config
|
||||
sudo -E -u \#10000 sh -c "/usr/bin/env /migrations/migrate.sh && /bin/notary-server -config=/config/server-config.json -logf=logfmt"
|
@ -2,10 +2,15 @@ FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf erase vim -y \
|
||||
&& tdnf clean all
|
||||
&& tdnf install -y shadow sudo \
|
||||
&& tdnf clean all \
|
||||
&& groupadd -r -g 10000 notary \
|
||||
&& useradd --no-log-init -r -g 10000 -u 10000 notary
|
||||
|
||||
COPY ./binary/notary-server /bin/notary-server
|
||||
COPY ./migrate /bin/migrate
|
||||
COPY ./migrations/ /migrations/
|
||||
|
||||
COPY ./server-start.sh /bin/server-start.sh
|
||||
RUN chmod u+x /bin/notary-server /migrations/migrate.sh /bin/migrate /bin/server-start.sh
|
||||
ENV SERVICE_NAME=notary_server
|
||||
ENTRYPOINT [ "notary-server" ]
|
||||
ENTRYPOINT [ "/bin/server-start.sh" ]
|
||||
|
3
make/photon/notary/signer-start.sh
Normal file
@ -0,0 +1,3 @@
|
||||
#!/bin/sh
|
||||
chown 10000:10000 -R /config
|
||||
sudo -E -u \#10000 sh -c "/usr/bin/env && /migrations/migrate.sh && /bin/notary-signer -config=/config/signer-config.json -logf=logfmt"
|
@ -2,10 +2,15 @@ FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf erase vim -y \
|
||||
&& tdnf clean all
|
||||
&& tdnf install -y shadow sudo \
|
||||
&& tdnf clean all \
|
||||
&& groupadd -r -g 10000 notary \
|
||||
&& useradd --no-log-init -r -g 10000 -u 10000 notary
|
||||
COPY ./binary/notary-signer /bin/notary-signer
|
||||
COPY ./migrate /bin/migrate
|
||||
COPY ./migrations/ /migrations/
|
||||
COPY ./signer-start.sh /bin/signer-start.sh
|
||||
|
||||
RUN chmod u+x /bin/notary-signer /migrations/migrate.sh /bin/migrate /bin/signer-start.sh
|
||||
ENV SERVICE_NAME=notary_signer
|
||||
ENTRYPOINT [ "notary-signer" ]
|
||||
ENTRYPOINT [ "/bin/signer-start.sh" ]
|
||||
|
@ -2,16 +2,17 @@ FROM vmware/photon:1.0
|
||||
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf erase vim -y \
|
||||
&& tdnf install sudo -y \
|
||||
&& tdnf clean all \
|
||||
&& groupadd -r -g 10000 harbor && useradd --no-log-init -r -g 10000 -u 10000 harbor \
|
||||
&& mkdir /harbor/
|
||||
COPY ./make/dev/ui/harbor_ui /harbor/
|
||||
|
||||
HEALTHCHECK CMD curl -s -o /dev/null -w "%{http_code}" 127.0.0.1:8080/api/systeminfo|grep 200
|
||||
COPY ./make/dev/ui/harbor_ui ./src/favicon.ico ./make/photon/ui/start.sh ./VERSION /harbor/
|
||||
COPY ./src/ui/views /harbor/views
|
||||
COPY ./src/ui/static /harbor/static
|
||||
COPY ./src/favicon.ico /harbor/favicon.ico
|
||||
COPY ./VERSION /harbor/VERSION
|
||||
|
||||
RUN chmod u+x /harbor/harbor_ui
|
||||
|
||||
RUN chmod u+x /harbor/start.sh /harbor/harbor_ui
|
||||
WORKDIR /harbor/
|
||||
ENTRYPOINT ["/harbor/harbor_ui"]
|
||||
|
||||
ENTRYPOINT ["/harbor/start.sh"]
|
||||
|
6
make/photon/ui/start.sh
Normal file
@ -0,0 +1,6 @@
|
||||
#!/bin/sh
|
||||
if [ -d /etc/ui/ ]; then
|
||||
chown -R 10000:10000 /etc/ui/
|
||||
fi
|
||||
sudo -E -u \#10000 "/harbor/harbor_ui"
|
||||
|
@ -72,8 +72,8 @@ func TestMain(t *testing.T) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
|
||||
secretKeyPath := "/tmp/secretkey"
|
||||
|
@ -36,7 +36,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
notaryCachePath = "/root/notary"
|
||||
notaryCachePath = "/etc/ui/notary-cache"
|
||||
trustPin trustpinning.TrustPinConfig
|
||||
mockRetriever notary.PassRetriever
|
||||
)
|
||||
|
@ -47,7 +47,7 @@ func TestMain(m *testing.M) {
|
||||
panic(err)
|
||||
}
|
||||
defer adminServer.Close()
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", adminServer.URL); err != nil {
|
||||
if err := os.Setenv("ADMINSERVER_URL", adminServer.URL); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := config.Init(); err != nil {
|
||||
|
@ -45,7 +45,7 @@ func Init() error {
|
||||
//init key provider
|
||||
initKeyProvider()
|
||||
|
||||
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
||||
adminServerURL := os.Getenv("ADMINSERVER_URL")
|
||||
if len(adminServerURL) == 0 {
|
||||
adminServerURL = "http://adminserver"
|
||||
}
|
||||
@ -163,7 +163,7 @@ func ExtEndpoint() (string, error) {
|
||||
|
||||
// InternalTokenServiceEndpoint ...
|
||||
func InternalTokenServiceEndpoint() string {
|
||||
return "http://ui/service/token"
|
||||
return LocalUIURL() + "/service/token"
|
||||
}
|
||||
|
||||
// ClairEndpoint returns the end point of clair instance, by default it's the one deployed within Harbor.
|
||||
|
@ -30,8 +30,8 @@ func TestConfig(t *testing.T) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
|
||||
secretKeyPath := "/tmp/secretkey"
|
||||
|
@ -55,8 +55,8 @@ func TestMain(m *testing.M) {
|
||||
log.Fatalf("failed to create a mock admin server: %v", err)
|
||||
}
|
||||
defer server.Close()
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
log.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
log.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
secretKeyPath := "/tmp/secretkey"
|
||||
_, err = test.GenerateKey(secretKeyPath)
|
||||
|
@ -290,6 +290,7 @@ func (c *Checker) createProject(project *models.Project) error {
|
||||
}
|
||||
|
||||
req.SetBasicAuth(c.dstUsr, c.dstPwd)
|
||||
req.Header.Set(http.CanonicalHeaderKey("content-type"), "application/json")
|
||||
|
||||
client := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
|
@ -71,8 +71,8 @@ func TestMain(t *testing.T) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
|
||||
secretKeyPath := "/tmp/secretkey"
|
||||
|
@ -33,8 +33,8 @@ func TestGetClient(t *testing.T) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
err = config.Init()
|
||||
if err != nil {
|
||||
|
@ -62,7 +62,7 @@ func Init() error {
|
||||
//init key provider
|
||||
initKeyProvider()
|
||||
|
||||
adminServerURL := os.Getenv("ADMIN_SERVER_URL")
|
||||
adminServerURL := os.Getenv("ADMINSERVER_URL")
|
||||
if len(adminServerURL) == 0 {
|
||||
adminServerURL = "http://adminserver"
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ func TestConfig(t *testing.T) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMIN_SERVER_URL", err)
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
t.Fatalf("failed to set env %s: %v", "ADMINSERVER_URL", err)
|
||||
}
|
||||
|
||||
secretKeyPath := "/tmp/secretkey"
|
||||
|
@ -40,7 +40,7 @@ func TestMain(m *testing.M) {
|
||||
panic(err)
|
||||
}
|
||||
defer adminServer.Close()
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", adminServer.URL); err != nil {
|
||||
if err := os.Setenv("ADMINSERVER_URL", adminServer.URL); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := config.Init(); err != nil {
|
||||
@ -129,7 +129,7 @@ func TestPMSPolicyChecker(t *testing.T) {
|
||||
panic(err)
|
||||
}
|
||||
defer adminServer.Close()
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", adminServer.URL); err != nil {
|
||||
if err := os.Setenv("ADMINSERVER_URL", adminServer.URL); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := config.Init(); err != nil {
|
||||
|
@ -41,7 +41,7 @@ func TestMain(m *testing.M) {
|
||||
}
|
||||
defer server.Close()
|
||||
|
||||
if err := os.Setenv("ADMIN_SERVER_URL", server.URL); err != nil {
|
||||
if err := os.Setenv("ADMINSERVER_URL", server.URL); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := config.Init(); err != nil {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "harbor-ui",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.0",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||
"scripts": {
|
||||
"start": "ng serve --host 0.0.0.0 --port 4500 --proxy-config proxy.config.json",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "harbor-ui",
|
||||
"version": "0.4.0",
|
||||
"version": "0.5.9",
|
||||
"description": "Harbor shared UI components based on Clarity and Angular4",
|
||||
"author": "VMware",
|
||||
"module": "index.js",
|
||||
|
@ -11,22 +11,22 @@ export const PROJECT_POLICY_CONFIG_TEMPLATE = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="withNotary || withClair">
|
||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SECURITY' | translate }}</label>
|
||||
<div class="form-content">
|
||||
<div>
|
||||
<div *ngIf="withNotary">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.ContentTrust" name="content-trust"
|
||||
[clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.CONTENT_TRUST_TOGGLE' | translate }}</clr-checkbox>
|
||||
<div class="chk-explain"><label> {{ 'PROJECT_CONFIG.CONTENT_TRUST_POLCIY' | translate }} </label></div>
|
||||
</div>
|
||||
<div>
|
||||
<div *ngIf="withClair">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.PreventVulImg" name="prevent-vulenrability-image" [clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_TOGGLE' | translate }}</clr-checkbox>
|
||||
<div class="chk-explain">
|
||||
<label>
|
||||
<div id="severity-blk">
|
||||
<div>{{ 'PROJECT_CONFIG.PREVENT_VULNERABLE_1' | translate }}</div>
|
||||
<div class="select">
|
||||
<select id="severity" name="severity" [(ngModel)]="projectPolicy.PreventVulImgServerity" [disabled]="!projectPolicy.PreventVulImg">
|
||||
<select id="severity" name="severity" [(ngModel)]="projectPolicy.PreventVulImgSeverity" [disabled]="!projectPolicy.PreventVulImg">
|
||||
<option *ngFor='let s of severityOptions' [ngValue]="s.severity">{{ s.severityLevel | translate | uppercase }}</option>
|
||||
</select>
|
||||
</div>
|
||||
@ -37,7 +37,7 @@ export const PROJECT_POLICY_CONFIG_TEMPLATE = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-group" *ngIf="withClair">
|
||||
<label for="projectPolicyForm">{{ 'PROJECT_CONFIG.SCAN' | translate }}</label>
|
||||
<div class="form-content">
|
||||
<clr-checkbox [(ngModel)]="projectPolicy.ScanImgOnPush" name="scan-image-on-push" [clrDisabled]="!hasProjectAdminRole">{{ 'PROJECT_CONFIG.AUTOSCAN_TOGGLE' | translate }}</clr-checkbox>
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { SystemInfoService, SystemInfoDefaultService } from './../service/system-info.service';
|
||||
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
import { ErrorHandler } from '../error-handler/error-handler';
|
||||
import { ConfirmationDialogComponent } from '../confirmation-dialog/confirmation-dialog.component';
|
||||
@ -5,13 +6,88 @@ import { ProjectPolicyConfigComponent } from './project-policy-config.component'
|
||||
import { SharedModule } from '../shared/shared.module';
|
||||
import { ProjectService, ProjectDefaultService} from '../service/project.service';
|
||||
import { SERVICE_CONFIG, IServiceConfig} from '../service.config';
|
||||
import { SystemInfo } from '../service/interface';
|
||||
import { Project } from './project';
|
||||
|
||||
describe('ProjectPolicyConfigComponent', () => {
|
||||
|
||||
let systemInfoService: SystemInfoService;
|
||||
let projectPolicyService: ProjectService;
|
||||
|
||||
let spySystemInfo: jasmine.Spy;
|
||||
let spyProjectPolicies: jasmine.Spy;
|
||||
|
||||
let mockSystemInfo: SystemInfo[] = [
|
||||
{
|
||||
'with_clair': true,
|
||||
'with_notary': true,
|
||||
'with_admiral': false,
|
||||
'admiral_endpoint': 'NA',
|
||||
'auth_mode': 'db_auth',
|
||||
'registry_url': '10.112.122.56',
|
||||
'project_creation_restriction': 'everyone',
|
||||
'self_registration': true,
|
||||
'has_ca_root': false,
|
||||
'harbor_version': 'v1.1.1-rc1-160-g565110d'
|
||||
},
|
||||
{
|
||||
'with_clair': false,
|
||||
'with_notary': false,
|
||||
'with_admiral': false,
|
||||
'admiral_endpoint': 'NA',
|
||||
'auth_mode': 'db_auth',
|
||||
'registry_url': '10.112.122.56',
|
||||
'project_creation_restriction': 'everyone',
|
||||
'self_registration': true,
|
||||
'has_ca_root': false,
|
||||
'harbor_version': 'v1.1.1-rc1-160-g565110d'
|
||||
}
|
||||
];
|
||||
|
||||
let mockPorjectPolicies: Project[] | any[] = [
|
||||
{
|
||||
'project_id': 1,
|
||||
'owner_id': 1,
|
||||
'name': 'library',
|
||||
'creation_time': '2017-11-03T02:37:24Z',
|
||||
'update_time': '2017-11-03T02:37:24Z',
|
||||
'deleted': 0,
|
||||
'owner_name': '',
|
||||
'togglable': false,
|
||||
'current_user_role_id': 0,
|
||||
'repo_count': 0,
|
||||
'metadata': {
|
||||
'public': 'true'
|
||||
}
|
||||
},
|
||||
{
|
||||
'project_id': 2,
|
||||
'owner_id': 1,
|
||||
'name': 'test',
|
||||
'creation_time': '2017-11-03T02:37:24Z',
|
||||
'update_time': '2017-11-03T02:37:24Z',
|
||||
'deleted': 0,
|
||||
'owner_name': '',
|
||||
'togglable': false,
|
||||
'current_user_role_id': 0,
|
||||
'repo_count': 0,
|
||||
'metadata': {
|
||||
'auto_scan': 'true',
|
||||
'enable_content_trust': 'true',
|
||||
'prevent_vul': 'true',
|
||||
'public': 'true',
|
||||
'severity': 'low'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
let component: ProjectPolicyConfigComponent;
|
||||
let fixture: ComponentFixture<ProjectPolicyConfigComponent>;
|
||||
|
||||
let config: IServiceConfig = {
|
||||
projectPolicyEndpoint: '/api/projects/testing/:id/'
|
||||
projectPolicyEndpoint: '/api/projects/testing',
|
||||
systemInfoEndpoint: '/api/systeminfo/testing',
|
||||
};
|
||||
|
||||
beforeEach(async(() => {
|
||||
@ -25,7 +101,8 @@ describe('ProjectPolicyConfigComponent', () => {
|
||||
providers: [
|
||||
ErrorHandler,
|
||||
{ provide: SERVICE_CONFIG, useValue: config },
|
||||
{ provide: ProjectService, useClass: ProjectDefaultService }
|
||||
{ provide: ProjectService, useClass: ProjectDefaultService },
|
||||
{ provide: SystemInfoService, useClass: SystemInfoDefaultService}
|
||||
]
|
||||
})
|
||||
.compileComponents();
|
||||
@ -36,6 +113,13 @@ describe('ProjectPolicyConfigComponent', () => {
|
||||
component = fixture.componentInstance;
|
||||
component.projectId = 1;
|
||||
component.hasProjectAdminRole = true;
|
||||
|
||||
systemInfoService = fixture.debugElement.injector.get(SystemInfoService);
|
||||
projectPolicyService = fixture.debugElement.injector.get(ProjectService);
|
||||
|
||||
spySystemInfo = spyOn(systemInfoService, 'getSystemInfo').and.returnValues(Promise.resolve(mockSystemInfo[0]));
|
||||
spyProjectPolicies = spyOn(projectPolicyService, 'getProject').and.returnValues(Promise.resolve(mockPorjectPolicies[0]));
|
||||
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
|
@ -14,19 +14,20 @@ import { ConfirmationAcknowledgement } from '../confirmation-dialog/confirmation
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
|
||||
import { Project } from './project';
|
||||
import {SystemInfo, SystemInfoService} from '../service/index';
|
||||
|
||||
export class ProjectPolicy {
|
||||
Public: boolean;
|
||||
ContentTrust: boolean;
|
||||
PreventVulImg: boolean;
|
||||
PreventVulImgServerity: string;
|
||||
PreventVulImgSeverity: string;
|
||||
ScanImgOnPush: boolean;
|
||||
|
||||
constructor() {
|
||||
this.Public = false;
|
||||
this.ContentTrust = false;
|
||||
this.PreventVulImg = false;
|
||||
this.PreventVulImgServerity = 'low';
|
||||
this.PreventVulImgSeverity = 'low';
|
||||
this.ScanImgOnPush = false;
|
||||
}
|
||||
|
||||
@ -34,7 +35,7 @@ export class ProjectPolicy {
|
||||
this.Public = pro.metadata.public === 'true' ? true : false;
|
||||
this.ContentTrust = pro.metadata.enable_content_trust === 'true' ? true : false;
|
||||
this.PreventVulImg = pro.metadata.prevent_vul === 'true' ? true : false;
|
||||
if (pro.metadata.severity) { this.PreventVulImgServerity = pro.metadata.severity; };
|
||||
if (pro.metadata.severity) { this.PreventVulImgSeverity = pro.metadata.severity; };
|
||||
this.ScanImgOnPush = pro.metadata.auto_scan === 'true' ? true : false;
|
||||
};
|
||||
}
|
||||
@ -42,7 +43,7 @@ export class ProjectPolicy {
|
||||
@Component({
|
||||
selector: 'hbr-project-policy-config',
|
||||
template: PROJECT_POLICY_CONFIG_TEMPLATE,
|
||||
styles: [PROJECT_POLICY_CONFIG_STYLE]
|
||||
styles: [PROJECT_POLICY_CONFIG_STYLE],
|
||||
})
|
||||
export class ProjectPolicyConfigComponent implements OnInit {
|
||||
onGoing = false;
|
||||
@ -54,6 +55,7 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
|
||||
@ViewChild('cfgConfirmationDialog') confirmationDlg: ConfirmationDialogComponent;
|
||||
|
||||
systemInfo: SystemInfo;
|
||||
orgProjectPolicy = new ProjectPolicy();
|
||||
projectPolicy = new ProjectPolicy();
|
||||
|
||||
@ -68,25 +70,41 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
private errorHandler: ErrorHandler,
|
||||
private translate: TranslateService,
|
||||
private projectService: ProjectService,
|
||||
private systemInfoService: SystemInfoService,
|
||||
) {}
|
||||
|
||||
ngOnInit(): void {
|
||||
// assert if project id exist
|
||||
if (!this.projectId) {
|
||||
this.errorHandler.error('Project ID cannot be unset.');
|
||||
return;
|
||||
}
|
||||
|
||||
// get system info
|
||||
toPromise<SystemInfo>(this.systemInfoService.getSystemInfo())
|
||||
.then(systemInfo => this.systemInfo = systemInfo)
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
|
||||
// retrive project level policy data
|
||||
this.retrieve();
|
||||
}
|
||||
|
||||
public get withNotary(): boolean {
|
||||
return this.systemInfo ? this.systemInfo.with_notary : false;
|
||||
}
|
||||
|
||||
public get withClair(): boolean {
|
||||
return this.systemInfo ? this.systemInfo.with_clair : false;
|
||||
}
|
||||
|
||||
retrieve(state?: State): any {
|
||||
toPromise<Project>(this.projectService.
|
||||
getProject(this.projectId))
|
||||
.then(
|
||||
response => {
|
||||
this.orgProjectPolicy.initByProject(response);
|
||||
this.projectPolicy.initByProject(response);
|
||||
})
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
toPromise<Project>(this.projectService.getProject(this.projectId))
|
||||
.then(
|
||||
response => {
|
||||
this.orgProjectPolicy.initByProject(response);
|
||||
this.projectPolicy.initByProject(response);
|
||||
})
|
||||
.catch(error => this.errorHandler.error(error));
|
||||
}
|
||||
|
||||
updateProjectPolicy(projectId: string|number, pp: ProjectPolicy) {
|
||||
@ -99,7 +117,7 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
|
||||
isValid() {
|
||||
let flag = false;
|
||||
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgServerity)) {
|
||||
if (!this.projectPolicy.PreventVulImg || this.severityOptions.some(x => x.severity === this.projectPolicy.PreventVulImgSeverity)) {
|
||||
flag = true;
|
||||
}
|
||||
return flag;
|
||||
@ -115,18 +133,18 @@ export class ProjectPolicyConfigComponent implements OnInit {
|
||||
}
|
||||
this.onGoing = true;
|
||||
toPromise<any>(this.projectService.updateProjectPolicy(this.projectId, this.projectPolicy))
|
||||
.then(() => {
|
||||
this.onGoing = false;
|
||||
.then(() => {
|
||||
this.onGoing = false;
|
||||
|
||||
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
||||
this.errorHandler.info(res);
|
||||
});
|
||||
this.refresh();
|
||||
})
|
||||
.catch(error => {
|
||||
this.onGoing = false;
|
||||
this.errorHandler.error(error);
|
||||
this.translate.get('CONFIG.SAVE_SUCCESS').subscribe((res: string) => {
|
||||
this.errorHandler.info(res);
|
||||
});
|
||||
this.refresh();
|
||||
})
|
||||
.catch(error => {
|
||||
this.onGoing = false;
|
||||
this.errorHandler.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
cancel(): void {
|
||||
|
@ -2,12 +2,11 @@ export class Project {
|
||||
project_id: number;
|
||||
owner_id: number;
|
||||
name: string;
|
||||
creation_time: Date;
|
||||
creation_time_str: string;
|
||||
creation_time: Date | string;
|
||||
deleted: number;
|
||||
owner_name: string;
|
||||
togglable: boolean;
|
||||
update_time: Date;
|
||||
update_time: Date | string;
|
||||
current_user_role_id: number;
|
||||
repo_count: number;
|
||||
has_project_admin_role: boolean;
|
||||
|
@ -74,7 +74,7 @@ export class ProjectDefaultService extends ProjectService {
|
||||
'public': projectPolicy.Public ? 'true' : 'false',
|
||||
'enable_content_trust': projectPolicy.ContentTrust ? 'true' : 'false',
|
||||
'prevent_vul': projectPolicy.PreventVulImg ? 'true' : 'false',
|
||||
'severity': projectPolicy.PreventVulImgServerity,
|
||||
'severity': projectPolicy.PreventVulImgSeverity,
|
||||
'auto_scan': projectPolicy.ScanImgOnPush ? 'true' : 'false'
|
||||
} }, HTTP_JSON_OPTIONS)
|
||||
.map(response => response.status)
|
||||
|
@ -31,7 +31,7 @@
|
||||
"clarity-icons": "^0.9.8",
|
||||
"clarity-ui": "^0.9.8",
|
||||
"core-js": "^2.4.1",
|
||||
"harbor-ui": "0.5.8",
|
||||
"harbor-ui": "0.5.9",
|
||||
"intl": "^1.2.5",
|
||||
"mutationobserver-shim": "^0.3.2",
|
||||
"ngx-cookie": "^1.0.0",
|
||||
|
@ -33,4 +33,4 @@ services:
|
||||
- /data/secretkey:/etc/adminserver/key
|
||||
- /data/:/data/
|
||||
ports:
|
||||
- 8888:80
|
||||
- 8888:8080
|
||||
|
@ -161,12 +161,13 @@ Do Log Advanced Search
|
||||
#others
|
||||
Click Element xpath=//audit-log//clr-dropdown/button
|
||||
Click Element xpath=//audit-log//clr-dropdown//a[contains(.,"Others")]
|
||||
Sleep 1
|
||||
Click element xpath=//audit-log//hbr-filter//clr-icon
|
||||
Input Text xpath = //audit-log//hbr-filter//input harbor
|
||||
Sleep 1
|
||||
${c} = Get Matching Xpath Count //audit-log//clr-dg-row
|
||||
Should be equal as integers ${c} 0
|
||||
Click Element xpath=//audit-log//hbr-filter//clr-icon
|
||||
Input Text xpath=//audit-log//hbr-filter//input harbor
|
||||
Sleep 1
|
||||
Capture Page Screenshot LogAdvancedSearch2.png
|
||||
${rc} = Get Matching Xpath Count //audit-log//clr-dg-row
|
||||
Should Be Equal As Integers ${rc} 0
|
||||
|
||||
Expand Repo
|
||||
[Arguments] ${projectname}
|
||||
|
@ -1,7 +1,7 @@
|
||||
FROM vmware/mariadb-photon:10.2.8
|
||||
|
||||
RUN tdnf distro-sync || echo \
|
||||
&& tdnf install -y mariadb-devel python2 python2-devel python-pip gcc\
|
||||
RUN tdnf distro-sync -y \
|
||||
&& tdnf install -y mariadb-devel python2 python2-devel python-pip gcc \
|
||||
linux-api-headers glibc-devel binutils zlib-devel openssl-devel \
|
||||
&& pip install mysqlclient alembic \
|
||||
&& tdnf clean all \
|
||||
|
@ -39,6 +39,11 @@ def upgrade():
|
||||
bind = op.get_bind()
|
||||
session = Session(bind=bind)
|
||||
|
||||
# This is to solve the legacy issue when upgrade from 1.2.0rc1 to 1.3.0 refered by #3077
|
||||
username_coloumn = session.execute("show columns from user where field='username'").fetchone()
|
||||
if username_coloumn[1] != 'varchar(255)':
|
||||
op.alter_column('user', 'username', type_=sa.String(255))
|
||||
|
||||
# create table project_metadata
|
||||
ProjectMetadata.__table__.create(bind)
|
||||
|
||||
|
@ -40,7 +40,7 @@ if [[ ( $1 = "up" || $1 = "upgrade" ) && ${SKIP_CONFIRM} != "y" ]]; then
|
||||
fi
|
||||
|
||||
echo 'Trying to start mysql server...'
|
||||
DBRUN=0
|
||||
chown -R 10000:10000 /var/lib/mysql
|
||||
mysqld &
|
||||
for i in {60..0}; do
|
||||
mysqladmin -u$DB_USR -p$DB_PWD processlist >/dev/null 2>&1
|
||||
|