sources/Google.Solutions.IapDesktop.Extensions.Session/Settings/ConnectionSettingsRepository.cs (145 lines of code) (raw):

// // Copyright 2020 Google LLC // // 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. // using Google.Solutions.Apis.Locator; using Google.Solutions.Common.Util; using Google.Solutions.IapDesktop.Application.Data; using Google.Solutions.IapDesktop.Application.Profile.Settings; using Google.Solutions.IapDesktop.Core.ObjectModel; using Google.Solutions.Settings; using System; using System.Collections.Generic; using System.Linq; namespace Google.Solutions.IapDesktop.Extensions.Session.Settings { /// <summary> /// Registry-backed repository for connection settings. /// /// To simplify key managent, a flat structure is used: /// /// [base-key] /// + [project-id] => values... /// + region-[region-id] => values... /// + zone-[zone-id] => values... /// + vm-[instance-name] => values... /// /// </summary> [Service] public class ConnectionSettingsRepository { private const string ZonePrefix = "zone-"; private const string VmPrefix = "vm-"; private readonly IProjectSettingsRepository projectRepository; public ConnectionSettingsRepository(IProjectSettingsRepository projectRepository) { this.projectRepository = projectRepository.ExpectNotNull(nameof(projectRepository)); } private ISettingsStore CreateProjectSettingsStore(ProjectLocator project) { var key = this.projectRepository.OpenRegistryKey(project.Name); if (key == null) { throw new KeyNotFoundException(project.Name); } return new RegistrySettingsStore(key); } private ISettingsStore CreateZoneSettingsStore(ZoneLocator zone) { var key = this.projectRepository.OpenRegistryKey( zone.ProjectId, ZonePrefix + zone.Name); // // Return zone settings, applying project settings // as defaults. // return new MergedSettingsStore(new[] { CreateProjectSettingsStore(zone.Project), new RegistrySettingsStore(key) }, MergedSettingsStore.MergeBehavior.Overlay); } private ISettingsStore CreateInstanceSettingsStore(InstanceLocator instance) { var key = this.projectRepository.OpenRegistryKey( instance.ProjectId, VmPrefix + instance.Name); // // Return instance settings, applying zone and // project settings as defaults. // return new MergedSettingsStore(new[] { CreateProjectSettingsStore(instance.Project), CreateZoneSettingsStore(new ZoneLocator(instance.ProjectId, instance.Zone)), new RegistrySettingsStore(key) }, MergedSettingsStore.MergeBehavior.Overlay); } private static void WriteAllSettings( ISettingsStore store, ConnectionSettings settings) { foreach (var setting in settings.Settings.Where(s => s.IsDirty)) { store.Write(setting); } } //--------------------------------------------------------------------- // Projects. //--------------------------------------------------------------------- public ConnectionSettings GetProjectSettings(ProjectLocator project) { using (var store = CreateProjectSettingsStore(project)) { return new ConnectionSettings(project, store); } } public void SetProjectSettings(ConnectionSettings settings) { if (!(settings.Resource is ProjectLocator project)) { throw new ArgumentException(nameof(settings)); } using (var store = CreateProjectSettingsStore(project)) { WriteAllSettings(store, settings); } } //--------------------------------------------------------------------- // Zones. //--------------------------------------------------------------------- public ConnectionSettings GetZoneSettings(ZoneLocator zone) { using (var store = CreateZoneSettingsStore(zone)) { return new ConnectionSettings(zone, store); } } public void SetZoneSettings(ConnectionSettings settings) { if (!(settings.Resource is ZoneLocator zone)) { throw new ArgumentException(nameof(settings)); } using (var store = CreateZoneSettingsStore(zone)) { WriteAllSettings(store, settings); } } //--------------------------------------------------------------------- // Virtual Machines. //--------------------------------------------------------------------- public ConnectionSettings GetInstanceSettings(InstanceLocator instance) { using (var store = CreateInstanceSettingsStore(instance)) { return new ConnectionSettings(instance, store); } } public void SetInstanceSettings(ConnectionSettings settings) { if (!(settings.Resource is InstanceLocator instance)) { throw new ArgumentException(nameof(settings)); } using (var store = CreateInstanceSettingsStore(instance)) { WriteAllSettings(store, settings); } } public ConnectionSettings GetInstanceSettings( IapRdpUrl url, out bool foundInInventory) { // // Populate an ephermeral settings store from the // URL parameters. // using (var urlSettingStore = new IapRdpUrlSettingsStore(url)) { try { // // We have a full set of settings for this VM, so use // that as basis and apply parameters from URL on top. // using (var storedSettingStore = CreateInstanceSettingsStore(url.Instance)) using (var mergedStore = new MergedSettingsStore( new[] { storedSettingStore, urlSettingStore }, MergedSettingsStore.MergeBehavior.Overlay)) { foundInInventory = true; return new ConnectionSettings(url.Instance, mergedStore); } } catch (KeyNotFoundException) { // // Project not found in inventory, all we have is the URL. // foundInInventory = false; return new ConnectionSettings(url.Instance, urlSettingStore); } } } } }