Skip to content
This repository was archived by the owner on Nov 24, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/ciab.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ on:
- 'misc/**'
- 'NOTICE'
- 'traffic_control/java/**'
- 'traffic_portal/**.spec.js'
- 'cache-config/testing/**'
- 'traffic_ops/testing/**'
- 'dev/**'
Expand Down Expand Up @@ -78,6 +79,7 @@ on:
- 'misc/**'
- 'NOTICE'
- 'traffic_control/java/**'
- 'traffic_portal/**.spec.js'
- 'cache-config/testing/**'
- 'traffic_ops/testing/**'
- 'dev/**'
Expand Down
44 changes: 40 additions & 4 deletions .github/workflows/tp.integration.tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@
# specific language governing permissions and limitations
# under the License.

name: TP Integration Tests
name: TP Tests

env:
# alpine:3.13
ALPINE_VERSION: sha256:08d6ca16c60fe7490c03d10dc339d9fd8ea67c6466dea8d558526b1330a85930
NODE_VERSION: 16

on:
push:
Expand All @@ -46,7 +47,42 @@ on:
types: [ opened, reopened, ready_for_review, synchronize ]

jobs:
TP_Integration_tests:
unit-tests:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3

- name: Cache node modules
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-modules-${{ hashFiles('traffic_portal/package-lock.json traffic_portal/test/integration/package-lock.json') }}

- name: Node ${{ env.NODE_VERSION }}
uses: actions/setup-node@v3
with:
node-version: ${{ env.NODE_VERSION }}.x

- name: Install latest Chrome
run: sudo apt-get update && sudo apt-get install google-chrome-stable

- name: NPM install
if: steps.restore-npm-cache.cache-hit != 'true'
working-directory: traffic_portal
run: npm ci

- name: Build Traffic Portal
working-directory: traffic_portal
run: npm run build

- name: Unit tests
working-directory: traffic_portal
run: npm run test:ci

