[eager-package-config] Move eager package configs into their own crate.

Both bin/omaha-client and bin/pkg-resolver have their own eager package
config; these configs are similar but specialized, but both come from
the same source, a build script.

Moving these structs into their own visible lib/eager-package-config
crate is necessary for later use in that build script.

Bug: 103263
Change-Id: I3b4053596654ec23caa8584e326e5b11ce3a5503
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/693804
Reviewed-by: Aaron Wood <aaronwood@google.com>
Reviewed-by: Sen Jiang <senj@google.com>
Commit-Queue: James Buckland <jbuckland@google.com>
diff --git a/src/lib/syslog/rust/log_visibility.gni b/src/lib/syslog/rust/log_visibility.gni
index 555a79c..8f75b7e 100644
--- a/src/lib/syslog/rust/log_visibility.gni
+++ b/src/lib/syslog/rust/log_visibility.gni
@@ -203,6 +203,7 @@
   "//src/sys/lib/runner:*",
   "//src/sys/lib/stress-test:*",
   "//src/sys/pkg/bin/omaha-client:*",
+  "//src/sys/pkg/lib/eager-package-config:*",
   "//src/sys/pkg/lib/fidl-fuchsia-update-installer-ext:*",
   "//src/sys/pkg/lib/isolated-swd:*",
   "//src/sys/pkg/lib/omaha-client:*",
diff --git a/src/sys/pkg/bin/omaha-client/BUILD.gn b/src/sys/pkg/bin/omaha-client/BUILD.gn
index e9daa40..2d99b97 100644
--- a/src/sys/pkg/bin/omaha-client/BUILD.gn
+++ b/src/sys/pkg/bin/omaha-client/BUILD.gn
@@ -54,6 +54,7 @@
     "//src/sys/pkg/fidl/fuchsia.update.installer:fuchsia.update.installer-rustc",
     "//src/sys/pkg/lib/bounded-node",
     "//src/sys/pkg/lib/channel-config",
+    "//src/sys/pkg/lib/eager-package-config",
     "//src/sys/pkg/lib/event-queue",
     "//src/sys/pkg/lib/fidl-fuchsia-update-ext",
     "//src/sys/pkg/lib/fidl-fuchsia-update-installer-ext",
@@ -66,6 +67,8 @@
     "//third_party/rust_crates:futures",
     "//third_party/rust_crates:hyper",
     "//third_party/rust_crates:hyper-rustls",
+
+    # TODO(https://fxbug.dev/103361): Migrate this crate away from log.
     "//third_party/rust_crates:log",
     "//third_party/rust_crates:rand",
     "//third_party/rust_crates:serde",
@@ -90,7 +93,6 @@
     "src/channel.rs",
     "src/cobalt.rs",
     "src/configuration.rs",
-    "src/eager_package_config.rs",
     "src/feedback_annotation.rs",
     "src/fidl.rs",
     "src/http_request.rs",
diff --git a/src/sys/pkg/bin/omaha-client/src/configuration.rs b/src/sys/pkg/bin/omaha-client/src/configuration.rs
index a0fe8fe..8c48d46 100644
--- a/src/sys/pkg/bin/omaha-client/src/configuration.rs
+++ b/src/sys/pkg/bin/omaha-client/src/configuration.rs
@@ -2,12 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use crate::{
-    app_set::{EagerPackage, FuchsiaAppSet},
-    eager_package_config::{EagerPackageConfig, EagerPackageConfigs},
-};
+use crate::app_set::{EagerPackage, FuchsiaAppSet};
 use anyhow::{anyhow, Error};
 use channel_config::{ChannelConfig, ChannelConfigs};
+use eager_package_config::omaha_client::{EagerPackageConfig, EagerPackageConfigs};
 use fidl_fuchsia_boot::{ArgumentsMarker, ArgumentsProxy};
 use fidl_fuchsia_pkg::{self as fpkg, CupMarker, CupProxy, GetInfoError};
 use log::{error, info, warn};
