public override Task <Tfplugin5.GetProviderSchema.Types.Response> GetSchema( Tfplugin5.GetProviderSchema.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(GetSchema)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { var response = new Tfplugin5.GetProviderSchema.Types.Response(); response.Provider = SchemaHelper.GetProviderSchema(PluginAssembly); response.DataSourceSchemas.Add(SchemaHelper.GetDataSourceSchemas()); response.ResourceSchemas.Add(SchemaHelper.GetResourceSchemas()); _log.LogTrace("Provider schema: {@schema}", response.Provider); _log.LogTrace("Data Source schemas: ({count})", response.DataSourceSchemas.Count); foreach (var rs in response.DataSourceSchemas) { _log.LogInformation(" * {dsType}={@dsSchema}", rs.Key, rs.Value); } _log.LogTrace("Resource schemas: ({count})", response.ResourceSchemas.Count); foreach (var rs in response.ResourceSchemas) { _log.LogInformation(" * {resType}={@resSchema}", rs.Key, rs.Value); } _log.LogTrace("<-result = {@response}", response); return(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.ValidateResourceTypeConfig.Types.Response> ValidateResourceTypeConfig( Tfplugin5.ValidateResourceTypeConfig.Types.Request request, ServerCallContext context) { _log.LogDebug(">>>{method}>>>", nameof(ValidateResourceTypeConfig)); _log.LogTrace($"->input[{nameof(request)}] = {{@request}}", request); _log.LogTrace($"->input[{nameof(context)}] = {{@context}}", context); try { if (_ProviderInstance == null) { throw new Exception("provider instance was not configured previously"); } var response = new Tfplugin5.ValidateResourceTypeConfig.Types.Response(); // ProviderHelper.ValidateResourceTypeConfig(_providerInstance, request.TypeName, // request.Config, PluginAssembly); var plugin = SchemaHelper.GetPluginDetails(PluginAssembly); var resType = plugin.Resources.Where(x => request.TypeName == x.GetCustomAttribute <TFResourceAttribute>()?.Name).First(); var invokeType = typeof(IHasValidateResourceTypeConfig <>).MakeGenericType(resType); if (invokeType.IsAssignableFrom(plugin.Provider)) { var invokeInputType = typeof(ValidateResourceTypeConfigInput <>).MakeGenericType(resType); var invokeResultType = typeof(ValidateResourceTypeConfigResult <>).MakeGenericType(resType); // Construct and populate the input type instance from the request var invokeInput = Activator.CreateInstance(invokeInputType); invokeInputType.GetProperty(nameof(request.Config)).SetValue(invokeInput, DynamicValue.Unmarshal(resType, request.Config)); // Invoke the functional method var invokeMethod = invokeType.GetMethod(nameof(IHasValidateResourceTypeConfig <object> .ValidateConfig)); 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()); } } _log.LogTrace("<-result = {@response}", response); return(await Task.FromResult(response)); } catch (Exception ex) { _log.LogError(ex, "<!exception = "); throw; } }