import { isEmpty } from 'lodash'; import React from 'react'; import { from as observableFrom, Subject } from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import type { Application, IFunction, IOverridableProps } from '@spinnaker/core'; import { AccountTag, CollapsibleSection, Details, Overrides } from '@spinnaker/core'; import { FunctionActions } from './FunctionActions'; import type { IAmazonFunction, IAmazonFunctionSourceData } from '../../domain'; import { AwsReactInjector } from '../../reactShims'; export interface IFunctionFromStateParams { account: string; region: string; functionName: string; } export interface IAmazonFunctionDetailsProps extends IOverridableProps { app: Application; functionObj: IFunction; } @Overrides('function.details', 'aws') export class AmazonFunctionDetails extends React.Component { private destroy$ = new Subject(); constructor(props: IAmazonFunctionDetailsProps) { super(props); this.state = { loading: true, }; } public extractFunction(): void { const { app, functionObj: functionFromProps } = this.props; const functionDef: IFunction = app.functions.data.find((test: IFunction) => { return ( test.functionName === functionFromProps.functionName && test.region === functionFromProps.region && test.account === functionFromProps.account ); }); if (functionDef) { observableFrom( AwsReactInjector.functionReader.getFunctionDetails( 'aws', functionFromProps.account, functionFromProps.region, functionFromProps.functionName, ), ) .pipe(takeUntil(this.destroy$)) .subscribe((details: IAmazonFunctionSourceData[]) => { if (details.length) { this.setState({ functionDef: details[0] as IAmazonFunction, loading: false, }); } }); } else { this.setState({ functionDef: {}, loading: false, }); } } public componentDidMount(): void { const { app } = this.props; const dataSource = app.functions; observableFrom(dataSource.ready()) .pipe(takeUntil(this.destroy$)) .subscribe(() => { const dataSourceUnsubscribe = dataSource.onRefresh(null, () => this.extractFunction()); this.setState({ dataSourceUnsubscribe }); this.extractFunction(); }); } public componentWillUnmount() { this.state.dataSourceUnsubscribe && this.state.dataSourceUnsubscribe(); this.destroy$.next(); } public render() { const { app } = this.props; const { loading, functionDef } = this.state; if (loading) { // Don't bother computing any children if we're loading return
; } const functionDetails = (
Last Modified
{functionDef.lastModified}
In
{functionDef.region}
VPC
{functionDef.vpcConfig ? functionDef.vpcConfig.vpcId : 'Default'}
Function ARN
{functionDef.functionArn}
Revision ID
{functionDef.revisionId}
Version
{functionDef.version}
); const eventSourceDetails = (
{functionDef.eventSourceMappings && functionDef.eventSourceMappings.length !== 0 ? functionDef.eventSourceMappings.map((value: any) => ( <>
Event Source
ARN
{value.eventSourceArn}
State
{value.state}
)) : 'None'}
); const aliasConfigurationDetails = (
{functionDef.aliasConfigurations && functionDef.aliasConfigurations.length !== 0 ? functionDef.aliasConfigurations.map((value: any) => ( <>
Alias Details
Name
{value.name}
ARN
{value.aliasArn}
)) : 'None'}
); const functionDetailsSection = ( {functionDetails} ); const eventSourceDetailsSection = ( {eventSourceDetails} ); const aliasConfigurationDetailsSection = ( {aliasConfigurationDetails} ); return (
{isEmpty(this.state.functionDef) ? ( 'Function not found.' ) : ( } name={this.state.functionDef.functionName} >
)} {!isEmpty(this.state.functionDef) ? functionDetailsSection : ''} {!isEmpty(this.state.functionDef) && !isEmpty(this.state.functionDef.eventSourceMappings) ? eventSourceDetailsSection : ''} {!isEmpty(this.state.functionDef) && !isEmpty(this.state.functionDef.aliasConfigurations) ? aliasConfigurationDetailsSection : ''}
); } }