@@ -326,7 +324,7 @@
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::eager_package_config::{EagerPackageConfig, OmahaServer};
+    use eager_package_config::omaha_client::{EagerPackageConfig, OmahaServer};
     use fidl::endpoints::create_proxy_and_stream;
     use fidl_fuchsia_boot::ArgumentsRequest;
     use fidl_fuchsia_pkg::CupRequest;
diff --git a/src/sys/pkg/bin/omaha-client/src/main.rs b/src/sys/pkg/bin/omaha-client/src/main.rs
index cdf7f53..2e939cb 100644
--- a/src/sys/pkg/bin/omaha-client/src/main.rs
+++ b/src/sys/pkg/bin/omaha-client/src/main.rs
@@ -19,7 +19,6 @@
 mod channel;
 mod cobalt;
 mod configuration;
-mod eager_package_config;
 mod feedback_annotation;
 mod fidl;
 mod http_request;
diff --git a/src/sys/pkg/bin/pkg-resolver/BUILD.gn b/src/sys/pkg/bin/pkg-resolver/BUILD.gn
index bd0dba4..ad77dc3 100644
--- a/src/sys/pkg/bin/pkg-resolver/BUILD.gn
+++ b/src/sys/pkg/bin/pkg-resolver/BUILD.gn
@@ -42,6 +42,7 @@
     "//src/sys/lib/fidl-fuchsia-pkg-rewrite-ext",
     "//src/sys/lib/fuchsia_backoff",
     "//src/sys/pkg/lib/async-generator",
+    "//src/sys/pkg/lib/eager-package-config",
     "//src/sys/pkg/lib/fuchsia-pkg",
     "//src/sys/pkg/lib/metrics:cobalt_sw_delivery_registry_rustlib",
     "//src/sys/pkg/lib/omaha-client",
diff --git a/src/sys/pkg/bin/pkg-resolver/src/eager_package_manager.rs b/src/sys/pkg/bin/pkg-resolver/src/eager_package_manager.rs
index e2508c3..2f9b543 100644
--- a/src/sys/pkg/bin/pkg-resolver/src/eager_package_manager.rs
+++ b/src/sys/pkg/bin/pkg-resolver/src/eager_package_manager.rs
@@ -6,6 +6,7 @@
     crate::resolver_service::Resolver,
     anyhow::{anyhow, Context as _, Error},
     async_lock::RwLock as AsyncRwLock,
+    eager_package_config::pkg_resolver::{EagerPackageConfig, EagerPackageConfigs},
     fidl_fuchsia_io as fio,
     fidl_fuchsia_pkg::{self as fpkg, CupRequest, CupRequestStream, GetInfoError, WriteError},
     fidl_fuchsia_pkg_ext::{cache, BlobInfo, CupData, CupMissingField},
@@ -20,11 +21,9 @@
         protocol::response::Response,
     },
     p256::ecdsa::{signature::Signature, DerSignature},
-    serde::Deserialize,
     std::{collections::BTreeMap, convert::TryInto, sync::Arc},
 };
 
-const EAGER_PACKAGE_CONFIG_PATH: &str = "/config/data/eager_package_config.json";
 const EAGER_PACKAGE_PERSISTENT_FIDL_NAME: &str = "eager_packages.pf";
 
 #[derive(Clone, Debug)]
@@ -417,43 +416,6 @@
     }
 }
 