integration-tests:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
services:
Expand Down Expand Up @@ -92,14 +128,14 @@ jobs:
- name: Checkout
uses: actions/checkout@master
- name: Cache Alpine Docker image
uses: actions/cache@v2
uses: actions/cache@v3
Comment thread
ocket8888 marked this conversation as resolved.
with:
path: ${{ github.workspace }}/docker-images
key: docker-images/alpine@${{ env.ALPINE_VERSION }}.tar.gz
- name: Import cached Alpine Docker image
run: .github/actions/save-alpine-tar/entrypoint.sh load ${{ env.ALPINE_VERSION }}
- name: Cache node modules
uses: actions/cache@v2
uses: actions/cache@v3
with:
path: ~/.npm
key: ${{ runner.os }}-node-modules-${{ hashFiles('traffic_portal/package-lock.json traffic_portal/test/integration/package-lock.json') }}
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/).
- [#7097](https://github.com/apache/trafficcontrol/issues/7097) *Traffic Ops, Traffic Portal, Traffic Control Cache Config (t3c)* Added the `regional` field to Delivery Services, which affects whether `maxOriginConnections` should be per Cache Group
- [#2388](https://github.com/apache/trafficcontrol/issues/2388) *Trafic Ops, Traffic Portal* Added the `TTLOverride` field to CDNs, which lets you override all TTLs in all Delivery Services of a CDN's snapshot with a single value
- [#7176](https://github.com/apache/trafficcontrol/pull/7176) *ATC Build system* Support building ATC for the `aarch64` CPU architecture
- [#7113](https://github.com/apache/trafficcontrol/pull/7113) *Traffic Portal* Minimize the Server Server Capability part of the *Traffic Servers* section of the Snapshot Diff

### Changed
- [#2564](https://github.com/apache/trafficcontrol/issues/2564) *Traffic Ops, Traffic Monitor* Renamed RASCAL references to TRAFFIC_MONITOR
Expand Down
33 changes: 33 additions & 0 deletions traffic_portal/app/src/common/service/utils/CollectionUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,39 @@

var CollectionUtils = function() {

// minimizeArrayDiff reduces the size of an index-sensitive Array diff by
// making common elements in the old and new arrays have the same index.
this.minimizeArrayDiff = function (oldItems, newItems) {
const minimalDiffItems = [];
const addedItems = [];

let newItemsIndex, newItem;
const oldItemsIterator = oldItems.entries();
const newItemsIterator = newItems.entries();
for (let oldItemsNext = oldItemsIterator.next(), newItemsNext = newItemsIterator.next(); !(oldItemsNext.done || newItemsNext.done);) {
const [, oldItem] = oldItemsNext.value;
[newItemsIndex, newItem] = newItemsNext.value;
if (oldItem < newItem) {
newItemsIndex--;
minimalDiffItems.push(undefined);
oldItemsNext = oldItemsIterator.next();
continue;
} else if (oldItem > newItem) {
addedItems.push(newItem);
newItemsNext = newItemsIterator.next();
continue;
}
minimalDiffItems.push(newItem);
oldItemsNext = oldItemsIterator.next();
newItemsNext = newItemsIterator.next();
}
minimalDiffItems.push(...addedItems);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fyi, there's a builtin for just concatenating two arrays without doing a spread operation into a push: Array.prototype.concat.

if (newItemsIndex !== undefined && newItemsIndex < newItems.length - 1) {
minimalDiffItems.push(...newItems.slice(newItemsIndex + 1));
}
return minimalDiffItems;
};

this.uniqArray = function(array1, array2, key) {
array1 = array1 || [];
array2 = array2 || [];
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

describe("CollectionUtils tests", function () {
describe("minimizeArrayDiff tests", function () {

let minimizeArrayDiff;
beforeEach(angular.mock.module("trafficPortal.utils"));
beforeEach(inject(function () {
const $injector = angular.injector(["trafficPortal.utils"]);
minimizeArrayDiff = $injector.get("collectionUtils").minimizeArrayDiff;
}));

it("pads removed capabilities with undefined", async function () {
let oldCapabilities = ["cap1"];
let newCapabilities = ["cap2"];
let expected = [undefined, "cap2"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(expected);

oldCapabilities = ["cap1", "cap2", "cap3"];
newCapabilities = ["cap1", "cap3"];
expected = ["cap1", undefined, "cap3"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(expected);

oldCapabilities = ["cap1", "cap2", "cap3"];
newCapabilities = ["cap1", "cap2"];
expected = ["cap1", "cap2"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(expected);
});

it("appends prepended capabilities", async function () {
let oldCapabilities = ["cap2"];
let newCapabilities = ["cap1", "cap2"];
let expected = ["cap2", "cap1"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(expected);
});

it("appends added capabilities", async function () {
let oldCapabilities = ["cap1"];
let newCapabilities = ["cap1", "cap2"];
let expected = ["cap1", "cap2"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(expected);
});

it("leaves equal capabilities arrays untouched", async function () {
let oldCapabilities = ["cap1", "cap2"];
let newCapabilities = ["cap1", "cap2"];
expect(minimizeArrayDiff(oldCapabilities, newCapabilities)).toEqual(newCapabilities);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
* under the License.
*/

let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $state, $uibModal, locationUtils, cdnService, propertiesModel) {
let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $state, $uibModal, locationUtils, collectionUtils, cdnService, propertiesModel) {

const oldConfig = currentSnapshot.config,
newConfig = newSnapshot.config;
Expand Down Expand Up @@ -72,6 +72,34 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta
$scope[destination + "Changes"] = diff;
};

function minimizeServerCapabilitiesDiff(oldTrafficServers, newTrafficServers) {
if (!(oldTrafficServers instanceof Object) || !(newTrafficServers instanceof Object)) {
return;
}
const oldServersIterator = Object.entries(oldTrafficServers).entries();
const newServersIterator = Object.entries(newTrafficServers).entries();
const capabilitiesKey = "capabilities";
for (let oldServersNext = oldServersIterator.next(), newServersNext = newServersIterator.next(); !(oldServersNext.done || newServersNext.done);) {
const [, [oldHostname, oldServer]] = oldServersNext.value;
const [, [newHostname, newServer]] = newServersNext.value;
if (oldHostname < newHostname) {
oldServersNext = oldServersIterator.next();
continue;
} else if (oldHostname > newHostname) {
newServersNext = newServersIterator.next();
continue;
}
const oldCapabilities = oldServer[capabilitiesKey];
const newCapabilities = newServer[capabilitiesKey];
if (oldCapabilities instanceof Object && newCapabilities instanceof Object) {
newServer[capabilitiesKey] = collectionUtils.minimizeArrayDiff(oldCapabilities, newCapabilities);
}
oldServersNext = oldServersIterator.next();
newServersNext = newServersIterator.next();
}

}

let snapshot = function () {
cdnService.snapshot(cdn);
};
Expand Down Expand Up @@ -196,6 +224,7 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta
performDiff(oldConfig, newConfig, 'config');
performDiff(oldTrafficRouters, newTrafficRouters, 'contentRouters');
performDiff(oldTrafficMonitors, newTrafficMonitors, 'monitors');
minimizeServerCapabilitiesDiff(oldTrafficServers, newTrafficServers);
performDiff(oldTrafficServers, newTrafficServers, 'contentServers');
performDiff(oldDeliveryServices, newDeliveryServices, 'deliveryServices');
performDiff(oldEdgeCacheGroups, newEdgeCacheGroups, 'edgeLocations');
Expand All @@ -207,5 +236,5 @@ let ConfigController = function (cdn, currentSnapshot, newSnapshot, $scope, $sta

};

ConfigController.$inject = ['cdn', 'currentSnapshot', 'newSnapshot', '$scope', '$state', '$uibModal', 'locationUtils', 'cdnService', 'propertiesModel'];
ConfigController.$inject = ['cdn', 'currentSnapshot', 'newSnapshot', '$scope', '$state', '$uibModal', 'locationUtils', 'collectionUtils', 'cdnService', 'propertiesModel'];
module.exports = ConfigController;
64 changes: 64 additions & 0 deletions traffic_portal/karma.conf.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/

// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
config.set({
basePath: "",
files: [
"app/dist/public/resources/assets/js/shared-libs.js",
"app/dist/public/resources/assets/js/ag-grid-community/**/*.js",
"node_modules/angular-mocks/angular-mocks.js",
"app/dist/public/resources/assets/js/config.js",
"app/dist/public/resources/assets/js/app.js",
"app/src/**/*.spec.js",
],
frameworks: ["jasmine"],
plugins: [
require("karma-jasmine"),
require("karma-chrome-launcher"),
require("karma-jasmine-html-reporter"),
require("karma-coverage"),
],
client: {
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
coverageReporter: {
dir: require("path").join(__dirname, "./coverage/traffic-portal"),
reports: [{type: "html"}, {type: "text-summary"}],
subdir: ".",
},
reporters: ["progress", "kjhtml"],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ["Chrome"],
singleRun: false,
restartOnFileChange: true,
customLaunchers: {
ChromeHeadlessCustom: {
base: "ChromeHeadless",
flags: ["--no-sandbox", "--disable-gpu"],
},
},
});
};
Loading