Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redirect #409

Merged
merged 53 commits into from
Aug 5, 2022
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
74a72bd
IoT COnfig redirect
grafnu Aug 3, 2022
9c978e5
Reset device config
grafnu Aug 3, 2022
358e73c
Style checks
grafnu Aug 3, 2022
129633a
Adding apt-get utils
grafnu Aug 3, 2022
9f05ac5
Adding needs clause
grafnu Aug 3, 2022
713a0c3
Fix compiile
grafnu Aug 3, 2022
c1b2b0e
Disable reconfig
grafnu Aug 3, 2022
dd8e1c8
Linty fixes
grafnu Aug 3, 2022
c4f400a
Reflector tweaking
grafnu Aug 3, 2022
9e63742
Working reflector
grafnu Aug 3, 2022
37cd4f8
Adding reflector to test
grafnu Aug 4, 2022
4fd8d38
Adding reset_config
grafnu Aug 4, 2022
9765b3d
Add reflector
grafnu Aug 4, 2022
15c897a
Add REFLECTOR mutual exclusion
grafnu Aug 4, 2022
39f44f5
Basics for extended test
grafnu Aug 4, 2022
7447fcb
Disable redirect
grafnu Aug 4, 2022
215b631
Review tweaks
grafnu Aug 4, 2022
35514b1
Add spongs check
grafnu Aug 4, 2022
c235c8e
Adding {} for all vars
grafnu Aug 4, 2022
f5eed7e
Debugging
grafnu Aug 4, 2022
15733d1
Debugging
grafnu Aug 4, 2022
f66dab4
Diagnostics
grafnu Aug 4, 2022
d095b88
Diagnostics
grafnu Aug 4, 2022
c6f5b32
Dont' die
grafnu Aug 4, 2022
aa4cef8
Remove some debugging
grafnu Aug 4, 2022
2c53812
Merge branch 'reflect' into redirect
grafnu Aug 4, 2022
bea11a5
Adding shared constants file
grafnu Aug 4, 2022
9c8900e
Cleanup
grafnu Aug 4, 2022
03b9ffb
Adding constants
grafnu Aug 4, 2022
3b9db9c
COMMIT to FINAL
grafnu Aug 4, 2022
d49bf30
Adding mergey
grafnu Aug 4, 2022
35073cb
Change order
grafnu Aug 4, 2022
67ef579
Merge branch 'reflect' into redirect
grafnu Aug 4, 2022
ea57cb8
Fixing config redirect
grafnu Aug 4, 2022
8a828a5
Updating test script
grafnu Aug 4, 2022
8e66884
Cleanup debug
grafnu Aug 4, 2022
318f1c1
Cleanup testing scripts
grafnu Aug 4, 2022
02c711c
Merge branch 'master' into redirect
grafnu Aug 5, 2022
a28b396
Merge branch 'master' into redirect
grafnu Aug 5, 2022
1758786
Cleanup timeout error
grafnu Aug 5, 2022
57ed11b
Add missing dep
grafnu Aug 5, 2022
dac16d7
Cleanup output log reporting
grafnu Aug 5, 2022
75d071a
Slight name relabel
grafnu Aug 5, 2022
0ccaf40
Testing
grafnu Aug 5, 2022
99b2fc8
Restore timeout
grafnu Aug 5, 2022
c9852e8
Use redirect registry
grafnu Aug 5, 2022
626313e
Fix reflect update function
grafnu Aug 5, 2022
e7f9f72
Tweak output
grafnu Aug 5, 2022
4985822
Fix target registry
grafnu Aug 5, 2022
619d9cb
Review cleanup
grafnu Aug 5, 2022
9d29a88
Reverting random changes
grafnu Aug 5, 2022
8d62d7f
Revert out/ changes
grafnu Aug 5, 2022
9bd06b2
Reset config before launching pubber
grafnu Aug 5, 2022
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
1 change: 1 addition & 0 deletions .gencode_hash.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ f48026471ae3cd7867bce416dc21c2fb728f48d8476a8d6e95f6acaf1d8b6cf3 gencode/docs/i
43019239edfdad71647c40d254b9b3aec68f3deb0c808ba636530c1cf9985fe0 gencode/docs/state.html
d39d7fe37a41c74a40080af7b0a429d201ab1fdff7444428c4b98eb7b38c332b gencode/java/udmi/schema/Asset.java
0825a5cec83003bb0a6488c4ed7010a04ae0d3848ef36fe01bb4e6718ba7b96d gencode/java/udmi/schema/Aux.java
df118b8e5abebac38579027b5a17192163f0cc97e55a8e44b847b1a965263636 gencode/java/udmi/schema/Blob.java
d5adb804697243f97cdd8589750401654f3fab075a9aeac4f2851e46695ef11d gencode/java/udmi/schema/BlobBlobsetConfig.java
2c03651cb2ecda072b1418222eebb5560185669f8ffdd03021ad5ad8ff7ba3b0 gencode/java/udmi/schema/BlobBlobsetState.java
d2c5b5aae8db27b68104fc83a1f38de0a3f1b5d683f2b13599adf24e96c7d124 gencode/java/udmi/schema/BlobsetConfig.java
Expand Down
14 changes: 10 additions & 4 deletions .github/workflows/testing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,15 @@ jobs:
run: |
# Simple checks that a redirect happened and failed
set +x
fgrep registries/ZZ-TRI-FECTA/devices/GAT-123 pubber.out
fgrep 'system.config.parse success' pubber.out
fgrep registries/missing/devices/GAT-123 pubber.out
fgrep 'Not authorized to connect' pubber.out
fgrep registries/ZZ-TRI-FECTA/devices/GAT-123 pubber.out.1
fgrep 'system.config.parse success' pubber.out.1
fgrep registries/missing/devices/GAT-123 pubber.out.1
fgrep 'Not authorized to connect' pubber.out.1
# Now check the redirect-by-config setup
fgrep registries/ZZ-TRI-FECTA/devices/GAT-123 pubber.out.2
fgrep 'system.config.parse success' pubber.out.2
fgrep registries/reconfigure/devices/GAT-123 pubber.out.2
fgrep 'Not authorized to connect' pubber.out.2
- name: pubber logs
if: ${{ always() }}
run: |
Expand All @@ -78,6 +83,7 @@ jobs:
name: Sequence tests
runs-on: ubuntu-latest
timeout-minutes: 15
needs: redirect # Access to UDMI-REFLECTOR is mutually exclusive
steps:
- uses: actions/checkout@v2
- uses: actions/setup-java@v1
Expand Down
4 changes: 2 additions & 2 deletions bin/gencode_java
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ echo Generating code in $OUTDIR
$JARBIN $JOPTS --source . --target $OUTDIR