-#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
-struct EagerPackageConfigs {
-    packages: Vec<EagerPackageConfig>,
-}
-
-#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
-struct EagerPackageConfig {
-    url: UnpinnedAbsolutePackageUrl,
-    #[serde(default)]
-    executable: bool,
-    public_keys: PublicKeys,
-}
-
-impl EagerPackageConfigs {
-    /// Read eager config from namespace. Returns an empty instance of `EagerPackageConfigs` in
-    /// case config was not found.
-    async fn from_namespace() -> Result<Self, Error> {
-        match fuchsia_fs::file::read_in_namespace(EAGER_PACKAGE_CONFIG_PATH).await {
-            Ok(json) => Ok(serde_json::from_slice(&json).context("parsing eager package config")?),
-            Err(e) => match e.into_inner() {
-                fuchsia_fs::file::ReadError::Open(fuchsia_fs::node::OpenError::OpenError(
-                    status,
-                ))
-                | fuchsia_fs::file::ReadError::Fidl(fidl::Error::ClientChannelClosed {
-                    status,
-                    ..
-                }) if status == zx::Status::NOT_FOUND => {
-                    Ok(EagerPackageConfigs { packages: Vec::new() })
-                }
-                err => Err(err).with_context(|| {
-                    format!("Error reading eager package config file {EAGER_PACKAGE_CONFIG_PATH}")
-                }),
-            },
-        }
-    }
-}
-
 pub async fn run_cup_service<T: Resolver>(
     manager: Arc<Option<AsyncRwLock<EagerPackageManager<T>>>>,
     mut stream: CupRequestStream,
diff --git a/src/sys/pkg/lib/BUILD.gn b/src/sys/pkg/lib/BUILD.gn
index 392f642..fa9c120 100644
--- a/src/sys/pkg/lib/BUILD.gn
+++ b/src/sys/pkg/lib/BUILD.gn
@@ -9,6 +9,7 @@
     "blobfs",
     "bounded-node",
     "channel-config",
+    "eager-package-config",
     "epoch",
     "event-queue",
     "far:lib",
@@ -38,6 +39,7 @@
     "blobfs:tests",
     "bounded-node:tests",
     "channel-config:tests",
+    "eager-package-config:tests",
     "epoch:tests",
     "event-queue:tests",
     "far:tests",
diff --git a/src/sys/pkg/lib/eager-package-config/BUILD.gn b/src/sys/pkg/lib/eager-package-config/BUILD.gn
new file mode 100644
index 0000000..73e3824
--- /dev/null
+++ b/src/sys/pkg/lib/eager-package-config/BUILD.gn
@@ -0,0 +1,46 @@
+# Copyright 2022 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//build/components.gni")
+import("//build/rust/rustc_library.gni")
+
+rustc_library("eager-package-config") {
+  version = "0.0.1"
+  edition = "2021"
+  with_unit_tests = true
+
+  deps = [
+    "//src/lib/fidl/rust/fidl",
+    "//src/lib/fuchsia-fs",
+    "//src/lib/fuchsia-url",
+    "//src/lib/zircon/rust:fuchsia-zircon",
+    "//src/sys/pkg/lib/channel-config",
+    "//src/sys/pkg/lib/fuchsia-pkg",
+    "//src/sys/pkg/lib/omaha-client",
+    "//third_party/rust_crates:anyhow",
+    "//third_party/rust_crates:log",
+    "//third_party/rust_crates:serde",
+    "//third_party/rust_crates:serde_json",
+  ]
+
+  test_deps = [
+    "//third_party/rust_crates:assert_matches",
+    "//third_party/rust_crates:pretty_assertions",
+  ]
+
+  sources = [
+    "src/lib.rs",
+    "src/omaha_client.rs",
+    "src/pkg_resolver.rs",
+  ]
+}
+
+fuchsia_unittest_package("eager-package-config-lib-tests") {
+  deps = [ ":eager-package-config_test" ]
+}
+
+group("tests") {
+  testonly = true
+  deps = [ ":eager-package-config-lib-tests" ]
+}
diff --git a/src/sys/pkg/lib/eager-package-config/OWNERS b/src/sys/pkg/lib/eager-package-config/OWNERS
new file mode 100644
index 0000000..5812a78
--- /dev/null
+++ b/src/sys/pkg/lib/eager-package-config/OWNERS
@@ -0,0 +1,4 @@
+senj@google.com
+jbuckland@google.com
+
+# COMPONENT: Packages
diff --git a/src/sys/pkg/lib/eager-package-config/README.md b/src/sys/pkg/lib/eager-package-config/README.md
new file mode 100644
index 0000000..0f1546d
--- /dev/null
+++ b/src/sys/pkg/lib/eager-package-config/README.md
@@ -0,0 +1,6 @@
+# Eager package configs
+
+Updated: 2022-06
+
+This crate contains structs and associated methods for reading and parsing eager
+package configs for both bin/omaha-client and bin/pkg-resolver.
diff --git a/src/sys/pkg/lib/eager-package-config/src/lib.rs b/src/sys/pkg/lib/eager-package-config/src/lib.rs
new file mode 100644
index 0000000..c762e28
--- /dev/null
+++ b/src/sys/pkg/lib/eager-package-config/src/lib.rs
@@ -0,0 +1,6 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+pub mod omaha_client;
+pub mod pkg_resolver;
diff --git a/src/sys/pkg/bin/omaha-client/src/eager_package_config.rs b/src/sys/pkg/lib/eager-package-config/src/omaha_client.rs
similarity index 98%
rename from src/sys/pkg/bin/omaha-client/src/eager_package_config.rs
rename to src/sys/pkg/lib/eager-package-config/src/omaha_client.rs
index a14cb58..b2a6d7a 100644
--- a/src/sys/pkg/bin/omaha-client/src/eager_package_config.rs
+++ b/src/sys/pkg/lib/eager-package-config/src/omaha_client.rs
@@ -31,7 +31,7 @@
 }
 
 #[derive(Clone, Debug, PartialEq, Eq, Deserialize)]
