public override async Task <Tfplugin5.PrepareProviderConfig.Types.Response> PrepareProviderConfig( Tfplugin5.PrepareProviderConfig.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(PrepareProviderConfig)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { var response = new Tfplugin5.PrepareProviderConfig.Types.Response(); // Default prepared config to incoming config response.PreparedConfig = request.Config; var plugin = SchemaHelper.GetPluginDetails(PluginAssembly); _ProviderInstance = DynamicValue.Unmarshal(plugin.Provider, request.Config); if (typeof(IHasPrepareProviderConfig).IsAssignableFrom(plugin.Provider)) { var invokeInput = new PrepareProviderConfigInput(); var invokeResult = (_ProviderInstance as IHasPrepareProviderConfig).PrepareConfig(invokeInput); if (invokeResult == null) { throw new Exception("invocation result returned null"); } var diagnostics = invokeResult.Diagnostics; if (diagnostics.Count() > 0) { response.Diagnostics.Add(diagnostics.All()); } response.PreparedConfig = DynamicValue.Marshal(plugin.Provider, _ProviderInstance); } _log.LogTrace("<-result = {@response}", response); return(await Task.FromResult(response)); } catch (Exception ex) { _log.LogError(ex, "<!exception = "); throw; } }
public override async Task <Tfplugin5.ImportResourceState.Types.Response> ImportResourceState( Tfplugin5.ImportResourceState.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(ImportResourceState)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { var response = new Tfplugin5.ImportResourceState.Types.Response(); var plugin = SchemaHelper.GetPluginDetails(PluginAssembly); var resType = plugin.Resources.Where(x => request.TypeName == x.GetCustomAttribute <TFResourceAttribute>()?.Name).First(); var invokeType = typeof(IHasImportResourceState <>).MakeGenericType(resType); if (invokeType.IsAssignableFrom(plugin.Provider)) { var invokeInputType = typeof(ImportResourceStateInput <>).MakeGenericType(resType); var invokeResultType = typeof(ImportResourceStateResult <>).MakeGenericType(resType); // Construct and populate the input type instance from the request var invokeInput = Activator.CreateInstance(invokeInputType); invokeInputType.GetProperty(nameof(request.Id)).SetValue(invokeInput, request.Id); // Invoke the functional method var invokeMethod = invokeType.GetMethod(nameof(IHasImportResourceState <object> .ImportResource)); var invokeResult = invokeMethod.Invoke(_ProviderInstance, new[] { invokeInput }); if (invokeResult == null) { throw new Exception("invocation result returned null"); } if (!invokeResultType.IsAssignableFrom(invokeResult.GetType())) { throw new Exception("invocation result not of expected type or subclass"); } // Deconstruct the result to response type var diagnostics = ((TFDiagnostics)invokeResultType.GetProperty(nameof(response.Diagnostics)) .GetValue(invokeResult)); if (diagnostics.Count() > 0) { response.Diagnostics.Add(diagnostics.All()); } var importedEnum = invokeResultType.GetProperty(nameof(response.ImportedResources)) .GetValue(invokeResult); if (importedEnum != null) { var importedType = typeof(ImportedResourceState <>).MakeGenericType(resType); var privateProp = importedType.GetProperty(nameof(ImportedResource.Private)); var stateProp = importedType.GetProperty(nameof(ImportedResource.State)); var importedResult = new List <ImportedResource>(); foreach (var imported in ((System.Collections.IEnumerable)importedEnum)) { importedResult.Add(new ImportedResource { // We assume the outgoing is the same as incoming TypeName = request.TypeName, // Convert over private and schema-defined state Private = ByteString.CopyFrom((byte[])privateProp.GetValue(imported)), State = DynamicValue.Marshal(resType, stateProp.GetValue(imported)), }); } response.ImportedResources.Add(importedResult); } } _log.LogTrace("<-result = {@response}", response); return(await Task.FromResult(response)); } catch (Exception ex) { _log.LogError(ex, "<!exception = "); throw; } }
public override async Task <Tfplugin5.PlanResourceChange.Types.Response> PlanResourceChange( Tfplugin5.PlanResourceChange.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(PlanResourceChange)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { var response = new Tfplugin5.PlanResourceChange.Types.Response(); var plugin = SchemaHelper.GetPluginDetails(PluginAssembly); var resType = plugin.Resources.Where(x => request.TypeName == x.GetCustomAttribute <TFResourceAttribute>()?.Name).First(); var invokeType = typeof(IHasPlanResourceChange <>).MakeGenericType(resType); if (invokeType.IsAssignableFrom(plugin.Provider)) { var invokeInputType = typeof(PlanResourceChangeInput <>).MakeGenericType(resType); var invokeResultType = typeof(PlanResourceChangeResult <>).MakeGenericType(resType); // Construct and populate the input type instance from the request var invokeInput = Activator.CreateInstance(invokeInputType); var config = DynamicValue.Unmarshal(resType, request.Config); var priorState = DynamicValue.Unmarshal(resType, request.PriorState); var priorPrivate = request.PriorPrivate.ToByteArray(); var proposedNewState = DynamicValue.Unmarshal(resType, request.ProposedNewState); var changeType = ResourceChangeType.Unknown; if (priorState != null) { if (config == null) { changeType = ResourceChangeType.Delete; } else { changeType = ResourceChangeType.Update; } } else if (config != null) { changeType = ResourceChangeType.Create; } else { _log.LogWarning("Planning NULL -> NULL : You Should Never See This!"); } _log.LogDebug("Planning " + changeType.ToString().ToUpper()); invokeInputType.GetProperty(nameof(PlanResourceChangeInput <object> .ChangeType)) .SetValue(invokeInput, changeType); invokeInputType.GetProperty(nameof(request.Config)) .SetValue(invokeInput, config); invokeInputType.GetProperty(nameof(request.PriorState)) .SetValue(invokeInput, priorState); invokeInputType.GetProperty(nameof(request.PriorPrivate)) .SetValue(invokeInput, priorPrivate); invokeInputType.GetProperty(nameof(request.ProposedNewState)) .SetValue(invokeInput, proposedNewState); // Invoke the functional method var invokeMethod = invokeType.GetMethod(nameof(IHasPlanResourceChange <object> .PlanChange)); var invokeResult = invokeMethod.Invoke(_ProviderInstance, new[] { invokeInput }); if (invokeResult == null) { throw new Exception("invocation result returned null"); } if (!invokeResultType.IsAssignableFrom(invokeResult.GetType())) { throw new Exception("invocation result not of expected type or subclass"); } // Deconstruct the result to response type var diagnostics = ((TFDiagnostics)invokeResultType .GetProperty(nameof(response.Diagnostics)).GetValue(invokeResult)); var plannedPrivate = invokeResultType .GetProperty(nameof(response.PlannedPrivate)).GetValue(invokeResult); var plannedState = invokeResultType .GetProperty(nameof(response.PlannedState)).GetValue(invokeResult); var requiresReplace = invokeResultType .GetProperty(nameof(response.RequiresReplace)).GetValue(invokeResult); if (diagnostics.Count() > 0) { response.Diagnostics.Add(diagnostics.All()); } if (plannedPrivate != null) { response.PlannedPrivate = ByteString.CopyFrom((byte[])plannedPrivate); } if (plannedState != null) { response.PlannedState = DynamicValue.Marshal(resType, plannedState); } if (requiresReplace != null) { // Translates our internal representation of ValuePath to AttributePath var paths = (IEnumerable <TFSteps>)requiresReplace; response.RequiresReplace.Add(TFAttributePaths.ToPaths(paths)); } } _log.LogTrace("<-result = {@response}", response); return(await Task.FromResult(response)); } catch (Exception ex) { _log.LogError(ex, "<!exception = "); throw; } }
public override async Task <Tfplugin5.ReadResource.Types.Response> ReadResource( Tfplugin5.ReadResource.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(ReadResource)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { var response = new Tfplugin5.ReadResource.Types.Response(); var plugin = SchemaHelper.GetPluginDetails(PluginAssembly); var resType = plugin.Resources.Where(x => request.TypeName == x.GetCustomAttribute <TFResourceAttribute>()?.Name).First(); var invokeType = typeof(IHasReadResource <>).MakeGenericType(resType); if (invokeType.IsAssignableFrom(plugin.Provider)) { var invokeInputType = typeof(ReadResourceInput <>).MakeGenericType(resType); var invokeResultType = typeof(ReadResourceResult <>).MakeGenericType(resType); // Construct and populate the input type instance from the request var invokeInput = Activator.CreateInstance(invokeInputType); invokeInputType.GetProperty(nameof(request.CurrentState)).SetValue(invokeInput, DynamicValue.Unmarshal(resType, request.CurrentState)); // Invoke the functional method var invokeMethod = invokeType.GetMethod(nameof(IHasReadResource <object> .Read)); var invokeResult = invokeMethod.Invoke(_ProviderInstance, new[] { invokeInput }); if (invokeResult == null) { throw new Exception("invocation result returned null"); } if (!invokeResultType.IsAssignableFrom(invokeResult.GetType())) { throw new Exception("invocation result not of expected type or subclass"); } // Deconstruct the result to response type var diagnostics = ((TFDiagnostics)invokeResultType.GetProperty(nameof(response.Diagnostics)) .GetValue(invokeResult)); if (diagnostics.Count() > 0) { response.Diagnostics.Add(diagnostics.All()); } var newState = invokeResultType.GetProperty(nameof(response.NewState)) .GetValue(invokeResult); if (newState != null) { response.NewState = DynamicValue.Marshal(resType, newState); } } _log.LogTrace("<-result = {@response}", response); return(await Task.FromResult(response)); } catch (Exception ex) { _log.LogError(ex, "<!exception = "); throw; } }