# There is no way to specify enum constants in generated code, so just hack it in manually.
echo Copying Level.java
cp -n $ROOT_DIR/etc/Level.java $OUTDIR/udmi/schema/Level.java
echo Copying shared constants $ROOT_DIR/etc/*.java
cp -n $ROOT_DIR/etc/*.java $OUTDIR/udmi/schema/

echo Cleaning up __ classes...
find $OUTDIR -name \*__\*.java | xargs rm
Expand Down
26 changes: 26 additions & 0 deletions bin/reset_config
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash -ex

ROOT=$(realpath $(dirname $0)/..)

if [[ $# != 3 ]]; then
echo Usage: $0 site_dir project_id device_id
false
fi

site_dir=$(realpath $1)
project_id=$2
device_id=$3
shift 3
cd ${ROOT}

pwd

device_config=/tmp/${device_id}_config.json
cp ${site_dir}/devices/${device_id}/out/generated_config.json ${device_config}
now_date=$(python3 -c 'import datetime; print(datetime.datetime.utcnow().isoformat() + "Z")')
echo Setting config timestamp ${now_date}
sponge < /dev/null || echo sponge command not found, might need workaround for osx or other
jq .timestamp=\"${now_date}\" < ${device_config} | sponge ${device_config}

echo Resetting device ${device_id} config...
validator/bin/reflector ${site_dir} ${project_id} ${device_id} update/config:${device_config}
2 changes: 1 addition & 1 deletion bin/setup_base
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/bin/bash

sudo apt-get install -y hxtools
sudo apt-get install -y hxtools moreutils

python3 -m venv venv

Expand Down
15 changes: 12 additions & 3 deletions bin/test_redirect
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,19 @@ if [[ -n $pids ]]; then
kill $pids
fi

echo Writing pubber output to $PUBBER_OUT
bin/reset_config $site_path $project_id $device_id

echo bin/pubber $site_path $project_id $device_id $serial_no

echo Writing pubber output to $PUBBER_OUT.1
result=0
timeout 5m bin/pubber $site_path $project_id $device_id $serial_no redirectRegistry=missing > $PUBBER_OUT 2>&1 || result=$?

timeout 5m bin/pubber $site_path $project_id $device_id $serial_no redirectRegistry=missing > $PUBBER_OUT.1 2>&1 || result=$?
echo Pubber exit code $result

echo Writing pubber output to $PUBBER_OUT.2
bin/pubber $site_path $project_id $device_id $serial_no > $PUBBER_OUT.2 2>&1 &

# Wait for initial connection, then reset config to redirect
sleep 20
bin/reset_config $site_path $project_id $device_id #redirect_config.json
sleep 20
6 changes: 4 additions & 2 deletions bin/test_validator
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Force consistent sort order
export LC_ALL=C

ROOT_DIR=$(dirname $0)/..
ROOT_DIR=$(realpath $(dirname $0)/..)
cd $ROOT_DIR

if [[ $# != 1 ]]; then
Expand Down Expand Up @@ -38,6 +38,8 @@ vpid=$!
sleep 10
echo Started validator pid $vpid

bin/reset_config $site_path $project_id $device_id

pubber/bin/build

echo Writing pubber output to $PUBBER_OUT
Expand Down Expand Up @@ -65,7 +67,7 @@ sleep 30

pids=`ps ax | fgrep pubber | fgrep java | awk '{print $1}'`
echo Killing pids $vpid $pids
kill $vpid $pids
kill $vpid $pids || true

outfiles=`find $site_path/out/devices -name \*.out | sort` || true
if [[ -z $outfiles ]]; then
Expand Down
3 changes: 3 additions & 0 deletions bin/validator
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ fi
echo Building validator...
$ROOT_DIR/validator/bin/build > /dev/null

echo Files built
(cd $ROOT_DIR; find validator/build -type f) || true

echo Running tools version `(cd $ROOT_DIR; git describe)`

if [[ -n $subscription ]]; then
Expand Down
8 changes: 8 additions & 0 deletions etc/Blob.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package udmi.schema;

// This class is manually curated and then copied into the gencode directory. Look for the
// proper source and don't be fooled! These are general constants for blob management.
public abstract class Blob {
public static final String FINAL_PHASE = "final";
public static final String IOT_CONFIG_BLOB = "_iot_config";
}
8 changes: 8 additions & 0 deletions gencode/java/udmi/schema/Blob.java

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pubber/.idea/runConfigurations/Pubber.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

58 changes: 54 additions & 4 deletions pubber/src/main/java/daq/pubber/Pubber.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package daq.pubber;

import static java.util.stream.Collectors.toMap;
import static udmi.schema.Blob.FINAL_PHASE;
import static udmi.schema.Blob.IOT_CONFIG_BLOB;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
Expand Down Expand Up @@ -43,6 +45,7 @@
import org.apache.http.ConnectionClosedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import udmi.schema.BlobBlobsetConfig;
import udmi.schema.CloudModel.Auth_type;
import udmi.schema.Config;
import udmi.schema.DiscoveryConfig;
Expand Down Expand Up @@ -136,6 +139,8 @@ public class Pubber {
private Consumer<String> onDone;
private boolean publishingLog;
private Map<String, Metadata> allMetadata;
private String appliedEndpoint;
private EndpointConfiguration extractedEndpoint;

/**
* Start an instance from a configuration file.
Expand Down Expand Up @@ -486,7 +491,7 @@ private void sendMessages() {
updatePoints();
sendDeviceMessage();
flushDirtyState();
// Some things can't be done from a on-message callback, so do them here instead.
// Some things can't be done from an on-message callback, so do them here instead.
maybeRedirectEndpoint();
} catch (Exception e) {
error("Fatal error during execution", e);
Expand Down Expand Up @@ -576,6 +581,7 @@ private void initializeMqtt() {
}
Preconditions.checkState(mqttPublisher == null, "mqttPublisher already defined");
ensureKeyBytes();
appliedEndpoint = toJson(configuration.endpoint);
mqttPublisher = new MqttPublisher(configuration, this::publisherException);
if (configuration.gatewayId != null) {
mqttPublisher.registerHandler(configuration.gatewayId, CONFIG_TOPIC,
Expand All @@ -587,13 +593,22 @@ private void initializeMqtt() {
this::configHandler, Config.class);
}

private String toJson(Object configuration) {
try {
return OBJECT_MAPPER.writeValueAsString(configuration);
} catch (Exception e) {
throw new RuntimeException("While converting object to string", e);
}
}

private void ensureKeyBytes() {
if (configuration.keyBytes != null) {
return;
}
Preconditions.checkNotNull(configuration.keyFile, "configuration keyFile not defined");
info("Loading device key bytes from " + configuration.keyFile);
configuration.keyBytes = getFileBytes(configuration.keyFile);
configuration.keyFile = null;
}

private String getDeviceKeyPrefix() {
Expand Down Expand Up @@ -705,29 +720,64 @@ private void processConfigUpdate(Config config) {
actualInterval = updateSystemConfig(config.pointset);
updatePointsetConfig(config.pointset);
updateDiscoveryConfig(config.discovery);
extractedEndpoint = extractEndpointBlobConfig();
} else {
info(getTimestamp() + " defaulting empty config");
actualInterval = DEFAULT_REPORT_SEC * 1000;
}
maybeRestartExecutor(actualInterval);
}

private EndpointConfiguration extractEndpointBlobConfig() {
try {
String iotConfig = extractConfigBlob(IOT_CONFIG_BLOB);
if (iotConfig == null) {
return null;
}
return OBJECT_MAPPER.readValue(iotConfig, EndpointConfiguration.class);
} catch (Exception e) {
throw new RuntimeException("While extracting endpoint blob config", e);
}
}

private void maybeRedirectEndpoint() {
String redirectRegistry = configuration.options.redirectRegistry;
if (redirectRegistry == null || redirectRegistry.equals(configuration.endpoint.registryId)
|| configLatch.getCount() > 0) {
if (extractedEndpoint != null && !toJson(extractedEndpoint).equals(appliedEndpoint)) {
info("New config blob endpoint detected");
configuration.endpoint = extractedEndpoint;
} else if (redirectRegistry != null && configLatch.getCount() <= 0
&& !redirectRegistry.equals(configuration.endpoint.registryId)) {
info("Mismatched redirectRegistry detected");
configuration.endpoint.registryId = redirectRegistry;
} else {
return;
}
try {
disconnectMqtt();
configuration.endpoint.registryId = redirectRegistry;
initializeMqtt();
startConnection(onDone);
} catch (Exception e) {
throw new RuntimeException("While redirecting connection endpoint", e);
}
}

private String extractConfigBlob(String blobName) {
try {
if (deviceConfig == null || deviceConfig.blobset == null
|| deviceConfig.blobset.blobs == null) {
return null;
}
BlobBlobsetConfig blobBlobsetConfig = deviceConfig.blobset.blobs.get(blobName);
if (blobBlobsetConfig != null && FINAL_PHASE.equals(blobBlobsetConfig.phase)
&& blobBlobsetConfig.base64 != null) {
return new String(Base64.getDecoder().decode(blobBlobsetConfig.base64));
}
return null;
} catch (Exception e) {
throw new RuntimeException("While extracting config blob " + blobName, e);
}
}

private void updateDiscoveryConfig(DiscoveryConfig discovery) {
DiscoveryConfig discoveryConfig = discovery == null ? new DiscoveryConfig() : discovery;
if (deviceState.discovery == null) {
Expand Down
17 changes: 17 additions & 0 deletions validator/.idea/runConfigurations/Reflector.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion validator/bin/build
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cd $ROOT
echo Building validataor in $PWD

rm -rf build
./gradlew shadow $check
./gradlew --info shadow $check

ls -l build/libs/validator-1.0-SNAPSHOT-all.jar

Expand Down
24 changes: 24 additions & 0 deletions validator/bin/reflector
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#!/bin/bash -e

ROOT=$(realpath $(dirname $0)/../..)

if [[ $# < 4 ]]; then
echo Usage: $0 site_dir project_id device_id directive [directives...]
echo " Directive is something like update/config:sites/udmi_site_model/devices/AHU-1/out/generated_config.json"
false
fi

site_dir=$(realpath $1)
project_id=$2
device_id=$3
shift 3
cd $ROOT

validator/bin/build

jarfile=validator/build/libs/validator-1.0-SNAPSHOT-all.jar
mainclass=com.google.daq.mqtt.validator.Reflector

cmd="java -cp $jarfile $mainclass -p $project_id -s $site_dir -d $device_id $*"
echo $cmd
$cmd
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ public IotReflectorClient(String projectId, CloudIotConfig iotConfig, String key
mqttPublisher = new MqttPublisher(projectId, cloudRegion, UDMS_REFLECT,
siteName, keyBytes, IOT_KEY_ALGORITHM, this::messageHandler, this::errorHandler);
} catch (Exception e) {
throw new RuntimeException("While connecting subscription " + subscriptionId, e);
throw new RuntimeException("While connecting MQTT endpoint " + subscriptionId, e);
}

active = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.google.daq.mqtt.registrar;

import static com.google.daq.mqtt.validator.Validator.NO_SITE;
import static com.google.daq.mqtt.util.Common.NO_SITE;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
Expand All @@ -9,7 +9,6 @@
import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.github.fge.jsonschema.core.load.configuration.LoadingConfiguration;
import com.github.fge.jsonschema.core.load.download.URIDownloader;
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.google.api.services.cloudiot.v1.model.Device;
Expand All @@ -30,7 +29,6 @@
import java.io.FilenameFilter;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.net.URI;
import java.time.Duration;
Expand Down
Loading