-struct EagerPackageConfigsJson {
+pub struct EagerPackageConfigsJson {
     pub eager_package_configs: Vec<EagerPackageConfigs>,
 }
 
diff --git a/src/sys/pkg/lib/eager-package-config/src/pkg_resolver.rs b/src/sys/pkg/lib/eager-package-config/src/pkg_resolver.rs
new file mode 100644
index 0000000..a36cf5f
--- /dev/null
+++ b/src/sys/pkg/lib/eager-package-config/src/pkg_resolver.rs
@@ -0,0 +1,50 @@
+// Copyright 2022 The Fuchsia Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+use {
+    anyhow::{Context as _, Error},
+    fuchsia_url::UnpinnedAbsolutePackageUrl,
+    fuchsia_zircon as zx,
+    omaha_client::cup_ecdsa::PublicKeys,
+    serde::Deserialize,
+};
+
+const EAGER_PACKAGE_CONFIG_PATH: &str = "/config/data/eager_package_config.json";
+
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
+pub struct EagerPackageConfigs {
+    pub packages: Vec<EagerPackageConfig>,
+}
+
+#[derive(Clone, Debug, Deserialize, PartialEq, Eq)]
+pub struct EagerPackageConfig {
+    pub url: UnpinnedAbsolutePackageUrl,
+    #[serde(default)]
+    pub executable: bool,
+    pub public_keys: PublicKeys,
+}
+
+impl EagerPackageConfigs {
+    /// Read eager config from namespace. Returns an empty instance of `EagerPackageConfigs` in
+    /// case config was not found.
+    pub async fn from_namespace() -> Result<Self, Error> {
+        match fuchsia_fs::file::read_in_namespace(EAGER_PACKAGE_CONFIG_PATH).await {
+            Ok(json) => Ok(serde_json::from_slice(&json).context("parsing eager package config")?),
+            Err(e) => match e.into_inner() {
+                fuchsia_fs::file::ReadError::Open(fuchsia_fs::node::OpenError::OpenError(
+                    status,
+                ))
+                | fuchsia_fs::file::ReadError::Fidl(fidl::Error::ClientChannelClosed {
+                    status,
+                    ..
+                }) if status == zx::Status::NOT_FOUND => {
+                    Ok(EagerPackageConfigs { packages: Vec::new() })
+                }
+                err => Err(err).with_context(|| {
+                    format!("Error reading eager package config file {EAGER_PACKAGE_CONFIG_PATH}")
+                }),
+            },
+        }
+    }
+}