Merge "Adding missing numerica validator util."
diff --git a/src/dockerfiles/compose/docker-compose.yaml b/src/dockerfiles/compose/docker-compose.yaml
index c3cd1db..f639621 100644
--- a/src/dockerfiles/compose/docker-compose.yaml
+++ b/src/dockerfiles/compose/docker-compose.yaml
@@ -144,6 +144,9 @@
depends_on:
- autotest
+ environment:
+ - GOOGLE_APPLICATION_CREDENTIALS=/home/moblab/.service_account.json
+
extra_hosts:
- "dockerhost:192.168.100.1"
diff --git a/src/dockerfiles/db/Dockerfile.db_init b/src/dockerfiles/db/Dockerfile.db_init
index ffa6548..149fd3c 100644
--- a/src/dockerfiles/db/Dockerfile.db_init
+++ b/src/dockerfiles/db/Dockerfile.db_init
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-FROM debian:buster
+FROM debian:buster-slim
COPY init_script.sh /
diff --git a/src/dockerfiles/devserver/Dockerfile b/src/dockerfiles/devserver/Dockerfile
index f1bac81..f59fb9b 100644
--- a/src/dockerfiles/devserver/Dockerfile
+++ b/src/dockerfiles/devserver/Dockerfile
@@ -13,16 +13,24 @@
RUN sed -i 's#python2#python3#g' /devserver-src/dev-util/devserver.py
######################################################################
-FROM debian:buster as run
+FROM debian:buster-slim as run
COPY --from=source /devserver-src /devserver-src
COPY --from=source /chromite /chromite
# Install packages
RUN apt-get update && apt-get install --no-install-recommends -yq \
- curl python3 sudo gcc python-dev procps \
- bzip2 unzip sudo ca-certificates python3-distutils python3-dev \
- openssh-server
+ bzip2 \
+ ca-certificates \
+ curl \
+ gcc \
+ openssh-server \
+ python-dev procps \
+ python3 \
+ python3-dev \
+ python3-distutils \
+ sudo \
+ unzip
RUN mkdir /run/sshd
RUN mkdir -p /config/.ssh/
@@ -45,6 +53,9 @@
RUN python -m pip install setuptools
RUN python /setup_chromite.py install
+RUN apt purge -yq gcc
+RUN apt-get clean
+
# Devserver requires an apache server to be running for a good health check
# this is a fake apache script that just sleeps forever.
# TODO remove requirement from devserver to need an apache process.
@@ -74,8 +85,6 @@
quick-provision/quick-provision \
/static_files_to_serve
-
-
EXPOSE 8080
## Add moblab user
diff --git a/src/dockerfiles/offloader/Dockerfile b/src/dockerfiles/offloader/Dockerfile
index c970a07..e1736cd 100644
--- a/src/dockerfiles/offloader/Dockerfile
+++ b/src/dockerfiles/offloader/Dockerfile
@@ -1,15 +1,22 @@
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+ARG REGISTRY_URI
+
+######################################################################
+
+FROM ${REGISTRY_URI}/protoc:haddowk3 as protoc
+
+######################################################################
FROM python:3.8-buster as proto_build
WORKDIR /
-RUN wget https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip
-RUN unzip protoc-3.10.0-linux-x86_64.zip
-RUN cp bin/protoc /usr/local/bin
+COPY --from=protoc /protoc/* /usr/local/bin
COPY third_party/autotest/tko/tko.proto /usr/local/autotest/tko/tko.proto
-RUN protoc --proto_path /usr/local/autotest/tko --python_out=/usr/local/autotest/tko /usr/local/autotest/tko/tko.proto
+RUN protoc --proto_path /usr/local/autotest/tko \
+ --python_out=/usr/local/autotest/tko \
+ /usr/local/autotest/tko/tko.proto
####################################################################
@@ -17,7 +24,8 @@
WORKDIR /
-RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 --disabled-password --gecos "" moblab
+RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 \
+ --disabled-password --gecos "" moblab
RUN apt-get update && apt-get install -yq sudo
RUN echo "moblab ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
RUN usermod -aG sudo moblab
diff --git a/src/dockerfiles/rpcserver/Dockerfile b/src/dockerfiles/rpcserver/Dockerfile
index 43a97f9..2bd0fae 100644
--- a/src/dockerfiles/rpcserver/Dockerfile
+++ b/src/dockerfiles/rpcserver/Dockerfile
@@ -2,34 +2,22 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-#############
-### build ###
-#############
+ARG ${REGISTRY_URI}
-# base image
+######################################################################
+
+FROM gcr.io/chromeos-partner-moblab/protoc:haddowk3 as protoc
+
+######################################################################
+
FROM python:3.8-buster as build
RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 \
--disabled-password --gecos "" moblab
-
-# install protoc
-ENV PROTOBUF_URL https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip
-RUN curl -L -o /tmp/protobuf.zip $PROTOBUF_URL
-WORKDIR /tmp/
-RUN unzip protobuf.zip
-RUN cp bin/protoc /usr/local/bin
-
-# install grpc_python_plugin
-RUN git clone https://github.com/grpc/grpc.git
-WORKDIR /tmp/grpc
-RUN git submodule update --init
-RUN make grpc_python_plugin
-RUN cp /tmp/grpc/bins/opt/grpc_python_plugin /usr/local/bin
-
-# set working directory
WORKDIR /etc/moblab/moblab-rpcserver
+COPY --from=protoc /protoc/* /usr/local/bin/
COPY src/moblab-rpcserver/ /etc/moblab/moblab-rpcserver
RUN protoc -I=/etc/moblab/moblab-rpcserver \
--python_out=:/etc/moblab/moblab-rpcserver \
@@ -37,18 +25,22 @@
--plugin=protoc-gen-grpc_python=/usr/local/bin/grpc_python_plugin \
moblabrpc.proto
-############
-### prod ###
-############
+######################################################################
-# base image
-FROM python:3-buster
+FROM python:3-slim-buster
RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 \
--disabled-password --gecos "" moblab
-# copy artifact build from the 'build environment'
-COPY --chown=moblab --from=build /etc/moblab/moblab-rpcserver /etc/moblab/moblab-rpcserver
-RUN apt-get update && apt-get install -yq unzip cmake libssl-dev fping
+
+COPY --chown=moblab --from=build /etc/moblab/moblab-rpcserver \
+ /etc/moblab/moblab-rpcserver
+RUN apt-get update && apt-get install -yq \
+ cmake \
+ curl \
+ fping \
+ libssl-dev \
+ unzip \
+ zlib1g-dev
COPY --chown=moblab src/dockerfiles/rpcserver/requirements.txt ./
RUN pip install --upgrade pip
@@ -57,18 +49,16 @@
# moblab_common
COPY --chown=moblab ./src/moblab_common /moblab/src/moblab_common
COPY --chown=moblab ./src/tools /moblab/src/tools
-COPY --chown=moblab ./src/dockerfiles /moblab/src/dockerfiles
COPY --chown=moblab ./src/host_services /moblab/src/host_services
COPY --chown=moblab ./setup.py /moblab/
WORKDIR /moblab
-RUN python ./setup.py install
+RUN python -m pip install .
+
+RUN rm -rf /moblab
RUN mkdir /var/log/moblab
-RUN apt purge -yq unzip cmake libssl-dev
-RUN apt-get clean
-
# Installs Moblab API client library
WORKDIR /tmp/moblab_api_client_library
RUN curl https://storage.googleapis.com/moblab-api-distribution/google-chromeos-moblab.tar.gz -o google-chromeos-moblab.tar.gz
@@ -76,6 +66,9 @@
RUN python -m pip install .
RUN rm -rf /tmp/moblab_api_client_library
+RUN apt purge -yq unzip cmake libssl-dev zlib1g-dev curl
+RUN apt-get clean
+
WORKDIR /moblab
USER moblab
diff --git a/src/dockerfiles/servod/Dockerfile b/src/dockerfiles/servod/Dockerfile
index d4df2cf..99e17b3 100644
--- a/src/dockerfiles/servod/Dockerfile
+++ b/src/dockerfiles/servod/Dockerfile
@@ -6,12 +6,25 @@
RUN apt update
-RUN apt install -y wget python-pexpect python-numpy python-setuptools python-serial python-pytest tidy libftdi-dev curl gcc make pkg-config libudev-dev usbutils
+RUN apt-get update && apt-get install --no-install-recommends -yq \
+ curl \
+ gcc \
+ libftdi-dev \
+ libudev-dev \
+ make \
+ pkg-config \
+ python-numpy \
+ python-pexpect \
+ python-pytest \
+ python-serial \
+ python-setuptools \
+ tidy \
+ usbutils \
+ wget
RUN wget https://github.com/libusb/libusb/releases/download/v1.0.23/libusb-1.0.23.tar.bz2
RUN tar xvf libusb-1.0.23.tar.bz2
WORKDIR /libusb-1.0.23
-
RUN ./configure && make && make install
RUN export LD_LIBRARY_PATH=/usr/local/lib
diff --git a/src/dockerfiles/ssp/Dockerfile b/src/dockerfiles/ssp/Dockerfile
index 2a6d7bb..2282cde 100644
--- a/src/dockerfiles/ssp/Dockerfile
+++ b/src/dockerfiles/ssp/Dockerfile
@@ -8,19 +8,26 @@
RUN git clone https://chromium.googlesource.com/chromiumos/chromite
-
###############################################################################
-FROM debian:buster as run
+FROM debian:buster-slim as run
WORKDIR /
COPY --from=source /chromite /chromite
-# Install packages
RUN apt-get update && apt-get install --no-install-recommends -yq \
- bzip2 wget curl python unzip rsync gnupg lsb-release \
- ca-certificates ssh sudo
+ bzip2 \
+ ca-certificates \
+ curl \
+ gnupg \
+ lsb-release \
+ python \
+ rsync \
+ ssh \
+ sudo \
+ unzip \
+ wget
# Install the google cloud sdk
RUN echo \
diff --git a/src/dockerfiles/ui/Dockerfile b/src/dockerfiles/ui/Dockerfile
index 44ab3f4..c2224c7 100644
--- a/src/dockerfiles/ui/Dockerfile
+++ b/src/dockerfiles/ui/Dockerfile
@@ -1,58 +1,51 @@
# Copyright 2019 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-#############
-### build ###
-#############
+ARG REGISTRY_URI=gcr.io/chromeos-partner-moblab
+ARG LABEL=release
+######################################################################
-# base image
+FROM ${REGISTRY_URI}/protoc:${LABEL} as protoc
+
+######################################################################
+
FROM node:12 as build
# install chrome for protractor tests
-RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
-RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
-RUN apt-get update && apt-get install -yq google-chrome-stable
+# RUN wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -
+# RUN sh -c 'echo "deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main" >> /etc/apt/sources.list.d/google.list'
+# RUN apt-get update && apt-get install -yq google-chrome-stable
-# install protoc
-RUN apt-get install -yq unzip
-ENV PROTOBUF_URL https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip
-RUN curl -L -o /tmp/protobuf.zip $PROTOBUF_URL
-WORKDIR /tmp/
-RUN unzip protobuf.zip
-RUN cp bin/protoc /usr/local/bin
-
-RUN curl -L -o /usr/local/bin/protoc-gen-grpc-web https://github.com/grpc/grpc-web/releases/download/1.0.7/protoc-gen-grpc-web-1.0.7-linux-x86_64
-RUN chmod uog+x /usr/local/bin/protoc-gen-grpc-web
-
-# set working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
-
# install and cache app dependencies
# add app
COPY ./moblab-ui /app
COPY ./moblab-rpcserver/moblabrpc.proto /app
+
+COPY --from=protoc /protoc/* /usr/local/bin/
+RUN protoc -I=/app --js_out=import_style=commonjs:/app/src/app/services \
+ --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:/app/src/app/services \
+ /app/moblabrpc.proto
+
RUN npm install
-RUN protoc -I=/app --js_out=import_style=commonjs:/app/src/app/services --grpc-web_out=import_style=commonjs+dts,mode=grpcwebtext:/app/src/app/services /app/moblabrpc.proto
# run tests
#RUN ng test --watch=false
#RUN ng e2e --port 4202
-# generate build
RUN ng build --output-path=dist
-############
-### prod ###
-############
+######################################################################
# base image
FROM nginx:alpine
-RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 --disabled-password --gecos "" moblab
+RUN addgroup --gid 246 moblab && adduser --ingroup moblab --uid 246 \
+ --disabled-password --gecos "" moblab
# copy artifact build from the 'build environment'
COPY --chown=moblab --from=build /app/dist /etc/nginx/html/
diff --git a/src/dockerfiles/utilities/Dockerfile.protoc b/src/dockerfiles/utilities/Dockerfile.protoc
new file mode 100644
index 0000000..27cd117
--- /dev/null
+++ b/src/dockerfiles/utilities/Dockerfile.protoc
@@ -0,0 +1,39 @@
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+FROM debian:buster-slim as download
+
+RUN apt-get update && apt-get install --no-install-recommends -yq \
+ ca-certificates \
+ curl \
+ dh-autoreconf \
+ g++ \
+ gcc \
+ git \
+ make \
+ unzip
+
+WORKDIR /
+RUN curl -L -o protobuf.zip https://github.com/protocolbuffers/protobuf/releases/download/v3.10.0/protoc-3.10.0-linux-x86_64.zip
+RUN unzip protobuf.zip
+
+RUN curl -L -o /usr/local/bin/protoc-gen-grpc-web https://github.com/grpc/grpc-web/releases/download/1.0.7/protoc-gen-grpc-web-1.0.7-linux-x86_64
+RUN chmod uog+x /usr/local/bin/protoc-gen-grpc-web
+
+# install grpc_python_plugin
+RUN git clone https://github.com/grpc/grpc.git
+WORKDIR /grpc
+RUN git submodule update --init
+RUN make grpc_python_plugin
+
+##############################################################################
+FROM debian:buster-slim
+
+RUN mkdir -p /protoc
+COPY --from=download bin/protoc /protoc
+COPY --from=download /usr/local/bin/protoc-gen-grpc-web /protoc
+COPY --from=download /grpc/bins/opt/grpc_python_plugin /protoc
+
+
+
diff --git a/src/moblab-rpcserver/__init__.py b/src/moblab-rpcserver/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/moblab-rpcserver/__init__.py
diff --git a/src/moblab-rpcserver/moblab_build_connector.py b/src/moblab-rpcserver/moblab_build_connector.py
new file mode 100644
index 0000000..f853845
--- /dev/null
+++ b/src/moblab-rpcserver/moblab_build_connector.py
@@ -0,0 +1,168 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""
+Interface for the Moblab RPC server to access build resources by using Moblab
+API.
+"""
+
+import logging
+
+import google.api_core.path_template
+
+from google.auth import exceptions as auth_exceptions
+from google.chromeos.moblab_v1beta1.services.build_service.client import \
+ BuildServiceClient
+from google.chromeos.moblab_v1beta1.types import build_service
+from google.protobuf import field_mask_pb2 as field_mask # type: ignore
+
+
+class MoblabBuildConnectorException(Exception):
+ """Generic exception for this module."""
+ pass
+
+
+class MoblabBuildConnector(object):
+ """
+ Class that provides RPC server an interface to access build resources by
+ using Moblab API.
+ """
+
+ @classmethod
+ def model_path(cls, build_target, model):
+ """Return a fully-qualified model string."""
+ return google.api_core.path_template.expand(
+ 'buildTargets/{build_target}/models/{model}',
+ build_target=build_target,
+ model=model,
+ )
+
+ @classmethod
+ def build_artifact_path(cls, build_target, model, build, artifact):
+ """Return a fully-qualified build_artifact string."""
+ return google.api_core.path_template.expand(
+ 'buildTargets/{build_target}/models/{model}/builds/{build}/artifacts/{artifact}',
+ build_target=build_target,
+ model=model,
+ build=build,
+ artifact=artifact,
+ )
+
+ def __init__(self, build_service_client=None):
+ """Instantiates the build connector and sets up the build service
+ client. The service account is set in the global environment.
+ """
+ try:
+ self.build_service_client = build_service_client if \
+ build_service_client is not None else BuildServiceClient()
+ except auth_exceptions.DefaultCredentialsError as e:
+ raise MoblabBuildConnectorException('No credentials loaded')
+
+ def list_available_milestones(self, build_target, model, page_size=50,
+ page_token=None):
+ """Lists the available milestones for the given build target and model.
+
+ Args:
+ build_target (str): Build target name.
+ model (str): Model name. For non-unibuilds, set the model name as
+ the same as build target name.
+ page_size (int): The number of milestones to return in the response.
+ The default size is 50.
+ page_token (str): A page token, received from a previous
+ ``ListBuilds`` call. Provide this to retrieve the subsequent
+ page.
+
+ Returns:
+ build_service.ListBuildsResponse: Response message for listing
+ builds with milestones.
+ """
+ milestone_field = field_mask.FieldMask(paths=["milestone"])
+ request = build_service.ListBuildsRequest(
+ parent=self.model_path(build_target, model),
+ page_size=page_size,
+ page_token=page_token,
+ read_mask=milestone_field,
+ group_by=milestone_field
+ )
+ return self.build_service_client.list_builds(request)
+
+ def list_builds_for_milestone(self, build_target, model, milestone,
+ page_size=50, page_token=None):
+ """Lists the builds for the given build target, model and milestone.
+
+ Args:
+ build_target (str): The build target name.
+ model (str): The model name. For non-unibuilds, set the model name as
+ the same as build target name.
+ milestone (int): The milestone number.
+ page_size (int): The number of milestones to return in the response.
+ The default size is 50.
+ page_token (str): The page token, received from a previous
+ ``ListBuilds`` call. Provide this to retrieve the subsequent
+ page.
+
+ Returns:
+ build_service.ListBuildsResponse: Response message for listing
+ builds.
+ """
+ milestone_filter = "milestone=milestones/" + str(milestone)
+ request = build_service.ListBuildsRequest(
+ parent=self.model_path(build_target, model),
+ page_size=page_size,
+ page_token=page_token,
+ filter=milestone_filter
+ )
+ return self.build_service_client.list_builds(request)
+
+ def check_build_stage_status(self, build_target, model, build, bucket_name):
+ """Checks the stage status for a given build artifact in a partner
+ Google Cloud Storage bucket.
+
+ Args:
+ build_target (str): The build target name.
+ model (str): The model name. For non-unibuilds, set the model name as
+ the same as build target name.
+ build (str): The build version.
+ bucket_name: The destination bucket name .
+
+ Returns:
+ build_service.CheckBuildStageStatusResponse: Response message for
+ check the stage status of a build artifact.
+ """
+ request = build_service.CheckBuildStageStatusRequest(
+ name=self.build_artifact_path(build_target, model, build,
+ bucket_name)
+ )
+ return self.build_service_client.check_build_stage_status(request)
+
+ def stage_build(self, build_target, model, build, bucket_name):
+ # TODO(zhihuixie): Long running operation cannot returned correctly in
+ # the python client library.
+ """Stages a given build artifact from a internal Google Cloud Storage
+ bucket to a partner Google Cloud Storage bucket. The stage will be
+ skipped if all the objects in the partner bucket are the same as in the
+ internal bucket.
+
+ Args:
+ build_target (str): The build target name.
+ model (str): The model name. For non-unibuilds, set the model name as
+ the same as build target name.
+ build (str): The build version.
+ bucket_name: The destination bucket name .
+
+ Returns:
+ operation.Operation:
+ An object representing a long-running operation. The result
+ type for the operation will be
+ ``build_service.StageBuildResponse``: Response
+ message for staging a build artifact.
+ """
+ request = build_service.StageBuildRequest(
+ name=self.build_artifact_path(build_target, model, build,
+ bucket_name)
+ )
+ return self.build_service_client.stage_build(request)
+
+if __name__ == '__main__':
+ connector = MoblabBuildConnector()
\ No newline at end of file
diff --git a/src/moblab-rpcserver/moblab_build_connector_unittest.py b/src/moblab-rpcserver/moblab_build_connector_unittest.py
new file mode 100644
index 0000000..3e2afbb
--- /dev/null
+++ b/src/moblab-rpcserver/moblab_build_connector_unittest.py
@@ -0,0 +1,106 @@
+# -*- coding: utf-8 -*-
+# Copyright 2020 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+"""Unit tests for the moblab_build_connector"""
+
+import unittest
+from unittest import mock
+
+from moblab_build_connector import MoblabBuildConnector
+
+from google.chromeos.moblab_v1beta1.types import build_service
+from google.chromeos.moblab_v1beta1.types import resources
+
+
+class MoblabBuildConnectorTest(unittest.TestCase):
+ """Testing the MoblabBuildConnector code."""
+
+ BUILD_TARGET = 'octopus'
+ MODEL = 'bobba'
+ MILESTONE = 80
+ BUILD_VERSION = '1234.5.6'
+ SOURCE_BUCKET = 'source_bucket'
+ DESTINATION_BUCKET = 'destination bucket'
+
+ def setUp(self):
+ self.mock_build_service_client = mock.MagicMock()
+ self.moblab_build_connector = MoblabBuildConnector(
+ self.mock_build_service_client)
+
+ def test_list_available_milestones(self):
+ build = resources.Build(
+ name=MoblabBuildConnector.model_path(self.BUILD_TARGET, self.MODEL),
+ milestone=str(self.MILESTONE))
+ expect = self.mock_build_service_client.list_builds.return_value = \
+ build_service.ListBuildsResponse(
+ builds=[build],
+ next_page_token='next_page_token_value',
+ total_size=1,
+ )
+
+ response = self.moblab_build_connector.list_available_milestones(
+ self.BUILD_TARGET, self.MODEL)
+
+ self.assertEqual(response.builds, expect.builds)
+ self.mock_build_service_client.list_builds.assert_called_once()
+
+ def test_list_builds_for_milestone(self):
+ build = resources.Build(
+ name=MoblabBuildConnector.model_path(self.BUILD_TARGET, self.MODEL),
+ milestone=str(self.MILESTONE),
+ build_version=self.BUILD_VERSION)
+ expect = self.mock_build_service_client.list_builds.return_value = \
+ build_service.ListBuildsResponse(
+ builds=[build],
+ next_page_token='next_page_token_value',
+ total_size=1,
+ )
+
+ response = self.moblab_build_connector.list_builds_for_milestone(
+ self.BUILD_TARGET, self.MODEL, self.MILESTONE)
+
+ self.assertEqual(response.builds, expect.builds)
+ self.mock_build_service_client.list_builds.assert_called_once()
+
+ def test_check_build_stage_status(self):
+ staged_build_artifact = resources.BuildArtifact(
+ bucket=self.DESTINATION_BUCKET
+ )
+ source_build_artifact = resources.BuildArtifact(
+ bucket=self.SOURCE_BUCKET)
+ expect = self.mock_build_service_client.check_build_stage_status.return_value = \
+ build_service.CheckBuildStageStatusResponse(
+ is_build_staged=True,
+ staged_build_artifact=staged_build_artifact,
+ source_build_artifact=source_build_artifact
+ )
+
+ response = self.moblab_build_connector.check_build_stage_status(
+ self.BUILD_TARGET, self.MODEL, self.BUILD_VERSION,
+ self.DESTINATION_BUCKET)
+
+ self.assertEqual(response.staged_build_artifact,
+ expect.staged_build_artifact)
+ self.mock_build_service_client.check_build_stage_status.assert_called_once()
+
+ def test_stage_build(self):
+ staged_build_artifact = resources.BuildArtifact(
+ bucket=self.DESTINATION_BUCKET
+ )
+ expect = self.mock_build_service_client.stage_build.return_value = \
+ build_service.StageBuildResponse(
+ staged_build_artifact=staged_build_artifact
+ )
+
+ response = self.moblab_build_connector.stage_build(
+ self.BUILD_TARGET, self.MODEL, self.BUILD_VERSION,
+ self.DESTINATION_BUCKET)
+
+ self.assertEqual(response.staged_build_artifact,
+ expect.staged_build_artifact)
+ self.mock_build_service_client.stage_build.assert_called_once()
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/src/moblab-ui/src/app/app-routing.module.ts b/src/moblab-ui/src/app/app-routing.module.ts
index 347789f..c9a5687 100644
--- a/src/moblab-ui/src/app/app-routing.module.ts
+++ b/src/moblab-ui/src/app/app-routing.module.ts
@@ -17,7 +17,7 @@
{path: 'job_detail', component: JobDetailComponent},
{path: 'job_detail/:job_id', component: JobDetailComponent},
{path: 'dut_detail', component: DutDetailComponent},
- {path: 'dut_detail/:dut_ip', component: DutDetailComponent},
+ {path: 'dut_detail/:dut_hostname', component: DutDetailComponent},
{
path: 'run_tests',
component: RunSuiteComponent,
diff --git a/src/moblab-ui/src/app/dut-detail/dut-detail.component.html b/src/moblab-ui/src/app/dut-detail/dut-detail.component.html
index e6222d1..ecc4229 100644
--- a/src/moblab-ui/src/app/dut-detail/dut-detail.component.html
+++ b/src/moblab-ui/src/app/dut-detail/dut-detail.component.html
@@ -50,6 +50,7 @@
</mat-expansion-panel-header>
<app-view-jobs
manualPopulate=true
+ hideActionBar=true
hideFilters=false
hideSelectors=true
pageSizeOverride=10>
diff --git a/src/moblab-ui/src/app/dut-detail/dut-detail.component.ts b/src/moblab-ui/src/app/dut-detail/dut-detail.component.ts
index 26522cd..78325a0 100644
--- a/src/moblab-ui/src/app/dut-detail/dut-detail.component.ts
+++ b/src/moblab-ui/src/app/dut-detail/dut-detail.component.ts
@@ -28,9 +28,19 @@
constructor(
private readonly moblabGrpcService: MoblabGrpcService,
+ private route: ActivatedRoute,
private snackBar: MatSnackBar
) {}
+ ngOnInit() {
+ this.route.paramMap.subscribe(params => {
+ this.dutQuery.setValue(params.get('dut_hostname'));
+ if (this.dutQuery.value) {
+ this.fetchDutDetails();
+ }
+ });
+ }
+
setDutDetails(dutInfo: ConnectedDutInfo) {
this.dutInfoTableRef.loadRows(
[
diff --git a/src/moblab-ui/src/app/job-detail/job-detail.component.html b/src/moblab-ui/src/app/job-detail/job-detail.component.html
index 11fce7e..657de35 100644
--- a/src/moblab-ui/src/app/job-detail/job-detail.component.html
+++ b/src/moblab-ui/src/app/job-detail/job-detail.component.html
@@ -113,6 +113,7 @@
</mat-expansion-panel-header>
<app-view-jobs
manualPopulate=true
+ hideActionBar=true
hideFilters=true
hideSelectors=true>
</app-view-jobs>